MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 1m32s
Corner counters on tabs (header, task lists, lists, workspace) sat on the tab's top border and close to the text; now -top-0.5 -right-2 with pr-3 on the label. The mobile bottom bar keeps its icon placement. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
71 lines
5.8 KiB
Markdown
71 lines
5.8 KiB
Markdown
# UI-Muster
|
||
|
||
Wiederkehrende Bedienelemente, die überall gleich aussehen und sich gleich verhalten. Wer eines davon neu braucht, nimmt die vorhandene Komponente und baut keine eigene Variante.
|
||
|
||
## Personen suchen (Type-to-Search)
|
||
|
||
Komponente: [UserAutocomplete.tsx](../frontend/src/features/UserAutocomplete.tsx)
|
||
|
||
Eingesetzt beim Teilen (`UnifiedShareModal`), beim Hinzufügen zu Gruppen (`GroupsView`) und beim Zuweisen von Aufgaben (`TaskDetailModal`).
|
||
|
||
- **Keine Liste vorab:** Solange das Feld leer ist, erscheint nichts, auch nicht beim Reinklicken. Kein Dropdown mit allen Personen.
|
||
- **Erst beim Tippen** erscheinen Treffer direkt unter dem Feld, **höchstens 3** (`MAX_RESULTS`). Gesucht wird in Anzeigename, `@Benutzername` und E-Mail.
|
||
- Der **erste Treffer ist vorausgewählt**: Tippen + Enter übernimmt ihn. Pfeiltasten wechseln, Escape schließt.
|
||
- Bereits gewählte oder freigegebene Personen werden über `excludeUserIds` ausgeblendet.
|
||
- **Einzelauswahl** (Teilen, Gruppen): `selectedUser` setzen; das Feld zeigt dann die gewählte Person mit ×.
|
||
- **Mehrfachauswahl** (Aufgaben zuweisen): `selectedUser={null}` lassen und in `onSelectUser` zur Liste hinzufügen. Die Gewählten stehen als Chips (Avatar, Name, ×) über dem Feld, das Feld bleibt für die nächste Suche frei.
|
||
|
||
## Profilbilder als Stapel
|
||
|
||
Komponente: [AvatarStack.tsx](../frontend/src/components/AvatarStack.tsx) (nutzt `UserAvatar`)
|
||
|
||
- Kleine runde Profilbilder, **leicht überlappend**, **höchstens 3**. Weitere Personen erscheinen als monochromer Kreis „+n“.
|
||
- Ohne Profilbild zeigt `UserAvatar` die Initialen.
|
||
- `ringClass` bekommt die Farbe der Fläche dahinter (meist `ring-[var(--bg-panel)]` oder `ring-[var(--bg-app)]`), damit die Kreise sauber getrennt sind.
|
||
- Größen: `xxs` (16 px) in Tabs, Kanban-Karten und Listeneinträgen, `xs` (20 px) in Aufgabenzeilen und Kopfzeilen.
|
||
- **Kein Hover-Effekt** im Stapel selbst. Einzige Ausnahme ist die Anwesenheit in Notizen ([PresenceAvatars.tsx](../frontend/src/features/workspace/PresenceAvatars.tsx)): Dort zeigt Hover oder Tastaturfokus die Liste „Gerade online“.
|
||
|
||
| Ort | Wer wird gezeigt |
|
||
|---|---|
|
||
| Notiz-Kopfzeile | wer die Notiz gerade geöffnet hat (Profilbilder aus `/users/directory`) |
|
||
| Tabs der Aufgabenlisten und Listen | alle mit Zugriff außer mir (`members`) |
|
||
| Aufgabenzeile und Kanban-Karte | zugewiesene Personen (nur in geteilten Listen) |
|
||
| Eintrag einer geteilten Liste | wer ihn hinzugefügt hat (`createdBy`); ältere Einträge ohne Autor zeigen nichts |
|
||
|
||
## Schalter
|
||
|
||
Komponente: [ToggleSwitch.tsx](../frontend/src/components/ToggleSwitch.tsx)
|
||
|
||
- Ein/Aus-Einstellungen sind immer Schalter, keine Checkbox-Haken (Einrichtung, Admin-Bereich).
|
||
- Text links (Titel, darunter eine kurze Erklärung in `text-muted`), Schalter rechts.
|
||
|
||
## Kleine Dialoge (Anlegen, Umbenennen)
|
||
|
||
Komponente: [FormSheet.tsx](../frontend/src/components/FormSheet.tsx), Tastatur-Abstand über [useKeyboardInset.ts](../frontend/src/lib/useKeyboardInset.ts)
|
||
|
||
- **Handy:** Bottom-Sheet über die volle Breite, das direkt über der Bildschirmtastatur sitzt (der Abstand kommt aus `visualViewport`), Griff oben, Felder und Buttons mindestens 44 px hoch, Eingaben in 16 px (sonst zoomt iOS), Abbrechen/Erstellen nebeneinander über die ganze Breite.
|
||
- **Desktop:** zentriertes Fenster, oder mit `anchor` neben der Klickposition (z. B. „Neuer Ordner“ im Explorer).
|
||
- Escape und Klick auf den Hintergrund schließen. Genutzt für neue Aufgabenliste, neue Einkaufsliste und neuen Ordner; das Emoji-Sheet nutzt denselben Tastatur-Abstand.
|
||
|
||
## Zähler
|
||
|
||
Komponente: [CountBadge.tsx](../frontend/src/components/CountBadge.tsx), CSS-Klassen `count-badge*` in [index.css](../frontend/src/index.css). Es gibt keine anderen Zähler-Stile mehr.
|
||
|
||
- **Form:** runder Kreis, mindestens 16 px, ab 100 als „99+“ (der Screenreader liest die echte Zahl). Bei 0 ausgeblendet, außer mit `showZero` (z. B. Mitgliederzahl, mobiles Menü).
|
||
- **Farbe (`variant`):**
|
||
- `accent`: Hier wartet etwas auf dich. Navigationsleiste: Triage (Inbox), Aufgaben (offene Aufgaben), Listen (offene Einträge aller eigenen und geteilten Listen). Workspace hat keinen Zähler.
|
||
- `muted` (Standard): reine Anzahl. Tabs der Aufgabenlisten und Listen, Organisationen, mobiles Menü.
|
||
- Beide kommen aus den Theme-Variablen (`--accent-primary`/`--text-on-accent` bzw. `--text-muted`/`--bg-panel`) und passen sich damit jedem Theme an.
|
||
- **Position (`position`):**
|
||
- `corner`: Benachrichtigungs-Badge oben rechts am nächsten `relative` Elternelement, mit Ring in der Seitenfarbe. In der Navigation und an den Tabs sitzt er **auf dem Text**: der Text steht in einem `relative inline-flex`-Span (mit `pr-3`, solange ein Zähler da ist), der Kreis bekommt `-top-0.5 -right-2`, damit er die obere Tab-Linie nicht anschneidet und nicht am Text klebt. In der mobilen Leiste sitzt er am Icon (`-top-1.5 -right-2.5`).
|
||
- `inline`: im Textfluss.
|
||
- Zahlen im mobilen Menü (`MobileActionContext`, `badge: number`) werden automatisch als `CountBadge` gezeigt; Text-Badges wie „2 aktiv“ bleiben Textmarken.
|
||
- **Wichtig für neue Klassen:** Tailwind entfernt Klassen aus `@layer components`, die nicht wörtlich im Code stehen. Klassennamen deshalb nie zusammensetzen (`count-badge-${variant}`), sondern ausschreiben.
|
||
|
||
## Ladebildschirm & Statusleiste
|
||
|
||
- `manifest.json`: `name` „MindSift“ (kurz, der Slogan steht in `description`), `background_color` und `theme_color` `#2563eb` – Android baut daraus den Splash-Screen.
|
||
- `index.html` enthält in `#root` einen reinen HTML-Platzhalter (vollflächig Blau, Logo in der Mitte, kein Text). React ersetzt ihn beim ersten Rendern, dazwischen blitzt nichts Weißes auf.
|
||
- `meta theme-color` startet blau und wird von [`theme.ts`](../frontend/src/lib/theme.ts) nach dem Start und bei jedem Theme-Wechsel auf `--bg-app` des aktiven Themes gesetzt, damit die Statusleiste zum Header passt.
|
||
|