LeoCRM UI-Design-Richtlinien
Version: 1.0
Datum: 2026-07-23
Gültig für: Alle Frontend-Komponenten, Plugin-Seiten und zukünftige Entwicklungen
1. Farbsystem
Alle Farben sind als Tailwind Design Tokens in tailwind.config.js definiert. Jede Farbe hat Schattierungen von 50 (hell) bis 900 (dunkel) plus einen DEFAULT-Wert.
| Token |
Hex (DEFAULT) |
Verwendung |
primary |
#2563eb (Blau) |
Hauptaktionen, aktive Zustände, Links, Fokus-Ringe |
secondary |
#64748b (Slate) |
Text, Borders, Hintergründe, inaktive Zustände |
accent |
#d946ef (Fuchsia) |
Hervorhebungen, Info-Badges, KI-Features |
danger |
#dc2626 (Rot) |
Löschen, Fehler, destruktive Aktionen |
warning |
#f59e0b (Amber) |
Warnungen, ausstehende Aktionen |
success |
#16a34a (Grün) |
Erfolg, Bestätigungen, aktive Status |
Verwendungsregeln
- Primary nur für die wichtigste Aktion pro View. Nicht mehr als eine Primary-Button pro Formular.
- Secondary für Text, Borders und inaktive UI-Elemente.
secondary-50 für Card-Footer, secondary-100 für Hover-Zustände.
- Accent sparsam für KI-Features und Hervorhebungen. Nicht für Standard-Aktionen.
- Danger ausschließlich für destruktive Aktionen (Löschen, Entfernen). Immer mit
ConfirmDialog kombinieren.
- Warning für Status-Badges und Warnhinweise. Nicht als Button-Farbe.
- Success für Erfolgsmeldungen und Status-Indikatoren. Nicht als Standard-Button.
Dark Mode
- Aktiviert via
darkMode: 'class' in Tailwind Config.
- CSS-Variablen in
:root (Light) und .dark (Dark) definiert.
- Dark Mode-Toggle in Settings.
- Beim Dark Mode werden
secondary-900 als Hintergrund und secondary-50 als Text verwendet.
2. Typografie
| Eigenschaft |
Wert |
| Font Family |
Inter (system-ui fallback) |
| Mono Font |
JetBrains Mono für Code/Daten |
| Rendering |
antialiased |
Schriftgrößen-Hierarchie
| Token |
Größe |
Zeilenhöhe |
Verwendung |
text-xs |
0.75rem |
1rem |
Badges, Tooltips, Metadaten |
text-sm |
0.875rem |
1.25rem |
Labels, Helper-Text, Tabellen-Spalten |
text-base |
1rem |
1.5rem |
Body-Text, Input-Felder |
text-lg |
1.125rem |
1.75rem |
Card-Titel, Section-Header |
text-xl |
1.25rem |
1.75rem |
Seiten-Titel |
text-2xl |
1.5rem |
2rem |
Dashboard-Überschriften |
text-3xl |
1.875rem |
2.25rem |
Große Überschriften |
text-4xl |
2.25rem |
2.5rem |
Hero-Text, Login-Titel |
Font-Weight
font-medium (500) — Buttons, Labels, Tab-Header
font-semibold (600) — Card-Titel, Seiten-Titel
font-bold (700) — Nur für Hervorhebungen, sparsam
3. Layout-Patterns
3-Spalten-Explorer-Layout
Standard-Layout für Explorer-Plugins (Calendar, Mail, DMS, Contacts):
- Linke Spalte:
ResizablePanel mit initialWidth=224, minWidth=150, maxWidth=600
- Mittlere Spalte:
ResizablePanel mit resizable=false (flex-1)
- Rechte Spalte:
ResizablePanel mit resizable=false oder handleSide="left"
- Drag-Handle auf der rechten Kante der linken Spalte
PluginToolbar
Jede Plugin-Seite registriert Aktionen über den usePluginToolbarStore:
- Toolbar-Items werden nach
group gruppiert mit Trennern zwischen Gruppen.
- Button-Labels sind auf Mobile (
hidden sm:inline) ausgeblendet, Icons bleiben sichtbar.
- Toolbar-Höhe:
min-h-[43px], Hintergrund bg-white, Border-Bottom border-secondary-200.
Modal-Dialoge
Für Formulare, Bestätigungen und Dialoge:
| Size |
max-width |
Verwendung |
sm |
max-w-md |
Bestätigungsdialoge |
md |
max-w-lg |
Einfache Formulare |
lg |
max-w-2xl |
Komplexe Formulare, Edit-Dialoge |
xl |
max-w-4xl |
Große Formulare, Multi-Step |
ConfirmDialog für destruktive Aktionen (Löschen, Entfernen).
- Focus-Trap: Fokus wird beim Öffnen auf erstes fokussierbares Element gesetzt, beim Schließen auf ursprüngliches Element zurückgegeben.
- Escape-Taste schließt Modal (sofern
closeOnEscape=true).
- Backdrop-Klick schließt Modal (sofern
closeOnBackdrop=true).
Settings-Layout
Settings-Seiten verwenden einen Tree-Navigator links und das Formular rechts:
4. Komponenten-Referenz
Button
| Prop |
Typ |
Default |
Beschreibung |
variant |
'primary' | 'secondary' | 'danger' | 'ghost' |
'primary' |
Visuelle Variante |
size |
'sm' | 'md' | 'lg' |
'md' |
Größe |
isLoading |
boolean |
false |
Zeigt Spinner, deaktiviert Button |
icon |
ReactNode |
— |
Icon links vom Text |
fullWidth |
boolean |
false |
width: 100% |
- Alle Buttons haben
min-h-touch (44px) für Touch-Accessibility.
focus-visible:ring-2 für Tastatur-Navigation.
motion-safe:duration-200 für Übergänge (respektiert prefers-reduced-motion).
Card
| Prop |
Typ |
Beschreibung |
title |
string |
Card-Header-Titel |
description |
string |
Subtitel im Header |
actions |
ReactNode |
Aktionen rechts im Header |
footer |
ReactNode |
Footer-Bereich (bg-secondary-50) |
- Hintergrund:
bg-white, Border: border-secondary-200, Radius: rounded-lg, Shadow: shadow-sm.
- Body-Padding:
px-6 py-4, Footer-Padding: px-6 py-3.
Badge
| Variant |
Verwendung |
default |
Neutrale Tags |
primary |
Primäre Zustände |
success |
Aktiv, bestätigt, online |
warning |
Ausstehend, Warnung |
danger |
Fehler, inaktiv, abgelaufen |
info |
Info, KI-Vorschläge |
secondary |
Sekundäre Tags |
dot prop zeigt einen farbigen Punkt links an.
- Größe:
text-xs, px-2.5 py-0.5, rounded-full.
Input / Select
focus:ring-2 focus:ring-primary-500 bei Fokus.
- Error-State:
border-danger-500, text-danger-900.
aria-invalid, aria-describedby für Accessibility.
min-h-touch (44px) für Touch-Targets.
- Label:
text-sm font-medium text-secondary-700.
Table / DataGrid
- Verwendet TanStack Table für Sortierung, Filterung, Pagination.
aria-label auf sortierbare Headers.
- Zebra-Stiping optional:
even:bg-secondary-50.
Toast
- Wird nach jeder CRUD-Aktion verwendet (Erfolg/Fehler).
- Auto-Dismiss nach 5 Sekunden.
- Position: Top-Right (Desktop), Top (Mobile).
EmptyState
- Verwendet wenn Liste leer ist.
- Icon groß zentriert, Titel + Beschreibung, optional Aktion.
Skeleton
- Verwendet während Daten laden.
animate-pulse Animation.
- Respektiert
prefers-reduced-motion.
5. Spacing & Sizing
Padding
| Element |
Padding |
| Card Body |
px-6 py-4 |
| Card Footer |
px-6 py-3 |
| Panel |
p-4 |
| Modal Body |
p-6 |
| Input |
px-3 py-2 |
Gap
| Verwendung |
Gap |
| Button-Gruppen |
gap-2 |
| Form-Sections |
gap-4 |
| Spalten / Panels |
gap-6 |
| Toolbar-Items |
gap-1 |
Border-Radius
| Token |
Wert |
Verwendung |
rounded-sm |
0.375rem |
Badges, kleine Elemente |
rounded-md |
0.5rem |
Inputs, Buttons, Panels (Standard) |
rounded-lg |
0.75rem |
Cards, Modals |
rounded-xl |
1rem |
Große Container |
rounded-full |
9999px |
Badges, Avatars |
Shadow
| Token |
Verwendung |
shadow-sm |
Cards, Panels |
shadow-md |
Dropdowns, Popovers |
shadow-lg |
Modals, Dialoge |
6. Accessibility
Pflicht-Regeln
- Focus-Ring: Alle interaktiven Elemente haben
focus-visible:ring-2 focus-visible:ring-primary-500.
- Touch-Targets: Mindestens 44×44px (
min-h-touch min-w-touch).
- ARIA-Labels: Dekorative SVGs erhalten
aria-hidden="true". Interaktive Elemente ohne sichtbaren Text erhalten aria-label.
- Screen Reader:
sr-only Klasse für Text nur für Screen Reader. sr-only-focusable für Skip-Links.
- Reduced Motion:
motion-safe: und motion-reduce: Präfixe verwenden. prefers-reduced-motion Media Query wird respektiert.
- Tastatur-Navigation: Tab-Reihenfolge folgt visueller Reihenfolge. Escape schließt Modals/Dropdowns.
- Farbkontrast: Mindestens 4.5:1 für Body-Text, 3:1 für große Texte und UI-Komponenten.
Implementierte Patterns
focus-ring Klasse: focus-visible:ring-2 focus-visible:ring-primary-500
btn-touch Klasse: min-h-touch min-w-touch (44px)
sr-only und sr-only-focusable Klassen
prefers-reduced-motion Media Query
aria-hidden="true" auf dekorativen Icons
aria-label auf Icon-Only-Buttons
aria-busy="true" auf ladenden Buttons
aria-invalid und aria-describedby auf Inputs mit Fehlern
7. Plugin-UI-Patterns
Neue Plugin-Seite — Checkliste
- 3-Spalten-Layout verwenden (wenn anwendbar): Tree | Liste | Detail
- PluginToolbar registrieren: Create, Import, Export, Search als Toolbar-Items
- Plugin-Settings als eigene Settings-Sub-Seite (Settings-Tree-Navigation)
- Detail-Tabs für Entity-Detail (z.B. "Dateien", "Verlauf", "Notizen")
- EmptyState wenn keine Daten vorhanden
- Skeleton/LoadingState während Daten laden
- Toast nach jeder CRUD-Aktion (Erfolg/Fehler)
- ConfirmDialog vor destruktiven Aktionen
- i18n — alle Texte über
useTranslation() (DE/EN)
- Dark Mode — alle Komponenten müssen in Light und Dark funktionieren
Plugin-Toolbar Registrierung
i18n
- Alle Texte über
useTranslation() Hook.
- Übersetzungen in
src/i18n/locales/de.json und src/i18n/locales/en.json.
- Keys nach Plugin-Präfix:
myplugin.actions.create, myplugin.search, etc.
- Ca. 750 Keys pro Sprache aktuell.
8. Do's & Don'ts
Do's
- ✅ Bestehende UI-Komponenten aus
components/ui/ verwenden
- ✅
clsx für bedingte Klassen verwenden
- ✅
lucide-react Icons verwenden (keine inline SVGs)
- ✅
date-fns für Datumsformatierung verwenden
- ✅ Zustand-Stores für State Management verwenden
- ✅ TanStack Query für API-Calls verwenden
- ✅
min-h-touch (44px) für alle interaktiven Elemente
- ✅
focus-visible:ring-2 für Tastatur-Accessibility
- ✅
motion-safe: / motion-reduce: für Animationen
- ✅ Toast nach jeder CRUD-Aktion anzeigen
- ✅ ConfirmDialog vor jeder destruktiven Aktion
- ✅ EmptyState für leere Listen
- ✅ Skeleton für Lade-Zustände
Don'ts
- ❌ Keine inline SVGs — immer
lucide-react verwenden
- ❌ Keine
Date.parse() oder new Date() Formatierung — date-fns verwenden
- ❌ Keine hardcoded Farben — Tailwind Design Tokens verwenden
- ❌ Keine
alert() oder confirm() — Toast und ConfirmDialog verwenden
- ❌ Keine CSS-Module oder styled-components — Tailwind-Klassen verwenden
- ❌ Keine
useEffect für State-Management — Zustand-Stores verwenden
- ❌ Keine direkten
fetch() Calls — TanStack Query Hooks verwenden
- ❌ Keine
any Types — TypeScript-Interfaces definieren
- ❌ Keine deutschen Strings im Code — i18n-Keys verwenden
- ❌ Keine
px- Werte für Touch-Targets unter 44px
- ❌ Keine
display: none für Accessibility-relevante Elemente — sr-only verwenden
9. Code-Beispiele
Beispiel: Plugin-Seite mit 3-Spalten-Layout
Beispiel: Formular mit Validation
10. Datei-Struktur
Diese Richtlinien sind verbindlich für alle Frontend-Entwicklung an LeoCRM.