From 4d0e9a6a3f8431c158a53e0e36e10e722fd29809 Mon Sep 17 00:00:00 2001 From: Till JS Date: Wed, 1 Apr 2026 12:11:34 +0200 Subject: [PATCH] feat: add Cmd+K spotlight actions to all 23 apps Each app's PillNavigation now has spotlightActions with app-specific quick actions (create, navigate, settings). Users can press Cmd+K / Ctrl+K from any app to search apps, navigate, and trigger actions. Apps: todo, calendar, contacts, chat, picture, clock, zitare, cards, storage, manacore, mukke, presi, context, questions, photos, planta, citycorners, guides, calc, moodlit, matrix, uload, arcade Co-Authored-By: Claude Opus 4.6 (1M context) --- .../apps/web/src/routes/(app)/+layout.svelte | 23 +++++++ .../apps/web/src/routes/(app)/+layout.svelte | 27 ++++++++ .../apps/web/src/routes/(app)/+layout.svelte | 27 +++++++- .../web/src/routes/(protected)/+layout.svelte | 27 +++++++- .../apps/web/src/routes/(app)/+layout.svelte | 24 ++++++- .../apps/web/src/routes/(app)/+layout.svelte | 32 +++++++++ .../apps/web/src/routes/(app)/+layout.svelte | 26 +++++++ .../apps/web/src/routes/(app)/+layout.svelte | 20 ++++++ .../apps/web/src/routes/(app)/+layout.svelte | 69 +++++++++++++++---- .../apps/web/src/routes/(app)/+layout.svelte | 21 +++++- .../apps/web/src/routes/(app)/+layout.svelte | 18 ++++- .../apps/web/src/routes/(app)/+layout.svelte | 19 ++++- .../apps/web/src/routes/(app)/+layout.svelte | 32 +++++++++ .../apps/web/src/routes/(app)/+layout.svelte | 25 ++++++- .../apps/web/src/routes/app/+layout.svelte | 33 ++++++++- .../apps/web/src/routes/(app)/+layout.svelte | 31 ++++++++- .../apps/web/src/routes/(app)/+layout.svelte | 31 ++++++++- .../apps/web/src/routes/(app)/+layout.svelte | 25 +++++++ .../apps/web/src/routes/+layout.svelte | 21 +++++- .../apps/web/src/routes/(app)/+layout.svelte | 32 +++++++++ .../apps/web/src/routes/(app)/+layout.svelte | 21 +++++- .../apps/web/src/routes/(app)/+layout.svelte | 25 ++++++- .../apps/web/src/routes/(app)/+layout.svelte | 20 ++++++ 23 files changed, 602 insertions(+), 27 deletions(-) diff --git a/apps/calc/apps/web/src/routes/(app)/+layout.svelte b/apps/calc/apps/web/src/routes/(app)/+layout.svelte index 5d88e234d..3a82a5991 100644 --- a/apps/calc/apps/web/src/routes/(app)/+layout.svelte +++ b/apps/calc/apps/web/src/routes/(app)/+layout.svelte @@ -10,6 +10,7 @@ PillDropdownItem, CommandBarItem, QuickAction, + SpotlightAction, } from '@manacore/shared-ui'; import { theme } from '$lib/stores/theme.svelte'; import { authStore } from '$lib/stores/auth.svelte'; @@ -246,6 +247,27 @@ goto('/login'); } + const spotlightActions: SpotlightAction[] = [ + { + id: 'calculator', + label: 'Rechner', + category: 'Navigation', + onExecute: () => goto('/standard'), + }, + { + id: 'converter', + label: 'Umrechner', + category: 'Navigation', + onExecute: () => goto('/converter'), + }, + { + id: 'settings', + label: 'Einstellungen', + category: 'Navigation', + onExecute: () => goto('/settings'), + }, + ]; + async function handleAuthReady() { await Promise.all([calcStore.initialize(), tagLocalStore.initialize()]); @@ -316,6 +338,7 @@ themesHref="/themes" helpHref="/help" allAppsHref="/apps" + {spotlightActions} /> {#if isTagStripVisible} diff --git a/apps/calendar/apps/web/src/routes/(app)/+layout.svelte b/apps/calendar/apps/web/src/routes/(app)/+layout.svelte index f663af2da..2265af077 100644 --- a/apps/calendar/apps/web/src/routes/(app)/+layout.svelte +++ b/apps/calendar/apps/web/src/routes/(app)/+layout.svelte @@ -16,6 +16,7 @@ QuickInputItem, PillTagSelectorConfig, PillNavElement, + SpotlightAction, } from '@manacore/shared-ui'; import { theme } from '$lib/stores/theme'; import { authStore } from '$lib/stores/auth.svelte'; @@ -403,6 +404,31 @@ ); } + const spotlightActions: SpotlightAction[] = [ + { + id: 'new-event', + label: 'Neues Event', + icon: 'plus', + shortcut: 'N', + category: 'Erstellen', + onExecute: () => goto('/new'), + }, + { id: 'today', label: 'Heute', category: 'Navigation', onExecute: () => goto('/') }, + { id: 'week', label: 'Wochenansicht', category: 'Navigation', onExecute: () => goto('/week') }, + { + id: 'month', + label: 'Monatsansicht', + category: 'Navigation', + onExecute: () => goto('/month'), + }, + { + id: 'settings', + label: 'Einstellungen', + category: 'Navigation', + onExecute: () => goto('/settings'), + }, + ]; + async function handleAuthReady() { // Initialize local-first databases (opens IndexedDB, seeds guest data) await Promise.all([ @@ -498,6 +524,7 @@ allAppsHref="/apps" onOpenInPanel={handleOpenInPanel} ariaLabel="Hauptnavigation" + {spotlightActions} /> {/if} diff --git a/apps/cards/apps/web/src/routes/(app)/+layout.svelte b/apps/cards/apps/web/src/routes/(app)/+layout.svelte index 33ae3294a..fbff19b2d 100644 --- a/apps/cards/apps/web/src/routes/(app)/+layout.svelte +++ b/apps/cards/apps/web/src/routes/(app)/+layout.svelte @@ -9,7 +9,12 @@ import { isNavCollapsed as collapsedStore } from '$lib/stores/navigation'; import { PillNavigation, QuickInputBar, TagStrip } from '@manacore/shared-ui'; import { SyncIndicator } from '@manacore/shared-ui'; - import type { PillNavItem, PillDropdownItem, QuickInputItem } from '@manacore/shared-ui'; + import type { + PillNavItem, + PillDropdownItem, + QuickInputItem, + SpotlightAction, + } from '@manacore/shared-ui'; import { tagLocalStore, tagMutations, @@ -190,6 +195,25 @@ goto(`/decks/${item.id}`); } + const spotlightActions: SpotlightAction[] = [ + { + id: 'new-deck', + label: 'Neues Deck', + icon: 'plus', + shortcut: 'N', + category: 'Erstellen', + onExecute: () => goto('/new'), + }, + { id: 'all-decks', label: 'Alle Decks', category: 'Navigation', onExecute: () => goto('/') }, + { id: 'study', label: 'Lernen', category: 'Navigation', onExecute: () => goto('/study') }, + { + id: 'settings', + label: 'Einstellungen', + category: 'Navigation', + onExecute: () => goto('/settings'), + }, + ]; + async function handleAuthReady() { // Initialize local-first database and shared tag store await Promise.all([cardsStore.initialize(), tagLocalStore.initialize()]); @@ -246,6 +270,7 @@ onLogout={handleSignOut} onToggleTheme={handleToggleTheme} {isDark} + {spotlightActions} {isCollapsed} onCollapsedChange={handleCollapsedChange} showThemeToggle={true} diff --git a/apps/chat/apps/web/src/routes/(protected)/+layout.svelte b/apps/chat/apps/web/src/routes/(protected)/+layout.svelte index 39c542256..988b68891 100644 --- a/apps/chat/apps/web/src/routes/(protected)/+layout.svelte +++ b/apps/chat/apps/web/src/routes/(protected)/+layout.svelte @@ -17,7 +17,7 @@ import { setContext } from 'svelte'; import { PillNavigation, TagStrip } from '@manacore/shared-ui'; import { SyncIndicator } from '@manacore/shared-ui'; - import type { PillNavItem, PillDropdownItem } from '@manacore/shared-ui'; + import type { PillNavItem, PillDropdownItem, SpotlightAction } from '@manacore/shared-ui'; import { tagLocalStore, tagMutations, @@ -124,6 +124,30 @@ filterHiddenNavItems('chat', baseNavItems, userSettings.nav?.hiddenNavItems || {}) ); + // Spotlight actions for PillNavigation + const spotlightActions: SpotlightAction[] = [ + { + id: 'new-chat', + label: 'Neuer Chat', + icon: 'plus', + shortcut: 'N', + category: 'Erstellen', + onExecute: () => goto('/chat'), + }, + { + id: 'templates', + label: 'Vorlagen', + category: 'Navigation', + onExecute: () => goto('/templates'), + }, + { + id: 'settings', + label: 'Einstellungen', + category: 'Navigation', + onExecute: () => goto('/settings'), + }, + ]; + // User email for user dropdown let userEmail = $derived(authStore.user?.email); @@ -254,6 +278,7 @@ themesHref="/themes" helpHref="/help" allAppsHref="/apps" + {spotlightActions} /> diff --git a/apps/citycorners/apps/web/src/routes/(app)/+layout.svelte b/apps/citycorners/apps/web/src/routes/(app)/+layout.svelte index 67eed1bce..4ab43278a 100644 --- a/apps/citycorners/apps/web/src/routes/(app)/+layout.svelte +++ b/apps/citycorners/apps/web/src/routes/(app)/+layout.svelte @@ -5,7 +5,12 @@ import { _, locale } from 'svelte-i18n'; import { PillNavigation, QuickInputBar, TagStrip } from '@manacore/shared-ui'; import { SyncIndicator } from '@manacore/shared-ui'; - import type { PillNavItem, PillDropdownItem, QuickInputItem } from '@manacore/shared-ui'; + import type { + PillNavItem, + PillDropdownItem, + QuickInputItem, + SpotlightAction, + } from '@manacore/shared-ui'; import { tagLocalStore, tagMutations, @@ -207,6 +212,22 @@ let showGuestWelcome = $state(false); + const spotlightActions: SpotlightAction[] = [ + { id: 'explore', label: 'Entdecken', category: 'Navigation', onExecute: () => goto('/') }, + { + id: 'favorites', + label: 'Favoriten', + category: 'Navigation', + onExecute: () => goto('/favorites'), + }, + { + id: 'settings', + label: 'Einstellungen', + category: 'Navigation', + onExecute: () => goto('/settings'), + }, + ]; + async function handleAuthReady() { await Promise.all([citycornersStore.initialize(), tagLocalStore.initialize()]); if (authStore.isAuthenticated) { @@ -259,6 +280,7 @@ themesHref="/themes" helpHref="/help" profileHref="/profile" + {spotlightActions} /> {/if} diff --git a/apps/clock/apps/web/src/routes/(app)/+layout.svelte b/apps/clock/apps/web/src/routes/(app)/+layout.svelte index 6ecc7481a..79c8a9c38 100644 --- a/apps/clock/apps/web/src/routes/(app)/+layout.svelte +++ b/apps/clock/apps/web/src/routes/(app)/+layout.svelte @@ -10,6 +10,7 @@ PillDropdownItem, CommandBarItem, QuickAction, + SpotlightAction, } from '@manacore/shared-ui'; import { theme } from '$lib/stores/theme.svelte'; import { authStore } from '$lib/stores/auth.svelte'; @@ -184,6 +185,36 @@ // User email for user dropdown — empty string for guests so PillNav shows login button let userEmail = $derived(authStore.isAuthenticated ? authStore.user?.email || 'Menü' : ''); + // Spotlight actions for PillNavigation + const spotlightActions: SpotlightAction[] = [ + { + id: 'new-alarm', + label: 'Neuer Alarm', + icon: 'plus', + category: 'Erstellen', + onExecute: () => goto('/alarms'), + }, + { + id: 'new-timer', + label: 'Neuer Timer', + icon: 'plus', + category: 'Erstellen', + onExecute: () => goto('/timers'), + }, + { + id: 'world-clock', + label: 'Weltuhren', + category: 'Navigation', + onExecute: () => goto('/world-clock'), + }, + { + id: 'settings', + label: 'Einstellungen', + category: 'Navigation', + onExecute: () => goto('/settings'), + }, + ]; + // TagStrip visibility let isTagStripVisible = $state(false); function handleTagStripToggle() { @@ -340,6 +371,7 @@ themesHref="/themes" helpHref="/help" allAppsHref="/apps" + {spotlightActions} /> diff --git a/apps/contacts/apps/web/src/routes/(app)/+layout.svelte b/apps/contacts/apps/web/src/routes/(app)/+layout.svelte index db9fd446a..1a141ef37 100644 --- a/apps/contacts/apps/web/src/routes/(app)/+layout.svelte +++ b/apps/contacts/apps/web/src/routes/(app)/+layout.svelte @@ -20,6 +20,7 @@ PillDropdownItem, QuickInputItem, CreatePreview, + SpotlightAction, } from '@manacore/shared-ui'; import { theme } from '$lib/stores/theme'; import { authStore } from '$lib/stores/auth.svelte'; @@ -305,6 +306,30 @@ previousOnboardingShow = showing; }); + const spotlightActions: SpotlightAction[] = [ + { + id: 'new-contact', + label: 'Neuer Kontakt', + icon: 'plus', + shortcut: 'N', + category: 'Erstellen', + onExecute: () => goto('/new'), + }, + { id: 'all', label: 'Alle Kontakte', category: 'Navigation', onExecute: () => goto('/') }, + { + id: 'favorites', + label: 'Favoriten', + category: 'Navigation', + onExecute: () => goto('/favorites'), + }, + { + id: 'settings', + label: 'Einstellungen', + category: 'Navigation', + onExecute: () => goto('/settings'), + }, + ]; + async function handleAuthReady() { // Initialize local-first databases (opens IndexedDB, seeds guest data) await Promise.all([ @@ -394,6 +419,7 @@ allAppsHref="/apps" onOpenInPanel={handleOpenInPanel} ariaLabel="Hauptnavigation" + {spotlightActions} /> diff --git a/apps/context/apps/web/src/routes/(app)/+layout.svelte b/apps/context/apps/web/src/routes/(app)/+layout.svelte index b06048abe..e5ee377ea 100644 --- a/apps/context/apps/web/src/routes/(app)/+layout.svelte +++ b/apps/context/apps/web/src/routes/(app)/+layout.svelte @@ -10,6 +10,7 @@ PillDropdownItem, CommandBarItem, QuickAction, + SpotlightAction, } from '@manacore/shared-ui'; import { theme } from '$lib/stores/theme.svelte'; import { authStore } from '$lib/stores/auth.svelte'; @@ -180,6 +181,24 @@ filterHiddenNavItems('context', baseNavItems, userSettings.nav?.hiddenNavItems || {}) ); + const spotlightActions: SpotlightAction[] = [ + { + id: 'new-space', + label: 'Neuer Space', + icon: 'plus', + shortcut: 'N', + category: 'Erstellen', + onExecute: () => goto('/new'), + }, + { id: 'all-spaces', label: 'Alle Spaces', category: 'Navigation', onExecute: () => goto('/') }, + { + id: 'settings', + label: 'Einstellungen', + category: 'Navigation', + onExecute: () => goto('/settings'), + }, + ]; + const navRoutes = baseNavItems.map((item) => item.href); function handleKeydown(event: KeyboardEvent) { @@ -295,6 +314,7 @@ themesHref="/themes" helpHref="/help" allAppsHref="/apps" + {spotlightActions} /> diff --git a/apps/guides/apps/web/src/routes/(app)/+layout.svelte b/apps/guides/apps/web/src/routes/(app)/+layout.svelte index 9c6060dcf..f218e8667 100644 --- a/apps/guides/apps/web/src/routes/(app)/+layout.svelte +++ b/apps/guides/apps/web/src/routes/(app)/+layout.svelte @@ -5,7 +5,7 @@ import { onMount, setContext } from 'svelte'; import { PillNavigation } from '@manacore/shared-ui'; import { SyncIndicator } from '@manacore/shared-ui'; - import type { PillNavItem, PillDropdownItem } from '@manacore/shared-ui'; + import type { PillNavItem, PillDropdownItem, SpotlightAction } from '@manacore/shared-ui'; import { theme } from '$lib/stores/theme'; import { authStore } from '$lib/stores/auth.svelte'; import { guidesStore } from '$lib/stores/guides.svelte'; @@ -28,8 +28,12 @@ // Context for child pages let showCreateModal = $state(false); let showImportModal = $state(false); - setContext('openCreateGuide', () => { showCreateModal = true; }); - setContext('openImportGuide', () => { showImportModal = true; }); + setContext('openCreateGuide', () => { + showCreateModal = true; + }); + setContext('openImportGuide', () => { + showImportModal = true; + }); // App switcher let appItems = $derived(getPillAppItems('guides', undefined, undefined, authStore.user?.tier)); @@ -96,13 +100,43 @@ function handleCollapsedChange(collapsed: boolean) { isCollapsed = collapsed; } - function handleToggleTheme() { theme.toggleMode(); } - function handleThemeModeChange(mode: 'light' | 'dark' | 'system') { theme.setMode(mode); } + function handleToggleTheme() { + theme.toggleMode(); + } + function handleThemeModeChange(mode: 'light' | 'dark' | 'system') { + theme.setMode(mode); + } async function handleLogout() { await authStore.signOut(); goto('/login'); } + const spotlightActions: SpotlightAction[] = [ + { + id: 'new-guide', + label: 'Neuer Guide', + icon: 'plus', + shortcut: 'N', + category: 'Erstellen', + onExecute: () => { + showCreateModal = true; + }, + }, + { id: 'all-guides', label: 'Alle Guides', category: 'Navigation', onExecute: () => goto('/') }, + { + id: 'collections', + label: 'Sammlungen', + category: 'Navigation', + onExecute: () => goto('/collections'), + }, + { + id: 'settings', + label: 'Einstellungen', + category: 'Navigation', + onExecute: () => goto('/settings'), + }, + ]; + async function handleAuthReady() { await dbStore.initialize(); if (authStore.isAuthenticated) { @@ -114,15 +148,17 @@ } - { - if ((e.ctrlKey || e.metaKey) && !e.shiftKey && !e.altKey) { - const num = parseInt(e.key); - if (num >= 1 && num <= baseNavItems.length) { - e.preventDefault(); - goto(baseNavItems[num - 1].href); + { + if ((e.ctrlKey || e.metaKey) && !e.shiftKey && !e.altKey) { + const num = parseInt(e.key); + if (num >= 1 && num <= baseNavItems.length) { + e.preventDefault(); + goto(baseNavItems[num - 1].href); + } } - } -}} /> + }} +/>
@@ -173,7 +210,11 @@ class="fixed bottom-20 right-4 z-50 flex h-14 w-14 items-center justify-center rounded-full bg-primary text-white shadow-lg transition-transform hover:scale-105 active:scale-95" aria-label="Neue Anleitung erstellen" > - + diff --git a/apps/manacore/apps/web/src/routes/(app)/+layout.svelte b/apps/manacore/apps/web/src/routes/(app)/+layout.svelte index 83b2dd05c..dbca971b0 100644 --- a/apps/manacore/apps/web/src/routes/(app)/+layout.svelte +++ b/apps/manacore/apps/web/src/routes/(app)/+layout.svelte @@ -7,7 +7,7 @@ import SessionWarning from '$lib/components/SessionWarning.svelte'; import { locale } from 'svelte-i18n'; import { PillNavigation, TagStrip } from '@manacore/shared-ui'; - import type { PillNavItem, PillDropdownItem } from '@manacore/shared-ui'; + import type { PillNavItem, PillDropdownItem, SpotlightAction } from '@manacore/shared-ui'; import { tagLocalStore, tagMutations, useAllTags } from '$lib/stores/tags.svelte'; import { linkLocalStore, linkMutations } from '@manacore/shared-links'; import { manacoreStore } from '$lib/data/local-store'; @@ -266,6 +266,24 @@ loading = false; }); + + const spotlightActions: SpotlightAction[] = [ + { id: 'home', label: 'Home', category: 'Navigation', onExecute: () => goto('/home') }, + { + id: 'dashboard', + label: 'Dashboard', + category: 'Navigation', + onExecute: () => goto('/dashboard'), + }, + { id: 'credits', label: 'Credits', category: 'Navigation', onExecute: () => goto('/credits') }, + { id: 'apps', label: 'Alle Apps', category: 'Navigation', onExecute: () => goto('/apps') }, + { + id: 'settings', + label: 'Einstellungen', + category: 'Navigation', + onExecute: () => goto('/settings'), + }, + ]; @@ -321,6 +339,7 @@ themesHref="/themes" helpHref="/help" allAppsHref="/apps" + {spotlightActions} /> diff --git a/apps/matrix/apps/web/src/routes/(app)/+layout.svelte b/apps/matrix/apps/web/src/routes/(app)/+layout.svelte index df77def56..1c87ddd4b 100644 --- a/apps/matrix/apps/web/src/routes/(app)/+layout.svelte +++ b/apps/matrix/apps/web/src/routes/(app)/+layout.svelte @@ -21,7 +21,12 @@ import type { ThemeVariant } from '@manacore/shared-theme'; import { isNavCollapsed as collapsedStore } from '$lib/stores/navigation.svelte'; import { PillNavigation, TagStrip } from '@manacore/shared-ui'; - import type { PillNavItem, PillDropdownItem, QuickInputItem } from '@manacore/shared-ui'; + import type { + PillNavItem, + PillDropdownItem, + QuickInputItem, + SpotlightAction, + } from '@manacore/shared-ui'; import { tagStore } from '$lib/stores/tags.svelte'; import { MagnifyingGlass, X } from '@manacore/shared-icons'; import { getPillAppItems } from '@manacore/shared-branding'; @@ -131,6 +136,16 @@ isTagStripVisible = !isTagStripVisible; } + const spotlightActions: SpotlightAction[] = [ + { id: 'rooms', label: 'Räume', category: 'Navigation', onExecute: () => goto('/') }, + { + id: 'settings', + label: 'Einstellungen', + category: 'Navigation', + onExecute: () => goto('/settings'), + }, + ]; + // Navigation items for Matrix const navItems: PillNavItem[] = [ { href: '/chat', label: 'Chat', icon: 'home' }, @@ -436,6 +451,7 @@ settingsHref="/settings" helpHref="/help" allAppsHref="https://mana.how" + {spotlightActions} /> {/if} diff --git a/apps/moodlit/apps/web/src/routes/(app)/+layout.svelte b/apps/moodlit/apps/web/src/routes/(app)/+layout.svelte index 18a2a94ed..3d22a716b 100644 --- a/apps/moodlit/apps/web/src/routes/(app)/+layout.svelte +++ b/apps/moodlit/apps/web/src/routes/(app)/+layout.svelte @@ -2,7 +2,7 @@ import { goto } from '$app/navigation'; import { page } from '$app/stores'; import { PillNavigation } from '@manacore/shared-ui'; - import type { PillNavItem } from '@manacore/shared-ui'; + import type { PillNavItem, SpotlightAction } from '@manacore/shared-ui'; import { getPillAppItems, getManaApp } from '@manacore/shared-branding'; import { AuthGate, GuestWelcomeModal, SessionExpiredBanner } from '@manacore/shared-auth-ui'; import { shouldShowGuestWelcome } from '@manacore/shared-auth-ui'; @@ -37,6 +37,22 @@ goto('/auth/login'); } + const spotlightActions: SpotlightAction[] = [ + { id: 'scenes', label: 'Szenen', category: 'Navigation', onExecute: () => goto('/moods') }, + { + id: 'sequences', + label: 'Sequences', + category: 'Navigation', + onExecute: () => goto('/sequences'), + }, + { + id: 'settings', + label: 'Einstellungen', + category: 'Navigation', + onExecute: () => goto('/settings'), + }, + ]; + function handleAuthReady() { if (authStore.isAuthenticated) moodlitStore.startSync(() => authStore.getValidToken()); if (!authStore.isAuthenticated && shouldShowGuestWelcome('moodlit')) showGuestWelcome = true; @@ -69,6 +85,7 @@ showAppSwitcher={true} {appItems} {userEmail} + {spotlightActions} > {#snippet logo()} 🌈 diff --git a/apps/mukke/apps/web/src/routes/(app)/+layout.svelte b/apps/mukke/apps/web/src/routes/(app)/+layout.svelte index 12590d4b2..a88e8d6ff 100644 --- a/apps/mukke/apps/web/src/routes/(app)/+layout.svelte +++ b/apps/mukke/apps/web/src/routes/(app)/+layout.svelte @@ -9,6 +9,7 @@ PillDropdownItem, QuickInputItem, CreatePreview, + SpotlightAction, } from '@manacore/shared-ui'; import { SplitPaneContainer, @@ -194,6 +195,36 @@ goto('/projects'); } + const spotlightActions: SpotlightAction[] = [ + { + id: 'new-project', + label: 'Neues Projekt', + icon: 'plus', + shortcut: 'N', + category: 'Erstellen', + onExecute: () => goto('/projects/new'), + }, + { id: 'songs', label: 'Songs', category: 'Navigation', onExecute: () => goto('/') }, + { + id: 'playlists', + label: 'Playlists', + category: 'Navigation', + onExecute: () => goto('/playlists'), + }, + { + id: 'projects', + label: 'Projekte', + category: 'Navigation', + onExecute: () => goto('/projects'), + }, + { + id: 'settings', + label: 'Einstellungen', + category: 'Navigation', + onExecute: () => goto('/settings'), + }, + ]; + let showGuestWelcome = $state(false); async function handleAuthReady() { @@ -248,6 +279,7 @@ profileHref="/profile" onOpenInPanel={handleOpenInPanel} ariaLabel="Main navigation" + {spotlightActions} /> diff --git a/apps/photos/apps/web/src/routes/(app)/+layout.svelte b/apps/photos/apps/web/src/routes/(app)/+layout.svelte index 25b919069..4ac34f821 100644 --- a/apps/photos/apps/web/src/routes/(app)/+layout.svelte +++ b/apps/photos/apps/web/src/routes/(app)/+layout.svelte @@ -4,7 +4,12 @@ import { _, locale } from 'svelte-i18n'; import { PillNavigation, QuickInputBar, TagStrip } from '@manacore/shared-ui'; import { SyncIndicator } from '@manacore/shared-ui'; - import type { PillNavItem, PillDropdownItem, QuickInputItem } from '@manacore/shared-ui'; + import type { + PillNavItem, + PillDropdownItem, + QuickInputItem, + SpotlightAction, + } from '@manacore/shared-ui'; import { theme } from '$lib/stores/theme'; import { authStore } from '$lib/stores/auth.svelte'; import { photoStore } from '$lib/stores/photos.svelte'; @@ -58,6 +63,23 @@ selectedTagIds = []; } + const spotlightActions: SpotlightAction[] = [ + { id: 'all-photos', label: 'Alle Fotos', category: 'Navigation', onExecute: () => goto('/') }, + { id: 'albums', label: 'Alben', category: 'Navigation', onExecute: () => goto('/albums') }, + { + id: 'favorites', + label: 'Favoriten', + category: 'Navigation', + onExecute: () => goto('/favorites'), + }, + { + id: 'settings', + label: 'Einstellungen', + category: 'Navigation', + onExecute: () => goto('/settings'), + }, + ]; + // Navigation items const navItems: PillNavItem[] = [ { href: '/', label: $_('nav.gallery'), icon: 'image' }, @@ -164,6 +186,7 @@ themesHref="/themes" helpHref="/help" profileHref="/profile" + {spotlightActions} /> diff --git a/apps/picture/apps/web/src/routes/app/+layout.svelte b/apps/picture/apps/web/src/routes/app/+layout.svelte index 3761d3554..47bd7797b 100644 --- a/apps/picture/apps/web/src/routes/app/+layout.svelte +++ b/apps/picture/apps/web/src/routes/app/+layout.svelte @@ -5,7 +5,12 @@ import { page } from '$app/stores'; import { locale } from 'svelte-i18n'; import { PillNavigation, TagStrip } from '@manacore/shared-ui'; - import type { PillNavItem, PillNavElement, PillDropdownItem } from '@manacore/shared-ui'; + import type { + PillNavItem, + PillNavElement, + PillDropdownItem, + SpotlightAction, + } from '@manacore/shared-ui'; import { THEME_DEFINITIONS, DEFAULT_THEME_VARIANTS, @@ -218,6 +223,31 @@ ); let currentLanguageLabel = $derived(getCurrentLanguageLabel(currentLocale)); + // Spotlight actions for PillNavigation + const spotlightActions: SpotlightAction[] = [ + { + id: 'new-image', + label: 'Neues Bild generieren', + icon: 'plus', + shortcut: 'N', + category: 'Erstellen', + onExecute: () => goto('/app/generate'), + }, + { + id: 'gallery', + label: 'Galerie', + category: 'Navigation', + onExecute: () => goto('/app/gallery'), + }, + { id: 'boards', label: 'Boards', category: 'Navigation', onExecute: () => goto('/app/board') }, + { + id: 'settings', + label: 'Einstellungen', + category: 'Navigation', + onExecute: () => goto('/app/settings'), + }, + ]; + // User email for user dropdown — empty string for guests so PillNav shows login button let userEmail = $derived(authStore.isAuthenticated ? authStore.user?.email || 'Menü' : ''); @@ -346,6 +376,7 @@ helpHref="/app/help" feedbackHref="/app/feedback" allAppsHref="/app/apps" + {spotlightActions} /> {#if isTagStripVisible} diff --git a/apps/planta/apps/web/src/routes/(app)/+layout.svelte b/apps/planta/apps/web/src/routes/(app)/+layout.svelte index 7b867e206..6a66b09f7 100644 --- a/apps/planta/apps/web/src/routes/(app)/+layout.svelte +++ b/apps/planta/apps/web/src/routes/(app)/+layout.svelte @@ -3,7 +3,12 @@ import { page } from '$app/stores'; import { PillNavigation, QuickInputBar, TagStrip } from '@manacore/shared-ui'; import { SyncIndicator } from '@manacore/shared-ui'; - import type { PillNavItem, QuickInputItem, CreatePreview } from '@manacore/shared-ui'; + import type { + PillNavItem, + QuickInputItem, + CreatePreview, + SpotlightAction, + } from '@manacore/shared-ui'; import { tagLocalStore, tagMutations, @@ -126,6 +131,29 @@ } } + const spotlightActions: SpotlightAction[] = [ + { + id: 'new-plant', + label: 'Neue Pflanze', + icon: 'plus', + shortcut: 'N', + category: 'Erstellen', + onExecute: () => goto('/add'), + }, + { + id: 'all-plants', + label: 'Alle Pflanzen', + category: 'Navigation', + onExecute: () => goto('/dashboard'), + }, + { + id: 'settings', + label: 'Einstellungen', + category: 'Navigation', + onExecute: () => goto('/settings'), + }, + ]; + async function handleAuthReady() { await Promise.all([plantaStore.initialize(), tagLocalStore.initialize()]); if (authStore.isAuthenticated) { @@ -156,6 +184,7 @@ themesHref="/themes" helpHref="/help" profileHref="/profile" + {spotlightActions} /> diff --git a/apps/presi/apps/web/src/routes/(app)/+layout.svelte b/apps/presi/apps/web/src/routes/(app)/+layout.svelte index 8f06d1aa1..f620851e0 100644 --- a/apps/presi/apps/web/src/routes/(app)/+layout.svelte +++ b/apps/presi/apps/web/src/routes/(app)/+layout.svelte @@ -5,7 +5,12 @@ import { locale } from 'svelte-i18n'; import { PillNavigation, QuickInputBar, TagStrip } from '@manacore/shared-ui'; import { SyncIndicator } from '@manacore/shared-ui'; - import type { PillNavItem, PillDropdownItem, QuickInputItem } from '@manacore/shared-ui'; + import type { + PillNavItem, + PillDropdownItem, + QuickInputItem, + SpotlightAction, + } from '@manacore/shared-ui'; import { tagLocalStore, tagMutations, @@ -156,6 +161,29 @@ goto(`/deck/${item.id}`); } + const spotlightActions: SpotlightAction[] = [ + { + id: 'new-deck', + label: 'Neue Präsentation', + icon: 'plus', + shortcut: 'N', + category: 'Erstellen', + onExecute: () => goto('/new'), + }, + { + id: 'all-decks', + label: 'Alle Präsentationen', + category: 'Navigation', + onExecute: () => goto('/'), + }, + { + id: 'settings', + label: 'Einstellungen', + category: 'Navigation', + onExecute: () => goto('/settings'), + }, + ]; + async function handleAuthReady() { // Initialize local-first databases (opens IndexedDB, seeds guest data) await Promise.all([presiStore.initialize(), tagLocalStore.initialize()]); @@ -242,6 +270,7 @@ themesHref="/themes" helpHref="/help" allAppsHref="/apps" + {spotlightActions} /> diff --git a/apps/questions/apps/web/src/routes/(app)/+layout.svelte b/apps/questions/apps/web/src/routes/(app)/+layout.svelte index 5841cff73..88a1cda51 100644 --- a/apps/questions/apps/web/src/routes/(app)/+layout.svelte +++ b/apps/questions/apps/web/src/routes/(app)/+layout.svelte @@ -22,6 +22,7 @@ PillDropdownItem, QuickInputItem, CreatePreview, + SpotlightAction, } from '@manacore/shared-ui'; import { getPillAppItems, getManaApp } from '@manacore/shared-branding'; import { @@ -172,6 +173,29 @@ isTagStripVisible = !isTagStripVisible; } + const spotlightActions: SpotlightAction[] = [ + { + id: 'new-question', + label: 'Neue Frage', + icon: 'plus', + shortcut: 'N', + category: 'Erstellen', + onExecute: () => goto('/'), + }, + { + id: 'collections', + label: 'Sammlungen', + category: 'Navigation', + onExecute: () => goto('/collections'), + }, + { + id: 'settings', + label: 'Einstellungen', + category: 'Navigation', + onExecute: () => goto('/settings'), + }, + ]; + // Navigation items let navItems = $derived([ { href: '/', label: 'Questions', icon: 'help-circle' }, @@ -235,6 +259,7 @@ themesHref="/themes" helpHref="/help" profileHref="/profile" + {spotlightActions} /> diff --git a/apps/storage/apps/web/src/routes/+layout.svelte b/apps/storage/apps/web/src/routes/+layout.svelte index d7fe98107..83d6c442a 100644 --- a/apps/storage/apps/web/src/routes/+layout.svelte +++ b/apps/storage/apps/web/src/routes/+layout.svelte @@ -5,7 +5,7 @@ import { locale } from 'svelte-i18n'; import { PillNavigation, setupGlobalErrorHandler, TagStrip } from '@manacore/shared-ui'; import { SyncIndicator } from '@manacore/shared-ui'; - import type { PillNavItem, PillDropdownItem } from '@manacore/shared-ui'; + import type { PillNavItem, PillDropdownItem, SpotlightAction } from '@manacore/shared-ui'; import { theme } from '$lib/stores/theme.svelte'; import { authStore } from '$lib/stores/auth.svelte'; import { userSettings } from '$lib/stores/user-settings.svelte'; @@ -174,6 +174,24 @@ goto('/login'); } + const spotlightActions: SpotlightAction[] = [ + { + id: 'upload', + label: 'Datei hochladen', + icon: 'plus', + shortcut: 'U', + category: 'Aktionen', + onExecute: () => goto('/'), + }, + { id: 'all-files', label: 'Alle Dateien', category: 'Navigation', onExecute: () => goto('/') }, + { + id: 'settings', + label: 'Einstellungen', + category: 'Navigation', + onExecute: () => goto('/settings'), + }, + ]; + async function handleAuthReady() { // Initialize local-first databases await Promise.all([storageStore.initialize(), tagLocalStore.initialize()]); @@ -237,6 +255,7 @@ homeRoute="/files" onToggleTheme={handleToggleTheme} {isDark} + {spotlightActions} {isCollapsed} onCollapsedChange={handleCollapsedChange} showThemeToggle={true} diff --git a/apps/todo/apps/web/src/routes/(app)/+layout.svelte b/apps/todo/apps/web/src/routes/(app)/+layout.svelte index a1f9e5df8..5ac610c45 100644 --- a/apps/todo/apps/web/src/routes/(app)/+layout.svelte +++ b/apps/todo/apps/web/src/routes/(app)/+layout.svelte @@ -15,6 +15,7 @@ PillNavElement, QuickInputItem, CreatePreview, + SpotlightAction, } from '@manacore/shared-ui'; import { authStore } from '$lib/stores/auth.svelte'; import { userSettings } from '$lib/stores/user-settings.svelte'; @@ -314,6 +315,36 @@ goto('/login'); } + const spotlightActions: SpotlightAction[] = [ + { + id: 'new-task', + label: 'Neue Aufgabe', + icon: 'plus', + shortcut: 'N', + category: 'Erstellen', + onExecute: () => goto('/'), + }, + { id: 'today', label: 'Heute', category: 'Navigation', onExecute: () => goto('/today') }, + { + id: 'upcoming', + label: 'Demnächst', + category: 'Navigation', + onExecute: () => goto('/upcoming'), + }, + { + id: 'kanban', + label: 'Kanban Board', + category: 'Navigation', + onExecute: () => goto('/kanban'), + }, + { + id: 'settings', + label: 'Einstellungen', + category: 'Navigation', + onExecute: () => goto('/settings'), + }, + ]; + async function handleAuthReady() { // Initialize local-first databases (opens IndexedDB, seeds guest data) await Promise.all([ @@ -418,6 +449,7 @@ helpHref="/help" onOpenInPanel={handleOpenInPanel} ariaLabel="Hauptnavigation" + {spotlightActions} /> diff --git a/apps/uload/apps/web/src/routes/(app)/+layout.svelte b/apps/uload/apps/web/src/routes/(app)/+layout.svelte index 399febe81..2f6040e14 100644 --- a/apps/uload/apps/web/src/routes/(app)/+layout.svelte +++ b/apps/uload/apps/web/src/routes/(app)/+layout.svelte @@ -3,7 +3,7 @@ import { page } from '$app/stores'; import { onMount } from 'svelte'; import { PillNavigation } from '@manacore/shared-ui'; - import type { PillNavItem } from '@manacore/shared-ui'; + import type { PillNavItem, SpotlightAction } from '@manacore/shared-ui'; import { getPillAppItems, getManaApp } from '@manacore/shared-branding'; import { AuthGate, GuestWelcomeModal, SessionExpiredBanner } from '@manacore/shared-auth-ui'; import { shouldShowGuestWelcome } from '@manacore/shared-auth-ui'; @@ -23,6 +23,24 @@ { href: '/settings', label: 'Settings', icon: 'settings' }, ]; + const spotlightActions: SpotlightAction[] = [ + { + id: 'new-link', + label: 'Neuer Link', + icon: 'plus', + shortcut: 'N', + category: 'Erstellen', + onExecute: () => goto('/'), + }, + { id: 'all-links', label: 'Alle Links', category: 'Navigation', onExecute: () => goto('/') }, + { + id: 'settings', + label: 'Einstellungen', + category: 'Navigation', + onExecute: () => goto('/settings'), + }, + ]; + let isSidebarMode = $state(false); let isCollapsed = $state(false); let isDark = $state(false); @@ -118,6 +136,7 @@ {appItems} {userEmail} settingsHref="/settings" + {spotlightActions} > {#snippet logo()} 🔗 diff --git a/apps/zitare/apps/web/src/routes/(app)/+layout.svelte b/apps/zitare/apps/web/src/routes/(app)/+layout.svelte index 909bc6d49..fbfa377c8 100644 --- a/apps/zitare/apps/web/src/routes/(app)/+layout.svelte +++ b/apps/zitare/apps/web/src/routes/(app)/+layout.svelte @@ -8,7 +8,12 @@ ImmersiveModeToggle, TagStrip, } from '@manacore/shared-ui'; - import type { PillNavItem, PillDropdownItem, QuickInputItem } from '@manacore/shared-ui'; + import type { + PillNavItem, + PillDropdownItem, + QuickInputItem, + SpotlightAction, + } from '@manacore/shared-ui'; import { SyncIndicator } from '@manacore/shared-ui'; import { tagLocalStore, @@ -247,6 +252,23 @@ zitareSettings.togglePillNav(); } + const spotlightActions: SpotlightAction[] = [ + { id: 'random', label: 'Zufälliges Zitat', category: 'Aktionen', onExecute: () => goto('/') }, + { + id: 'favorites', + label: 'Favoriten', + category: 'Navigation', + onExecute: () => goto('/favorites'), + }, + { id: 'lists', label: 'Listen', category: 'Navigation', onExecute: () => goto('/lists') }, + { + id: 'settings', + label: 'Einstellungen', + category: 'Navigation', + onExecute: () => goto('/settings'), + }, + ]; + async function handleAuthReady() { // Initialize local-first databases (app + shared tags) await Promise.all([zitareStore.initialize(), tagLocalStore.initialize()]); @@ -286,6 +308,7 @@ homeRoute="/" onToggleTheme={handleToggleTheme} {isDark} + {spotlightActions} showThemeToggle={true} showThemeVariants={true} {themeVariantItems} diff --git a/games/arcade/apps/web/src/routes/(app)/+layout.svelte b/games/arcade/apps/web/src/routes/(app)/+layout.svelte index 431c5e2e5..0365751aa 100644 --- a/games/arcade/apps/web/src/routes/(app)/+layout.svelte +++ b/games/arcade/apps/web/src/routes/(app)/+layout.svelte @@ -8,6 +8,7 @@ PillDropdownItem, CommandBarItem, QuickAction, + SpotlightAction, } from '@manacore/shared-ui'; import { theme } from '$lib/stores/theme.svelte'; import { authStore } from '$lib/stores/auth.svelte'; @@ -49,6 +50,24 @@ let { children } = $props(); + const spotlightActions: SpotlightAction[] = [ + { + id: 'new-game', + label: 'Neues Spiel erstellen', + icon: 'plus', + shortcut: 'N', + category: 'Erstellen', + onExecute: () => goto('/create'), + }, + { id: 'games', label: 'Alle Spiele', category: 'Navigation', onExecute: () => goto('/') }, + { + id: 'settings', + label: 'Einstellungen', + category: 'Navigation', + onExecute: () => goto('/settings'), + }, + ]; + let commandBarOpen = $state(false); const commandBarQuickActions: QuickAction[] = [ @@ -223,6 +242,7 @@ themesHref="/themes" helpHref="/help" allAppsHref="/apps" + {spotlightActions} />