6740038e9a
- Convert codexInfo.md to CLAUDE.md as the central project context. - Rewrite GUI/style.md with a modernized, file-first direction (layered surfaces, refined typography, motion budget, ambient gradients). - Refresh global tokens in global.css, page-layouts.css and surface-patterns.css: extended palette (primary 050/800, surface elevated, border subtle), four-tier shadow system, dark-mode parity, new utilities (hoard-chip, hoard-icon-tile, hoard-spotlight, hoard-section-head, hoard-divider-soft, status pulse dot). - Rebuild Layout.vue: premium app shell with brand halo, animated active-indicator, account pill with avatar/initials, drawer footer card, refined banner stack and footer. - Redesign every route while preserving routing and API contracts: Home, Login, ChangePassword, Dashboard, AdminUsers, AdminUserDetail, Impressum, 404, Forbidden. Adds search/admin stats, password hint list, dashboard greeting with avatar, modernized hero/spotlight treatments and consistent mobile layouts (safe-areas, 44/48px tap targets). - Drop @fontsource/roboto import in vuetify.ts and load Inter via the rsms.me CSS in index.html; update Vuetify defaults and palette to match the new tokens.
359 lines
15 KiB
Markdown
359 lines
15 KiB
Markdown
# 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 (160–240 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: `--hoard-page-width` 1120–1200px, 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 268–284 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.
|
||
|
||
### Footer
|
||
- 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`.
|
||
- `hoard-list-row` (Datei-/Item-Zeilen): luftiges Padding, klare Spalten, `transform: translateX(2px)` beim Hover.
|
||
|
||
### Status-Pills (`hoard-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** (`hoard-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 (`hoard-chip`/`hoard-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 (`hoard-panel`, `hoard-page`, `hoard-action-row`, `hoard-kicker`, `hoard-status`, `hoard-chip`, `hoard-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
|
||
|
||
```css
|
||
: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.**
|