Files
Hoard/GUI/style.md
Jonas 7e2ca4c9e2 Rename hoard- to ui- and add UI components
Mass rename of CSS classes, tokens and animations from the hoard- namespace to ui- (classes, variables like --ui-*, and keyframes). Introduces new UI components: EmptyState, StatusPill, and UserAvatar and updates admin views to import and use them. Updates many route/layout components and global.css to use the new ui- patterns and responsive variables. Also updates Impressum contact emails and adds .claude/settings.local.json to allow running npm scripts in the Claude local settings.
2026-04-28 21:52:22 +02:00

15 KiB
Raw Permalink Blame History

Hoard Style Guide

Zielbild

Hoard soll wirken wie eine moderne, produktive Dateiverwaltung im Browser ruhig, klar und mit hoher visueller Sorgfalt. Die Grundphilosophie bleibt dateiorientiert: Inhalte, Dateinamen, Pfade und Aktionen stehen im Vordergrund, nicht UI-Effekte. Gleichzeitig darf sich Hoard hochwertig und präzise anfühlen „polished" statt „fancy", näher an einer modernen Linear-/Vercel-/Notion-Sidebar als an einer alten Admin-UI.

Die Gestaltung folgt drei Prinzipien:

  1. Dateien zuerst Inhalte, Namen, Strukturen und Aktionen sind optisch dominant, nicht die Chrome.
  2. Ruhe mit Charakter viel Weißraum, klare Flächen, ausgewählte Akzente. Wenig Elemente, aber jedes mit Sorgfalt.
  3. Grün als Identität, nicht als Dauerfeuer die Markenfarbe wird gezielt für Auswahl, Primäraktionen, Status und Branding eingesetzt nicht flächendeckend.

Modernisierungs-Direktive

Beim Redesign gilt zusätzlich:

  • Hochwertige App-Shell: Sidebar und Topbar dürfen sich „premium" anfühlen (klare Hierarchie, animierter Active-Indicator, gradient-tinged Brand-Bereich).
  • Layered Surfaces: Statt einer einzigen Surface-Farbe gibt es eine kleine Surface-Hierarchie (surface, surface-alt, surface-elevated) mit subtil gestaffelten Schatten.
  • Microinteractions: kurze, präzise Hover-/Active-/Focus-Animationen (160240 ms). Keine wabernden, dauerhaften Bewegungen.
  • Ambient Gradients: Hero-/Brand-Bereiche dürfen sehr weiche, breit gestreute Verläufe in Markenfarbe haben. Arbeitsflächen bleiben funktional und ruhig.
  • Typografische Präzision: klare Größen-Hierarchie, ruhige Headlines, viel letter-spacing Disziplin, keine dekorativen Schriften.
  • Konsistente Iconographie: ausschließlich MDI Outline-Icons mit gleicher Größe und Farbverhalten.
  • Light- und Dark-Mode gleichwertig: alle neuen Stile müssen in beiden Modi funktional und ästhetisch tragen, ausschließlich über Tokens (color-mix, CSS-Variablen) gelöst.

Was weiterhin tabu ist:

  • kein Glassmorphism (echte Backdrop-Blur-Karten),
  • kein Neon-/Gaming-Look,
  • keine harten, durchgängigen Kontraste,
  • keine Mehrfarbigkeit aus dem Akzent-Setup,
  • keine dauerhaften Animationen oder Parallax-Spielereien.

Visuelle Identität

Markenwirkung basiert auf neutralen, leicht warmen Flächen mit kontrolliertem Grün. Das Grün stammt aus dem Logo (Stapel-/Ordner-Idee) und steht für Ablage, Struktur und „self-hosted tool" statt „Social App". Akzent-Lime nur als gezielter Akzent-Glow im Branding und in Marketing-Sektionen.

Die App ist light-first, Dark-Mode ist gleichwertig zu pflegen. Neue Komponenten beziehen Farben aus Design-Tokens.

Farbpalette

Primärfarben (Light)

  • Primary 800: #10421E tiefster Markenton, Texte auf Light-Surface.
  • Primary 700: #1C652F Primärbuttons, aktive Icons, Fokusrahmen.
  • Primary 600: #2E7D32 Hover-Zustände, aktive Navigation.
  • Primary 500: #3C8F42 ausgewählte Einträge, Badges, bestätigende States.
  • Primary 300: #A8D5A2 weiche Hintergründe für Auswahlflächen.
  • Primary 100: #EAF5E8 sehr subtile Hervorhebungen, Tints.
  • Primary 050: #F4FAF1 fast unsichtbare Pflasterfläche für Hero-Glows.

Akzent

  • Accent Lime: #B7E36B sparsam: Logo-Glow, kleine Highlights, Upload-Fortschritt.

Neutrale (Light)

  • Background: #F5F8F2
  • Background Tint: #EEF3EA ambient Hintergrund-Verlauf.
  • Surface: #FFFFFF Karten, Panels, Dialoge.
  • Surface Alt: #F1F4EE Toolbar, Tabellenkopf, Sekundärflächen.
  • Surface Elevated: #FBFCF8 höhere Layer (Drawer-Inhalt, Dropdowns).
  • Border: #DCE3D6
  • Border Strong: #C5CFBE
  • Border Subtle: #E8EDE2 innere Trennlinien.

Text (Light)

  • Text Primary: #1A2A1E
  • Text Secondary: #5A6A5E
  • Text Muted: #7B897F
  • Text On Primary: #FFFFFF

Dark Mode

Dark-Mode wird vollständig über Tokens gespiegelt. Eckwerte:

  • Background: #0E1115
  • Surface: #161A20
  • Surface Alt: #1B2028
  • Surface Elevated: #1F252E
  • Border: #2A323D
  • Border Strong: #3A4452
  • Text Primary: #E9EFF3
  • Text Secondary: #B6BEC8
  • Primary 700 (dark): #5FB968
  • Primary 600 (dark): #4EA758
  • Primary 100 (dark): #1F2922

Status

  • Success: #2E7D32
  • Warning: #B7791F
  • Danger: #C0392B
  • Info: #2F6FB3

Typografie

Neutral, gut lesbar, unauffällig modern keine dekorativen Schriften.

Stack: Inter, "Segoe UI", Roboto, system-ui, sans-serif

Skala (rem-orientiert, fixe px-Breakpoints, keine viewport-Skalierung):

  • --font-size-2xs: 11px Status-Labels, Mini-Meta.
  • --font-size-xs: 12px Tabellenmeta, Helper-Text.
  • --font-size-sm: 13px sekundärer UI-Text.
  • --font-size-md: 14px Standard-UI-Text, Listen.
  • --font-size-lg: 16px akzentuierte UI-Hervorhebung.
  • --font-size-xl: 20px Bereichsüberschriften.
  • --font-size-2xl: 26px Seitenüberschriften.
  • --font-size-3xl: 32px Display-Headlines (Hero).
  • --font-size-display: 44px sehr seltene Marketing-Display-Texte.

Gewichte:

  • 400 für Fließtext.
  • 500 für UI-Text und Labels.
  • 600 für Titel, Kicker, aktive Items.
  • 700 nur sehr gezielt (Display-Headlines, Logo-Wortmarke).

Letter-Spacing-Disziplin:

  • Display-Headlines: leicht negatives Tracking (-0.01em bis -0.02em).
  • Kicker/Labels (uppercase): 0.05em bis 0.08em.
  • Standard: 0.

Spacing

Modulare Skala in 4er-Schritten:

--space-1: 4px
--space-2: 8px
--space-3: 12px
--space-4: 16px
--space-5: 20px
--space-6: 24px
--space-7: 28px
--space-8: 32px
--space-10: 40px
--space-12: 48px
--space-16: 64px

Hauptseiten: --ui-page-width 11201200px, Padding orientiert sich an --space-6/--space-8.

Formensprache (Border-Radien)

  • --radius-xs: 6px kleine Pills, Status-Badges.
  • --radius-sm: 10px Buttons, kleine Controls.
  • --radius-md: 14px Inputs, Dropdowns, Listzeilen.
  • --radius-lg: 18px Cards, Panels.
  • --radius-xl: 22px Hero-Shells, Modals.
  • --radius-full: 999px nur für Avatar/Tag-Pills.

Keine pillenförmigen Vollflächen als Grundstil.

Schatten & Tiefe

Mehrstufiges, sehr ruhiges Schatten-System:

--shadow-xs: 0 1px 1px rgba(20, 30, 22, 0.04);
--shadow-sm: 0 2px 6px rgba(20, 30, 22, 0.06);
--shadow-md: 0 8px 22px rgba(20, 30, 22, 0.08);
--shadow-lg: 0 18px 44px rgba(20, 30, 22, 0.12);
--shadow-glow: 0 12px 36px rgba(28, 101, 47, 0.18);

Regeln:

  • Panels: --shadow-sm.
  • Hover-Lift max. 2 px, nur bei klar interaktiven Elementen.
  • Dropdowns/Modals: --shadow-md bis --shadow-lg.
  • --shadow-glow ausschließlich für Brand-Bereiche (Login-Hero, Welcome-Hero).
  • Keine farbigen Schatten in Arbeitsflächen.

Motion

  • Standard-Easing: cubic-bezier(0.2, 0, 0, 1).
  • --transition-fast: 160 ms (Hover, Buttons, Listzeilen).
  • --transition-medium: 220 ms (Route-Wechsel, Banner).
  • --transition-slow: 320 ms (Hero-Enter, Drawer).
  • Globale Page-Enter-Animation: weicher Y-Slide + Fade (≤ 8 px).
  • prefers-reduced-motion: alle Transitions auf 1 ms reduzieren, keine Translates.

App-Shell

Topbar

  • Höhe ca. 64 px, opaker surface-Hintergrund, dünne Bottom-Border.
  • Branding links: Icon + Wortmarke + dezenter Subtext („Self-hosted Workspace").
  • Page-Kontext (Name + Beschreibung) als sekundäre Info, nur ab >1180px.
  • Rechts: Theme-Toggle, Account-Menü oder Login-Button.
  • Subtile bottom shadow (--shadow-xs).

Sidebar

  • Breite 268284 px, Hintergrund surface-alt, leicht abgesetzt.
  • Active-Indicator: linker, animierter, vertikaler Strich (--color-primary-600) + grüne Tint-Fläche + dunklerer Text.
  • Hover: leichte Tint-Fläche, kein Scaling.
  • Sektionen mit Kicker-Labels (Navigation, Admin).
  • Mindesthöhe pro Item: 44 px (Desktop), 48 px (Mobile).
  • Mobile = Bottom-Sheet-Drawer mit abgerundeten Top-Ecken.
  • Sehr ruhig, kompakt, surface mit dünner oberer Border.
  • Links nur auf rechtlich/strukturell wichtige Routen (Impressum etc.).
  • Mobile: in Grid mit Tap-Größen ≥ 44 px.

Komponenten

Cards / Panels

  • Hintergrund: surface mit subtilem 180°-Verlauf zu surface-alt.
  • Border: --color-border.
  • Radius: --radius-lg.
  • Padding: --space-6 (Standard), kleinere Inhalte --space-4.
  • Hover (nur klar interaktive Cards): Border in Primary-300-Mix, --shadow-md, 2 px Y-Lift.

Buttons

  • Primary: grüner Hintergrund (--color-primary-700), weiße Schrift, --shadow-xs. Hover: --color-primary-600 + leichter Glow. Active: ohne Lift.
  • Outlined: transparenter Hintergrund, --color-border-strong, dunkler Text. Hover: leichte Primary-Tint-Fläche, Border zu Primary-Mix.
  • Text/Tertiary: für Zeilenaktionen, Toolbar, Nav. Hover: Surface-Tint.
  • Icon-Buttons: mind. 40×40 (Desktop), 44×44 (Mobile).
  • Letter-Spacing 0, kein Uppercase.
  • Pro Bereich genau eine Primäraktion.

Inputs

  • Outline-Variante, surface Hintergrund.
  • Border --color-border-strong, Focus-Ring 3 px Primary-300-Tint + Primary-600-Border.
  • Labels oberhalb (Vuetify-Outlined-Label), keine reinen Placeholder.
  • Mind. 44 px Höhe auf Mobile.

Listen / Tabellen

  • Tabelle: surface Hintergrund, abgesetzter Tabellen-Header (surface-alt).
  • Hover: sehr subtile Primary-Tint-Tönung.
  • Selected Row: Primary-100 Hintergrund, --color-primary-700 Text.
  • Border-Bottom in --color-border-subtle.
  • ui-list-row (Datei-/Item-Zeilen): luftiges Padding, klare Spalten, transform: translateX(2px) beim Hover.

Status-Pills (ui-status)

  • Kompakt, --radius-xs, mit dezentem Text/Background-Tint pro Status (Success/Info/Warning/Danger/Neutral).
  • Optional kleines Punktindikator-Dot vor dem Text.

Banner-Stack

  • Position: fixiert unten rechts (Desktop), unten zentriert (Mobile).
  • Stapelbar, einzeln dismissable.
  • Opake Hintergründe, --shadow-md, sauber lesbar auf jedem Inhalt.
  • Enter/Leave: 180 ms Fade + 10 px Y.

Hero-/Marketing-Bereiche

  • Erlauben einen ambient Verlauf (ui-panel-gradient + Variablen).
  • Optional dezenter „Spotlight"-Glow (radialer Verlauf, --color-primary-300 mit niedriger Opazität, blur).
  • Inhaltsbreite max ~64ch.
  • Display-Headlines mit --font-size-3xl oder --font-size-display (nur Hero).
  • Hero-Tags (ui-chip/ui-tag) als kompakte, dezent gerahmte Pills.

Vorschau-Bereich (Files)

  • PDF-Vorschau: neutraler Hintergrund, weiße „Papier"-Fläche mit --shadow-md, genug Rand. Controls minimal.
  • Bildvorschau: dunklerer neutraler Viewer-Hintergrund nur, wenn das Bild dadurch besser wirkt; UI-Chrome konsistent.
  • Markdown-Editor/Reader: wirkt wie ein Arbeitsdokument, nicht wie Blogpost. Lesbreite ~70ch, klare Heading-Hierarchie, sehr ruhige Codeblöcke.

Empty-/Loading-States

  • Empty: kleines Outline-Icon in Primary-Tint, kurzer Titel, ein Satz Begründung, eine klare CTA.
  • Loading: Skeletons (graue Pulslinien) bevorzugt, ansonsten ein kleiner zentraler Spinner mit beschreibendem Text. Keine flackernden Spinner-Felder.

Responsive Verhalten

Desktop ist Hauptfokus, Mobile muss aber sauber funktionieren.

Breakpoints

  • @media (width <= 1180px) Topbar-Kontextleiste verkürzen.
  • @media (width <= 960px) Sidebar wird Bottom-Drawer; Karten-/Grid-Bereiche werden einspaltig; Spacing wird reduziert.
  • @media (width <= 600px) CTAs full-width; Schriften minimal kompakter; Footer als Grid; Status-Pills behalten Lesbarkeit.

Pflicht

  • Desktop-Baseregeln nicht anfassen, nur Mobile-Overrides per Media Query.
  • Touch-Größen: Buttons ≥ 44 px, Icon-Buttons ≥ 44×44, Nav-Items ≥ 48 px.
  • Safe-Areas via env(safe-area-inset-*) (Topbar-Padding, Footer/Drawer Bottom).
  • Banner-Stack respektiert Safe-Area Bottom.
  • Pflicht-Viewports im QA: 360x800, 390x844, 768x1024, 1024x768, >=1280 jeweils Light + Dark.

Interaktionsprinzipien

  • Primäraktionen klar sichtbar.
  • Destruktives nie direkt neben Standardaktion.
  • Dateizeilen sind klickbar, dürfen aber nicht wie Buttons aussehen.
  • Hover, Active und Selected klar unterscheidbar (unterschiedliche Tints/Outlines).
  • Fokus für Tastaturbedienung immer sichtbar (outline: 2px solid var(--color-primary-500); outline-offset: 2px).

Designregeln für die Umsetzung

Immer

  • Tokens nutzen (Farben, Spacing, Radius, Shadow).
  • Patterns wiederverwenden (ui-panel, ui-page, ui-action-row, ui-kicker, ui-status, ui-chip, ui-spotlight).
  • Light- und Dark-Mode gleichwertig prüfen.
  • Animationen kurz halten und prefers-reduced-motion respektieren.

Vermeiden

  • zu viele Karten ohne Funktion,
  • zu viele Akzentfarben gleichzeitig,
  • harte 1:1-Kontraste,
  • echte Glasflächen / Backdrop-Blur,
  • dauernde Bewegungen,
  • Schriftgrößen, die mit der Viewport-Breite skalieren.

Beispiel: Design-Tokens

:root {
  /* Surfaces */
  --color-bg: #f5f8f2;
  --color-bg-tint: #eef3ea;
  --color-surface: #ffffff;
  --color-surface-alt: #f1f4ee;
  --color-surface-elevated: #fbfcf8;

  --color-border: #dce3d6;
  --color-border-strong: #c5cfbe;
  --color-border-subtle: #e8ede2;

  /* Text */
  --color-text: #1a2a1e;
  --color-text-secondary: #5a6a5e;
  --color-text-muted: #7b897f;
  --color-text-on-primary: #ffffff;

  /* Brand */
  --color-primary-800: #10421e;
  --color-primary-700: #1c652f;
  --color-primary-600: #2e7d32;
  --color-primary-500: #3c8f42;
  --color-primary-300: #a8d5a2;
  --color-primary-100: #eaf5e8;
  --color-primary-050: #f4faf1;
  --color-accent-lime: #b7e36b;

  /* Status */
  --color-success: #2e7d32;
  --color-warning: #b7791f;
  --color-danger: #c0392b;
  --color-info: #2f6fb3;

  /* Radius */
  --radius-xs: 6px;
  --radius-sm: 10px;
  --radius-md: 14px;
  --radius-lg: 18px;
  --radius-xl: 22px;
  --radius-full: 999px;

  /* Shadows */
  --shadow-xs: 0 1px 1px rgba(20, 30, 22, 0.04);
  --shadow-sm: 0 2px 6px rgba(20, 30, 22, 0.06);
  --shadow-md: 0 8px 22px rgba(20, 30, 22, 0.08);
  --shadow-lg: 0 18px 44px rgba(20, 30, 22, 0.12);
  --shadow-glow: 0 12px 36px rgba(28, 101, 47, 0.18);

  /* Spacing */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 20px;
  --space-6: 24px;
  --space-7: 28px;
  --space-8: 32px;
  --space-10: 40px;
  --space-12: 48px;
  --space-16: 64px;

  /* Motion */
  --transition-fast: 160ms cubic-bezier(0.2, 0, 0, 1);
  --transition-medium: 220ms cubic-bezier(0.2, 0, 0, 1);
  --transition-slow: 320ms cubic-bezier(0.2, 0, 0, 1);
}

Kurzfassung als Design-Leitlinie

Wenn du bei einer UI-Entscheidung unsicher bist:

Lieber präzise als spektakulär. Lieber ruhige Flächen mit Charakter als visuelle Effekte. Grün ist Identität, nicht Dekoration. Jedes Element muss eine Funktion haben sonst fliegt es raus.