61 lines
3 KiB
Markdown
61 lines
3 KiB
Markdown
# Design-System (Theme-Basis, F6 / Issue #31)
|
|
|
|
Stand: Basis. Konkrete Komponenten (Formularfelder, Banner, Spiel-Kachel usw.) folgen in U1.
|
|
Code: `app/lib/core/theme/` (`app_theme.dart`, `app_spacing.dart`), Tests: `app/test/core/theme/`.
|
|
|
|
## Theme
|
|
|
|
- Material 3, `AppTheme.light()` und `AppTheme.dark()`; `ShuffleApp` nutzt `ThemeMode.system`.
|
|
- Farben: `ColorScheme.fromSeed` mit Seed `#4F46E5` (Indigo). Einzige Abweichung: `outline` ist
|
|
etwas dunkler (hell `#6B6A7A`) bzw. heller (dunkel `#9A99AB`), damit Feldrahmen mindestens 3:1 erreichen.
|
|
- Keine Farbwerte in Widgets: immer `Theme.of(context).colorScheme` und `textTheme` verwenden.
|
|
|
|
## Kontraste (WCAG 2.1 AA)
|
|
|
|
Geprüft im Test `app_theme_test.dart` für Hell und Dunkel. Text mindestens 4.5:1, Bedienelemente
|
|
(Rahmen, Fokusring, Fehlerrahmen) mindestens 3:1.
|
|
|
|
| Paar | Hell | Dunkel |
|
|
|---|---|---|
|
|
| onSurface / surface | 16.3 | 14.4 |
|
|
| onSurfaceVariant / surface | 8.9 | 10.9 |
|
|
| onSurfaceVariant / Feldfüllung | 7.2 | 7.3 |
|
|
| onPrimary / primary (Buttons) | 6.5 | 7.7 |
|
|
| Fehlertext (error) / Feldfüllung | 5.0 | 7.3 |
|
|
| SnackBar-Text / SnackBar-Fläche | 11.5 | 10.1 |
|
|
| SnackBar-Aktion / SnackBar-Fläche | 7.7 | 5.0 |
|
|
| Feldrahmen (outline) / Feldfüllung | 4.1 | 4.4 |
|
|
| Fokusring (primary) / Feldfüllung | 5.0 | 7.2 |
|
|
|
|
Regeln: Informationen nie nur über Farbe vermitteln (Fehler = Text + Rahmen + Icon). Neue Farbpaare
|
|
müssen in den Test aufgenommen werden. Deaktivierte Elemente sind von der Kontrastpflicht ausgenommen.
|
|
|
|
## Touch-Ziele und Fokus
|
|
|
|
- Mindestgröße 48 x 48 dp für alle Buttons und Icon-Buttons (`minimumSize`), `MaterialTapTargetSize.padded`,
|
|
`VisualDensity.standard`. Nicht auf `compact` verkleinern.
|
|
- Tastaturfokus (Web/Desktop): Buttons und Textfelder zeigen einen 3 dp breiten Rahmen in `primary`.
|
|
- Icons ohne Text brauchen `tooltip` bzw. `Semantics(label: ...)`; Bilder ein Label oder `excludeSemantics`.
|
|
- Text muss bis 200 % Skalierung ohne Abschneiden funktionieren (kein fixes Höhen-Layout für Text).
|
|
|
|
## Typografie
|
|
|
|
Material-2021-Skala (`textTheme`), Farbe `onSurface`. Überschriften `headline*`/`title*`, Fließtext `bodyLarge/Medium`,
|
|
Hinweise `bodySmall` (`onSurfaceVariant`). Schriftgrößen nie hart codieren.
|
|
|
|
## Abstände, Radien, Breakpoints (`app_spacing.dart`)
|
|
|
|
| Token | Wert (dp) |
|
|
|---|---|
|
|
| `AppSpacing` xxs / xs / sm / md / lg / xl / xxl / xxxl | 2 / 4 / 8 / 12 / 16 / 24 / 32 / 48 |
|
|
| `AppRadius` sm / md / lg / xl | 8 / 12 / 16 / 28 |
|
|
| Breakpoints (`AppWidthClass`) | kompakt < 600, mittel 600-1023, groß >= 1024 |
|
|
| `AppBreakpoints.maxContentWidth` | 560 (Formulare/Text auf breiten Bildschirmen begrenzen) |
|
|
|
|
`AppSpacing.pagePadding(width)` liefert den Seitenrand je Breitenklasse (16 / 24 / 32). Web darf nicht
|
|
wie eine gestreckte Handy-App wirken: Inhalt zentrieren und auf `maxContentWidth` begrenzen.
|
|
|
|
## Komponenten-Themes in der Basis
|
|
|
|
FilledButton, ElevatedButton, OutlinedButton, TextButton, IconButton, Checkbox, InputDecoration
|
|
(gefüllt, Rahmen 1 dp, Fokus 3 dp, Fehler 2 dp), Card, AppBar, Divider, SnackBar (schwebend, mit Schließen-Icon).
|