managarten/docs/central-services/THEMING.md
Till-JS ee42b6cc76 feat: major update with network graphs, themes, todo extensions, and more
## New Features

### Network Graph Visualization (Contacts, Calendar, Todo)
- D3.js force simulation for physics-based layout
- Zoom & pan with mouse/touchpad
- Keyboard shortcuts: +/- zoom, 0 reset, Esc deselect, / search, F focus
- Filtering by tags, company/location/project, connection strength
- Shared components in @manacore/shared-ui

### Central Tags API (mana-core-auth)
- CRUD endpoints for tags
- Schema: tags table with userId, name, color, app
- Shared tag components in @manacore/shared-ui

### Custom Themes System
- Theme editor with live preview and color picker
- Community theme gallery
- Theme sharing (public, unlisted, private)
- Backend API in mana-core-auth

### Todo App Extensions
- Glass-pill design for task input and items
- Settings page with 20+ preferences
- Task edit modal with inline editing
- Statistics page with visualizations
- PWA support with offline capabilities
- Multiple kanban boards

### Contacts App Features
- Duplicate detection
- Photo upload
- Batch operations
- Enhanced favorites page with multiple view modes
- Alphabet view improvements
- Search modal

### Help System
- @manacore/shared-help-content
- @manacore/shared-help-ui
- @manacore/shared-help-types

### Other Features
- Themes page for all apps
- Referral system frontend
- CommandBar (global search)
- Skeleton loaders
- Settings page improvements

## Bug Fixes
- Network graph simulation initialization
- Database schema TEXT for user_id columns (Better Auth compatibility)
- Various styling fixes

## Documentation
- Daily report for 2025-12-10
- CI/CD deployment guide

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-10 02:37:46 +01:00

13 KiB

Central Theming System

Das zentrale Theming-System ermöglicht einheitliches Aussehen und Benutzereinstellungen über alle Manacore-Apps hinweg. Es besteht aus mehreren Schichten: Theme-Varianten, Light/Dark-Modus, Accessibility-Einstellungen und Custom Themes.

Architektur

┌─────────────────────────────────────────────────────────────┐
│                     mana-core-auth                          │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  user_settings (JSON-Feld)                           │   │
│  │  - theme: { mode, colorScheme, pinnedThemes }       │   │
│  │  - nav: { desktopPosition, sidebarCollapsed }       │   │
│  │  - locale: "de"                                      │   │
│  │  - general: { startPages, sounds, etc. }            │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  custom_themes Tabelle (Community Themes)            │   │
│  │  - lightColors, darkColors, author, downloads, etc.  │   │
│  └─────────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────────┘
                             │
        ┌────────────────────┼────────────────────┐
        │                    │                    │
   ┌────▼────┐         ┌─────▼────┐        ┌─────▼────┐
   │  Todo   │         │ Calendar │        │ Contacts │
   │         │         │          │        │          │
   │ shared- │         │ shared-  │        │ shared-  │
   │ theme   │         │ theme    │        │ theme    │
   └─────────┘         └──────────┘        └──────────┘

Packages

Package Beschreibung
@manacore/shared-theme Theme Store, Types, Utilities, Konstanten
@manacore/shared-theme-ui Svelte UI-Komponenten (ThemeSelector, ThemePage, etc.)

Theme-Varianten

Es gibt 8 vordefinierte Theme-Varianten:

Standard-Varianten (PillNav)

Name Farbe Icon Hue
lume Gold sparkle 47
nature Grün 🌿 leaf 122
stone Blau-Grau 🪨 hexagon 200
ocean Blau 🌊 waves 199

Erweiterte Varianten (Themes-Seite)

Name Farbe Icon Hue
sunset Coral/Orange 🌅 sun 15
midnight Violett 🌙 moon 260
rose Pink 🌹 flower 340
lavender Lavendel 💜 sparkle 270

Theme-Modus

type ThemeMode = 'light' | 'dark' | 'system';
  • light: Heller Modus
  • dark: Dunkler Modus
  • system: Folgt der System-Einstellung

Color Tokens

Jede Theme-Variante definiert diese HSL-Farbwerte für Light und Dark:

interface ThemeColors {
  primary: string;           // Hauptfarbe
  primaryForeground: string; // Text auf Primary
  secondary: string;         // Sekundärfarbe
  secondaryForeground: string;
  background: string;        // Seitenhintergrund
  foreground: string;        // Haupttext
  surface: string;           // Karten-Hintergrund
  surfaceHover: string;      // Hover-Zustand
  surfaceElevated: string;   // Modals, Dropdowns
  muted: string;             // Deaktivierte Elemente
  mutedForeground: string;
  border: string;            // Rahmen
  borderStrong: string;      // Starke Rahmen
  error: string;             // Fehler-Rot
  success: string;           // Erfolg-Grün
  warning: string;           // Warnung-Orange
  input: string;             // Input-Hintergrund
  ring: string;              // Focus-Ring
}

HSL-Format

Farben werden als HSL-Strings ohne hsl() Wrapper gespeichert:

// Format: "H S% L%"
const gold = '47 95% 58%';
const darkBlue = '199 100% 18%';

// CSS-Verwendung
--color-primary: 47 95% 58%;
background-color: hsl(var(--color-primary));

Store-Nutzung

Theme Store

import { createThemeStore } from '@manacore/shared-theme';

// Store erstellen
export const theme = createThemeStore({
  appId: 'calendar',
  defaultMode: 'system',
  defaultVariant: 'ocean',
});

// In Komponente initialisieren
onMount(() => {
  const cleanup = theme.initialize();
  return cleanup;
});

// Zugriff auf State
theme.mode       // 'light' | 'dark' | 'system'
theme.variant    // 'ocean' | 'nature' | ...
theme.effectiveMode // 'light' | 'dark' (aufgelöst)
theme.isDark     // boolean

// Aktionen
theme.setMode('dark');
theme.setVariant('nature');
theme.toggleMode();   // Light ↔ Dark
theme.cycleMode();    // Light → Dark → System → Light

App-spezifische Primary Color

export const theme = createThemeStore({
  appId: 'memoro',
  primaryColor: {
    light: '47 95% 58%',  // Gold
    dark: '47 95% 58%',
  },
});

User Settings Store (Server-Sync)

import { createUserSettingsStore } from '@manacore/shared-theme';

export const userSettings = createUserSettingsStore({
  appId: 'calendar',
  authUrl: 'http://localhost:3001',
  getAccessToken: () => authStore.getAccessToken(),
});

// Laden
await userSettings.load();

// Zugriff
userSettings.theme.mode       // Theme-Modus
userSettings.theme.colorScheme // Variante
userSettings.nav.desktopPosition // 'top' | 'bottom'
userSettings.locale           // 'de'
userSettings.general.soundsEnabled

// Aktualisieren (speichert auf Server)
await userSettings.updateGlobal({
  theme: { mode: 'dark' }
});

// App-spezifische Überschreibung
await userSettings.updateAppOverride({
  theme: { colorScheme: 'nature' }
});

Accessibility (A11y)

A11y Store

import { createA11yStore } from '@manacore/shared-theme';

export const a11y = createA11yStore({ appId: 'calendar' });

// State
a11y.contrast      // 'normal' | 'high'
a11y.colorblind    // 'none' | 'deuteranopia' | 'protanopia' | 'monochrome'
a11y.reduceMotion  // boolean

// Aktionen
a11y.setContrast('high');
a11y.setColorblind('deuteranopia');
a11y.setReduceMotion(true);
a11y.resetAll();

A11y-Optionen

Kontrast:

  • normal: Standard (WCAG AA 4.5:1)
  • high: Erhöhter Kontrast (WCAG AAA 7:1)

Farbenblindheit:

  • none: Keine Anpassung
  • deuteranopia: Grün-Blindheit (~6% der Männer)
  • protanopia: Rot-Blindheit (~1% der Männer)
  • monochrome: Graustufen

Reduzierte Bewegung:

  • Respektiert prefers-reduced-motion
  • Kann manuell überschrieben werden

Custom Themes

Custom Themes Store

import { createCustomThemesStore } from '@manacore/shared-theme';

export const customThemes = createCustomThemesStore({
  authUrl: 'http://localhost:3001',
  getAccessToken: () => authStore.getAccessToken(),
});

// Eigene Themes laden
await customThemes.loadCustomThemes();

// Theme erstellen
const newTheme = await customThemes.createTheme({
  name: 'Mein Theme',
  emoji: '🎨',
  lightColors: { primary: '200 80% 50%', ... },
  darkColors: { primary: '200 70% 60%', ... },
});

// Community Themes durchsuchen
await customThemes.browseCommunity({
  sort: 'popular',
  search: 'dark',
});

// Theme herunterladen
await customThemes.downloadTheme(themeId);

// Theme anwenden
customThemes.applyCustomTheme(theme);

Theme Editor

Der Theme Editor erlaubt das visuelle Erstellen von Themes:

Hauptfarben (immer sichtbar):

  • Primary, Background, Surface, Foreground
  • Error, Success, Warning

Erweiterte Farben (zugeklappt):

  • PrimaryForeground, Secondary, SecondaryForeground
  • SurfaceHover, SurfaceElevated, Muted, MutedForeground
  • Border, BorderStrong, Input, Ring

UI-Komponenten

ThemePage

Vollständige Themes-Seite mit allen Optionen:

<script>
  import { ThemePage } from '@manacore/shared-theme-ui';
  import { theme, a11y } from '$lib/stores';
</script>

<ThemePage
  themeStore={theme}
  a11yStore={a11y}
  showAccessibility={true}
  showPinnedThemes={true}
/>

ThemeSelector

Dropdown zur Theme-Auswahl:

<script>
  import { ThemeSelector } from '@manacore/shared-theme-ui';
  import { theme } from '$lib/stores';
</script>

<ThemeSelector themeStore={theme} />

ThemeModeSelector

Umschalter für Light/Dark/System:

<script>
  import { ThemeModeSelector } from '@manacore/shared-theme-ui';
  import { theme } from '$lib/stores';
</script>

<ThemeModeSelector themeStore={theme} />

ThemeToggle

Einfacher Dark/Light Toggle:

<script>
  import { ThemeToggle } from '@manacore/shared-theme-ui';
  import { theme } from '$lib/stores';
</script>

<ThemeToggle themeStore={theme} />

A11ySettings

Vollständige Accessibility-Einstellungen:

<script>
  import { A11ySettings } from '@manacore/shared-theme-ui';
  import { a11y } from '$lib/stores';
</script>

<A11ySettings store={a11y} />

CSS-Integration

Tailwind CSS

Die Themes werden als CSS-Variablen angewendet:

:root {
  --color-primary: 199 98% 45%;
  --color-background: 199 100% 97%;
  --color-foreground: 199 100% 18%;
  /* ... weitere Tokens */
}

.dark {
  --color-primary: 199 98% 48%;
  --color-background: 200 25% 7%;
  --color-foreground: 0 0% 100%;
}

In Tailwind:

<div class="bg-background text-foreground">
  <button class="bg-primary text-primary-foreground">
    Klick mich
  </button>
</div>

tailwind.config.js

theme: {
  extend: {
    colors: {
      background: 'hsl(var(--color-background))',
      foreground: 'hsl(var(--color-foreground))',
      primary: {
        DEFAULT: 'hsl(var(--color-primary))',
        foreground: 'hsl(var(--color-primary-foreground))',
      },
      // ... weitere
    }
  }
}

Dateien

@manacore/shared-theme

Datei Beschreibung
src/types.ts Alle TypeScript Interfaces
src/constants.ts Theme-Definitionen (8 Varianten)
src/store.svelte.ts Theme Store Factory
src/a11y-store.svelte.ts Accessibility Store
src/a11y-constants.ts A11y Konstanten
src/a11y-utils.ts A11y Helper
src/user-settings-store.svelte.ts Server-Sync Store
src/custom-themes-store.svelte.ts Custom Themes Store
src/utils.ts Theme Utilities
src/app-routes.ts Start-Page Konfiguration

@manacore/shared-theme-ui

Datei Beschreibung
src/ThemeSelector.svelte Theme-Dropdown
src/ThemeModeSelector.svelte Light/Dark/System Selector
src/ThemeToggle.svelte Einfacher Toggle
src/components/ThemeCard.svelte Theme-Vorschau Karte
src/components/ThemeGrid.svelte Grid von Theme-Karten
src/components/A11ySettings.svelte A11y Einstellungen
src/components/editor/ Theme Editor Komponenten
src/components/community/ Community Themes Komponenten
src/pages/ThemePage.svelte Vollständige Themes-Seite
src/pages/ThemeEditorPage.svelte Theme Editor Seite
src/pages/CommunityThemesPage.svelte Community Themes

Integration in eine App

1. Dependencies installieren

{
  "dependencies": {
    "@manacore/shared-theme": "workspace:*",
    "@manacore/shared-theme-ui": "workspace:*"
  }
}

2. Store erstellen

// src/lib/stores/theme.ts
import { createThemeStore, createA11yStore } from '@manacore/shared-theme';

export const theme = createThemeStore({
  appId: 'myapp',
  defaultVariant: 'ocean',
});

export const a11y = createA11yStore({
  appId: 'myapp',
});

3. Im Root-Layout initialisieren

<!-- src/routes/+layout.svelte -->
<script>
  import { onMount } from 'svelte';
  import { theme, a11y } from '$lib/stores/theme';

  onMount(() => {
    const cleanupTheme = theme.initialize();
    const cleanupA11y = a11y.initialize();
    return () => {
      cleanupTheme();
      cleanupA11y();
    };
  });
</script>

<slot />

4. Themes-Seite hinzufügen

<!-- src/routes/(app)/themes/+page.svelte -->
<script>
  import { ThemePage } from '@manacore/shared-theme-ui';
  import { theme, a11y } from '$lib/stores/theme';
</script>

<ThemePage themeStore={theme} a11yStore={a11y} />

Vorteile

  • Konsistenz: Alle Apps sehen einheitlich aus
  • User Experience: Theme-Einstellungen werden gespeichert
  • Accessibility: Barrierefreiheit ist eingebaut
  • Anpassbarkeit: Nutzer können eigene Themes erstellen
  • Community: Themes können geteilt werden