mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-14 22:21:10 +02:00
feat(theme): add themes page to picture, manadeck, and presi apps
- Add dedicated /themes page with ThemePage component to all three apps - Add theme variant dropdown with "Alle Themes" link in navigation - Add keyboard shortcut 'T' for quick access to themes page - Export PillNavElement type from shared-ui package 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
54383bf7c2
commit
8a4cc298f6
7 changed files with 150 additions and 6 deletions
|
|
@ -9,7 +9,8 @@
|
|||
isNavCollapsed as collapsedStore,
|
||||
} from '$lib/stores/navigation';
|
||||
import { PillNavigation } from '@manacore/shared-ui';
|
||||
import type { PillNavItem } from '@manacore/shared-ui';
|
||||
import type { PillNavItem, PillDropdownItem } from '@manacore/shared-ui';
|
||||
import { THEME_DEFINITIONS } from '@manacore/shared-theme';
|
||||
|
||||
let { children } = $props();
|
||||
|
||||
|
|
@ -28,6 +29,27 @@
|
|||
{ href: '/profile', label: 'Profile', icon: 'user' },
|
||||
];
|
||||
|
||||
// Theme variant dropdown items
|
||||
let themeVariantItems = $derived<PillDropdownItem[]>([
|
||||
...theme.variants.map((variant) => ({
|
||||
id: variant,
|
||||
label: `${THEME_DEFINITIONS[variant].emoji} ${THEME_DEFINITIONS[variant].label}`,
|
||||
onClick: () => theme.setVariant(variant),
|
||||
active: theme.variant === variant,
|
||||
})),
|
||||
{
|
||||
id: 'all-themes',
|
||||
label: '🎨 Alle Themes',
|
||||
onClick: () => goto('/themes'),
|
||||
active: false,
|
||||
},
|
||||
]);
|
||||
|
||||
// Current theme variant label
|
||||
let currentThemeVariantLabel = $derived(
|
||||
`${THEME_DEFINITIONS[theme.variant].emoji} ${THEME_DEFINITIONS[theme.variant].label}`
|
||||
);
|
||||
|
||||
// Navigation shortcuts (Ctrl+1-5)
|
||||
const navRoutes = navItems.map((item) => item.href);
|
||||
|
||||
|
|
@ -37,6 +59,7 @@
|
|||
return;
|
||||
}
|
||||
|
||||
// Ctrl+Number navigation
|
||||
if ((event.ctrlKey || event.metaKey) && !event.shiftKey && !event.altKey) {
|
||||
const num = parseInt(event.key);
|
||||
if (num >= 1 && num <= navRoutes.length) {
|
||||
|
|
@ -47,6 +70,14 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Single key shortcuts (no modifiers)
|
||||
if (!event.ctrlKey && !event.metaKey && !event.shiftKey && !event.altKey) {
|
||||
if (event.key.toLowerCase() === 't') {
|
||||
event.preventDefault();
|
||||
goto('/themes');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function handleModeChange(isSidebar: boolean) {
|
||||
|
|
@ -125,6 +156,9 @@
|
|||
{isCollapsed}
|
||||
onCollapsedChange={handleCollapsedChange}
|
||||
showThemeToggle={true}
|
||||
showThemeVariants={true}
|
||||
{themeVariantItems}
|
||||
{currentThemeVariantLabel}
|
||||
showLanguageSwitcher={false}
|
||||
primaryColor="#6366f1"
|
||||
/>
|
||||
|
|
|
|||
19
apps/manadeck/apps/web/src/routes/(app)/themes/+page.svelte
Normal file
19
apps/manadeck/apps/web/src/routes/(app)/themes/+page.svelte
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
<script lang="ts">
|
||||
import { goto } from '$app/navigation';
|
||||
import { ThemePage } from '@manacore/shared-theme-ui';
|
||||
import { theme } from '$lib/stores/theme';
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>Themes | ManaDeck</title>
|
||||
</svelte:head>
|
||||
|
||||
<ThemePage
|
||||
currentVariant={theme.variant}
|
||||
onSelectTheme={(v) => theme.setVariant(v)}
|
||||
showModeSelector={true}
|
||||
currentMode={theme.mode}
|
||||
onModeChange={(m) => theme.setMode(m)}
|
||||
showBackButton={true}
|
||||
onBack={() => goto('/decks')}
|
||||
/>
|
||||
|
|
@ -3,7 +3,8 @@
|
|||
import { goto } from '$app/navigation';
|
||||
import { page } from '$app/stores';
|
||||
import { PillNavigation } from '@manacore/shared-ui';
|
||||
import type { PillNavItem, PillNavElement } from '@manacore/shared-ui';
|
||||
import type { PillNavItem, PillNavElement, PillDropdownItem } from '@manacore/shared-ui';
|
||||
import { THEME_DEFINITIONS } from '@manacore/shared-theme';
|
||||
import KeyboardShortcutsModal from '$lib/components/ui/KeyboardShortcutsModal.svelte';
|
||||
import { theme } from '$lib/stores/theme';
|
||||
import { isUIVisible, toggleUI, showKeyboardShortcuts } from '$lib/stores/ui';
|
||||
|
|
@ -71,6 +72,27 @@
|
|||
{ id: 'gridSmall', icon: 'gridSmall', title: 'Klein (3)' },
|
||||
];
|
||||
|
||||
// Theme variant dropdown items
|
||||
let themeVariantItems = $derived<PillDropdownItem[]>([
|
||||
...theme.variants.map((variant) => ({
|
||||
id: variant,
|
||||
label: `${THEME_DEFINITIONS[variant].emoji} ${THEME_DEFINITIONS[variant].label}`,
|
||||
onClick: () => theme.setVariant(variant),
|
||||
active: theme.variant === variant,
|
||||
})),
|
||||
{
|
||||
id: 'all-themes',
|
||||
label: '🎨 Alle Themes',
|
||||
onClick: () => goto('/app/themes'),
|
||||
active: false,
|
||||
},
|
||||
]);
|
||||
|
||||
// Current theme variant label
|
||||
let currentThemeVariantLabel = $derived(
|
||||
`${THEME_DEFINITIONS[theme.variant].emoji} ${THEME_DEFINITIONS[theme.variant].label}`
|
||||
);
|
||||
|
||||
// Elements (divider + view mode tabs)
|
||||
let elements: PillNavElement[] = $derived([
|
||||
{ type: 'divider' as const },
|
||||
|
|
@ -129,6 +151,10 @@
|
|||
e.preventDefault();
|
||||
goto('/app/archive');
|
||||
break;
|
||||
case 't':
|
||||
e.preventDefault();
|
||||
goto('/app/themes');
|
||||
break;
|
||||
case '1':
|
||||
e.preventDefault();
|
||||
setViewMode('single');
|
||||
|
|
@ -174,6 +200,9 @@
|
|||
{isCollapsed}
|
||||
onCollapsedChange={handleCollapsedChange}
|
||||
showThemeToggle={true}
|
||||
showThemeVariants={true}
|
||||
{themeVariantItems}
|
||||
{currentThemeVariantLabel}
|
||||
showLanguageSwitcher={false}
|
||||
primaryColor="#3b82f6"
|
||||
/>
|
||||
|
|
|
|||
19
apps/picture/apps/web/src/routes/app/themes/+page.svelte
Normal file
19
apps/picture/apps/web/src/routes/app/themes/+page.svelte
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
<script lang="ts">
|
||||
import { goto } from '$app/navigation';
|
||||
import { ThemePage } from '@manacore/shared-theme-ui';
|
||||
import { theme } from '$lib/stores/theme';
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>Themes | Picture</title>
|
||||
</svelte:head>
|
||||
|
||||
<ThemePage
|
||||
currentVariant={theme.variant}
|
||||
onSelectTheme={(v) => theme.setVariant(v)}
|
||||
showModeSelector={true}
|
||||
currentMode={theme.mode}
|
||||
onModeChange={(m) => theme.setMode(m)}
|
||||
showBackButton={true}
|
||||
onBack={() => goto('/app/gallery')}
|
||||
/>
|
||||
|
|
@ -20,14 +20,20 @@
|
|||
let isCollapsed = $state(false);
|
||||
|
||||
// Theme variant dropdown items
|
||||
let themeVariantItems = $derived<PillDropdownItem[]>(
|
||||
theme.variants.map((variant) => ({
|
||||
let themeVariantItems = $derived<PillDropdownItem[]>([
|
||||
...theme.variants.map((variant) => ({
|
||||
id: variant,
|
||||
label: `${THEME_DEFINITIONS[variant].emoji} ${THEME_DEFINITIONS[variant].label}`,
|
||||
onClick: () => theme.setVariant(variant),
|
||||
active: theme.variant === variant,
|
||||
}))
|
||||
);
|
||||
})),
|
||||
{
|
||||
id: 'all-themes',
|
||||
label: '🎨 Alle Themes',
|
||||
onClick: () => goto('/themes'),
|
||||
active: false,
|
||||
},
|
||||
]);
|
||||
|
||||
// Current theme variant label
|
||||
let currentThemeVariantLabel = $derived(
|
||||
|
|
@ -76,6 +82,21 @@
|
|||
goto('/login');
|
||||
}
|
||||
|
||||
function handleKeydown(event: KeyboardEvent) {
|
||||
const target = event.target as HTMLElement;
|
||||
if (target.tagName === 'INPUT' || target.tagName === 'TEXTAREA' || target.isContentEditable) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Single key shortcuts (no modifiers)
|
||||
if (!event.ctrlKey && !event.metaKey && !event.shiftKey && !event.altKey) {
|
||||
if (event.key.toLowerCase() === 't') {
|
||||
event.preventDefault();
|
||||
goto('/themes');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Redirect to login if not authenticated
|
||||
$effect(() => {
|
||||
if (!auth.isLoading && !auth.isAuthenticated && !publicRoutes.includes($page.url.pathname)) {
|
||||
|
|
@ -110,6 +131,8 @@
|
|||
});
|
||||
</script>
|
||||
|
||||
<svelte:window onkeydown={handleKeydown} />
|
||||
|
||||
<svelte:head>
|
||||
<title>Presi - Presentation Creator</title>
|
||||
</svelte:head>
|
||||
|
|
|
|||
19
apps/presi/apps/web/src/routes/themes/+page.svelte
Normal file
19
apps/presi/apps/web/src/routes/themes/+page.svelte
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
<script lang="ts">
|
||||
import { goto } from '$app/navigation';
|
||||
import { ThemePage } from '@manacore/shared-theme-ui';
|
||||
import { theme } from '$lib/stores/theme';
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>Themes | Presi</title>
|
||||
</svelte:head>
|
||||
|
||||
<ThemePage
|
||||
currentVariant={theme.variant}
|
||||
onSelectTheme={(v) => theme.setVariant(v)}
|
||||
showModeSelector={true}
|
||||
currentMode={theme.mode}
|
||||
onModeChange={(m) => theme.setMode(m)}
|
||||
showBackButton={true}
|
||||
onBack={() => goto('/')}
|
||||
/>
|
||||
|
|
@ -44,5 +44,6 @@ export type {
|
|||
KeyboardShortcut,
|
||||
PillNavItem,
|
||||
PillDropdownItem,
|
||||
PillNavElement,
|
||||
PillNavigationProps,
|
||||
} from './navigation';
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue