Komponentenseite auf ihren tatsaechlichen Zweck schaerfen
Sie war als "Referenz fuer den Einbau" ausgeschildert. Das trifft es nicht: Wer den Prototyp einbaut, liest Code und Doku und kann sich keine gerenderte Seite ansehen — die Datei-Pfade und DESIGN-SYSTEM.md tun diese Arbeit ohnehin. Nuetzlich ist die Seite fuer die Abstimmung mit Menschen: Auf den Analyse-Seiten sieht man von jedem Baustein immer nur den Zustand, den die Daten gerade hergeben. Neu ausgeschildert, und die fehlenden Zustaende ergaenzt: - Seitenzustaende (laedt / leer / Fehler). In HiveGrid sind alle fuenf VMState-Zustaende Pflicht, im Prototyp ist keiner davon je zu sehen, weil die Demo-Daten immer liefern. Gestaltet werden muessen sie trotzdem — "laedt", "nichts gefunden" und "kaputt" sind drei verschiedene Aussagen. - Dashboard-Kacheln: Begruessung, WidgetKachel, reservierte Kachel. Das Dashboard benutzt nicht ChartCard, sondern einen eigenen Rahmen; bisher war der in der Galerie gar nicht vertreten. Zwei Fehler dabei gefunden und behoben: - Die Regelliste nannte noch den dunklen Tooltip (#393939). Seit Carbon v11 ist er hell (#ffffff auf #161616); im Code war das laengst umgestellt, auf dieser Seite nicht. Eine Referenzseite, die eine ueberholte Regel behauptet, ist schlimmer als keine. - Die Abschnittstexte beginnen mit einem Dateipfad, und ein Pfad ist ein Wort ohne Trennstelle. Bei 375 px lief "features/dashboard/components/layout/SeitenZustand.tsx" neun Pixel ueber den Rand — von verify:layout gefunden. Die Regel zu den Kartenhoehen aus dem letzten Commit steht jetzt auch hier. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QPeZNwSeU7qG3RRCwaxEZX
This commit is contained in:
1 parent
ffbe70aede
commit
885c7b9609
2 files changed
+107
-6
No files matched your search
@@ -67,8 +67,15 @@ export const NAV_GRUPPEN: NavGruppe[] = [
|
||||
|
||||
/**
|
||||
* Unterer Bereich, durch einen Trenner abgesetzt — wie in der Software.
|
||||
* Hier steht nur, was zum Prototyp gehört: die Bausteingalerie für die
|
||||
* Entwicklung. Sie ist kein Produktfeature und wandert beim Einbau nicht mit.
|
||||
*
|
||||
* Hier steht nur, was zum Prototyp gehört: die Bausteingalerie. Sie ist für
|
||||
* die **Abstimmung** da, nicht für die Umsetzung — sie zeigt jeden Baustein in
|
||||
* allen Zuständen, auch in denen, die die Demo-Daten nie erzeugen (negativer
|
||||
* Trend, leer, Fehler, „kleiner ist besser"). Wer den Prototyp einbaut,
|
||||
* braucht sie nicht: Dafür sind die Datei-Pfade und `docs/DESIGN-SYSTEM.md`
|
||||
* maßgeblich.
|
||||
*
|
||||
* Kein Produktfeature, wandert beim Einbau nicht mit.
|
||||
*/
|
||||
export const NAV_SEKUNDAER: NavEintrag[] = [
|
||||
{
|
||||
|
||||
@@ -16,6 +16,11 @@ import { AuslastungsBalken } from "../components/charts/AuslastungsBalken";
|
||||
import { ChartLeer } from "../components/charts/ChartLeer";
|
||||
import { ChartLegende } from "../components/charts/ChartLegende";
|
||||
import { AuftragBadge, RechnungBadge } from "../components/tables/StatusBadge";
|
||||
import { SeitenZustand } from "../components/layout/SeitenZustand";
|
||||
import { WidgetKachel } from "../components/dashboard/WidgetKachel";
|
||||
import { ReservierteKachel } from "../components/dashboard/ReservierteKachel";
|
||||
import { Begruessung } from "../components/dashboard/Begruessung";
|
||||
import type { VMState } from "../view-models";
|
||||
import {
|
||||
KATEGORIE_FARBEN,
|
||||
MAX_KATEGORIEN,
|
||||
@@ -54,14 +59,15 @@ export function KomponentenSeite() {
|
||||
<>
|
||||
<PageHeader
|
||||
titel="Komponenten & Regeln"
|
||||
beschreibung="Alle Bausteine dieses Prototyps an einem Ort — als Referenz für den Einbau in die Software."
|
||||
beschreibung="Jeder Baustein einzeln und in allen Zuständen — die Seite zum Draufzeigen in der Abstimmung."
|
||||
/>
|
||||
|
||||
<PageContainer>
|
||||
<Abschnitt
|
||||
titel="Warum diese Seite existiert"
|
||||
text="Der Prototyp ist eine Gestaltungsvorlage, kein Produkt. Diese Seite zeigt jeden Baustein isoliert, damit beim Einbau klar ist, welche Komponente wofür gedacht ist und welche Regeln dahinterstehen. Datei-Pfade stehen jeweils darunter."
|
||||
text="Auf den Analyse-Seiten sieht man von jedem Baustein immer nur den einen Zustand, den die Daten gerade hergeben — die Kennzahlenkarte mit steigendem Trend, das Diagramm mit Werten darin. Die anderen Zustände existieren trotzdem und müssen mitgestaltet werden. Diese Seite zeigt sie alle nebeneinander, damit man in der Abstimmung darauf zeigen kann, ohne erst einen Filter zu suchen, der den passenden Fall herstellt."
|
||||
/>
|
||||
<Hinweis text="Diese Seite ist kein Produktfeature. Sie gehört weder zu Dashboard noch zu Analytics, steht in der Seitenleiste unter dem Trenner und wandert beim Einbau nicht mit. Für die Umsetzung selbst sind die Datei-Pfade unter jedem Abschnitt und docs/DESIGN-SYSTEM.md maßgeblich — beides steht im Repo und braucht diese Seite nicht." />
|
||||
|
||||
<ChartCard
|
||||
id="komp-farben"
|
||||
@@ -272,6 +278,87 @@ export function KomponentenSeite() {
|
||||
</ChartCard>
|
||||
</div>
|
||||
|
||||
<Abschnitt
|
||||
titel="Seitenzustände"
|
||||
text="features/dashboard/components/layout/SeitenZustand.tsx — die vier Zustände außer „fertig“. Sie sind in HiveGrid Pflicht (VMState: idle · loading · ready · empty · error) und im laufenden Prototyp nie zu sehen, weil die Demo-Daten immer liefern. Gestaltet werden müssen sie trotzdem: „lädt“, „nichts gefunden“ und „kaputt“ sind drei verschiedene Aussagen und dürfen nicht gleich aussehen."
|
||||
/>
|
||||
<div className="grid grid-cols-1 gap-4 xl:grid-cols-3">
|
||||
{([
|
||||
["Lädt", { status: "loading" } as VMState<unknown>],
|
||||
["Leer — Filter schneiden alles weg", { status: "empty" } as VMState<unknown>],
|
||||
[
|
||||
"Fehler",
|
||||
{
|
||||
status: "error",
|
||||
error: { messageKey: "Zeitüberschreitung beim Laden der Kennzahlen" },
|
||||
} as VMState<unknown>,
|
||||
],
|
||||
] as const).map(([titel, vm]) => (
|
||||
<div key={titel} className="flex flex-col gap-2">
|
||||
<span className="text-[12px] font-medium text-text-neutral-tertiary">{titel}</span>
|
||||
{/* -mx-4: SeitenZustand bringt seinen eigenen Seitenrand mit, weil
|
||||
er im Normalfall die ganze Seite füllt. Hier steht er in einer
|
||||
Rasterspalte und braucht ihn nicht.
|
||||
|
||||
Ohne zusätzlichen Rahmen: Die Komponente hat bereits eine
|
||||
gestrichelte Kante. Ein Kasten darum wäre ein zweiter Rahmen
|
||||
und zeigte den Baustein anders, als er in der Anwendung
|
||||
aussieht. */}
|
||||
<div className="-mx-4 sm:-mx-6">
|
||||
<SeitenZustand vm={vm} />
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<Abschnitt
|
||||
titel="Dashboard-Kacheln"
|
||||
text="features/dashboard/components/dashboard/ — das Dashboard benutzt nicht ChartCard, sondern einen eigenen Kachelrahmen. Gleiche Kante, gleiche Abstände, aber ohne das ⋯-Menü von Analytics; dafür mit Domänen-Icon, eigenem Zeitraum und Absprung. Der Grund steht in docs/SCOPE-ANALYTICS-DASHBOARD.md: In Analytics gilt ein Filter für alle Karten, im Dashboard trägt jede Kachel ihren eigenen."
|
||||
/>
|
||||
{/* Wie bei den Seitenzuständen: Die Begrüßung trägt ihren eigenen
|
||||
Seitenrand, weil sie im Dashboard direkt auf der Seite steht. In der
|
||||
Galerie liegt sie schon im Innenabstand des Containers und wäre
|
||||
sonst doppelt eingerückt. */}
|
||||
<div className="-mx-4 sm:-mx-6">
|
||||
<Begruessung
|
||||
anrede="Guten Tag"
|
||||
name="Dejan"
|
||||
datum="Donnerstag, 30. Juli"
|
||||
rolle="Geschäftsführung"
|
||||
lage="2 Punkte brauchen heute Ihre Aufmerksamkeit."
|
||||
kritisch
|
||||
/>
|
||||
</div>
|
||||
<div className="grid grid-cols-1 gap-4 lg:grid-cols-3">
|
||||
<WidgetKachel
|
||||
titel="Umsatz nach Gewerk"
|
||||
untertitel="Zahlungseingang der letzten 30 Tage"
|
||||
hinweis="Der Zeitraum steht im Kopf, weil es auf dem Dashboard keinen seitenweiten Filter gibt."
|
||||
domaene="finance"
|
||||
zeitraum="30_tage"
|
||||
absprung="/analytics/finanzen"
|
||||
className="lg:col-span-2"
|
||||
>
|
||||
<BalkenHorizontal
|
||||
daten={BEISPIEL_KATEGORIEN.slice(0, 5)}
|
||||
formatWert={formatEuroKompakt}
|
||||
einfarbig={false}
|
||||
/>
|
||||
</WidgetKachel>
|
||||
|
||||
<ReservierteKachel
|
||||
bereich={{
|
||||
key: "hr",
|
||||
domaene: "hr",
|
||||
titel: "HR-Anträge",
|
||||
beschreibung: "Offene Urlaubs- und Zeitkorrekturanträge.",
|
||||
icon: "UserCheck",
|
||||
quelle: "HR-Hub",
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<Hinweis text="Die reservierte Kachel zeigt bewusst keine Zahl. „2 neue Anträge“ aus erfundenen Daten liest sich in einer Abnahme wie eine fertige Funktion — und irgendwann fragt jemand, warum die Zahl nie hochzählt. Die gestrichelte Kante sagt dasselbe ehrlicher: Hier kommt etwas hin, die Fläche ist dafür da." />
|
||||
|
||||
<ChartCard
|
||||
id="komp-badges"
|
||||
titel="Status-Kennzeichnung"
|
||||
@@ -315,12 +402,13 @@ export function KomponentenSeite() {
|
||||
{[
|
||||
"Nur horizontale Gridlines in #e0e0e0. Vertikale Linien lenken vom Verlauf ab.",
|
||||
"Achsenbeschriftungen 12 px in #525252, keine Tick-Marks, Achsenlinie #8d8d8d.",
|
||||
"Ein Tooltip für alle Charts: dunkle Fläche #393939, weißer Text, kein Doppelpunkt.",
|
||||
"Ein Tooltip für alle Charts: weiße Fläche #ffffff, Text #161616, Schatten statt Rahmen — seit Carbon v11 hell, nicht mehr dunkel.",
|
||||
"Maximal fünf Kategorien je Chart, alles darüber wird zu „Sonstige“ zusammengefasst.",
|
||||
"Balkenabstand mindestens halbe Balkenbreite; Balken nie breiter als 48 px.",
|
||||
"Zahlen rechtsbündig und in Tabellenziffern, Text linksbündig.",
|
||||
"Karten: 16 px Innenabstand, 16 px Abstand zwischen Karten — innen nie größer als außen.",
|
||||
"Jede Karte braucht einen Leerzustand. Filter können jedes Chart leer laufen lassen.",
|
||||
"Karten einer Zeile nur strecken, wenn sie dieselbe Bauart haben. Ein Diagramm mit fester Höhe neben einer Balkenliste bleibt oben bündig — sonst wird aus einer Karte mit einem Balken eine 427 px hohe Fläche.",
|
||||
].map((regel) => (
|
||||
<li key={regel} className="flex gap-2.5 text-[13px] leading-relaxed text-text-neutral-secondary">
|
||||
<span className="mt-1.5 h-1.5 w-1.5 flex-none rounded-full bg-neutral-400" />
|
||||
@@ -338,7 +426,13 @@ function Abschnitt({ titel, text }: { titel: string; text: string }) {
|
||||
return (
|
||||
<div className="flex flex-col gap-1 pt-2">
|
||||
<h2 className="text-[15px] font-semibold text-text-neutral-primary">{titel}</h2>
|
||||
<p className="max-w-3xl text-[13px] leading-relaxed text-text-neutral-tertiary">{text}</p>
|
||||
{/* break-words: Diese Absätze beginnen mit einem Dateipfad, und ein Pfad
|
||||
ist ein einziges Wort ohne Trennstelle. Bei 375 px lief
|
||||
"features/dashboard/components/layout/SeitenZustand.tsx" neun Pixel
|
||||
über den Rand. */}
|
||||
<p className="max-w-3xl break-words text-[13px] leading-relaxed text-text-neutral-tertiary">
|
||||
{text}
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user