diff --git a/apps/calendar/apps/web/src/lib/components/calendar/WeekView.svelte b/apps/calendar/apps/web/src/lib/components/calendar/WeekView.svelte
index ceb0d9d0a..b92335d4a 100644
--- a/apps/calendar/apps/web/src/lib/components/calendar/WeekView.svelte
+++ b/apps/calendar/apps/web/src/lib/components/calendar/WeekView.svelte
@@ -20,6 +20,7 @@
import EventCard from './EventCard.svelte';
import TaskBlock from './TaskBlock.svelte';
import EventContextMenu from '$lib/components/event/EventContextMenu.svelte';
+ import CalendarHeaderContextMenu from './CalendarHeaderContextMenu.svelte';
import { goto } from '$app/navigation';
import {
format,
diff --git a/apps/calendar/apps/web/src/lib/config/helpConfig.ts b/apps/calendar/apps/web/src/lib/config/helpConfig.ts
new file mode 100644
index 000000000..047f59619
--- /dev/null
+++ b/apps/calendar/apps/web/src/lib/config/helpConfig.ts
@@ -0,0 +1,108 @@
+import { NavigationArrow, CalendarBlank, ListChecks } from '@manacore/shared-icons';
+import {
+ COMMON_SHORTCUTS,
+ COMMON_SYNTAX,
+ DEFAULT_LIVE_EXAMPLE,
+ type HelpModalConfig,
+ type ShortcutCategory,
+ type SyntaxGroup,
+} from '@manacore/shared-ui';
+
+/**
+ * Calendar-specific keyboard shortcuts
+ */
+const CALENDAR_SHORTCUTS: ShortcutCategory[] = [
+ {
+ id: 'navigation',
+ title: 'Navigation',
+ icon: NavigationArrow,
+ shortcuts: [
+ {
+ keys: ['Cmd', '1'],
+ altKeys: ['Ctrl', '1'],
+ description: 'Kalender öffnen',
+ category: 'navigation',
+ },
+ {
+ keys: ['Cmd', '2'],
+ altKeys: ['Ctrl', '2'],
+ description: 'Aufgaben öffnen',
+ category: 'navigation',
+ },
+ {
+ keys: ['Cmd', '3'],
+ altKeys: ['Ctrl', '3'],
+ description: 'Statistiken öffnen',
+ category: 'navigation',
+ },
+ {
+ keys: ['Cmd', '4'],
+ altKeys: ['Ctrl', '4'],
+ description: 'Einstellungen öffnen',
+ category: 'navigation',
+ },
+ ],
+ },
+ {
+ id: 'calendar',
+ title: 'Kalender',
+ icon: CalendarBlank,
+ shortcuts: [
+ {
+ keys: ['Enter'],
+ description: 'Event/Task öffnen',
+ category: 'calendar',
+ },
+ {
+ keys: ['Space'],
+ description: 'Event/Task öffnen',
+ category: 'calendar',
+ },
+ {
+ keys: ['Esc'],
+ description: 'Drag/Resize abbrechen',
+ category: 'calendar',
+ },
+ ],
+ },
+ {
+ id: 'tasks',
+ title: 'Aufgaben',
+ icon: ListChecks,
+ shortcuts: [
+ {
+ keys: ['Enter'],
+ description: 'Aufgabe öffnen',
+ category: 'tasks',
+ },
+ {
+ keys: ['Space'],
+ description: 'Aufgabe abhaken',
+ category: 'tasks',
+ },
+ ],
+ },
+];
+
+/**
+ * Calendar-specific syntax patterns (extends common syntax)
+ */
+const CALENDAR_SYNTAX: SyntaxGroup[] = [
+ // Calendar uses all common syntax patterns
+];
+
+/**
+ * Complete help configuration for the Calendar app
+ * Combines common shortcuts/syntax with Calendar-specific ones
+ */
+export const CALENDAR_HELP_CONFIG: HelpModalConfig = {
+ shortcuts: [...COMMON_SHORTCUTS, ...CALENDAR_SHORTCUTS],
+ syntax: [...COMMON_SYNTAX, ...CALENDAR_SYNTAX],
+ defaultTab: 'shortcuts',
+ liveExample: DEFAULT_LIVE_EXAMPLE,
+};
+
+/**
+ * Export individual parts for customization
+ */
+export { CALENDAR_SHORTCUTS, CALENDAR_SYNTAX };
diff --git a/packages/shared-ui/src/context-menu/ContextMenu.svelte b/packages/shared-ui/src/context-menu/ContextMenu.svelte
index 0f7db0995..997a6a1bd 100644
--- a/packages/shared-ui/src/context-menu/ContextMenu.svelte
+++ b/packages/shared-ui/src/context-menu/ContextMenu.svelte
@@ -89,9 +89,19 @@
@@ -149,6 +159,8 @@
z-index: 9998;
/* Transparent backdrop - just blocks clicks */
background: transparent;
+ /* Ensure backdrop can receive events even when parent has pointer-events: none */
+ pointer-events: auto;
}
.context-menu {
@@ -160,6 +172,8 @@
background: var(--color-surface-elevated-3);
border: 1px solid hsl(var(--color-border));
border-radius: var(--radius-lg);
+ /* Ensure menu can receive events even when parent has pointer-events: none */
+ pointer-events: auto;
}
.menu-item {
diff --git a/packages/shared-ui/src/help/HelpModal.svelte b/packages/shared-ui/src/help/HelpModal.svelte
new file mode 100644
index 000000000..94b206bfb
--- /dev/null
+++ b/packages/shared-ui/src/help/HelpModal.svelte
@@ -0,0 +1,183 @@
+
+
+
+
+
+
+
+
+
+ {#if effectiveTab() === 'shortcuts' && config.shortcuts}
+
+ {:else if effectiveTab() === 'syntax' && config.syntax}
+
+ {/if}
+
+
+
+
+
diff --git a/packages/shared-ui/src/help/KeyboardShortcutsPanel.svelte b/packages/shared-ui/src/help/KeyboardShortcutsPanel.svelte
new file mode 100644
index 000000000..d28c04116
--- /dev/null
+++ b/packages/shared-ui/src/help/KeyboardShortcutsPanel.svelte
@@ -0,0 +1,251 @@
+
+
+
+ {#each categories as category}
+ {@const CategoryIcon = getCategoryIcon(category)}
+
+
+
+
+ {#each category.shortcuts as shortcut}
+ {@const ShortcutIcon = getShortcutIcon(shortcut.keys)}
+
+
+
+
+
+ {#each shortcut.keys as key, i}
+ {#if i > 0}+{/if}
+ {key}
+ {/each}
+ {#if shortcut.altKeys && !compact}
+
+ oder
+ {#each shortcut.altKeys as key, i}
+ {#if i > 0}+{/if}
+ {key}
+ {/each}
+
+ {/if}
+
+
{shortcut.description}
+
+ {/each}
+
+
+ {/each}
+
+
+
diff --git a/packages/shared-ui/src/help/SyntaxHelpPanel.svelte b/packages/shared-ui/src/help/SyntaxHelpPanel.svelte
new file mode 100644
index 000000000..f39896d5f
--- /dev/null
+++ b/packages/shared-ui/src/help/SyntaxHelpPanel.svelte
@@ -0,0 +1,415 @@
+
+
+
+ {#if introText && !compact}
+
{introText}
+ {/if}
+
+ {#each groups as group}
+
+
{group.title}
+
+ {#each group.items as item}
+ {@const Icon = item.icon ?? getPatternIcon(item.pattern)}
+
+
+
+
+
+
+
+ {#each item.examples as ex}
+ {#if typeof ex === 'string'}
+ {ex}
+ {:else}
+
+ {ex.text}
+ {#if ex.label}
+ {ex.label}
+ {/if}
+
+ {/if}
+ {/each}
+
+
+
+ {/each}
+
+
+ {/each}
+
+ {#if showLiveExample && !compact}
+
+
Beispiel-Eingabe
+
+ {#each example.highlights as hl}
+ {hl.content}
+ {/each}
+
+
+ {/if}
+
+
+
diff --git a/packages/shared-ui/src/help/constants.ts b/packages/shared-ui/src/help/constants.ts
new file mode 100644
index 000000000..e57e158a7
--- /dev/null
+++ b/packages/shared-ui/src/help/constants.ts
@@ -0,0 +1,122 @@
+import type { ShortcutCategory, SyntaxGroup } from './types';
+
+/**
+ * Common keyboard shortcuts shared across all apps with InputBar
+ */
+export const COMMON_SHORTCUTS: ShortcutCategory[] = [
+ {
+ id: 'inputbar',
+ title: 'Eingabefeld',
+ shortcuts: [
+ {
+ keys: ['Enter'],
+ description: 'Auswahl bestätigen / Erstellen',
+ category: 'inputbar',
+ },
+ {
+ keys: ['Cmd', 'Enter'],
+ altKeys: ['Ctrl', 'Enter'],
+ description: 'Direkt erstellen',
+ category: 'inputbar',
+ },
+ {
+ keys: ['Esc'],
+ description: 'Schließen & Eingabe löschen',
+ category: 'inputbar',
+ },
+ {
+ keys: ['↑', '↓'],
+ description: 'Durch Ergebnisse navigieren',
+ category: 'inputbar',
+ },
+ {
+ keys: ['Rechtsklick'],
+ description: 'Einstellungen öffnen',
+ category: 'inputbar',
+ },
+ ],
+ },
+ {
+ id: 'dialogs',
+ title: 'Dialoge',
+ shortcuts: [
+ {
+ keys: ['Esc'],
+ description: 'Dialog schließen',
+ category: 'dialogs',
+ },
+ ],
+ },
+];
+
+/**
+ * Common syntax patterns shared across all apps with InputBar
+ */
+export const COMMON_SYNTAX: SyntaxGroup[] = [
+ {
+ title: 'Kategorien & Tags',
+ items: [
+ {
+ pattern: '#tag',
+ description: 'Tag hinzufügen',
+ examples: ['#arbeit', '#privat', '#wichtig'],
+ color: 'primary',
+ },
+ {
+ pattern: '@name',
+ description: 'Kalender oder Projekt zuweisen',
+ examples: ['@team', '@privat', '@projekt'],
+ color: 'success',
+ },
+ ],
+ },
+ {
+ title: 'Zeit & Datum',
+ items: [
+ {
+ pattern: 'Datum',
+ description: 'Natürliche Datumsangaben',
+ examples: ['heute', 'morgen', 'montag', 'in 3 tagen', 'nächste woche'],
+ color: 'accent',
+ },
+ {
+ pattern: 'Uhrzeit',
+ description: 'Zeitangaben',
+ examples: ['14:00', '9 uhr', 'um 15:30'],
+ color: 'accent',
+ },
+ ],
+ },
+ {
+ title: 'Priorität',
+ items: [
+ {
+ pattern: 'Priorität',
+ description: 'Dringlichkeit festlegen',
+ examples: [
+ { text: '!!!', label: 'dringend', color: 'error' },
+ { text: '!!', label: 'hoch', color: 'warning' },
+ { text: '!', label: 'normal', color: 'warning-soft' },
+ ],
+ color: 'error',
+ },
+ ],
+ },
+];
+
+/**
+ * Default live example for syntax highlighting demo
+ */
+export const DEFAULT_LIVE_EXAMPLE = {
+ text: 'Meeting mit Team morgen 14:00 @arbeit #wichtig',
+ highlights: [
+ { type: 'text' as const, content: 'Meeting mit Team ' },
+ { type: 'date' as const, content: 'morgen' },
+ { type: 'text' as const, content: ' ' },
+ { type: 'time' as const, content: '14:00' },
+ { type: 'text' as const, content: ' ' },
+ { type: 'reference' as const, content: '@arbeit' },
+ { type: 'text' as const, content: ' ' },
+ { type: 'tag' as const, content: '#wichtig' },
+ ],
+};
diff --git a/packages/shared-ui/src/help/index.ts b/packages/shared-ui/src/help/index.ts
new file mode 100644
index 000000000..cf2bbb318
--- /dev/null
+++ b/packages/shared-ui/src/help/index.ts
@@ -0,0 +1,18 @@
+// Help Components
+export { default as HelpModal } from './HelpModal.svelte';
+export { default as KeyboardShortcutsPanel } from './KeyboardShortcutsPanel.svelte';
+export { default as SyntaxHelpPanel } from './SyntaxHelpPanel.svelte';
+
+// Types
+export type {
+ KeyboardShortcut,
+ ShortcutCategory,
+ SyntaxColor,
+ SyntaxExample,
+ SyntaxPattern,
+ SyntaxGroup,
+ HelpModalConfig,
+} from './types';
+
+// Constants
+export { COMMON_SHORTCUTS, COMMON_SYNTAX, DEFAULT_LIVE_EXAMPLE } from './constants';
diff --git a/packages/shared-ui/src/help/types.ts b/packages/shared-ui/src/help/types.ts
new file mode 100644
index 000000000..6fca61d09
--- /dev/null
+++ b/packages/shared-ui/src/help/types.ts
@@ -0,0 +1,93 @@
+import type { Component } from 'svelte';
+
+/**
+ * Represents a single keyboard shortcut
+ */
+export interface KeyboardShortcut {
+ /** Keys to press, e.g. ['Cmd', 'Enter'] or ['↑', '↓'] */
+ keys: string[];
+ /** Description of what the shortcut does */
+ description: string;
+ /** Category ID for grouping */
+ category: string;
+ /** Alternative keys (e.g. Ctrl instead of Cmd) */
+ altKeys?: string[];
+}
+
+/**
+ * A category/group of related shortcuts
+ */
+export interface ShortcutCategory {
+ /** Unique identifier */
+ id: string;
+ /** Display title */
+ title: string;
+ /** Optional icon component */
+ icon?: Component;
+ /** Shortcuts in this category */
+ shortcuts: KeyboardShortcut[];
+}
+
+/**
+ * Color variants for syntax highlighting
+ */
+export type SyntaxColor = 'primary' | 'success' | 'accent' | 'error' | 'warning' | 'warning-soft';
+
+/**
+ * A syntax example - can be a simple string or an object with label
+ */
+export type SyntaxExample =
+ | string
+ | {
+ text: string;
+ label?: string;
+ color?: SyntaxColor;
+ };
+
+/**
+ * A syntax pattern that can be used in the InputBar
+ */
+export interface SyntaxPattern {
+ /** The pattern syntax, e.g. '#tag', '@name', 'Datum' */
+ pattern: string;
+ /** Description of what the pattern does */
+ description: string;
+ /** Example usages */
+ examples: SyntaxExample[];
+ /** Color for highlighting */
+ color: SyntaxColor;
+ /** Optional icon component */
+ icon?: Component;
+}
+
+/**
+ * A group of related syntax patterns
+ */
+export interface SyntaxGroup {
+ /** Group title */
+ title: string;
+ /** Patterns in this group */
+ items: SyntaxPattern[];
+}
+
+/**
+ * Configuration for the HelpModal
+ */
+export interface HelpModalConfig {
+ /** Shortcut categories to display */
+ shortcuts?: ShortcutCategory[];
+ /** Syntax groups to display */
+ syntax?: SyntaxGroup[];
+ /** Whether to show tabs (auto-detected if both shortcuts and syntax are provided) */
+ showTabs?: boolean;
+ /** Default tab to show */
+ defaultTab?: 'shortcuts' | 'syntax';
+ /** Live example text for syntax highlighting demo */
+ liveExample?: {
+ text: string;
+ highlights: Array<{
+ type: 'text' | 'tag' | 'reference' | 'date' | 'time' | 'priority';
+ content: string;
+ }>;
+ };
+}
diff --git a/packages/shared-ui/src/index.ts b/packages/shared-ui/src/index.ts
index 7ccc8a9b6..d55e11ae9 100644
--- a/packages/shared-ui/src/index.ts
+++ b/packages/shared-ui/src/index.ts
@@ -172,3 +172,22 @@ export type {
// Context Menu
export { ContextMenu, createContextMenuState } from './context-menu';
export type { ContextMenuItem, ContextMenuState } from './context-menu';
+
+// Help Components
+export {
+ HelpModal,
+ KeyboardShortcutsPanel as HelpKeyboardShortcutsPanel,
+ SyntaxHelpPanel,
+ COMMON_SHORTCUTS,
+ COMMON_SYNTAX,
+ DEFAULT_LIVE_EXAMPLE,
+} from './help';
+export type {
+ KeyboardShortcut as HelpKeyboardShortcut,
+ ShortcutCategory,
+ SyntaxColor,
+ SyntaxExample,
+ SyntaxPattern,
+ SyntaxGroup,
+ HelpModalConfig,
+} from './help';
diff --git a/packages/shared-ui/src/organisms/Modal.svelte b/packages/shared-ui/src/organisms/Modal.svelte
index 0e33ba862..efeeec703 100644
--- a/packages/shared-ui/src/organisms/Modal.svelte
+++ b/packages/shared-ui/src/organisms/Modal.svelte
@@ -53,7 +53,8 @@
e.key === 'Enter' && handleBackdropClick(e as unknown as MouseEvent)}
role="dialog"
diff --git a/packages/shared-ui/src/quick-input/InputBarHelpModal.svelte b/packages/shared-ui/src/quick-input/InputBarHelpModal.svelte
index b0b773981..01889a9dd 100644
--- a/packages/shared-ui/src/quick-input/InputBarHelpModal.svelte
+++ b/packages/shared-ui/src/quick-input/InputBarHelpModal.svelte
@@ -1,6 +1,7 @@
-
- {#if mode === 'shortcuts'}
-
-
- {#each shortcuts as { keys, description }}
-
- {keys}
- {description}
-
- {/each}
-
-
- {:else}
-
-
- Du kannst natürliche Sprache verwenden, um schnell Einträge zu erstellen. Die InputBar
- erkennt automatisch Daten, Zeiten, Tags und mehr.
-
-
-
- {#each syntaxExamples as { icon: Icon, pattern, description, example }}
-
-
-
-
-
-
- {pattern}
- {description}
-
-
{example}
-
-
- {/each}
-
-
-
-
Beispiel:
-
Meeting mit Team morgen 14:00 @arbeit #wichtig
-
-
- {/if}
-
-
-
+