Drei Probleme adressiert:
1. **Icon-Vereinheitlichung**: alle Feedback-Affordances tragen jetzt
das phosphor `heart-half`-Icon (statt vorher Lightbulb/Mix). Geändert
in PillNav-Usermenü, ModuleShell-Header (FeedbackHook), Phosphor-Icon-
Map. Eine Stelle, ein Icon — Wiedererkennung steigt.
2. **Inline statt Modal in Workbench-Cards**: AppPage.svelte rendert
das Feedback-Formular jetzt im selben Slot wie die Hilfe-Seite —
Klick auf das Heart-Half-Icon togglet den Inline-Panel statt einen
Modal-Backdrop über die ganze Workbench zu legen. Hilfe und Feedback
sind mutually-exclusive (eines geht zu, sobald das andere aufgeht).
3. **Form-Body extrahiert**: FeedbackForm.svelte enthält jetzt das
Formular ohne jegliches Chrome. FeedbackQuickModal nutzt es im Modal-
Mode (Standalone-Routen, PillNav), AppPage im Inline-Mode. Eine
Quelle, beide Surfaces bleiben in sync.
ModuleShell schluckt zusätzlich `onFeedback`/`feedbackOpen`-Props: wenn
gesetzt, ruft die FeedbackHook-Komponente onClick statt das eigene Modal
zu öffnen — der Host (AppPage) übernimmt das Rendering.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Der Submit-Handler hat den Body 1:1 an feedbackService.createFeedback
weitergereicht. Da CreateFeedbackInput appId nicht enthält (Client
schickt es als X-App-Id-Header), schlug jeder INSERT mit "null value
in column app_id violates not-null constraint" fehl.
Außerdem: lightbulb-Icon im phosphor-icon-map nachgezogen, sonst
zeigt der "Idee teilen"-Eintrag in der barMode-Variante des Usermenüs
kein Icon (nur Label).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Ersetzt den schwebenden "Idee?"-Pill durch einen Eintrag im rechten
Usermenü (Profil / Credits / Idee teilen / Logout). Ein Affordance an
einer Stelle statt zwei nebeneinander.
- PillNavigation: neuer onFeedback-Prop + Lightbulb-Icon. Wenn gesetzt,
ersetzt der Eintrag den Legacy-/feedback-Link in accountLinks und
taucht zusätzlich oben in den userMenuBarItems (barMode) auf.
- UserMenuPanel: AccountLink kennt jetzt onClick? als Alternative zu
href? — Action-Chips schließen das Panel direkt nach dem Klick.
- (app)/+layout: GlobalFeedbackPill-Mount entfernt, FeedbackQuickModal
wird state-gebunden gerendert (moduleContext aus Pfad/?app= abgeleitet
wie bisher in der alten Pill).
- GlobalFeedbackPill.svelte gelöscht — niemand referenziert sie mehr.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Before: guests had to open the user-menu dropdown to find the login
button. Now the login CTA renders as a visible primary pill immediately
right of the (icon-only) user-menu trigger, so signing in is one click.
Removed the duplicate Anmelden entry from userMenuBarItems — theme,
mode toggle, and language stay in the bar for signed-out users.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Repositions the switcher from its floating spot in the top right of
the workbench into the bottom-fixed PillNav so it sits with the rest
of the nav chrome. Matches how every other persistent nav control
(app switcher, AI tier, sync status) lives in the PillNav.
Mechanics:
- @mana/shared-ui PillNavigation gains a `startSlot?: Snippet` prop
rendered inside .pill-nav-container, before AppDrawer. Generic slot
— any host component drops in.
- (app)/+layout.svelte passes the existing <SpaceSwitcher /> as the
snippet (authenticated only). The old .space-bar wrapper above
<main> is removed along with its CSS.
- SpaceSwitcher trigger is restyled to match Pill conventions: pill
radius 999px, 32px height, 0.8125rem text, tighter paddings, shorter
name cap (7rem). Visually merges with the surrounding Pills.
- Dropdown menu flips upward (bottom: calc(100% + 4px)) because the
PillNav is position:fixed bottom — opening downward would land
off-screen.
Type-check: 0 errors across 7200 files.
Scope tests: 10/10 pass.
Go tests + bun tests (mana-auth): all pass.
Plan: docs/plans/spaces-foundation.md
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Remove empty dirs: modules/mana/, modules/subscription/, and 7
empty route dirs (spiral, profile, themes, help, apps, mana, credits)
- Remove @mana/subscriptions from web app dependencies (never imported)
- PillNavigation: drop settingsHref, manaHref, allAppsHref/allAppsLabel
props + their link-builder blocks (none are passed anymore; all system
pages route via /?app=<id> deep-links now)
- Update layout comment to reflect current architecture
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Settings lives in the Workbench now — no longer needs its own pill.
settingsHref becomes optional; both places that render the entry
(user-menu link list + nav overflow dropdown) skip it when unset.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The standalone "Cloud Sync" pill sat fifth in the bar-mode pill row
on mobile / narrow layouts, pushing the pill row to 5+ items and
duplicating actions the user menu already surfaces (Sync-Einstellungen,
credits link). Move the sync status + actions into userMenuBarItems
so they appear as a labelled section inside the bar that opens when
the user pill is tapped.
Render order for signed-in users now goes:
account · settings · theme-mode · theme · [Sync section] · logout
The section header uses the existing `divider: true, label: 'Sync'`
shape PillDropdownBar already understands, so the status line ("Cloud
Sync aktiv", etc.) sits under a real heading. For guests the section
is skipped entirely — sync doesn't apply before login.
Left the non-barMode popover path alone (showSyncStatus + syncStatusItems
still drive the inline PillDropdown when a popover is in use) since
the complaint was specifically about the bar's fifth pill on mobile.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The 2rem linear-gradient mask at each end of the tag strip was
supposed to hint at scrollable overflow, but it cuts off the
leading + trailing tags on narrow layouts where they're already
just barely visible. Dropping both mask-image declarations lets
the pills render edge-to-edge. Overflow scrolling + hidden
scrollbar stay as they were, plus the hover-lift removal from
the previous commit.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The whole pill family used a translateY(-1px / -2px) on :hover that
made the chrome jitter every time the cursor crossed anything —
especially noticeable in the TagStrip, PillNav, and the user-menu
bar where pills sit close together and a 1-2px jump reads as
twitching rather than polish.
Removed the hover transform (and the matching :active reset on
the base Pill) from:
- Pill.svelte — base primitive, covers PillNav + every bar pill
- AppDrawer.svelte — .glass-pill in the app switcher
- PillTagSelector.svelte — .glass-pill in the quick-input tag selector
- PillTimeRangeSelector.svelte — .glass-pill in the calendar range picker
- UserMenuPanel.svelte — .chip hover in the popover variant
Background, border, and shadow hover states are kept — only the
vertical displacement is gone.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When the right-hand user pill is clicked as a guest (barMode), the
opening bar used to show just a decorative "Menü" label pill on
the left and then settings + theme toggles — none of which are a
useful first action for someone not logged in.
- phosphor-icon-map: register SignIn as `login`, so PillDropdownBar
can render it the same way as the existing `logout` glyph.
- PillNavigation.userMenuBarItems: prepend an "Anmelden" item for
guests (no userEmail + loginHref given) that navigates to
loginHref. It becomes the first CTA in the bar, above settings /
theme / language.
- PillNavigation.userBarConfig: drop the bar-header label when the
viewer is a guest. The decorative "Menü" pill added nothing
alongside the new Anmelden action and just cluttered the leading
edge of the bar.
The popover variant of the user menu (UserMenuPanel) already had
its own guest login button — this mirrors that behaviour for the
bottom-bar variant used on mobile / narrow layouts.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sync status, user menu (bar-mode + overlay fallback) and logout now use
the shared Pill component like the rest of PillNavigation. All pill
styling now lives in a single place.
- Pill gains an escape-hatch `data?: Record<string, string>` prop for
arbitrary data-* attributes (used by the user-menu trigger which is
click()-ed via querySelector from the consuming layout) and a
bindable `element` binding for imperative focus/positioning
(replaces the old bind:this={userMenuTrigger}).
- Remove the now-dead inline .pill / .glass-pill / .logout-pill /
.pill-label / .pill.active / .pill.icon-only CSS from PillNavigation
(all living in Pill.svelte now). ~110 lines of CSS gone.
- The mobile override that forced 44px min-height on .pill is also gone;
Pill sizes are controlled via the size prop.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
PillNavigation rendered three near-identical inline pill blocks (prepended
elements, main nav items, appended elements). Consolidate onto the Pill
component so the visual base stays in lockstep with the bottom-stack bars.
- Extend Pill with size='sm'|'md'. sm = 36px with 18px icons (PillNav
style); md = 44px with 20px icons (bar pills, default).
- Move the icon-only padding override into Pill itself.
- Extract the Mana-Logo SVG (duplicated inline) to ManaLogoIcon.svelte.
- Replace the three inline pill loops in PillNavigation with <Pill size='sm'>.
Mana-logo and iconSvg cases ride the `leading` snippet. onClick vs href
disambiguation is collapsed into a single Pill call per item.
- Remove the now-unreachable .pill-icon scoped CSS that was only meaningful
for the removed inline SVGs (Phosphor icon sizing comes from the size
prop).
Net: ~70 lines removed from PillNavigation.svelte without changing the
render output. Bar-mode triggers (sync / ai / theme / user) still render
inline because their logic is too entangled with activeBarId — leave for
a follow-up.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Both QuickInputBar (InputBar.svelte), CommandBar.svelte, and GlobalSpotlight
were duplicating syntax highlighting and the 150ms search debounce. Pull
these into a new `packages/shared-ui/src/search-core/` module so the two
input surfaces stay in sync on feel and matching rules.
- search-core/highlight.ts — HighlightPattern type, locale-aware
getHighlightPatterns(), and the shared highlightText() (HTML-escape +
span wrap). Patterns were previously in quick-input/highlightPatterns.ts
+ inline in CommandBar.svelte.
- search-core/config.ts — SEARCH_DEBOUNCE_MS = 150. Used from InputBar,
CommandBar, GlobalSpotlight, and apps/mana web SearchEngine.
- quick-input/highlightPatterns.ts + types.ts become thin back-compat
re-exports.
- Public surface: @mana/shared-ui now exports getHighlightPatterns,
highlightText, SEARCH_DEBOUNCE_MS, and the HighlightPattern type.
No UX change. UIs still live in their own files (per earlier split
recommendation: shared backend, separate surfaces).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Extract Pill.svelte as the single visual primitive (44px, icon+label,
active/primary/danger variants) used by PillDropdownBar and TagStrip.
PillNav keeps its own internal .pill class (36px, icon-only-oriented).
- Extract phosphor-icon-map.ts to deduplicate the icon lookup tables
that previously lived inline in PillDropdownBar.
- Unify bar slot heights in (app)/+layout.svelte: 56px PillNav,
64px for tags / quickinput / tabbar / dropdown-bar. Remove debug
outlines. Collapse bottom-stack gap so bars sit flush below PillNav.
- SceneAppBar wrapped in 64px slot, scene-pill/app-tab 40px to match.
- Enforce single-bar policy: opening one bar closes the others.
- QuickInputBar strip-down: remove leading CheckSquare icon and trailing
nav-toggle snippet; bar is pure search input now.
- Move user-menu (last PillNav pill) to bar-mode with short content:
Einstellungen, Light/Dark/System segmented, Theme, Logout.
- Swap tabs nav icon from Columns to Cards for better readability.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- 1–9 scroll to the Nth open app on the workbench homepage; 0 opens the
app picker.
- q/w/e toggle the bottom bars (workbench tabs / search / tags); r opens
the user-menu PillDropdownBar (expanding the PillNav first if needed);
t toggles the PillNav visibility.
Adds a `data-user-menu-trigger` hook on the user pill so the layout can
drive the menu bar programmatically without duplicating its config.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace inline PillDropdownBar for user menu with a centered overlay
panel (UserMenuPanel). Move AI tier, theme, and language selectors
into the panel. Make app switcher and user pill icon-only. AI section
split into "Textgenerierung" and "Spracherkennung" subsections.
- AppDrawer trigger: icon-only (no label/chevron)
- User pill: icon-only, opens overlay panel instead of bar
- Theme + AI pills removed from nav bar (now in user panel)
- UserMenuPanel: centered on desktop, bottom-sheet on mobile
- Login button in footer, structured sections with subsection headers
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
PillNav overhaul:
- Dropdown-as-bar: theme/AI/sync/user menus render as horizontal
bars in the bottom stack (PillDropdownBar) instead of floating
popovers. New onOpenBar/activeBarId props on PillNavigation.
- iconOnly pills: tags/search/workbench-tabs pills show only icons.
Home pill removed. New iconOnly flag on PillNavItem.
- Segmented toggle groups: items sharing a `group` id render as a
single segmented pill (e.g. Light/Dark/System triple).
- Fullscreen mode: press "f" to hide all bottom chrome, Esc to exit.
- QuickInputBar + bottom bar visibility toggles via new pills.
- Progress ring on AI trigger pill during model download
(conic-gradient ::after, follows pill border-radius).
@mana/local-stt — new package for browser-local speech-to-text:
- Whisper models via transformers.js v4 (WebGPU + WASM fallback)
- Same Web Worker architecture as @mana/local-llm
- Two models: Whisper Tiny (150 MB) and Whisper Small (950 MB)
- Reactive Svelte 5 bindings (getLocalSttStatus, loadLocalStt, transcribe)
Voice-to-text integration:
- useLocalStt() composable: mic capture via AudioContext +
ScriptProcessor, resample to 16kHz mono, feed into Whisper worker
- Mic button in QuickInputBar (leftAction slot) with
recording/loading/transcribing states + pulse animation
- Transcribed text injected into InputBar via new injectedText prop
- STT model selector in AI bar alongside LLM tier controls
Also: vite.config.ts server.fs.allow expanded to monorepo root
so workspace package workers resolve in dev.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Profile/Settings/Spiral/Credits move out of the standalone nav pills and
into the user-menu dropdown so the bottom bar stays compact. The dropdown
now also renders for guests (login users) — auth-only items (Profil,
Mana, Feedback, Logout) get filtered out, and a primary-styled "Anmelden"
entry replaces Logout. Themes is dropped from the dropdown since it
already has its own theme-variant pill.
New PillNavigation props: creditsHref, guestMenuLabel. New PillDropdown
icon paths: creditCard, spiral. New PillDropdownItem flag: primary
(prominent CTA styling), used for the guest Anmelden item.
All .glass-pill classes across PillNavigation, PillDropdown, PillTabGroup,
PillTagSelector, PillViewSwitcher, PillTimeRangeSelector, PillToolbar,
AppDrawer and ExpandableToolbar move from rgba+backdrop-blur to solid
theme tokens (hsl(var(--color-card)) / --color-border / --color-foreground)
so pills are fully opaque and follow the active theme variant instead of
having a frosted look that varied by background.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Settings page now uses a sidebar layout with category buttons (Profil,
Allgemein, KI, Sicherheit, Credits, Daten & Sync), an inline search field
that jumps to the matching section, and componentized sections under
lib/components/settings/. Each section owns its own data loading; the
+page.svelte shrinks from 617 to ~85 lines as a thin orchestrator.
The pill-nav AI tier dropdown now renders an icon per option (cpu, server,
cloud) and a power icon for the off state, and the "KI-Einstellungen"
shortcut deep-links to /settings#ai-options which auto-selects the KI tab
and scrolls to the panel.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
PillNavigation sync dropdown:
- New cloud icon pill showing sync status (Lokal/Sync/Pausiert)
- Dropdown with contextual actions: activate, top up credits, settings
- Shows next charge date when active
- Only visible for authenticated users
Onboarding wizard:
- New SyncStep between AI tier and Credits steps
- Explains local-first model: data always stays local, sync is optional
- Interval selection (monthly 30 / quarterly 90 / yearly 360 credits)
- Activate button with balance check and error handling
- Also fixed missing AiTierStep rendering in wizard template
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Quick-access dropdown in the bottom navigation bar for toggling LLM
tiers without navigating to the full Settings page. Follows the same
PillDropdown pattern as the existing theme variant selector.
Three files changed:
packages/shared-ui/src/navigation/types.ts
Add showAiTierSelector, aiTierItems, currentAiTierLabel to
PillNavigationProps. Same shape as the existing theme variant
and language switcher props.
packages/shared-ui/src/navigation/PillNavigation.svelte
Destructure the three new props (defaults: false, [], 'KI').
Render a PillDropdown with icon="cpu" between the theme
variant selector and the theme toggle button.
apps/mana/apps/web/src/routes/(app)/+layout.svelte
Import llmSettingsState, updateLlmSettings, tierLabel, type
LlmTier from @mana/shared-llm. Import isLocalLlmSupported,
getLocalLlmStatus, loadLocalLlm from @mana/local-llm.
Build aiTierItems as a $derived array of PillDropdownItem:
- Three tier toggles: Browser (Gemma 4), Server (Gemma 4),
Cloud (Gemini). Each shows active checkmark when enabled.
Clicking toggles the tier in/out of allowedTiers. Browser
toggle hidden when WebGPU isn't available.
- Browser model status line: "✓ Modell geladen" (disabled,
green) or "Lade... X%" (disabled, progress) or "Modell
laden (~500 MB)" (clickable, triggers loadLocalLlm).
Only shown when browser tier is enabled.
- Divider + "KI-Einstellungen" link to /settings for the
full configuration (cloud consent, behavior toggles, etc.)
Build currentAiTierLabel as privacy-sorted first-active-tier
short name: "Browser" or "Server" or "Cloud" or "Aus".
Wire all three to PillNavigation via showAiTierSelector={true}
+ {aiTierItems} + {currentAiTierLabel}.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Comprehensive warning sweep across 128 files that brings svelte-check
from 270 warnings → 0 (plus 3 new errors from concurrent upstream
changes fixed inline).
Final state: 6473 files, 0 errors, 0 warnings, 0 files with problems.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Eight more package-level type errors that all came from the same
small handful of patterns.
Modal escape-key handlers calling click-style functions
Four modals (AuthGateModal, GuestWelcomeModal, ConfirmationPopover,
ShareModal) had `onkeydown={(e) => { if (e.key === 'Escape')
handleBackdropClick(); }}` — but handleBackdropClick took a MouseEvent
parameter, so the no-arg call failed with "Expected 1 arguments,
got 0". Fix: route the keyboard escape path through the right
no-arg helper (`onClose` / `handleClose` / `handleContinueAsGuest`)
or pass the keyboard event through with a cast for the popover
trigger that genuinely shares its handler with the click path.
WallpaperModal $derived
`currentLayout` and `currentBackground` were declared with
`$derived(() => {...})` — passing a function expression. The
variant that takes a thunk is `$derived.by(...)`; plain `$derived`
expects a single value expression. Result: the variables held the
arrow function itself, the call sites had to invoke them as
`currentLayout()`, and TS rejected the function value where Layout
was expected. Switch to `$derived.by`, drop the call-site parens.
TagList.svelte
Generic param was named `Tag` in the handler signature
(`tag: Tag`) but the imported type was aliased as `TagType`. Tag
was undefined → "Cannot find name 'Tag'". Renamed to TagType.
TagStrip.svelte
`dropAccepts?: string[]` is too wide for `passiveDropZone`'s
`accepts: DragType[]`. Narrowed the prop type to `DragType[]`
and added the missing import.
shared-auth/types: UserData.{name,image}?
Two more optional fields for the public user shape. Both come
from the JWT user_metadata claim when the user has filled in
their profile during onboarding. Without these the
ProfileStep.svelte onboarding component couldn't read
`authStore.user?.name` / `?.image` without `as any`. Added
alongside `twoFactorEnabled` from the previous shared-auth
commit; same Optional rationale (guest tokens omit the claim).
Net: -10 type errors.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Five unrelated packages each had a few imports pointing at the wrong
file or missing from their public surface. Grouped because none of
the individual fixes warrants its own commit and they all unblock
the same downstream consumer (apps/mana/apps/web type-check).
packages/help
- HelpPage.svelte: `'../types.js'` and `'./content'` for
HelpPageProps/HelpSection/SearchResult — neither path exists.
Real homes are `../ui-types` (props) and `../search-types`
(search shapes). Fix the imports.
- HelpSearch.svelte: same `'../content'` typo for SearchResult →
`'../search-types'`.
- translations.ts: `'./types.js'` for HelpPageTranslations →
`'./ui-types'`.
- ui-types.ts: was importing SearchResult from `'./content'` but
that module only exports content shapes. Split into two imports
so HelpContent stays from content.ts and SearchResult comes from
search-types.ts.
packages/feedback
- FeedbackPage.svelte: imported `Feedback` and `CreateFeedbackInput`
from `'./createFeedbackService'` but the service module only
exports the service factory. Real homes are `'./feedback'`
(Feedback) and `'./api'` (CreateFeedbackInput).
- FeedbackForm.svelte: same `'./feedback'` typo for
CreateFeedbackInput → `'./api'`.
packages/subscriptions
- UsageCard / CostCard / pages/SubscriptionPage: all imported
UsageData / CostItem from `'./plans'` but those types live in
`'./usage'`. SubscriptionPage additionally had a relative-path
bug — it's at `src/pages/`, not `src/`, so `./plans` resolved
to `pages/plans` (nonexistent). Now imports `'../plans'` for
plan types and `'../usage'` for usage/cost types.
packages/shared-ui
- index.ts: re-exports the QuickInputItem family from
`./quick-input` but had forgotten `HighlightPattern`. Added.
Apps that build their own InputBar pattern config (e.g.
mana/web/src/lib/quick-input/types.ts) need it as a public type.
- PillNavigation.svelte: imported `SpotlightAction` and
`ContentSearcher` from `./GlobalSpotlight.svelte` (a Svelte
component file), which only re-exports the default. Both types
live in `./types`. Move them to the existing types-import
block; the GlobalSpotlight import becomes a plain default.
packages/shared-auth-ui
- stores/createAuthStore.svelte.ts: imported AuthServiceAdapter /
AuthResult / BaseUser from `'./types'` (nonexistent — the file
is `'./store-types'`).
Net: -23 type errors. Zero behavior change.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
ListViews (25 remaining modules):
- All module ListViews now have responsive container padding (p-3 sm:p-4)
- All interactive items have min-h-[44px] touch targets on mobile
- Picture/Moodlit grids: grid-cols-2 on mobile, grid-cols-3 on desktop
DetailViews (17 modules):
- All DetailViews have reduced padding on mobile (0.75rem vs 1rem)
- All buttons, inputs, selects have min-height: 44px on mobile
Modals (14 components):
- Shared Modal.svelte: bottom-sheet pattern on mobile (slides up from bottom)
- 13 app-specific modals: same bottom-sheet treatment
- Reduced padding, larger close buttons, max-h-[95vh] on mobile
Shared UI components:
- GlobalSpotlight: bottom-sheet on mobile, prevents iOS zoom, hides keyboard hints
- PillDropdown: full-width bottom-sheet on mobile with backdrop
- AppDrawer: 44px touch targets on buttons and search
- TagStrip: 44px min-height on all pill buttons
- ToastContainer: larger touch targets, safe-area positioning
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds right-click context menus to workbench cards, minimized tabs, PillNavigation,
and item-level context menus for todo, calendar, contacts, habits, notes, places,
and moodlit modules. Uses a shared builder pattern with app-specific actions
registered via AppDescriptor.contextMenuActions.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
All app clicks in the PillNav app drawer now open in a new tab via
window.open('_blank'). Previously internal URLs used window.location.href
(same tab navigation) which was confusing in the unified app context.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace 4 independent position:fixed elements with one flex container that
stacks them naturally from bottom to top. Elements push each other
automatically — no more hardcoded offsets or z-index conflicts.
Stack order (bottom → top):
1. PillNavigation (collapsible)
2. TagStrip (togglable)
3. QuickInputBar + toggle button row
Shared-UI changes:
- PillNavigation: add positioning='fixed'|'static' prop
- QuickInputBar: add positioning='fixed'|'static' prop
- TagStrip: add positioning='fixed'|'static' prop
- All default to 'fixed' for backward compatibility
Layout changes:
- Wrap all bottom elements in .bottom-stack (position:fixed, flex-column)
- Remove hardcoded bottomOffset calculations
- Toggle button is now inline next to QuickInputBar (not separately positioned)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The panel was positioned below the trigger button using top, causing
it to render off-screen since PillNav sits at the bottom. Changed to
bottom positioning so the drawer opens upward.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add ContentSearcher interface, debounced cross-app search with AbortController,
loading indicators, and content result rendering to the spotlight component.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add NotificationBar shared component for in-stack notifications
- Add BottomNotification type and top snippet slot to BottomStack
- Add bottomOffset prop to PillNavigationProps for flexible positioning
- Remove pillNavCollapsed from todo settings (PillNav now always visible,
toggled by layout FAB that hides all bottom bars)
- Replace floating GuestRegistrationNudge with integrated NotificationBar
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Shared TagStrip: add dragSource on tag pills + passiveDropZone for item→tag
drops. New onTagDrop and dropAccepts props. DnD CSS for hover/success states.
- Unified app layout: add DragPreview, context-based tagDropHandler so child
pages can register their own drop logic.
- Todo module: add updateLabels() to tasks store (with metadata merge).
- Todo page: add dropTarget on task items, tag badge display via getTaskTags(),
register tagDropHandler for passive task→tag drops.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
mana-apps.ts:
- Change all APP_URLS from subdomains to internal paths
(e.g., https://todo.mana.how → https://mana.how/todo)
- Keep separate subdomains only for games (arcade) and matrix
PillNavigation, AppDrawer, GlobalSpotlight:
- Detect internal URLs and navigate directly instead of window.open
- External URLs (games, matrix) still open in new tab
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Migrate 41 inline SVG icons to Phosphor components across 21 shared-ui
files including CommandBar, InputBar, Sidebar, AudioPlayer, PageHeader,
Select, TagBadge, SettingsRow, and more.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Implement the foundational local-first data layer for ManaCore apps:
- New @manacore/local-store package (Dexie.js IndexedDB, sync engine, Svelte 5 reactive queries)
- New mana-sync Go service (sync protocol, WebSocket push, field-level LWW conflict resolution)
- Todo app migrated as pilot: stores read/write IndexedDB, guest mode with onboarding seed data
- PillNavigation: prominent login pill for unauthenticated users
- SyncIndicator component showing local/syncing/offline status
- GuestWelcomeModal on first visit for Todo app
- Removed demo-mode auth_required checks from Todo components (all writes are now local)
- CSP fix for local development (localhost:3001, localhost:3050)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- PillNavigation: add helpHref and themesHref props with help icon in account dropdown
- PillDropdown: add help icon (question mark circle) to iconPaths
- shared-help-types: add getManaFAQs/getManaFeature for shared Mana credit FAQs
- shared-help-types: add getPrivacyFAQs for shared privacy/GDPR/tech independence FAQs
- ManaScore: add Help-Seite and Feedback-Seite as UX criteria, shared-help-ui and
shared-feedback-ui as Core cross-app packages
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Rewrite TaskListSkeleton to match notepad design (spiral holes, red margin line, cream background)
- Rewrite TaskItemSkeleton as flat rows with border-bottom instead of card style
- Rewrite KanbanColumnSkeleton with glassmorphism and pill-shaped task cards
- Update KanbanBoardSkeleton with matching border-radius and dark mode support
- Group navigation pills (Liste/Kanban/Tags) into PillTabGroup for clear UX distinction from toggle pills (Filter)
- Add Phosphor icon support to PillTabGroup component
- Fix %sveltekit.head% appearing as literal text in production by removing duplicate placeholder from HTML comment
- Disable PWA service worker in dev mode
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Move secondary navigation items (Themes, Spiral) from the main pill
nav bar into the user profile dropdown menu. Feedback and Settings
were already there. This declutters the main nav to just core views:
Liste, Kanban, Filter, Tags.
Add themesHref and spiralHref optional props to PillNavigation
component so any app can show these in the user dropdown.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Raise FAB z-index from 50 to 1002 so close button is clickable above PillNav (z:1000)
- Remove Settings from standalone nav items (already in account dropdown)
- Move Mana button from standalone pill into account dropdown
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>