From ffd608cbb9ba711477b7fd8051ba41e9cfaa4710 Mon Sep 17 00:00:00 2001 From: Till JS Date: Wed, 1 Apr 2026 11:59:36 +0200 Subject: [PATCH] feat(shared-ui, manacore/web): cross-app navigation enhancement (3 phases) Phase 1: Enhanced App Drawer in PillNavigation - appNavigationStore: localStorage-backed favorites, recents, usage counts - AppDrawer: replaces PillDropdown for apps with search, favorites, recents, grid - All apps using PillNavigation get this automatically Phase 2: Cmd+K Command Palette (GlobalSpotlight) - GlobalSpotlight: modal with app search, quick actions, keyboard navigation - useGlobalSpotlight: Cmd+K / Ctrl+K keyboard listener - Integrated into PillNavigation via optional spotlightActions prop Phase 3: Improved /home page - AppRow: horizontal scrollable app row for favorites/recents with pin toggle - ActivityFeed: cross-app timeline (completed tasks, upcoming events, contacts) - Replaced hardcoded 3-category layout with dynamic favorites, recents, activity feed, and usage-frequency sorted app grid Co-Authored-By: Claude Opus 4.6 (1M context) --- .../src/lib/components/ActivityFeed.svelte | 225 ++++++ .../apps/web/src/lib/components/AppRow.svelte | 167 +++++ .../web/src/routes/(app)/home/+page.svelte | 226 +++--- packages/shared-ui/src/index.ts | 12 + .../shared-ui/src/navigation/AppDrawer.svelte | 697 ++++++++++++++++++ .../src/navigation/GlobalSpotlight.svelte | 556 ++++++++++++++ .../src/navigation/PillNavigation.svelte | 40 +- .../navigation/appNavigationStore.svelte.ts | 142 ++++ packages/shared-ui/src/navigation/index.ts | 14 + .../navigation/useGlobalSpotlight.svelte.ts | 39 + 10 files changed, 1985 insertions(+), 133 deletions(-) create mode 100644 apps/manacore/apps/web/src/lib/components/ActivityFeed.svelte create mode 100644 apps/manacore/apps/web/src/lib/components/AppRow.svelte create mode 100644 packages/shared-ui/src/navigation/AppDrawer.svelte create mode 100644 packages/shared-ui/src/navigation/GlobalSpotlight.svelte create mode 100644 packages/shared-ui/src/navigation/appNavigationStore.svelte.ts create mode 100644 packages/shared-ui/src/navigation/useGlobalSpotlight.svelte.ts diff --git a/apps/manacore/apps/web/src/lib/components/ActivityFeed.svelte b/apps/manacore/apps/web/src/lib/components/ActivityFeed.svelte new file mode 100644 index 000000000..9408658e0 --- /dev/null +++ b/apps/manacore/apps/web/src/lib/components/ActivityFeed.svelte @@ -0,0 +1,225 @@ + + +{#if feedItems.length > 0} +
+

{locale === 'de' ? 'Aktivität' : 'Activity'}

+
+ {#each feedItems as item (item.id)} +
+ {item.icon} +
+ {item.title} + {#if item.subtitle} + {item.subtitle} + {/if} +
+ {formatRelative(item.timestamp)} +
+ {/each} +
+
+{/if} + + diff --git a/apps/manacore/apps/web/src/lib/components/AppRow.svelte b/apps/manacore/apps/web/src/lib/components/AppRow.svelte new file mode 100644 index 000000000..c115abc3a --- /dev/null +++ b/apps/manacore/apps/web/src/lib/components/AppRow.svelte @@ -0,0 +1,167 @@ + + +{#if apps.length > 0} +
+

{title}

+
+ {#each apps as app (app.id)} + + {/if} + + {/each} +
+
+{:else if emptyText} +
+

{title}

+

{emptyText}

+
+{/if} + + diff --git a/apps/manacore/apps/web/src/routes/(app)/home/+page.svelte b/apps/manacore/apps/web/src/routes/(app)/home/+page.svelte index 37cc7634f..7af25dfe0 100644 --- a/apps/manacore/apps/web/src/routes/(app)/home/+page.svelte +++ b/apps/manacore/apps/web/src/routes/(app)/home/+page.svelte @@ -1,16 +1,19 @@ + + +
+ + + + {#if isOpen} + + + + + + {/if} +
+ + diff --git a/packages/shared-ui/src/navigation/GlobalSpotlight.svelte b/packages/shared-ui/src/navigation/GlobalSpotlight.svelte new file mode 100644 index 000000000..153c582ba --- /dev/null +++ b/packages/shared-ui/src/navigation/GlobalSpotlight.svelte @@ -0,0 +1,556 @@ + + +{#if open} + +
+ +
e.stopPropagation()}> + +
+ + + + + Esc +
+ + + {#if results.length > 0} +
+ {#each groupedResults as group, gi} + {#if group.category} +
{group.category}
+ {/if} + {#each group.items as item, ii} + {@const flatIdx = getFlatIndex(gi, ii)} + + {/each} + {/each} +
+ {:else if searchQuery} +
Keine Ergebnisse
+ {/if} + + + +
+
+{/if} + + diff --git a/packages/shared-ui/src/navigation/PillNavigation.svelte b/packages/shared-ui/src/navigation/PillNavigation.svelte index 9bd845489..c06d50420 100644 --- a/packages/shared-ui/src/navigation/PillNavigation.svelte +++ b/packages/shared-ui/src/navigation/PillNavigation.svelte @@ -11,6 +11,9 @@ import PillDropdown from './PillDropdown.svelte'; import PillTabGroup from './PillTabGroup.svelte'; import PillTagSelector from './PillTagSelector.svelte'; + import AppDrawer from './AppDrawer.svelte'; + import GlobalSpotlight, { type SpotlightAction } from './GlobalSpotlight.svelte'; + import { createGlobalSpotlightState } from './useGlobalSpotlight.svelte'; // Phosphor Icons (via shared-icons) import { Archive, @@ -275,6 +278,10 @@ showA11yQuickToggles?: boolean; /** Called when an app should be opened in a split panel */ onOpenInPanel?: (appId: string, url: string) => void; + /** Quick actions for Cmd+K spotlight (pass to enable spotlight) */ + spotlightActions?: SpotlightAction[]; + /** Placeholder text for spotlight search */ + spotlightPlaceholder?: string; /** Accessible label for the nav element */ ariaLabel?: string; /** Feedback page href (shown in user dropdown). Set to empty string to hide. */ @@ -326,6 +333,8 @@ onA11yReduceMotionChange, showA11yQuickToggles = false, onOpenInPanel, + spotlightActions, + spotlightPlaceholder, ariaLabel, feedbackHref = '/feedback', themesHref, @@ -371,6 +380,12 @@ // Dropdown direction: always up since nav is always at bottom const dropdownDirection = 'up' as const; + // App drawer state + let appDrawerOpen = $state(false); + + // Global spotlight (Cmd+K) — only active when spotlightActions are provided + const spotlight = spotlightActions ? createGlobalSpotlightState() : null; + function collapseNav() { if (onCollapsedChange) { onCollapsedChange(true); @@ -401,12 +416,14 @@
{#if showAppSwitcher && appItems.length > 0} - (appDrawerOpen = open)} + {onOpenInPanel} + {allAppsHref} + {allAppsLabel} + triggerLabel={appName} /> {:else} @@ -802,6 +819,17 @@ {/if} + +{#if spotlight && spotlightActions} + +{/if} +