@conciso/design-system-mcp 2.3.0 → 2.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/package.json +1 -1
- package/snapshot/manifests/components.json +30 -0
- package/snapshot/manifests/docs.json +1 -9
- package/snapshot/services/addon-docs/mdx/grundlagen-farben.json +18 -0
- package/snapshot/services/addon-docs/mdx/grundlagen-typografie.json +18 -0
- package/snapshot/services/addon-docs/mdx/komponenten-buttons-button.json +18 -0
- package/snapshot/services/addon-docs/mdx/komponenten-cards-teaser--verwendung.json +1 -1
- package/snapshot/services/addon-docs/mdx/komponenten-sektion--/303/274bersicht.json +1 -1
- package/snapshot/services/addon-docs/mdx/komponenten-theme-umschalter--verwendung.json +2 -2
- package/snapshot/services/addon-docs/mdx/marke-bildsprache--/303/274bersicht.json +1 -1
- package/snapshot/services/addon-docs/mdx/marke-markenrad--/303/274bersicht.json +1 -1
- package/snapshot/services/core/story-docs/komponenten-inputs-forms-radio.json +5 -0
- package/src/instructions.mjs +9 -1
- package/snapshot/services/addon-docs/mdx/komponenten-buttons--verwendung.json +0 -18
package/README.md
CHANGED
|
@@ -33,6 +33,7 @@ Beim Verbinden gibt der Server dem Assistenten außerdem feste Regeln mit:
|
|
|
33
33
|
2. Kein eigenes CSS für Design-System-Komponenten, keine erfundenen CSS-Klassen.
|
|
34
34
|
3. Nur Inputs und Outputs verwenden, die `docs-show` liefert. Vorher nachsehen, nie raten.
|
|
35
35
|
4. Bei Fragen zur Einrichtung die Storybook-Seite „Einrichtung“ lesen.
|
|
36
|
+
5. Für Auswahl- und Gestaltungsfragen zusätzlich die Verwendungsguidance der Komponente heranziehen, sonst über `docs-list` die passende „Verwendung“-Seite suchen.
|
|
36
37
|
|
|
37
38
|
Weitere Eigenschaften:
|
|
38
39
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@conciso/design-system-mcp",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.5.0",
|
|
4
4
|
"description": "MCP-Server für Consumer des Conciso Design System, beantwortet docs-list, docs-show und docs-show-story über stdio aus einem mitgelieferten Storybook-Snapshot, ohne Netzzugriff.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -28,6 +28,16 @@
|
|
|
28
28
|
"name": "grundlagen-farben",
|
|
29
29
|
"stories": {
|
|
30
30
|
"$ref": "../services/core/story-docs/grundlagen-farben.json#/components/grundlagen-farben"
|
|
31
|
+
},
|
|
32
|
+
"docs": {
|
|
33
|
+
"grundlagen-farben--verwendung": {
|
|
34
|
+
"id": "grundlagen-farben--verwendung",
|
|
35
|
+
"name": "Verwendung",
|
|
36
|
+
"mdx": {
|
|
37
|
+
"$ref": "../services/addon-docs/mdx/grundlagen-farben.json#/components/grundlagen-farben/docs/grundlagen-farben--verwendung"
|
|
38
|
+
},
|
|
39
|
+
"summary": "# Verwendung Vier Bereichspaletten (Corporate, Angewandte KI, Effektive Software, Wirksame..."
|
|
40
|
+
}
|
|
31
41
|
}
|
|
32
42
|
},
|
|
33
43
|
"grundlagen-typografie": {
|
|
@@ -35,6 +45,16 @@
|
|
|
35
45
|
"name": "grundlagen-typografie",
|
|
36
46
|
"stories": {
|
|
37
47
|
"$ref": "../services/core/story-docs/grundlagen-typografie.json#/components/grundlagen-typografie"
|
|
48
|
+
},
|
|
49
|
+
"docs": {
|
|
50
|
+
"grundlagen-typografie--verwendung": {
|
|
51
|
+
"id": "grundlagen-typografie--verwendung",
|
|
52
|
+
"name": "Verwendung",
|
|
53
|
+
"mdx": {
|
|
54
|
+
"$ref": "../services/addon-docs/mdx/grundlagen-typografie.json#/components/grundlagen-typografie/docs/grundlagen-typografie--verwendung"
|
|
55
|
+
},
|
|
56
|
+
"summary": "# Verwendung Zwei Schriften tragen zwei unterschiedliche Aufgaben. Libre Baskerville (Seri..."
|
|
57
|
+
}
|
|
38
58
|
}
|
|
39
59
|
},
|
|
40
60
|
"komponenten-buttons-button": {
|
|
@@ -46,6 +66,16 @@
|
|
|
46
66
|
},
|
|
47
67
|
"stories": {
|
|
48
68
|
"$ref": "../services/core/story-docs/komponenten-buttons-button.json#/components/komponenten-buttons-button"
|
|
69
|
+
},
|
|
70
|
+
"docs": {
|
|
71
|
+
"komponenten-buttons-button--verwendung": {
|
|
72
|
+
"id": "komponenten-buttons-button--verwendung",
|
|
73
|
+
"name": "Verwendung",
|
|
74
|
+
"mdx": {
|
|
75
|
+
"$ref": "../services/addon-docs/mdx/komponenten-buttons-button.json#/components/komponenten-buttons-button/docs/komponenten-buttons-button--verwendung"
|
|
76
|
+
},
|
|
77
|
+
"summary": "# Verwendung Buttons sind die primäre Aktions-Komponente des Systems: fünf Stilvarianten (..."
|
|
78
|
+
}
|
|
49
79
|
}
|
|
50
80
|
},
|
|
51
81
|
"komponenten-chips-badges-pills-chip": {
|
|
@@ -89,14 +89,6 @@
|
|
|
89
89
|
},
|
|
90
90
|
"summary": "# Barrierefreiheit Kontrastverhältnisse aller Brand-Farben, Tastaturnavigation, ARIA Patte..."
|
|
91
91
|
},
|
|
92
|
-
"komponenten-buttons--verwendung": {
|
|
93
|
-
"id": "komponenten-buttons--verwendung",
|
|
94
|
-
"name": "Verwendung",
|
|
95
|
-
"mdx": {
|
|
96
|
-
"$ref": "../services/addon-docs/mdx/komponenten-buttons--verwendung.json#/components/komponenten-buttons--verwendung/docs/komponenten-buttons--verwendung"
|
|
97
|
-
},
|
|
98
|
-
"summary": "# Verwendung Buttons sind die primäre Aktions-Komponente des Systems: fünf Stilvarianten (..."
|
|
99
|
-
},
|
|
100
92
|
"komponenten-chips-badges-pills--verwendung": {
|
|
101
93
|
"id": "komponenten-chips-badges-pills--verwendung",
|
|
102
94
|
"name": "Verwendung",
|
|
@@ -223,7 +215,7 @@
|
|
|
223
215
|
"mdx": {
|
|
224
216
|
"$ref": "../services/addon-docs/mdx/komponenten-theme-umschalter--verwendung.json#/components/komponenten-theme-umschalter--verwendung/docs/komponenten-theme-umschalter--verwendung"
|
|
225
217
|
},
|
|
226
|
-
"summary": "# Theme-Umschalter · Verwendung
|
|
218
|
+
"summary": "# Theme-Umschalter · Verwendung `docs/index.html` hat für den Theme-Umschalter eine eigene..."
|
|
227
219
|
},
|
|
228
220
|
"seitenmuster-wissensbeitrag--übersicht": {
|
|
229
221
|
"id": "seitenmuster-wissensbeitrag--übersicht",
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"components": {
|
|
3
|
+
"grundlagen-farben": {
|
|
4
|
+
"id": "grundlagen-farben",
|
|
5
|
+
"name": "grundlagen-farben",
|
|
6
|
+
"docs": {
|
|
7
|
+
"grundlagen-farben--verwendung": {
|
|
8
|
+
"id": "grundlagen-farben--verwendung",
|
|
9
|
+
"name": "Verwendung",
|
|
10
|
+
"path": "./src/docs/grundlagen/farben.mdx",
|
|
11
|
+
"title": "Grundlagen/Farben",
|
|
12
|
+
"content": "import { Meta } from '@storybook/addon-docs/blocks';\nimport * as FarbenStories from '../../foundations/colors.stories';\n\n<Meta of={FarbenStories} name=\"Verwendung\" />\n\n# Verwendung\n\nVier Bereichspaletten (Corporate, Angewandte KI, Effektive Software, Wirksame Organisationen) plus Rosé und die Neutrals tragen je eine Tonal-Skala von 50 bis 900 (Live-Swatches in der Story „Paletten“). Diese Seite hält fest, welche Stufe wofür steht, wie Kontrast in beiden Modi funktioniert, und wo Tönung Akzent bleibt statt Standard-Grund zu werden. Kontrast-Schwellen (auf Weiß): AA ab 4,5:1 für Fließtext, AA Large ab 3,0:1 für großen Text (ab 24 px) und UI-Komponenten, AAA ab 7,0:1.\n\n## Farbstufen, wofür?\n\n| Stufe | Verwendungszweck |\n|---|---|\n| `-50` | Tonal Overlay, Chip-Hintergrund, Badge-Hintergrund, Sub-Strip-Background, sehr helle Fläche |\n| `-100` bis `-300` | Dezente UI-Akzente, Media-Hintergründe in Cards, Hero-Gradient, Borders |\n| `-500` | Brand-Akzent: Hero-Gradient, dekorative Flächen, aktive Marker, Icon. **Kein** Button-Background, **kein** Text auf Weiß (Co, KI und WO unterschreiten den Kontrast) |\n| `-700` | Standard für farbigen Text auf Weiß (Co, ES) und Filled-Button-Background (`.btn-co`, `.btn-es`, `.btn-wo`). Erfüllt WCAG AA (≥ 4,5:1). **Ausnahme KI:** KI-700 erreicht nur 4,4:1, für Text und Filled-Button `-800` nehmen (`.btn-ki` nutzt das bereits) |\n| `-800` bis `-900` | Dunkle Kontexte, Text auf Bereichsfarbe (`-500`), Hover-Zustände, Page-End-CTA-Band-Background, KI-Text/-Button (siehe Zeile oben) |\n\n## Semantische Farben\n\n| Token | Wann einsetzen |\n|---|---|\n| `--c-success` | Erfolgreiche Aktionen, OK-Snackbar, Bestätigungs-Badge |\n| `--c-warning` | Hinweise, Beta-Zustände, nicht kritische Warnungen |\n| `--c-error` | Fehler-Snackbar, Validierungsfehler im Formular, Deprecated-Badge |\n| `--tx-primary` | Fließtext, Headlines, UI-Labels. `#333E48`, deutlich über AAA gegen Weiß |\n| `--tx-secondary` | Sekundärer Text: Lead, Sub-Titel, Captions. `var(--n-500)`, AA gegen Weiß |\n| `--tx-muted` | Inhaltlich leise Texte: Eyebrow, Meta, Counter. `#5A7171`, AA gegen Weiß, gegen `n-50` und gegen getönte Hellflächen |\n| `--co-ink` · `--ki-ink` · `--es-ink` · `--wo-ink` | Farbiger Text und farbige Icons, die in **beiden** Modi lesbar bleiben müssen: Light `-700` (KI `-800`, weil KI-700 nur 4,05:1 trägt), Dark `-200` (ES `-100`). Ein fest gesetztes `-700` trägt im Dark nur 3,17:1, ein fest gesetztes `-200` im Light umgekehrt zu wenig, darum **immer das Ink-Token**, nicht die Stufe selbst |\n| `--co-fill` · `--ki-fill` · `--es-fill` · `--wo-fill` | Füllung von Pill und Bereichs-Badge. Im Light identisch mit `--XX-50` (der ruhige Tint mit kräftiger dunkler Schrift). Im Dark eigene, gehobene Werte, weil dort helle Schrift auf dunklem Tint liegt und der Tint sich sonst nicht von der Karte löst |\n| `--co-band` · `--ki-band` · `--es-band` · `--wo-band` | Große Sektionsfläche (Hero, CTA-Band). Im Light identisch mit `--XX-50`. Im Dark ein eigener, dunklerer Wert, damit das Band unter den Karten bleibt statt die Ebenen-Ordnung umzukehren |\n\n## Vier Rollen, ein Bereichston\n\nWCAG verlangt für eine dekorative Fläche nichts, für ein textführendes Bauteil verlangt die Hausregel (CONTRIBUTING § 3) mindestens 1,3:1 gegen den Grund und 10 L\\* Helligkeitsabstand. Deshalb hat jeder Bereichston vier Rollen mit vier Namen: `--XX-50` ruhiger dekorativer Tint (Icon-Kachel, Timeline-Marker, Chip-Hover, Inline-Code), `--XX-fill` textführende Bauteil-Füllung, `--XX-band` große Sektionsfläche, `--XX-ink` farbiger Text.\n\nIm Light sind `--XX-50`, `--XX-fill` und `--XX-band` identisch, dort gibt es zwischen kleiner Füllung und großem Band keinen Konflikt. Im Dark trennen sie sich: eine kleine Füllung (Badge, Pill, Icon-Kachel) muss *heller* sein als ihr Grund, sonst liest sie nicht mehr als Fläche. Ein großes Band (Hero, CTA-Sektion) muss dagegen *dunkler* bleiben als die Karten darauf, sonst kehrt sich die Ebenen-Ordnung um. Bei einer Basisfläche von 17,5:1 gegen Weiß und reinem Schwarz bei 21:1 reicht der verbleibende Spielraum nicht, damit ein einzelner Wert beide Aufgaben trägt.\n\n## Text-Tokens vs. dekorative Neutrals\n\n`--tx-muted` ist für inhaltlich leise, aber AA-konforme Texte gedacht (Eyebrow, Counter, Meta-Angaben). Rein dekorative Elemente (Trenner, Ornament, Disabled-Hintergrund) nutzen direkt das Neutral-Token `var(--n-300)` oder heller, diese sind absichtlich unter AA, weil sie keinen Textinhalt tragen.\n\n**Faustregel:** Soll ein Screenreader den Text vorlesen, mindestens `--tx-muted` verwenden. Ist das Element rein visuell und für Screenreader ausgeblendet (`aria-hidden`, dekorative Border), darf es heller sein.\n\nFarbiger Text oder ein farbiges Icon auf einer hellen `-100`-Kachel (Chip, Häkchen-Kreis, Label-Pille) wird fest auf `--XX-800` gesetzt, **nicht** über `.t-*` beziehungsweise `--XX-ink`. Diese `-100`-Kacheln flippen im Dark nicht mit, sie bleiben hell, damit sie auf dem dunklen Grund sichtbar bleiben. `.t-*`/`--XX-ink` würde dagegen auf den hellen `-200`-Ton kippen, hell auf hell, unsichtbar. `--XX-800` ist in beiden Modi stabil. Entscheidend ist immer, ob der Hintergrund mit dem Theme mitflippt.\n\n## Hintergrundflächen & Rhythmus\n\n- Aufeinanderfolgende Sektionen wechseln im Standard zwischen Weiß (`--bg-surface`) und ruhigem Grau (`--n-50`). Kein hartes `#fff`, das schaltet im Dark Mode nicht mit.\n- **Faustregel: Tönung ist Akzent, nicht Standard-Grund.** Eine Bereichsfläche (`-50`) wirkt als Akzent, etwa als Aktions-Brücke direkt unter dem Hero, die dunkle `-800` als CTA-Band am Seitenende bildet die Gegen-Klammer. Mehrere große getönte Bänder hintereinander lassen die Seite bunt wirken und schwächen die Bereichsfarbe dort, wo sie Bedeutung trägt.\n- **Dark: nur zwei Flächen-Stufen.** Statt Weiß/Grau gibt es im Dark nur `--bg-page` (Basis) und das hellere `--bg-surface`, dazu `--bg-surface-hover` als Hover-Zustand, keine dritte statische Stufe. `n-50`-Sektionen werden im Dark ausnahmslos auf `--bg-surface` gehoben, damit die Tonfolge dieselbe bleibt wie im Light.\n- Kartentragende Sektionen sind dabei kein Sonderfall: Eine gehobene Sektion trifft zwar den Ton ihrer eigenen `bg-surface`-Karten, das passiert im Light auf weißen Sektionen mit weißen Karten genauso. Die Karte liest dort über ihren Rand (`--bd-strong-c`), im Dark deutlich kräftiger als die Haarlinie im Light.\n- Naheliegend wäre, kartentragende Sektionen auf `bg-page` zu lassen, damit die Karten die hellere Stufe bilden. Gemessen über die Beispielseiten kostet das aber den Rhythmus: deutlich mehr verschmolzene Übergänge zwischen benachbarten Sektionen als mit der gehobenen Fläche.\n- Ein heller `-100`-Rahmen auf einer getönten Fläche ist im Light ein zarter gleichfarbiger Whisper, `-100` flippt aber nicht mit dem Theme. Im Dark wird daraus eine grelle helle Linie auf dunkler Tönung. Trennlinien und Rahmen getönter Flächen im Dark deshalb auf den neutralen `var(--bd)` heben, nie eine `-100`-Stufe direkt verwenden.\n- Umgekehrt bei neutralem `--n-100`: Im Light passt `1px solid var(--n-100)` zu dem, was `--bd` auflöst. Im Dark wird `--n-100` selbst zu einer dunklen Fläche, der Rahmen verschwindet praktisch. Für Rahmen und Trennlinien deshalb ausnahmslos `var(--bd)` beziehungsweise `var(--bd-strong)` verwenden, nie eine `-100`-Stufe direkt.\n\n## Dos & Don'ts\n\n**Tun**\n\n- Bereichsfarbe `-700` für farbigen Text auf Weiß (Co, ES und WO erfüllen damit WCAG AA). **Ausnahme KI:** `-700` erreicht nur 4,4:1, für Text und Filled-Button auf Weiß `-800` verwenden\n- Stufe `-50` für Hintergründe und Tonal Overlays, sie wirkt, ohne zu dominieren\n- Semantische Tokens `--c-success`, `--c-warning`, `--c-error` konsequent für Status einsetzen\n- Jede Seite gehört zu genau einer Brand Area, deren Farbpalette durchgängig verwenden\n- Neutrals (`--tx-primary`, `--tx-secondary`) für Fließtext, Bereichsfarben nur für Akzente\n\n**Nicht tun**\n\n- Stufe `-500` als Textfarbe auf Weiß: Co-500 und KI-500 unterschreiten AA komplett, WO-500 erreicht nur AA Large. Nur ES-500 und Rosé-500 erfüllen AA\n- Paletten verschiedener Bereiche auf derselben Seite mischen, bricht die Markenzugehörigkeit\n- Bereichsfarbe für Fließtext, lange Texte in Farbe ermüden und verringern die Lesbarkeit\n- Semantische Farben zweckfremden, `--c-success` nicht für dekorative grüne Elemente\n- Hardcodierte Hex-Werte statt Tokens, verhindert Dark-Mode-Unterstützung und Theme-Wechsel\n\n## Siehe auch\n\n- CONTRIBUTING.md § 3 Farbe & Kontrast\n- `Grundlagen/Design Tokens` für das Präfix-Schema aller Tokens\n",
|
|
13
|
+
"summary": "# Verwendung Vier Bereichspaletten (Corporate, Angewandte KI, Effektive Software, Wirksame..."
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"components": {
|
|
3
|
+
"grundlagen-typografie": {
|
|
4
|
+
"id": "grundlagen-typografie",
|
|
5
|
+
"name": "grundlagen-typografie",
|
|
6
|
+
"docs": {
|
|
7
|
+
"grundlagen-typografie--verwendung": {
|
|
8
|
+
"id": "grundlagen-typografie--verwendung",
|
|
9
|
+
"name": "Verwendung",
|
|
10
|
+
"path": "./src/docs/grundlagen/typografie.mdx",
|
|
11
|
+
"title": "Grundlagen/Typografie",
|
|
12
|
+
"content": "import { Meta } from '@storybook/addon-docs/blocks';\nimport * as TypografieStories from '../../foundations/typography.stories';\n\n<Meta of={TypografieStories} name=\"Verwendung\" />\n\n# Verwendung\n\nZwei Schriften tragen zwei unterschiedliche Aufgaben. Libre Baskerville (Serifenschrift, Display und Headline) trägt Hero-Überschriften, Seitentitel, Pull Quotes und emotionale Akzente. Montserrat (Grotesk, Title, Body und Label) trägt UI-Text, Fließtext, Buttons, Navigation und Captions. Minimum-Font-Size systemweit ist 12 px, kleinere Größen werden bewusst vermieden.\n\n## Wann welche Schrift\n\n| Schrift | Tokens | Einsatz |\n|---|---|---|\n| Libre Baskerville, Serifenschrift | Display, Headline | Hero-Überschriften, Seitentitel, Pull Quotes, emotionale Akzente |\n| Montserrat, Grotesk | Title, Body, Label | UI-Text, Fließtext, Buttons, Navigation, Captions |\n\n## Token-Übersicht\n\n| Kategorie | Einsatz | Größen |\n|---|---|---|\n| Display | Hero-Texte, ep-Seiten, große Kampagnentitel | responsive (fluid), clamp 28 bis 46 px, 30 bis 40 px, 28 bis 36 px |\n| Headline | Sektions-Überschriften, Abschnittstitel | responsive (fluid), clamp 23 bis 28 px, 21 bis 24 px, 20 bis 22 px |\n| Title | Title Small für Karten-Titel und Komponenten-Header | 20 px |\n| Body | Fließtext, Card-Beschreibungen, Meta-Daten, Captions | 16, 14, 12 px |\n| Label | Buttons, Badges, UI-Beschriftungen, Eyebrows (UC-Variante) | 14, 12, 12 px UC |\n\nDie Token-Hierarchie ist verbindlich und wird nicht übersprungen: *Display → Headline → Title → Body → Label*.\n\n## Barrierefreiheit\n\n| Aspekt | Regel |\n|---|---|\n| Hierarchie | Überschriften-Ebenen nie überspringen (h1 → h2 → h3), Screenreader navigieren anhand der Heading-Struktur |\n| rem statt px | Alle Typo-Tokens sind rem-basiert (1rem = 16px), damit sie die Browser-Schriftgröße respektieren, px ignoriert sie (WCAG 1.4.4) |\n| Zeilenhöhe | Body-Text mindestens `line-height: 1.5` (WCAG 1.4.8), erleichtert das Lesen bei Dyslexie und Sehschwäche |\n| Nicht nur Stil | Bedeutung nie ausschließlich durch Schriftschnitt (fett, kursiv) vermitteln, der Kontext muss auch ohne Formatierung erkennbar sein |\n\n## Dos & Don'ts\n\n**Tun**\n\n- Libre Baskerville für Überschriften und emotionale Akzente, der markentypische Kontrast zur UI\n- Display-Tokens ausschließlich auf Landing Pages und Kampagnenseiten einsetzen\n- Body Medium (16 px) als Standard für Fließtext, optimale Lesbarkeit auf allen Screens\n- Token-Hierarchie einhalten: Display → Headline → Title → Body → Label\n- Label-Tokens für alle UI-Beschriftungen: Buttons, Chips, Badges, Eyebrows\n\n**Nicht tun**\n\n- Libre Baskerville als Fließtext, Serifenschriften ermüden bei langen Texten auf Screens\n- Libre Baskerville für Navigation, Buttons oder kleine UI-Labels, falsche semantische Ebene\n- Freihand-Fontgrößen (zum Beispiel 13 px, 17 px) statt Token-Werte, bricht den visuellen Rhythmus\n- Title-Tokens für Hero-Überschriften, zu klein, nimmt der Marke den Ausdruck\n- Body-Text fett formatieren statt ein Title-Token zu wählen, falsche Hierarchiesignale\n\n## Siehe auch\n\n- CONTRIBUTING.md § 6 Typografie\n- `Grundlagen/Design Tokens` für das Präfix-Schema aller Tokens\n",
|
|
13
|
+
"summary": "# Verwendung Zwei Schriften tragen zwei unterschiedliche Aufgaben. Libre Baskerville (Seri..."
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"components": {
|
|
3
|
+
"komponenten-buttons-button": {
|
|
4
|
+
"id": "komponenten-buttons-button",
|
|
5
|
+
"name": "komponenten-buttons-button",
|
|
6
|
+
"docs": {
|
|
7
|
+
"komponenten-buttons-button--verwendung": {
|
|
8
|
+
"id": "komponenten-buttons-button--verwendung",
|
|
9
|
+
"name": "Verwendung",
|
|
10
|
+
"path": "./src/docs/komponenten/buttons-verwendung.mdx",
|
|
11
|
+
"title": "Komponenten/Buttons/Button",
|
|
12
|
+
"content": "import { Meta, Unstyled } from '@storybook/addon-docs/blocks';\nimport * as ButtonStories from '../../lib/button/button.stories';\n\n<Meta of={ButtonStories} name=\"Verwendung\" />\n\n# Verwendung\n\nButtons sind die primäre Aktions-Komponente des Systems: fünf Stilvarianten (Filled · Tonal · Elevated · Outlined · Text), drei Größen (Standard · Small · Large), der Ton-Modifier `.btn-err` für destruktive Aktionen und der Inversions-Modifier `.btn-on-band` für Buttons auf farbigen Bereichs-Bändern. Jede Variante steht in allen vier Brand Areas zur Verfügung (Bereichsreihenfolge co · ki · es · wo), das Mindestmaß für ein Touch-Target ist 44 Pixel.\n\n## Wann welche Variante\n\nDie Hierarchie ist verbindlich: Filled vor Tonal oder Outlined vor Text. Pro Kontext höchstens ein Filled-Button, sonst ist die Hauptaktion nicht mehr eindeutig erkennbar. Elevated steht außerhalb dieser Kette und markiert eine freistehende, vom Hintergrund abgehobene Aktion.\n\nSo löst sich die Hierarchie in typischen Kontexten auf: ein Dialog mit Text- neben Filled-Button, ein Formular mit Outlined- neben Filled-Button und eine Feature-Karte mit Text- neben Tonal-Button.\n\n<Unstyled>\n <div style={{ display: 'flex', flexDirection: 'column', gap: 'var(--s4)' }}>\n <div\n style={{\n border: 'var(--bd-strong)',\n borderRadius: 'var(--r-lg)',\n padding: 'var(--s5)',\n background: 'var(--bg-surface)',\n }}\n >\n <div style={{ font: '500 16px/24px var(--font)', color: 'var(--tx-primary)', marginBottom: 'var(--s2)' }}>\n Aktion bestätigen\n </div>\n <div style={{ font: '400 14px/20px var(--font)', color: 'var(--tx-secondary)', marginBottom: 'var(--s5)' }}>\n Möchtest du die Änderungen wirklich speichern?\n </div>\n <div style={{ display: 'flex', justifyContent: 'flex-end', gap: 'var(--s2)', marginBottom: 'var(--s3)' }}>\n <button className=\"btn btn-text btn-sm btn-co\">Abbrechen</button>\n <button className=\"btn btn-filled btn-sm btn-co\">Speichern</button>\n </div>\n <div style={{ font: '400 12px/16px var(--font)', color: 'var(--tx-secondary)', textAlign: 'right' }}>\n Text → Abbrechen · Filled → Hauptaktion\n </div>\n </div>\n <div\n style={{\n border: 'var(--bd-strong)',\n borderRadius: 'var(--r-lg)',\n padding: 'var(--s5)',\n background: 'var(--bg-surface)',\n }}\n >\n <div style={{ font: '500 16px/24px var(--font)', color: 'var(--tx-primary)', marginBottom: 'var(--s4)' }}>\n Formular einreichen\n </div>\n <div\n style={{\n height: '32px',\n background: 'var(--bg-overlay)',\n borderRadius: 'var(--r-sm)',\n border: 'var(--bd-strong)',\n marginBottom: 'var(--s5)',\n }}\n ></div>\n <div style={{ display: 'flex', gap: 'var(--s2)', marginBottom: 'var(--s3)' }}>\n <button className=\"btn btn-outlined btn-sm btn-co\">Vorschau</button>\n <button className=\"btn btn-filled btn-sm btn-co\">Absenden</button>\n </div>\n <div style={{ font: '400 12px/16px var(--font)', color: 'var(--tx-secondary)' }}>\n Outlined → Alternativaktion · Filled → Primäraktion\n </div>\n </div>\n <div\n style={{\n border: 'var(--bd-strong)',\n borderRadius: 'var(--r-lg)',\n padding: 'var(--s5)',\n background: 'var(--bg-surface)',\n }}\n >\n <div style={{ font: '500 16px/24px var(--font)', color: 'var(--tx-primary)', marginBottom: 'var(--s2)' }}>\n Feature entdecken\n </div>\n <div style={{ font: '400 14px/20px var(--font)', color: 'var(--tx-secondary)', marginBottom: 'var(--s5)' }}>\n Drei Bereiche, ein Ziel, Gelassenheit durch klare Struktur.\n </div>\n <div style={{ display: 'flex', alignItems: 'center', gap: 'var(--s2)', marginBottom: 'var(--s3)' }}>\n <button className=\"btn btn-text btn-sm btn-co\">Mehr erfahren</button>\n <button className=\"btn btn-tonal btn-sm btn-co\">Jetzt starten</button>\n </div>\n <div style={{ font: '400 12px/16px var(--font)', color: 'var(--tx-secondary)' }}>\n Text → Nebenaktion · Tonal → unterstützende Aktion\n </div>\n </div>\n </div>\n</Unstyled>\n\n| Variante | Rolle in der Hierarchie | Einsatz | Beispiele |\n|---|---|---|---|\n| Filled | 1. Primäre Hauptaktion | Max. 1 bis 2 pro Kontext | Speichern, Absenden, Starten |\n| Tonal | 2. Sekundäre Bestätigung | Neben Filled oder eigenständig | Weiter, Übernehmen |\n| Outlined | 2. Gleichwertige Alternative | Ohne Primärfokus | Vorschau, Exportieren |\n| Text | 3. Nebenaktion | Niedrigste Priorität, link-ähnliche Funktion | Abbrechen, Mehr erfahren |\n| Elevated | Außerhalb der Hierarchie | Freistehende Aktion, visuell vom Hintergrund getrennt | Schwebende Elemente, FAB |\n\n## Destruktive Aktionen\n\n`.btn-err` (Angular: `tone=\"err\"`) markiert eine Aktion, die sich nicht rückgängig machen lässt: Löschen, Verwerfen, Entfernen. Der Modifier **ersetzt** die Bereichsfarbe, er wird statt `.btn-co` gesetzt, nicht zusätzlich. Gedacht für Filled, Outlined und Text.\n\n<Unstyled>\n <div style={{ display: 'flex', gap: 'var(--s4)', flexWrap: 'wrap', alignItems: 'center', marginBottom: 'var(--s5)' }}>\n <button className=\"btn btn-filled btn-err\">Löschen</button>\n <button className=\"btn btn-outlined btn-err\">Verwerfen</button>\n <button className=\"btn btn-text btn-err\">Entfernen</button>\n </div>\n</Unstyled>\n\nWelcher Button gefüllt ist, entscheidet der Kontext:\n\n| Kontext | Beispiel | Hauptaktion (Filled) | Nebenaktion |\n|---|---|---|---|\n| Selbst ausgelöst | Klick auf „Löschen“, danach eine Rückfrage | „Löschen“ mit `.btn-err` | „Abbrechen“ als Text |\n| Unterbrechung | Ungespeicherte Änderungen beim Verlassen | „Weiter bearbeiten“ in der Bereichsfarbe | „Verwerfen“ als Outlined mit `.btn-err` |\n\nBei einer Unterbrechung wollte die Person etwas anderes, das Verwerfen ist Nebenwirkung. Deshalb bekommt dort der sichere Weg das Gewicht. Die Farbe ist nie der einzige Hinweis, das Label nennt immer die Folge.\n\n## Barrierefreiheit\n\n| Aspekt | Regel |\n|---|---|\n| Icon-only | Buttons ohne sichtbaren Text benötigen `aria-label`, der SVG-Inhalt allein reicht für Screenreader nicht aus |\n| Disabled | `aria-disabled=\"true\"` statt HTML `disabled`, wenn der Button im Fokus-Flow bleiben soll, `disabled` entfernt das Element aus der Tastaturreihenfolge |\n| Touch-Target | Mindestgröße 44 mal 44 Pixel für alle Button-Varianten (WCAG 2.5.5), `btn-sm` bei Bedarf mit zusätzlichem Padding kompensieren |\n| Focus-Ring | Nie `outline: none` ohne sichtbaren Ersatz, der Design-System-Focus-Ring (`--focus-aa`) muss für alle Buttons erhalten bleiben |\n| Filled auf Bereichs-Section | Filled-Buttons auf hellen Bereichs-Hintergründen (`--co-50`, `--ki-50`, `--wo-50`, `--es-50`) brauchen eine ausreichend dunkle Variante mit weißer Schrift, sonst fehlt der UI-Komponenten-Kontrast (WCAG 1.4.11, mindestens 3 zu 1) zwischen Button-Fläche und Section |\n\nDrei der vier Bereiche sind über die Modifier-Klasse bereits korrekt abgedeckt: `.btn-co` auf `--co-700`, `.btn-ki` auf `--ki-800`, `.btn-es` auf `--es-700`. Die Default-Farbe von `.btn-wo` (`--wo-700`) ist im Allgemeinen passend, verfehlt aber auf `--wo-50`-Sub-Streifen den Kontrast. Dort die Bereichs-Klasse mit einem minimalen Inline-Override kombinieren:\n\n```html\n<button class=\"btn btn-filled btn-wo\" style=\"--c500:var(--wo-600)\">\n```\n\n`--c50` erbt korrekt von `.btn-wo`, ein `color`-Override entfällt, weil der Default aus `.btn-filled` (Weiß) bereits greift.\n\n**Anti-Pattern:** Inline-Style verwenden, der nur die Token-Werte einer Modifier-Klasse dupliziert (etwa `style=\"--c500:var(--co-700);--c50:var(--co-50)\"` statt `.btn-co`). Macht das Markup laut, das Refactoring teuer und verlangsamt das Lesen. Wenn eine Wiederholung auftaucht, lieber einen neuen Modifier definieren (wie `.btn-on-band`) statt das Pattern an mehreren Stellen inline zu kopieren.\n\n## Dos & Don'ts\n\n**Tun**\n\n- Pro Kontext maximal ein Filled Button, klare Priorisierung der Hauptaktion für die Nutzerin.\n- Verb-Labels: konkret und handlungsorientiert, „Starten“, „Speichern“, „Anfragen“, „Absenden“.\n- Hierarchie konsequent einhalten: Filled vor Tonal oder Outlined vor Text.\n- Bereichsklasse passend zum Seitenkontext: `.btn-co`, `.btn-ki`, `.btn-es`, `.btn-wo`.\n- Touch-Target mindestens 44 Pixel einhalten, auch im Small-Modus ausreichend groß für sichere Bedienung.\n- `.btn-err` nur für Aktionen, die sich nicht rückgängig machen lassen, höchstens einer pro Ansicht, mit einem Label, das die Folge nennt: „Löschen“, „Verwerfen“.\n\n**Nicht tun**\n\n- Mehrere Filled Buttons nebeneinander, das lässt keine klare Primäraktion erkennen.\n- Substantive oder lange Phrasen als Labels, „Antragsformular einreichen“ statt lieber „Absenden“.\n- Disabled-State ohne sichtbare Begründung, Helper-Text oder Tooltip nutzen, um zu erklären warum.\n- Bereichsfarbe willkürlich tauschen, Corporate-Kontext immer `.btn-co`, nie `.btn-ki`.\n- Filled-Button mit `--area-500` auf hellem Bereichs-Hintergrund (`--area-50`), stattdessen die dunklere Bereichs-Variante nutzen (siehe Barrierefreiheits-Tabelle oben).\n- `.btn-err` als Blickfang oder für umkehrbare Aktionen („Abmelden“, „Filter zurücksetzen“), und nie neben einer Bereichsklasse am selben Button.\n\n## Verwandte Seiten\n\n- Buttons (`Komponenten/Buttons/Button`), alle Stilvarianten, Größen und Zustände als Stories.\n",
|
|
13
|
+
"summary": "# Verwendung Buttons sind die primäre Aktions-Komponente des Systems: fünf Stilvarianten (..."
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"name": "Verwendung",
|
|
10
10
|
"path": "./src/docs/komponenten/cards-verwendung.mdx",
|
|
11
11
|
"title": "Komponenten/Cards & Teaser",
|
|
12
|
-
"content": "import { Meta, Unstyled } from '@storybook/addon-docs/blocks';\n\n<Meta title=\"Komponenten/Cards & Teaser\" name=\"Verwendung\" tags={['angular']} />\n\n# Verwendung\n\nGenerische Karten (statisch, Link-Karte) und Inhaltskarten (Stat), alle Brand Areas, barrierefrei. Der Abschnitt deckt mehr ab, als es eigene Bauteile gibt: die editoriale Kennzahl-Zeile ist ein reines CSS-Rezept ohne eigene Komponente. Klickbare Karte, Featured-Karte, Icon-Karte, offene Feature-Liste und Tier-Trenner haben jeweils ein eigenes Angular-Bauteil (siehe „Verwandte Seiten“).\n\n## Anatomie\n\nDie folgende Anatomie zeigt die fünf Bausteine einer generischen Karte: Media-Bereich, Eyebrow, Title, Text und Footer. Die Ziffern korrespondieren mit den Begriffen, die in den übrigen Abschnitten dieser Seite verwendet werden.\n\n<Unstyled>\n <div style={{ border: 'var(--bd-strong)', borderRadius: 'var(--r-lg)', overflow: 'hidden' }}>\n <div\n style={{\n height: 60,\n background: 'var(--co-50)',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n borderBottom: 'var(--bd)',\n }}\n >\n <span style={{ font: '400 12px/16px var(--font)', color: 'var(--tx-secondary)' }}>\n ① Media, Bereichsfarbe <code className=\"token\">-50</code>\n </span>\n </div>\n <div style={{ padding: 'var(--s4)' }}>\n <div\n className=\"t-co\"\n style={{\n font: '500 12px/16px var(--font)',\n letterSpacing: '.08em',\n textTransform: 'uppercase',\n marginBottom: 'var(--s1)',\n }}\n >\n ② Eyebrow, Bereichsname\n </div>\n <div\n style={{\n font: '500 16px/24px var(--font)',\n color: 'var(--tx-primary)',\n marginBottom: 'var(--s1)',\n }}\n >\n ③ Title, Kernaussage\n </div>\n <div style={{ font: 'var(--ty-body-md)', color: 'var(--tx-secondary)', marginBottom: 'var(--s4)' }}>\n ④ Text, max. 2 Sätze, konkret\n </div>\n <div\n style={{\n display: 'flex',\n justifyContent: 'flex-end',\n gap: 'var(--s2)',\n borderTop: 'var(--bd)',\n paddingTop: 'var(--s3)',\n }}\n >\n <span style={{ font: '400 12px/16px var(--font)', color: 'var(--tx-muted)' }}>\n ⑤ Footer, max. 2 Aktionen\n </span>\n </div>\n </div>\n </div>\n</Unstyled>\n\n## Wann welche Variante\n\n| Variante | Klasse | Wann einsetzen | Elevation |\n|---|---|---|---|\n| Statisch | `.card` | Der Standard, Karten deren Aktionen in Footer-Buttons liegen, dazu Listen- und Tabellen-Kontexte ohne visuelle Schwere | `--e0` + Rahmen |\n| Link-Karte | `a.card.card-elevated` | Wenn die ganze Karte zu einem Ziel führt: Listing-Teaser, Beitrags-, Job- und Veranstaltungs-Karten | `--e1`, Hover `--e2` + Lift |\n\n**Klickbare Karte als Modus.** Wenn die ganze Karte zu einem Ziel führen soll, gibt es zwei Patterns, je nach Karten-Typ und Inhaltsdichte:\n\n| Pattern | Wrapping | Wann einsetzen |\n|---|---|---|\n| `.ep-card.ep-card-link` | `<a class=\"ep-card ep-card-link\">` | Kompakte Teaser-Kacheln mit Icon, Eyebrow, Titel, kurzem Text und CTA-Pfeil-Zeile, ohne Card-Footer-Buttons |\n| `a.card.card-elevated` | `<a class=\"card card-elevated\">` | Textreiche Listing-Cards mit Card-Media, Card-Body (Pill, Titel, Text, Meta-Zeile) und implizitem „Beitrag lesen →“-Anker am Ende |\n| `a.card.card-elevated.card-featured` | `<a class=\"card card-elevated card-featured\">` | Horizontale Großkarte für genau einen hervorgehobenen Beitrag oder Termin, Bild links im 16:9, Content rechts |\n\nIn Angular deckt jedes der drei Patterns ein eigenes Bauteil ab: `<a cdsIconCard>` (Icon-Karte), `cds-link-card` (Klickbare Karte) und `cds-featured-card` (Featured-Karte).\n\n**Weitere CSS-Rezepte ohne eigenes Bauteil**, sinnvoll dort, wo ein weiteres Karten-Grid die Seite überladen würde:\n\n| Muster | Rolle | Wann statt Karte |\n|---|---|---|\n| Stat-Karte (`.card-stat`) | Eigenständige KPI-Kachel mit Rahmen | Kennzahlen auf Landingpages, Jahresberichten, Dashboards |\n| Bandstreifen (`.card-stat-strip` / `.card-stat-flat`) | Flache Variante ohne Rahmen und Schatten | Kompakte KPI-Bänder, Footer-Stats, Hero-Anschluss-Sektionen |\n| Editoriale Kennzahl-Zeile | Redaktioneller Fließinhalt, nur durch Haarlinien getrennt, kein Karten-Chrome | Case-, Projekt- und Leistungslisten, wenn auf der Seite bereits Karten-Grids stehen |\n| Offene Feature-Liste (`.ep-feature`, in Angular `<div cdsFeature>`) | Icon-geführte Aufzählung ohne Rahmen, Schatten oder Media-Fläche | Vollständiger Funktionsumfang, wenn ein weiteres Karten-Grid überladen würde |\n\nKarten sind für Angebots-Menüs und Teaser da: Lösungs- und Leistungskacheln, Artikel-Vorschauen, Elemente, die zu einem Ziel führen und als abgeschlossene, klickbare Einheit funktionieren. Für Stimmen, Funktions- und Case-Listen ist meist eine offene, redaktionelle Darstellung die bessere Wahl: direkt auf der Fläche, durch Haarlinien getrennt. Das hält inhaltsdichte Abschnitte luftig und vermeidet den Eindruck einer Kachelwand, wenn mehrere Karten-Grids aufeinanderfolgen.\n\n**Testimonial-Karte**: wohnt unter `Komponenten/Zitate & Testimonials/Testimonial`, hier nur der Querverweis. Zitat mit Quellenangabe, farbiger Top-Border signalisiert die Brand Area, Auszeichnung über `<figure>` + `<blockquote>` für korrekte Semantik.\n\n<Unstyled>\n <div className=\"layout-grid\">\n <div className=\"col-4\">\n <div\n style={{\n font: '500 12px/16px var(--font)',\n color: 'var(--tx-muted)',\n marginBottom: 'var(--s2)',\n }}\n >\n Mit Media-Bereich → keine Linie\n </div>\n <div style={{ border: 'var(--bd-strong)', borderRadius: 'var(--r-lg)', overflow: 'hidden' }}>\n <div\n style={{\n height: 40,\n background: 'var(--co-50)',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n }}\n >\n <span style={{ font: '400 12px/16px var(--font)', color: 'var(--tx-secondary)' }}>\n Media\n </span>\n </div>\n <div style={{ padding: 'var(--s3) var(--s4)' }}>\n <div\n style={{\n height: 6,\n borderRadius: 3,\n background: 'var(--n-200)',\n marginBottom: 6,\n width: '55%',\n }}\n />\n <div style={{ height: 8, borderRadius: 3, background: 'var(--n-100)', marginBottom: 4 }} />\n <div style={{ height: 8, borderRadius: 3, background: 'var(--n-100)', width: '80%' }} />\n </div>\n </div>\n </div>\n <div className=\"col-4\">\n <div\n style={{\n font: '500 12px/16px var(--font)',\n color: 'var(--tx-muted)',\n marginBottom: 'var(--s2)',\n }}\n >\n Ohne Media-Bereich → Linie oben\n </div>\n <div\n style={{\n border: 'var(--bd-strong)',\n borderTop: '4px solid var(--co-500)',\n borderRadius: 'var(--r-lg)',\n overflow: 'hidden',\n }}\n >\n <div style={{ padding: 'var(--s3) var(--s4)' }}>\n <div\n style={{\n height: 6,\n borderRadius: 3,\n background: 'var(--n-200)',\n marginBottom: 6,\n width: '55%',\n }}\n />\n <div style={{ height: 8, borderRadius: 3, background: 'var(--n-100)', marginBottom: 4 }} />\n <div style={{ height: 8, borderRadius: 3, background: 'var(--n-100)', width: '80%' }} />\n </div>\n </div>\n </div>\n </div>\n</Unstyled>\n\n## Barrierefreiheit\n\n| Aspekt | Regel |\n|---|---|\n| Semantik | `<article>` für eigenständige Cards, Screenreader listen Artikel als navigierbare Landmark, Überschriften-Hierarchie einhalten (Card-Titel als `h3` unter einer Section-`h2`) |\n| Klickbereich | Wenn die ganze Karte zu einem Ziel führt: das umschließende Element auf `<a>` oder `<button>` umstellen, nie `<div>` mit `onclick`. Pfeil-Suffix in `<span aria-hidden=\"true\">` hüllen, Focus-Ring sichtbar lassen. Trägt die Karte nur passive Information, gehören Interaktionselemente ausschließlich in den Card-Footer |\n| Bilder & Icons | Card-Media-Bilder mit beschreibendem `alt`-Text versehen, dekorative SVGs mit `aria-hidden=\"true\"` + `focusable=\"false\"` ausblenden |\n\n**Bildslots sind 16/9 und kommen aus `.card-media`.** Listing-Grid und Featured-Card teilen sich das Verhältnis, damit Redaktion pro Beitrag ein Bild in einem Zuschnitt pflegt statt einen je Slot. Den Bildausschnitt setzt `object-position` am `<img>`, nicht `background-position` an einem Container, sonst gilt der Zuschnitt nur in einem Slot. Eigene Verhältnisse haben nur Hero und Slider (21/9) sowie Avatare (1/1). Reicht die Höhe nicht, wird Text gekappt, nicht das Verhältnis gedehnt.\n\n**Der Abstand gehört dem Container, nicht dem Kind.** `.card-body` ist eine Flex-Spalte mit `gap: var(--s3)`, das ist der einzige vertikale Rhythmus der Karte. `.card-eyebrow`, `.card-cta-link` und die Pill setzen im Card-Body keine eigene Marge, sonst addiert sie sich zum `gap`, statt zu kollabieren, denn im Flex-Layout kollabieren Margen nicht. Braucht eine Karte mehr Luft, wird nur der `gap` überschrieben, nicht eine Marge nachgeschoben.\n\n## Dos & Don'ts\n\n**Tun**\n\n- Eyebrow und Media konsequent in der Bereichsfarbe halten, die Karte ist immer einem Bereich zugehörig.\n- Schatten nur auf Link-Karten (`a.card.card-elevated`), Karten mit Aktionen im Footer ruhen flach mit Rahmen.\n- Max. 2 Aktionen im Card-Footer: Text-Button (sekundär) plus Filled-Button (primär).\n- Card-Text auf max. 2 Sätze begrenzen, prägnant und scanbar, kein Fließtext.\n- Gleichartige Karten in einem Grid konsistent halten, gleiche Variante, gleiche Breite.\n\n**Nicht tun**\n\n- Statische und Link-Karten in derselben Reihe mischen, der Schatten liest sich dann als Zufall statt als Klick-Angebot.\n- Mehr als 2 Filled Buttons im Footer, die Hierarchie wird unklar, eine Hauptaktion reicht.\n- Bereichsfarben einer Karte und ihrer Nachbarkarte mischen, jede Karte gehört zu einem Bereich.\n- Eine Karte erhöhen, deren Fläche nirgendwohin führt, das verspricht Klickbarkeit, die es nicht gibt.\n- Langen Fließtext in Card-Body, stattdessen einen Teaser formulieren und auf eine Detailseite verlinken.\n\n## Verwandte Seiten\n\n- Card (`Komponenten/Cards & Teaser/Card`)\n- Klickbare Karte (`Komponenten/Cards & Teaser/Klickbare Karte`), `cds-link-card`\n- Featured-Karte (`Komponenten/Cards & Teaser/Featured-Karte`), `cds-featured-card`\n- Icon-Karte (`Komponenten/Cards & Teaser/Icon-Karte`), `[cdsIconCard]`\n- Feature-Liste (`Komponenten/Cards & Teaser/Feature-Liste`), `[cdsFeature]`\n- Tier-Trenner (`Komponenten/Cards & Teaser/Tier-Trenner`), `cds-tier`\n- StatCard (`Komponenten/Cards & Teaser/StatCard`)\n- StatStrip (`Komponenten/Cards & Teaser/StatStrip`)\n- Testimonial (`Komponenten/Zitate & Testimonials/Testimonial`), Zitat-Karte mit Quellenangabe, hier nur verlinkt\n",
|
|
12
|
+
"content": "import { Meta, Unstyled } from '@storybook/addon-docs/blocks';\n\n<Meta title=\"Komponenten/Cards & Teaser\" name=\"Verwendung\" tags={['angular']} />\n\n# Verwendung\n\nGenerische Karten (statisch, Link-Karte) und Inhaltskarten (Stat), alle Brand Areas, barrierefrei. Der Abschnitt deckt mehr ab, als es eigene Bauteile gibt: die editoriale Kennzahl-Zeile ist ein reines CSS-Rezept ohne eigene Komponente. Klickbare Karte, Featured-Karte, Icon-Karte, offene Feature-Liste und Tier-Trenner haben jeweils ein eigenes Angular-Bauteil (siehe „Verwandte Seiten“).\n\n## Anatomie\n\nDie folgende Anatomie zeigt die fünf Bausteine einer generischen Karte: Media-Bereich, Eyebrow, Title, Text und Footer. Die Ziffern korrespondieren mit den Begriffen, die in den übrigen Abschnitten dieser Seite verwendet werden.\n\n<Unstyled>\n <div style={{ border: 'var(--bd-strong)', borderRadius: 'var(--r-lg)', overflow: 'hidden' }}>\n <div\n style={{\n height: 60,\n background: 'var(--co-50)',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n borderBottom: 'var(--bd)',\n }}\n >\n <span style={{ font: '400 12px/16px var(--font)', color: 'var(--tx-secondary)' }}>\n ① Media, Bereichsfarbe <code className=\"token\">-50</code>\n </span>\n </div>\n <div style={{ padding: 'var(--s4)' }}>\n <div\n className=\"t-co\"\n style={{\n font: '500 12px/16px var(--font)',\n letterSpacing: '.08em',\n textTransform: 'uppercase',\n marginBottom: 'var(--s1)',\n }}\n >\n ② Eyebrow, Bereichsname\n </div>\n <div\n style={{\n font: '500 16px/24px var(--font)',\n color: 'var(--tx-primary)',\n marginBottom: 'var(--s1)',\n }}\n >\n ③ Title, Kernaussage\n </div>\n <div style={{ font: 'var(--ty-body-md)', color: 'var(--tx-secondary)', marginBottom: 'var(--s4)' }}>\n ④ Text, max. 2 Sätze, konkret\n </div>\n <div\n style={{\n display: 'flex',\n justifyContent: 'flex-end',\n gap: 'var(--s2)',\n borderTop: 'var(--bd)',\n paddingTop: 'var(--s3)',\n }}\n >\n <span style={{ font: '400 12px/16px var(--font)', color: 'var(--tx-muted)' }}>\n ⑤ Footer, max. 2 Aktionen\n </span>\n </div>\n </div>\n </div>\n</Unstyled>\n\n## Wann welche Variante\n\n| Variante | Klasse | Wann einsetzen | Elevation |\n|---|---|---|---|\n| Statisch | `.card` | Der Standard, Karten deren Aktionen in Footer-Buttons liegen, dazu Listen- und Tabellen-Kontexte ohne visuelle Schwere | `--e0` + Rahmen |\n| Link-Karte | `a.card.card-elevated` | Wenn die ganze Karte zu einem Ziel führt: Listing-Teaser, Beitrags-, Job- und Veranstaltungs-Karten | `--e1`, Hover `--e2` + Lift |\n\n**Klickbare Karte als Modus.** Wenn die ganze Karte zu einem Ziel führen soll, gibt es zwei Patterns, je nach Karten-Typ und Inhaltsdichte:\n\n| Pattern | Wrapping | Wann einsetzen |\n|---|---|---|\n| `.ep-card.ep-card-link` | `<a class=\"ep-card ep-card-link\">` | Kompakte Teaser-Kacheln mit Icon, Eyebrow, Titel, kurzem Text und CTA-Pfeil-Zeile, ohne Card-Footer-Buttons |\n| `a.card.card-elevated` | `<a class=\"card card-elevated\">` | Textreiche Listing-Cards mit Card-Media, Card-Body (Pill, Titel, Text, Meta-Zeile) und implizitem „Beitrag lesen →“-Anker am Ende |\n| `a.card.card-elevated.card-featured` | `<a class=\"card card-elevated card-featured\">` | Horizontale Großkarte für genau einen hervorgehobenen Beitrag oder Termin, Bild links im 16:9, Content rechts |\n\nIn Angular deckt jedes der drei Patterns ein eigenes Bauteil ab: `<a cdsIconCard>` (Icon-Karte), `cds-link-card` (Klickbare Karte) und `cds-featured-card` (Featured-Karte).\n\n**Weitere CSS-Rezepte ohne eigenes Bauteil**, sinnvoll dort, wo ein weiteres Karten-Grid die Seite überladen würde:\n\n| Muster | Rolle | Wann statt Karte |\n|---|---|---|\n| Stat-Karte (`.card-stat`) | Eigenständige KPI-Kachel mit Rahmen | Kennzahlen auf Landingpages, Jahresberichten, Dashboards |\n| Bandstreifen (`.card-stat-strip` / `.card-stat-flat`) | Flache Variante ohne Rahmen und Schatten | Kompakte KPI-Bänder, Footer-Stats, Hero-Anschluss-Sektionen |\n| Editoriale Kennzahl-Zeile | Redaktioneller Fließinhalt, nur durch Haarlinien getrennt, kein Karten-Chrome | Case-, Projekt- und Leistungslisten, wenn auf der Seite bereits Karten-Grids stehen |\n| Offene Feature-Liste (`.ep-feature`, in Angular `<div cdsFeature>`) | Icon-geführte Aufzählung ohne Rahmen, Schatten oder Media-Fläche | Vollständiger Funktionsumfang, wenn ein weiteres Karten-Grid überladen würde |\n\nKarten sind für Angebots-Menüs und Teaser da: Lösungs- und Leistungskacheln, Artikel-Vorschauen, Elemente, die zu einem Ziel führen und als abgeschlossene, klickbare Einheit funktionieren. Für Stimmen, Funktions- und Case-Listen ist meist eine offene, redaktionelle Darstellung die bessere Wahl: direkt auf der Fläche, durch Haarlinien getrennt. Das hält inhaltsdichte Abschnitte luftig und vermeidet den Eindruck einer Kachelwand, wenn mehrere Karten-Grids aufeinanderfolgen.\n\n**Testimonial-Karte**: wohnt unter `Komponenten/Zitate & Testimonials/Testimonial`, hier nur der Querverweis. Zitat mit Quellenangabe, farbiger Top-Border signalisiert die Brand Area, Auszeichnung über `<figure>` + `<blockquote>` für korrekte Semantik.\n\n**Warum oben und nicht links?** Die Leserichtung ist von links nach rechts, von oben nach unten, der oberste Kartenrand ist der erste Fixpunkt beim Scannen einer Seite. Die Linie links eignet sich für redaktionellen Fließinhalt (Blockquote), weil der Text direkt daneben beginnt und die Linie als Begleiter wirkt. Bei einer abgeschlossenen Karte würde ein linker Rand mit dem Layout-Raster kollidieren und die Außenkante der Karte unruhig machen.\n\n<Unstyled>\n <div className=\"layout-grid\">\n <div className=\"col-4\">\n <div\n style={{\n font: '500 12px/16px var(--font)',\n color: 'var(--tx-muted)',\n marginBottom: 'var(--s2)',\n }}\n >\n Mit Media-Bereich → keine Linie\n </div>\n <div style={{ border: 'var(--bd-strong)', borderRadius: 'var(--r-lg)', overflow: 'hidden' }}>\n <div\n style={{\n height: 40,\n background: 'var(--co-50)',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n }}\n >\n <span style={{ font: '400 12px/16px var(--font)', color: 'var(--tx-secondary)' }}>\n Media\n </span>\n </div>\n <div style={{ padding: 'var(--s3) var(--s4)' }}>\n <div\n style={{\n height: 6,\n borderRadius: 3,\n background: 'var(--n-200)',\n marginBottom: 6,\n width: '55%',\n }}\n />\n <div style={{ height: 8, borderRadius: 3, background: 'var(--n-100)', marginBottom: 4 }} />\n <div style={{ height: 8, borderRadius: 3, background: 'var(--n-100)', width: '80%' }} />\n </div>\n </div>\n </div>\n <div className=\"col-4\">\n <div\n style={{\n font: '500 12px/16px var(--font)',\n color: 'var(--tx-muted)',\n marginBottom: 'var(--s2)',\n }}\n >\n Ohne Media-Bereich → Linie oben\n </div>\n <div\n style={{\n border: 'var(--bd-strong)',\n borderTop: '4px solid var(--co-500)',\n borderRadius: 'var(--r-lg)',\n overflow: 'hidden',\n }}\n >\n <div style={{ padding: 'var(--s3) var(--s4)' }}>\n <div\n style={{\n height: 6,\n borderRadius: 3,\n background: 'var(--n-200)',\n marginBottom: 6,\n width: '55%',\n }}\n />\n <div style={{ height: 8, borderRadius: 3, background: 'var(--n-100)', marginBottom: 4 }} />\n <div style={{ height: 8, borderRadius: 3, background: 'var(--n-100)', width: '80%' }} />\n </div>\n </div>\n </div>\n </div>\n</Unstyled>\n\n## Barrierefreiheit\n\n| Aspekt | Regel |\n|---|---|\n| Semantik | `<article>` für eigenständige Cards, Screenreader listen Artikel als navigierbare Landmark, Überschriften-Hierarchie einhalten (Card-Titel als `h3` unter einer Section-`h2`) |\n| Klickbereich | Wenn die ganze Karte zu einem Ziel führt: das umschließende Element auf `<a>` oder `<button>` umstellen, nie `<div>` mit `onclick`. Pfeil-Suffix in `<span aria-hidden=\"true\">` hüllen, Focus-Ring sichtbar lassen. Trägt die Karte nur passive Information, gehören Interaktionselemente ausschließlich in den Card-Footer |\n| Bilder & Icons | Card-Media-Bilder mit beschreibendem `alt`-Text versehen, dekorative SVGs mit `aria-hidden=\"true\"` + `focusable=\"false\"` ausblenden |\n\n**Bildslots sind 16/9 und kommen aus `.card-media`.** Listing-Grid und Featured-Card teilen sich das Verhältnis, damit Redaktion pro Beitrag ein Bild in einem Zuschnitt pflegt statt einen je Slot. Den Bildausschnitt setzt `object-position` am `<img>`, nicht `background-position` an einem Container, sonst gilt der Zuschnitt nur in einem Slot. Eigene Verhältnisse haben nur Hero und Slider (21/9) sowie Avatare (1/1). Reicht die Höhe nicht, wird Text gekappt, nicht das Verhältnis gedehnt.\n\n**Der Abstand gehört dem Container, nicht dem Kind.** `.card-body` ist eine Flex-Spalte mit `gap: var(--s3)`, das ist der einzige vertikale Rhythmus der Karte. `.card-eyebrow`, `.card-cta-link` und die Pill setzen im Card-Body keine eigene Marge, sonst addiert sie sich zum `gap`, statt zu kollabieren, denn im Flex-Layout kollabieren Margen nicht. Braucht eine Karte mehr Luft, wird nur der `gap` überschrieben, nicht eine Marge nachgeschoben.\n\n## Dos & Don'ts\n\n**Tun**\n\n- Eyebrow und Media konsequent in der Bereichsfarbe halten, die Karte ist immer einem Bereich zugehörig.\n- Schatten nur auf Link-Karten (`a.card.card-elevated`), Karten mit Aktionen im Footer ruhen flach mit Rahmen.\n- Max. 2 Aktionen im Card-Footer: Text-Button (sekundär) plus Filled-Button (primär).\n- Card-Text auf max. 2 Sätze begrenzen, prägnant und scanbar, kein Fließtext.\n- Gleichartige Karten in einem Grid konsistent halten, gleiche Variante, gleiche Breite.\n\n**Nicht tun**\n\n- Statische und Link-Karten in derselben Reihe mischen, der Schatten liest sich dann als Zufall statt als Klick-Angebot.\n- Mehr als 2 Filled Buttons im Footer, die Hierarchie wird unklar, eine Hauptaktion reicht.\n- Bereichsfarben einer Karte und ihrer Nachbarkarte mischen, jede Karte gehört zu einem Bereich.\n- Eine Karte erhöhen, deren Fläche nirgendwohin führt, das verspricht Klickbarkeit, die es nicht gibt.\n- Langen Fließtext in Card-Body, stattdessen einen Teaser formulieren und auf eine Detailseite verlinken.\n\n## Verwandte Seiten\n\n- Card (`Komponenten/Cards & Teaser/Card`)\n- Klickbare Karte (`Komponenten/Cards & Teaser/Klickbare Karte`), `cds-link-card`\n- Featured-Karte (`Komponenten/Cards & Teaser/Featured-Karte`), `cds-featured-card`\n- Icon-Karte (`Komponenten/Cards & Teaser/Icon-Karte`), `[cdsIconCard]`\n- Feature-Liste (`Komponenten/Cards & Teaser/Feature-Liste`), `[cdsFeature]`\n- Tier-Trenner (`Komponenten/Cards & Teaser/Tier-Trenner`), `cds-tier`\n- StatCard (`Komponenten/Cards & Teaser/StatCard`)\n- StatStrip (`Komponenten/Cards & Teaser/StatStrip`)\n- Testimonial (`Komponenten/Zitate & Testimonials/Testimonial`), Zitat-Karte mit Quellenangabe, hier nur verlinkt\n",
|
|
13
13
|
"summary": "# Verwendung Generische Karten (statisch, Link-Karte) und Inhaltskarten (Stat), alle Brand..."
|
|
14
14
|
}
|
|
15
15
|
}
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"name": "Übersicht",
|
|
10
10
|
"path": "./src/docs/komponenten/sektion.mdx",
|
|
11
11
|
"title": "Komponenten/Sektion",
|
|
12
|
-
"content": "import { Meta } from '@storybook/addon-docs/blocks';\n\n<Meta title=\"Komponenten/Sektion\" name=\"Übersicht\" />\n\n# Sektion\n\nDas strukturelle Gerüst, in dem auf den Beispielseiten praktisch jeder andere\nBaustein sitzt: `.ep-section` mit dem optionalen Kopf-Trio aus Kicker, Überschrift\nund Lead. 133 Vorkommen in den Beispielseiten, 85 davon mit Kopfzeile. Das\nAngular-Bauteil ist `Komponenten/Sektion/Sektion` (`[cdsSection]`).\n\nQuelle: `docs/index.html#sec-section`.\n\n## Aufbau\n\nDrei Klassen bilden den Kopf: `.ep-section-label` (Kicker, bereichsfärbbar über\n`.t-co` / `.t-ki` / `.t-es` / `.t-wo`), `.ep-section-h2` (Überschrift) und\n`.ep-section-sub` (Lead). Alle drei sind Beiwerk: Eine Sektion besteht auch ganz\nohne Kopf, nur aus ihrem Inhalt darunter.\n\n```html\n<div class=\"ep-section\" style=\"background:var(--n-50)\">\n <div class=\"ep-section-label t-co\">Was wir tun</div>\n <h2 class=\"ep-section-h2\">So ist eine Sektion aufgebaut.</h2>\n <p class=\"ep-section-sub\">Kicker, Überschrift und Lead sind Beiwerk, der Inhalt darunter ist frei.</p>\n <!-- beliebiger Inhalt -->\n</div>\n```\n\n## Angular-Wrapper\n\n`[cdsSection]` ist ein Attributselektor statt eines eigenen Elements\n(`docs/adr/0008-selektortyp-der-wrapper-komponenten.md`). Der\nKonsument wählt das Tag: `<section cdsSection>` oder `<div cdsSection>`. Die\nKomponente setzt `aria-labelledby`, wenn ein zugänglicher Name verfügbar ist:\nentweder die eigene Überschrift oder eine per `labelledBy` übergebene id einer\nÜberschrift außerhalb der Komponente. Fehlt beides, setzt sie kein\n`aria-labelledby`.\n\n## Verwendung\n\nDie Fläche gehört der Seite, nicht dem Bauteil. Sektionen wechseln im Rhythmus\nzwischen `--bg-surface` und `--n-50`, auf einzelnen Sektionsflächen kommt\nzusätzlich eine Bereichstönung als Akzent vor. Welche Fläche eine Sektion trägt,\nhängt von ihren Nachbarn ab, und nur die Seite kennt diese Nachbarn. Deshalb setzt\n`.ep-section` selbst keinen Hintergrund, und `[cdsSection]` hat keinen\n`background`-Input: Die Fläche kommt per Klasse oder Inline-Style direkt an das\nElement, das `cdsSection` trägt (`<section cdsSection style=\"background:…\">`).\n",
|
|
12
|
+
"content": "import { Meta } from '@storybook/addon-docs/blocks';\n\n<Meta title=\"Komponenten/Sektion\" name=\"Übersicht\" />\n\n# Sektion\n\nDas strukturelle Gerüst, in dem auf den Beispielseiten praktisch jeder andere\nBaustein sitzt: `.ep-section` mit dem optionalen Kopf-Trio aus Kicker, Überschrift\nund Lead. 133 Vorkommen in den Beispielseiten, 85 davon mit Kopfzeile. Das\nAngular-Bauteil ist `Komponenten/Sektion/Sektion` (`[cdsSection]`).\n\nQuelle: `docs/index.html#sec-section`.\n\n## Aufbau\n\nDrei Klassen bilden den Kopf: `.ep-section-label` (Kicker, bereichsfärbbar über\n`.t-co` / `.t-ki` / `.t-es` / `.t-wo`), `.ep-section-h2` (Überschrift) und\n`.ep-section-sub` (Lead). Alle drei sind Beiwerk: Eine Sektion besteht auch ganz\nohne Kopf, nur aus ihrem Inhalt darunter.\n\n```html\n<div class=\"ep-section\" style=\"background:var(--n-50)\">\n <div class=\"ep-section-label t-co\">Was wir tun</div>\n <h2 class=\"ep-section-h2\">So ist eine Sektion aufgebaut.</h2>\n <p class=\"ep-section-sub\">Kicker, Überschrift und Lead sind Beiwerk, der Inhalt darunter ist frei.</p>\n <!-- beliebiger Inhalt -->\n</div>\n```\n\n## Angular-Wrapper\n\n`[cdsSection]` ist ein Attributselektor statt eines eigenen Elements\n(`docs/adr/0008-selektortyp-der-wrapper-komponenten.md`). Der\nKonsument wählt das Tag: `<section cdsSection>` oder `<div cdsSection>`. Die\nKomponente setzt `aria-labelledby`, wenn ein zugänglicher Name verfügbar ist:\nentweder die eigene Überschrift oder eine per `labelledBy` übergebene id einer\nÜberschrift außerhalb der Komponente. Fehlt beides, setzt sie kein\n`aria-labelledby`.\n\n## Verwendung\n\nDie Fläche gehört der Seite, nicht dem Bauteil. Sektionen wechseln im Rhythmus\nzwischen `--bg-surface` und `--n-50`, auf einzelnen Sektionsflächen kommt\nzusätzlich eine Bereichstönung als Akzent vor. Welche Fläche eine Sektion trägt,\nhängt von ihren Nachbarn ab, und nur die Seite kennt diese Nachbarn. Deshalb setzt\n`.ep-section` selbst keinen Hintergrund, und `[cdsSection]` hat keinen\n`background`-Input: Die Fläche kommt per Klasse oder Inline-Style direkt an das\nElement, das `cdsSection` trägt (`<section cdsSection style=\"background:…\">`).\n\n## Dos & Don'ts\n\n**Tun**\n\n- Die Hintergrundfläche als Klasse oder Style auf dem Element setzen, das `cdsSection` trägt, im Wechsel mit den Nachbar-Sektionen.\n- Kicker, Überschrift und Lead weglassen, wenn eine Sektion keinen eigenen Kopf braucht.\n- Ohne eigene Überschrift `labelledBy` auf eine vorhandene Überschrift setzen, damit die Sektion einen zugänglichen Namen behält.\n\n**Nicht tun**\n\n- Eine Hintergrundfarbe fest in die Komponente einbauen, sie kennt ihre Nachbar-Sektionen nicht.\n- Mehrere getönte Sektionen direkt hintereinander setzen, das wirkt schnell bunt statt ruhig.\n- Im Angular-Wrapper `<section cdsSection>` ohne Überschrift und ohne `labelledBy` schreiben, wenn `<div cdsSection>` genügt: die Sektion bliebe für Screenreader ohnehin namenlos, das Tag verspricht aber eine Landmark, die nie entsteht.\n",
|
|
13
13
|
"summary": "# Sektion Das strukturelle Gerüst, in dem auf den Beispielseiten praktisch jeder andere Ba..."
|
|
14
14
|
}
|
|
15
15
|
}
|
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
"name": "Verwendung",
|
|
10
10
|
"path": "./src/docs/komponenten/theme-umschalter.mdx",
|
|
11
11
|
"title": "Komponenten/Theme-Umschalter",
|
|
12
|
-
"content": "import { Meta } from '@storybook/addon-docs/blocks';\n\n<Meta title=\"Komponenten/Theme-Umschalter\" name=\"Verwendung\" tags={['angular']} />\n\n# Theme-Umschalter · Verwendung\n\
|
|
13
|
-
"summary": "# Theme-Umschalter · Verwendung
|
|
12
|
+
"content": "import { Meta } from '@storybook/addon-docs/blocks';\n\n<Meta title=\"Komponenten/Theme-Umschalter\" name=\"Verwendung\" tags={['angular']} />\n\n# Theme-Umschalter · Verwendung\n\n`docs/index.html` hat für den Theme-Umschalter eine eigene Sektion (`sec-theme`,\nÜberschrift „Theme-Umschalter“) mit einem `gt-theme-verwendung`-Block. Deren\nPlatzierungsregeln (welches der drei Bauteile wo eingesetzt wird) folgen hier\nnoch. Diese Seite beschreibt deshalb vor allem das Bauteil aus dem Repo selbst:\nder Angular-Lib\n(`angular-lib/projects/design-system-angular/src/lib/theme-switch/`) und der\nStorybook-Konfiguration (`.storybook/preview.ts`).\n\n## Dreistufiger Modus\n\n`CdsThemeMode` kennt drei Werte: `light`, `dark`, `system`. `system` folgt der\nBetriebssystem-Einstellung (`prefers-color-scheme`). Die Reihenfolge, in der alle\ndrei Umschalter zyklen beziehungsweise Optionen anbieten, ist fest:\n`CDS_THEME_ORDER = ['light', 'dark', 'system']`.\n\n| Modus | Label | Icon-Key |\n|---|---|---|\n| `light` | Hell | `heroSun` |\n| `dark` | Dunkel | `heroMoon` |\n| `system` | System | `heroComputerDesktop` |\n\nAlle drei Umschalter teilen denselben `showSystem`-Parameter: `true` zeigt alle drei\nModi (tri), `false` blendet „System“ aus und zyklt nur zwischen Hell und Dunkel\n(binär). Die Auswahl trifft `cdsThemeModes(showSystem)` in `theme-mode.ts`.\n\n## `themeStore` als einziger Schreiber von `data-theme`\n\nAlle drei Komponenten und die Storybook-Toolbar lesen und schreiben über\n`themeStore` (`theme-mode.ts`), eine modul-globale Quelle, kein Angular-Service:\nJede Story hat ihre eigene App-Instanz mit eigenem Root-Injector, Angular-DI allein\nwürde den Zustand also nicht über alle Stories hinweg teilen. `ThemeModeService` ist\nnur ein dünner Injectable-Wrapper darüber für `inject(ThemeModeService)` im\ngewohnten Muster.\n\n`themeStore` ist die **einzige** Stelle im System, die das Attribut `data-theme` am\n`<html>`-Element setzt oder entfernt:\n\n- `dark` gesetzt → `data-theme=\"dark\"`.\n- `light` → Attribut entfernt (Light ist der Default ohne Attribut).\n- `system` → koppelt live an `window.matchMedia('(prefers-color-scheme: dark)')`\n und reflektiert dessen `matches`-Wert als `dark` oder `light`; ein\n `change`-Listener hält das synchron, solange der Modus `system` bleibt.\n\nEin `document`/`window`-Guard schützt SSR und Prerendering: Ohne `document` wird\ndas Attribut übersprungen, der Modus bleibt im Signal erhalten und greift, sobald im\nBrowser das nächste `apply()` läuft. Die Lib fasst den globalen Cascade sonst nicht\nan (siehe `docs/adr/0001`).\n\n## Synchronisation mit der Storybook-Toolbar\n\n`.storybook/preview.ts` verdrahtet zwei Richtungen:\n\n1. **Store → Toolbar.** `themeStore.subscribe(...)` emittiert bei jeder Änderung\n `UPDATE_GLOBALS` an den Storybook-Channel, damit der globale\n Theme-Toolbar-Schalter mitwandert, wenn eine Story-Komponente den Modus ändert.\n2. **Toolbar → Store.** Ein Decorator ruft bei jedem Kontextwechsel\n `themeStore.setSilent(context.globals['theme'])` auf: `setSilent` wendet den\n Modus an, **ohne** erneut zu emittieren, sonst entstünde eine Rückkopplungs-\n schleife zwischen Toolbar und Store.\n\nDamit bleiben Toolbar, Docs-Vorschau und alle drei Switcher-Komponenten immer\ndenselben Modus zeigen. Das Docs-Chrome selbst (Überschriften, Tabellen) bleibt\ndavon unabhängig immer im Light-Theme (`concisoLight`), weil Storybook Toolbar- und\nDocs-Theme nicht koppelt.\n\n## Dark Mode: der Unterbau aus der CSS-Schicht\n\nDer CSS-Schicht-Vertrag (`docs/GETTING-STARTED.md` § 3) kennt nur ein Attribut:\n\n```js\ndocument.documentElement.setAttribute('data-theme', 'dark'); // dunkel\ndocument.documentElement.removeAttribute('data-theme'); // hell (Default)\n```\n\n**Genau zwei Modi in der ausgelieferten CSS.** Das System kennt Light und Dark,\nkeinen dritten Modus, der der Betriebssystem-Präferenz folgt: `prefers-color-scheme`\nwird im ausgelieferten CSS nicht ausgewertet, Default ist Light. Der dritte,\nUI-seitige Modus „System“ der drei Theme-Umschalter-Komponenten liegt deshalb eine\nEbene **über** der CSS-Schicht: `themeStore` löst `system` selbst über\n`matchMedia` auf und schreibt der CSS-Schicht am Ende immer nur einen der zwei\nZustände, die sie kennt (`data-theme=\"dark\"` gesetzt oder entfernt). Ein Consumer,\nder die Betriebssystem-Präferenz ohne diese Komponenten übernehmen will, wertet sie\nim eigenen Produkt genauso aus:\n\n```js\nif (matchMedia('(prefers-color-scheme: dark)').matches)\n document.documentElement.setAttribute('data-theme', 'dark');\n```\n\n**Anti-Flash-Snippet.** Als erstes Skript im `<head>`, vor dem CSS-Paint, damit beim\nReload nicht kurz Light aufblitzt. Liest die gespeicherte Präferenz aus\n`localStorage`:\n\n```html\n<script>\n (function(){\n try {\n var t = localStorage.getItem('ds-theme');\n if (t && t !== 'light') document.documentElement.setAttribute('data-theme', t);\n } catch(e) {}\n })();\n</script>\n```\n\nPersistenz beim Umschalten: `localStorage.setItem('ds-theme', 'dark' | 'light')`.\nDie drei Angular-Umschalter selbst persistieren nicht; das bleibt Aufgabe des\nConsumers, der `themeStore.subscribe(...)` an die eigene Persistenz anschließt.\n\n**Warum das für jede Komponente gilt (CONTRIBUTING § 5).** `data-theme` ist der\neinzige Schalter im System: Alle Token flippen darüber, keine Komponente wertet\n`prefers-color-scheme` selbst aus oder führt eine eigene dritte Flächen-Stufe ein.\nWeil `themeStore` der einzige Schreiber dieses Attributs ist, bleibt diese Garantie\nauch mit drei unterschiedlichen Umschalter-Bauteilen (Cycle-Button, Segment,\nDropdown) und der Storybook-Toolbar intakt: Es gibt genau eine Quelle der Wahrheit\nfür den Modus, unabhängig davon, über welchen Umschalter er gesetzt wurde.\n\n## Verwandte Seiten\n\n- `Komponenten/Theme-Umschalter/Cycle-Button` (Icon-Button, ein Klick zyklt durch die Modi, vorgesehen für den Header)\n- `Komponenten/Theme-Umschalter/Segment` (Segment-Leiste zum Hovern, immer responsiv und animiert)\n- `Komponenten/Theme-Umschalter/Dropdown` (Custom Select, vorgesehen nur in den Einstellungen, nicht als persistentes Element)\n",
|
|
13
|
+
"summary": "# Theme-Umschalter · Verwendung `docs/index.html` hat für den Theme-Umschalter eine eigene..."
|
|
14
14
|
}
|
|
15
15
|
}
|
|
16
16
|
}
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"name": "Übersicht",
|
|
10
10
|
"path": "./src/docs/marke/bildsprache.mdx",
|
|
11
11
|
"title": "Marke/Bildsprache",
|
|
12
|
-
"content": "import { Meta, Unstyled } from '@storybook/addon-docs/blocks';\nimport icons from '../../../../icons/icons.json';\n\n<Meta title=\"Marke/Bildsprache\" name=\"Übersicht\" />\n\n# Bildsprache\n\nFotografie · Illustration · vier Brand Areas, abgeleitet aus dem Markenrad.\n\nBilder kommunizieren schneller als Worte. Die Bildsprache von Conciso übersetzt den Kernwert **Gelassenheit** in visuelle Reize: ruhige Kompositionen, klare Motive und echte Energie statt inszenierter Hochglanz-Ästhetik.\n\n## Grundprinzipien aus dem Markenrad\n\nJeder der drei Markenpfeiler übersetzt sich direkt in visuelle Entscheidungen, von der Wahl des Motivs bis zur Bildbearbeitung.\n\n| Markenpfeiler | Eigenschaften | Bildsprache-Übersetzung |\n|---|---|---|\n| Ruhig | Verlässlich · Selbstsicher · Kompetent | Ausgewogene Komposition, großzügiger Weißraum, natürliches, diffuses Licht ohne harte Schatten, keine überfüllten Bildausschnitte |\n| Klar | Aufmerksam · Präzise · Pragmatisch | Scharfer Motivfokus, aufgeräumte Hintergründe, ein dominantes Motiv pro Bild, kein dekoratives Beiwerk ohne Zweck |\n| Energiegeladen | Kraftvoll · Agil · Leidenschaftlich | Echte Momente statt Pose, Menschen in echter Konzentration oder Zusammenarbeit, Bewegung und Dynamik, ohne Unruhe zu erzeugen |\n\n## Fotografie\n\nJede Brand Area hat einen eigenen Bildkontext, die gemeinsamen Stilprinzipien (siehe unten) gelten übergreifend. Reihenfolge co · ki · es · wo.\n\n**Corporate · Vertrauen & Kompetenz.** Menschen im Gespräch, beim Beratungsgespräch oder in ruhiger Konzentration, neutrale, helle Büroumgebungen, Handshakes und partnerschaftliche Gesten, Blickkontakt und Offenheit. Stichworte: Gespräch, Partnerschaft, Büroatmosphäre.\n\n**Angewandte KI · Mensch & Technologie.** Nahaufnahmen von Screens und Interfaces, Menschen, die mit KI-Tools interagieren, abstrakte Datenmuster als visuelle Akzente, immer mit menschlichem Fokus: Technologie ist Werkzeug, nicht Hauptdarsteller. Stichworte: Interfaces, Interaktion, Muster & Daten.\n\n**Effektive Software · Fokus & Präzision.** Nahaufnahmen von Code und Interfaces, Entwickler in tiefer Konzentration, saubere, aufgeräumte Screens, Terminal, IDE und Architekturdiagramme als visuelle Metaphern. Stichworte: Code, Interfaces, Konzentration.\n\n**Wirksame Organisationen · Kollaboration & Wirkung.** Diverse Teams in echter Zusammenarbeit, Workshops, Retrospektiven, Whiteboard-Momente, echte Emotionen wie Lachen und Konzentration, keine uniformen Gruppenfotos ohne Leben. Stichworte: Teams, Workshop, Echte Momente.\n\n**Ergänzung aus `conciso-claude-powerpoint-instructions.md` § 7.2** (dort geführt, in der Doku-Sektion nicht vollständig): Effektive Software zusätzlich mit dem Stichwort *geometrische Strukturen*, Wirksame Organisationen zusätzlich mit *organische Strukturen* und *Wandel*.\n\nStorybook bindet bewusst keine Personenfotos ein: Der folgende Block zeigt je Brand Area nur den Bildslot und seine Bereichsfarbe, nicht das Motiv.\n\nexport const imagerySlots = [\n { area: 'co', iconKey: 'co-building', name: 'Corporate', keywords: 'Gespräch, Partnerschaft, Büroatmosphäre' },\n { area: 'ki', iconKey: 'ki-bot', name: 'Angewandte KI', keywords: 'Interfaces, Interaktion, Muster & Daten' },\n { area: 'es', iconKey: 'es-window-check', name: 'Effektive Software', keywords: 'Code, Interfaces, Konzentration' },\n { area: 'wo', iconKey: 'wo-network', name: 'Wirksame Organisationen', keywords: 'Teams, Workshop, Echte Momente' },\n];\n\nexport const ImagerySlot = ({ area, iconKey, name, keywords }) => {\n const icon = icons[iconKey];\n const svgAttrs =\n icon.style === 'solid'\n ? { fill: 'currentColor' }\n : { fill: 'none', stroke: 'currentColor', strokeWidth: icon.strokeWidth || '1' };\n return (\n <div className=\"card\" data-area={area}>\n <div className=\"card-media\">\n <svg\n viewBox={icon.viewBox}\n width={64}\n height={64}\n aria-hidden=\"true\"\n {...svgAttrs}\n dangerouslySetInnerHTML={{ __html: icon.body }}\n />\n </div>\n <div className=\"card-body\">\n <span className=\"card-eyebrow\">{name}</span>\n <p className=\"card-text\">{keywords}</p>\n </div>\n </div>\n );\n};\n\n<Unstyled>\n <div\n style={{\n display: 'grid',\n gridTemplateColumns: 'repeat(auto-fit, minmax(220px, 1fr))',\n gap: 'var(--s5)',\n }}\n >\n {imagerySlots.map((slot) => (\n <ImagerySlot key={slot.area} {...slot} />\n ))}\n </div>\n</Unstyled>\n\nDie Kacheln oben zeigen Slot, Seitenverhältnis (16:9) und Bereichsfarbe je Brand Area; konkrete Beispielfotos zeigt weiterhin die Doku-Site (`docs/index.html#gt-imagery-beispiele`).\n\n## Stilprinzipien Fotografie\n\n- **Licht & Ton.** Natürliches, weiches Licht, helle, leicht entsättigte Töne, kein Filmdrama, kein HDR, Helligkeit leicht anheben, Kontrast etwas reduzieren.\n- **Komposition.** Drittel-Regel und goldener Schnitt, Freiflächen für Text-Overlays einplanen, ein dominantes Motiv, ruhige Umgebung, kein Informations-Overload im Bild.\n- **Menschen.** Authentische Personen aus echten Arbeitskontexten, diverse Repräsentation, Blickkontakt oder echte Konzentration, keine Stockphoto-Posen.\n\n## Illustration\n\nIllustrationen werden ergänzend eingesetzt, für abstrakte Konzepte, die sich nicht fotografisch abbilden lassen: KI-Prozesse, Systemarchitektur, Organisationsmodelle.\n\n- **Linienstil.** Klare, gleichmäßige Linien, keine Füllflächen ohne Bedeutung, Strichstärke konsistent.\n- **Geometrisch.** Vereinfachte Formen statt realistischer Darstellung, keine Gradients innerhalb von Figuren.\n- **Systemfarben.** Ausschließlich Design-System-Tokens (`--co-500`, `--ki-500` und so weiter), keine Freihandfarben.\n- **Weißraum.** Leere Fläche ist gestalterisches Element, nicht jeder Pixel muss belegt sein, Illustration atmen lassen.\n\n## Verwendung\n\nKontext entscheidet über das richtige Bildformat: Hero-Bereiche brauchen Freiräume für Text, Teaser-Cards arbeiten mit Ausschnitten, Illustrationen kommen dort zum Einsatz, wo Fotos zu konkret wären.\n\n| Kontext | Empfehlung |\n|---|---|\n| Hero-Bereich | Querformat, heller, ruhiger Hintergrund im Bild, untere Bildhälfte frei für Text-Overlay, Foto darf nicht mit der Headline konkurrieren |\n| Card / Teaser | 16:9 oder 3:2, Motiv mittig, kein Text im Bild selbst, Brand-Area-Farbe als Eyebrow über dem Bild, nicht als Tint im Bild |\n| Wissensartikel | Illustration für abstrakte Prozesse, Foto für Praxisbeispiele, Bildunterschrift immer vorhanden, Bilder nie als einziger Informationsträger |\n| Testimonial | Porträt im quadratischen oder runden Ausschnitt, Blick zur Kamera oder leicht seitlich, neutraler, heller Hintergrund, kein Hintergrund-Clutter |\n\n### Barrierefreiheit\n\n| Aspekt | Regel |\n|---|---|\n| Alt-Text | Jedes inhaltstragende Bild benötigt einen beschreibenden `alt`-Text: er beschreibt, was zu sehen ist, nicht was das Bild bedeutet. Dekorative Bilder erhalten `alt=\"\"` |\n| Text-Overlay | Text auf Foto-Hintergründen mindestens 4,5:1 (WCAG 1.4.3), gerechnet gegen die hellste Stelle unter dem Text, nicht gegen den Bilddurchschnitt: Fotos haben ausgebrannte Bereiche, dort entscheidet sich die Lesbarkeit. Weiße Schrift braucht dafür einen Scrim von mindestens `rgba(0,0,0,.60)`, `.45` reicht nicht (trägt über einer weißen Bildstelle nur rund 3:1). Bei einem Verlauf gilt der Wert an der Stelle, an der der Text sitzt, nicht am dichten Ende. `text-shadow` hilft optisch, zählt für WCAG nicht |\n| Auslaufstrecke des Scrims | Genauso wichtig wie der Deckkraft-Wert ist die Strecke, über die er aufgebaut wird: ein Verlauf fällt dort auf, wo seine Steilheit springt, nicht wo er dicht ist. Faustwert: rund 0,007 Deckkraft pro Pixel. Für 0,6 Deckkraft am obersten Textelement sind das etwa 90 px Auslauf darüber. Reicht die Höhe nicht, wächst die Polsterung, nicht die Steilheit |\n| Nicht allein | Informationen nie ausschließlich im Bild transportieren, der gleiche Inhalt muss als Text verfügbar sein (WCAG 1.1.1) |\n| Bewegung | Animierte Illustrationen oder Hintergrund-Videos mit `prefers-reduced-motion` pausieren |\n\n### Dos & Don'ts\n\n✓ Tun\n\n- Authentische Menschen aus echten Arbeitskontexten wählen, kein gestelltes Stockphoto-Lächeln.\n- Helles, leicht entsättigtes Farbklima beibehalten, Gelassenheit überträgt sich auf die Bildstimmung.\n- Freiraum für Text-Overlays im Bild einplanen, besonders bei Hero-Fotos.\n- Illustrationen ausschließlich mit Design-System-Tokens, Farb-Konsistenz auch im SVG.\n- Brand-Area-Farbe als Kontext-Element um das Bild herum einsetzen, nicht als Farbfilter im Bild.\n\n✕ Nicht tun\n\n- Generische Stockfotos (lachende Gruppe am Tisch, Handshake vor weißem Hintergrund): wirken unecht und austauschbar.\n- Übersättigte oder hochkontrastige Bearbeitungen widersprechen dem Markenwert Gelassenheit.\n- Bereichsfarbe als Tint-Filter über das Foto legen, wirkt aufdringlich und überdeckt die natürliche Bildstimmung.\n- Realistische oder fotografische Illustrationsstile, das bricht den klaren, geometrischen Linienstil.\n- Bilder ohne `alt`-Text oder mit generischem „Foto“: Screenreader-Nutzende erhalten keinen Mehrwert.\n",
|
|
12
|
+
"content": "import { Meta, Unstyled } from '@storybook/addon-docs/blocks';\nimport icons from '../../../../icons/icons.json';\n\n<Meta title=\"Marke/Bildsprache\" name=\"Übersicht\" />\n\n# Bildsprache\n\nFotografie · Illustration · vier Brand Areas, abgeleitet aus dem Markenrad.\n\nBilder kommunizieren schneller als Worte. Die Bildsprache von Conciso übersetzt den Kernwert **Gelassenheit** in visuelle Reize: ruhige Kompositionen, klare Motive und echte Energie statt inszenierter Hochglanz-Ästhetik.\n\n## Grundprinzipien aus dem Markenrad\n\nJeder der drei Markenpfeiler übersetzt sich direkt in visuelle Entscheidungen, von der Wahl des Motivs bis zur Bildbearbeitung.\n\n| Markenpfeiler | Eigenschaften | Bildsprache-Übersetzung |\n|---|---|---|\n| Ruhig | Verlässlich · Selbstsicher · Kompetent | Ausgewogene Komposition, großzügiger Weißraum, natürliches, diffuses Licht ohne harte Schatten, keine überfüllten Bildausschnitte |\n| Klar | Aufmerksam · Präzise · Pragmatisch | Scharfer Motivfokus, aufgeräumte Hintergründe, ein dominantes Motiv pro Bild, kein dekoratives Beiwerk ohne Zweck |\n| Energiegeladen | Kraftvoll · Agil · Leidenschaftlich | Echte Momente statt Pose, Menschen in echter Konzentration oder Zusammenarbeit, Bewegung und Dynamik, ohne Unruhe zu erzeugen |\n\n## Fotografie\n\nJede Brand Area hat einen eigenen Bildkontext, die gemeinsamen Stilprinzipien (siehe unten) gelten übergreifend. Reihenfolge co · ki · es · wo.\n\n**Corporate · Vertrauen & Kompetenz.** Menschen im Gespräch, beim Beratungsgespräch oder in ruhiger Konzentration, neutrale, helle Büroumgebungen, Handshakes und partnerschaftliche Gesten, Blickkontakt und Offenheit. Stichworte: Gespräch, Partnerschaft, Büroatmosphäre.\n\n**Angewandte KI · Mensch & Technologie.** Nahaufnahmen von Screens und Interfaces, Menschen, die mit KI-Tools interagieren, abstrakte Datenmuster als visuelle Akzente, immer mit menschlichem Fokus: Technologie ist Werkzeug, nicht Hauptdarsteller. Stichworte: Interfaces, Interaktion, Muster & Daten.\n\n**Effektive Software · Fokus & Präzision.** Nahaufnahmen von Code und Interfaces, Entwickler in tiefer Konzentration, saubere, aufgeräumte Screens, Terminal, IDE und Architekturdiagramme als visuelle Metaphern. Stichworte: Code, Interfaces, Konzentration.\n\n**Wirksame Organisationen · Kollaboration & Wirkung.** Diverse Teams in echter Zusammenarbeit, Workshops, Retrospektiven, Whiteboard-Momente, echte Emotionen wie Lachen und Konzentration, keine uniformen Gruppenfotos ohne Leben. Stichworte: Teams, Workshop, Echte Momente.\n\n**Ergänzung aus `docs/marke/conciso-claude-powerpoint-instructions.md` § 7.2** (dort geführt, in der Doku-Sektion nicht vollständig): Effektive Software zusätzlich mit dem Stichwort *geometrische Strukturen*, Wirksame Organisationen zusätzlich mit *organische Strukturen* und *Wandel*.\n\nStorybook bindet bewusst keine Personenfotos ein: Der folgende Block zeigt je Brand Area nur den Bildslot und seine Bereichsfarbe, nicht das Motiv.\n\nexport const imagerySlots = [\n { area: 'co', iconKey: 'co-building', name: 'Corporate', keywords: 'Gespräch, Partnerschaft, Büroatmosphäre' },\n { area: 'ki', iconKey: 'ki-bot', name: 'Angewandte KI', keywords: 'Interfaces, Interaktion, Muster & Daten' },\n { area: 'es', iconKey: 'es-window-check', name: 'Effektive Software', keywords: 'Code, Interfaces, Konzentration' },\n { area: 'wo', iconKey: 'wo-network', name: 'Wirksame Organisationen', keywords: 'Teams, Workshop, Echte Momente' },\n];\n\nexport const ImagerySlot = ({ area, iconKey, name, keywords }) => {\n const icon = icons[iconKey];\n const svgAttrs =\n icon.style === 'solid'\n ? { fill: 'currentColor' }\n : { fill: 'none', stroke: 'currentColor', strokeWidth: icon.strokeWidth || '1' };\n return (\n <div className=\"card\" data-area={area}>\n <div className=\"card-media\">\n <svg\n viewBox={icon.viewBox}\n width={64}\n height={64}\n aria-hidden=\"true\"\n {...svgAttrs}\n dangerouslySetInnerHTML={{ __html: icon.body }}\n />\n </div>\n <div className=\"card-body\">\n <span className=\"card-eyebrow\">{name}</span>\n <p className=\"card-text\">{keywords}</p>\n </div>\n </div>\n );\n};\n\n<Unstyled>\n <div\n style={{\n display: 'grid',\n gridTemplateColumns: 'repeat(auto-fit, minmax(220px, 1fr))',\n gap: 'var(--s5)',\n }}\n >\n {imagerySlots.map((slot) => (\n <ImagerySlot key={slot.area} {...slot} />\n ))}\n </div>\n</Unstyled>\n\nDie Kacheln oben zeigen Slot, Seitenverhältnis (16:9) und Bereichsfarbe je Brand Area; konkrete Beispielfotos zeigt weiterhin die Doku-Site (`docs/index.html#gt-imagery-beispiele`).\n\n## Stilprinzipien Fotografie\n\n- **Licht & Ton.** Natürliches, weiches Licht, helle, leicht entsättigte Töne, kein Filmdrama, kein HDR, Helligkeit leicht anheben, Kontrast etwas reduzieren.\n- **Komposition.** Drittel-Regel und goldener Schnitt, Freiflächen für Text-Overlays einplanen, ein dominantes Motiv, ruhige Umgebung, kein Informations-Overload im Bild.\n- **Menschen.** Authentische Personen aus echten Arbeitskontexten, diverse Repräsentation, Blickkontakt oder echte Konzentration, keine Stockphoto-Posen.\n\n## Illustration\n\nIllustrationen werden ergänzend eingesetzt, für abstrakte Konzepte, die sich nicht fotografisch abbilden lassen: KI-Prozesse, Systemarchitektur, Organisationsmodelle.\n\n- **Linienstil.** Klare, gleichmäßige Linien, keine Füllflächen ohne Bedeutung, Strichstärke konsistent.\n- **Geometrisch.** Vereinfachte Formen statt realistischer Darstellung, keine Gradients innerhalb von Figuren.\n- **Systemfarben.** Ausschließlich Design-System-Tokens (`--co-500`, `--ki-500` und so weiter), keine Freihandfarben.\n- **Weißraum.** Leere Fläche ist gestalterisches Element, nicht jeder Pixel muss belegt sein, Illustration atmen lassen.\n\n## Verwendung\n\nKontext entscheidet über das richtige Bildformat: Hero-Bereiche brauchen Freiräume für Text, Teaser-Cards arbeiten mit Ausschnitten, Illustrationen kommen dort zum Einsatz, wo Fotos zu konkret wären.\n\n| Kontext | Empfehlung |\n|---|---|\n| Hero-Bereich | Querformat, heller, ruhiger Hintergrund im Bild, untere Bildhälfte frei für Text-Overlay, Foto darf nicht mit der Headline konkurrieren |\n| Card / Teaser | 16:9 oder 3:2, Motiv mittig, kein Text im Bild selbst, Brand-Area-Farbe als Eyebrow über dem Bild, nicht als Tint im Bild |\n| Wissensartikel | Illustration für abstrakte Prozesse, Foto für Praxisbeispiele, Bildunterschrift immer vorhanden, Bilder nie als einziger Informationsträger |\n| Testimonial | Porträt im quadratischen oder runden Ausschnitt, Blick zur Kamera oder leicht seitlich, neutraler, heller Hintergrund, kein Hintergrund-Clutter |\n\n### Barrierefreiheit\n\n| Aspekt | Regel |\n|---|---|\n| Alt-Text | Jedes inhaltstragende Bild benötigt einen beschreibenden `alt`-Text: er beschreibt, was zu sehen ist, nicht was das Bild bedeutet. Dekorative Bilder erhalten `alt=\"\"` |\n| Text-Overlay | Text auf Foto-Hintergründen mindestens 4,5:1 (WCAG 1.4.3), gerechnet gegen die hellste Stelle unter dem Text, nicht gegen den Bilddurchschnitt: Fotos haben ausgebrannte Bereiche, dort entscheidet sich die Lesbarkeit. Weiße Schrift braucht dafür einen Scrim von mindestens `rgba(0,0,0,.60)`, `.45` reicht nicht (trägt über einer weißen Bildstelle nur rund 3:1). Bei einem Verlauf gilt der Wert an der Stelle, an der der Text sitzt, nicht am dichten Ende. `text-shadow` hilft optisch, zählt für WCAG nicht |\n| Auslaufstrecke des Scrims | Genauso wichtig wie der Deckkraft-Wert ist die Strecke, über die er aufgebaut wird: ein Verlauf fällt dort auf, wo seine Steilheit springt, nicht wo er dicht ist. Faustwert: rund 0,007 Deckkraft pro Pixel. Für 0,6 Deckkraft am obersten Textelement sind das etwa 90 px Auslauf darüber. Reicht die Höhe nicht, wächst die Polsterung, nicht die Steilheit |\n| Nicht allein | Informationen nie ausschließlich im Bild transportieren, der gleiche Inhalt muss als Text verfügbar sein (WCAG 1.1.1) |\n| Bewegung | Animierte Illustrationen oder Hintergrund-Videos mit `prefers-reduced-motion` pausieren |\n\n### Dos & Don'ts\n\n✓ Tun\n\n- Authentische Menschen aus echten Arbeitskontexten wählen, kein gestelltes Stockphoto-Lächeln.\n- Helles, leicht entsättigtes Farbklima beibehalten, Gelassenheit überträgt sich auf die Bildstimmung.\n- Freiraum für Text-Overlays im Bild einplanen, besonders bei Hero-Fotos.\n- Illustrationen ausschließlich mit Design-System-Tokens, Farb-Konsistenz auch im SVG.\n- Brand-Area-Farbe als Kontext-Element um das Bild herum einsetzen, nicht als Farbfilter im Bild.\n\n✕ Nicht tun\n\n- Generische Stockfotos (lachende Gruppe am Tisch, Handshake vor weißem Hintergrund): wirken unecht und austauschbar.\n- Übersättigte oder hochkontrastige Bearbeitungen widersprechen dem Markenwert Gelassenheit.\n- Bereichsfarbe als Tint-Filter über das Foto legen, wirkt aufdringlich und überdeckt die natürliche Bildstimmung.\n- Realistische oder fotografische Illustrationsstile, das bricht den klaren, geometrischen Linienstil.\n- Bilder ohne `alt`-Text oder mit generischem „Foto“: Screenreader-Nutzende erhalten keinen Mehrwert.\n",
|
|
13
13
|
"summary": "# Bildsprache Fotografie · Illustration · vier Brand Areas, abgeleitet aus dem Markenrad. ..."
|
|
14
14
|
}
|
|
15
15
|
}
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"name": "Übersicht",
|
|
10
10
|
"path": "./src/docs/marke/markenrad.mdx",
|
|
11
11
|
"title": "Marke/Markenrad",
|
|
12
|
-
"content": "import { Meta, Unstyled } from '@storybook/addon-docs/blocks';\n\n<Meta title=\"Marke/Markenrad\" name=\"Übersicht\" />\n\n# Markenrad\n\nDer Kernwert **Gelassenheit** entfaltet sich in drei Markenpfeilern (Ruhig, Klar, Energiegeladen) mit je drei charakterisierenden Eigenschaften. Das Unternehmen erzeugt Gelassenheit, auf ruhige, klare und energiegeladene Weise.\n\nDiese Seite ist die Begründungsschicht für die übrige Marke-Dokumentation (Brand Areas, Logo, Bildsprache): Wer eine dortige Regel hinterfragt, findet die Begründung hier.\n\n{/* Geometrie bewusst aus docs/index.html dupliziert: die Doku-Site ist eine statische\n Einzeldatei ohne Build, es gibt keinen gemeinsamen Import-Pfad für dieses SVG. Farben\n und Schriftgrößen kommen aus den .bw-*-Klassen in css/components.css und\n css/dark-mode.css, deshalb stimmt das Rad in Light und Dark automatisch mit der\n Doku-Site überein. */}\n\n<Unstyled>\n <div className=\"bw-wrap\">\n <svg viewBox=\"0 0 520 520\" className=\"bw-svg\" role=\"img\" aria-labelledby=\"bw-title bw-desc\">\n <title id=\"bw-title\">Markenrad: Ruhige Energie</title>\n <desc id=\"bw-desc\">Kreisdiagramm mit Kernwert Gelassenheit im Zentrum. Pfeiler Ruhig mit den Eigenschaften Verlässlich, Selbstsicher, Kompetent. Pfeiler Klar mit Aufmerksam, Präzise, Pragmatisch. Pfeiler Energiegeladen mit Kraftvoll, Agil, Leidenschaftlich.</desc>\n\n <path className=\"bw-outer\" d=\"M 73.8 367.5 A 215 215 0 0 1 260 45 L 260 100 A 160 160 0 0 0 121.4 340 Z\" />\n <path className=\"bw-outer\" d=\"M 260 45 A 215 215 0 0 1 446.2 367.5 L 398.6 340 A 160 160 0 0 0 260 100 Z\" />\n <path className=\"bw-outer\" d=\"M 446.2 367.5 A 215 215 0 0 1 73.8 367.5 L 121.4 340 A 160 160 0 0 0 398.6 340 Z\" />\n\n <path className=\"bw-middle\" d=\"M 121.4 340 A 160 160 0 0 1 260 100 L 260 175 A 85 85 0 0 0 186.4 302.5 Z\" />\n <path className=\"bw-middle\" d=\"M 260 100 A 160 160 0 0 1 398.6 340 L 333.6 302.5 A 85 85 0 0 0 260 175 Z\" />\n <path className=\"bw-middle\" d=\"M 398.6 340 A 160 160 0 0 1 121.4 340 L 186.4 302.5 A 85 85 0 0 0 333.6 302.5 Z\" />\n\n <circle className=\"bw-inner\" cx=\"260\" cy=\"260\" r=\"85\" />\n\n <line className=\"bw-divider\" x1=\"260\" y1=\"260\" x2=\"260\" y2=\"45\" />\n <line className=\"bw-divider\" x1=\"260\" y1=\"260\" x2=\"446.2\" y2=\"367.5\" />\n <line className=\"bw-divider\" x1=\"260\" y1=\"260\" x2=\"73.8\" y2=\"367.5\" />\n\n <circle className=\"bw-ring-outline\" cx=\"260\" cy=\"260\" r=\"215\" />\n\n <text className=\"bw-label-core\" x=\"260\" y=\"260\" textAnchor=\"middle\" dominantBaseline=\"middle\">GELASSENHEIT</text>\n\n <text className=\"bw-label-segment\" x=\"154\" y=\"199\" textAnchor=\"middle\" dominantBaseline=\"middle\">RUHIG</text>\n <text className=\"bw-label-segment\" x=\"366\" y=\"199\" textAnchor=\"middle\" dominantBaseline=\"middle\">KLAR</text>\n <text className=\"bw-label-segment\" x=\"260\" y=\"382\" textAnchor=\"middle\" dominantBaseline=\"middle\">ENERGIEGELADEN</text>\n\n <text className=\"bw-label-attr\" x=\"75.8\" y=\"292.5\" textAnchor=\"middle\" dominantBaseline=\"middle\">VERLÄSSLICH</text>\n <text className=\"bw-label-attr\" x=\"98\" y=\"166.5\" textAnchor=\"middle\" dominantBaseline=\"middle\">SELBSTSICHER</text>\n <text className=\"bw-label-attr\" x=\"196\" y=\"84\" textAnchor=\"middle\" dominantBaseline=\"middle\">KOMPETENT</text>\n\n <text className=\"bw-label-attr\" x=\"324\" y=\"84\" textAnchor=\"middle\" dominantBaseline=\"middle\">AUFMERKSAM</text>\n <text className=\"bw-label-attr\" x=\"422\" y=\"166.5\" textAnchor=\"middle\" dominantBaseline=\"middle\">PRÄZISE</text>\n <text className=\"bw-label-attr\" x=\"444\" y=\"292.5\" textAnchor=\"middle\" dominantBaseline=\"middle\">PRAGMATISCH</text>\n\n <text className=\"bw-label-attr\" x=\"380\" y=\"403\" textAnchor=\"middle\" dominantBaseline=\"middle\">KRAFTVOLL</text>\n <text className=\"bw-label-attr\" x=\"260\" y=\"447\" textAnchor=\"middle\" dominantBaseline=\"middle\">AGIL</text>\n <text className=\"bw-label-attr\" x=\"140\" y=\"403\" textAnchor=\"middle\" dominantBaseline=\"middle\">LEIDENSCHAFTLICH</text>\n </svg>\n </div>\n</Unstyled>\n\n## Drei Markenpfeiler\n\n| Pfeiler | Eigenschaften | Sprachliche Wirkung |\n|---|---|---|\n| Ruhig | Verlässlich · Selbstsicher · Kompetent | nicht aufgeregt, keine Verkaufs-Rhetorik, keine Übertreibungen |\n| Klar | Aufmerksam · Präzise · Pragmatisch | konkret statt blumig, kurze Sätze, eindeutige Verben |\n| Energiegeladen | Kraftvoll · Agil · Leidenschaftlich | aktive Verben, Tempo wo angemessen, Überzeugung statt Floskel |\n\nWirkt ein Text wie auf einer Beratungs-Mainstream-Seite („visionäre Lösungen für die digitale Transformation“), ist er nicht im Conciso-Ton.\n\nDie neun Eigenschaften (verlässlich, selbstsicher, kompetent, aufmerksam, präzise, pragmatisch, kraftvoll, agil, leidenschaftlich) sollen in Karten-Texten und längerer Copy spürbar werden, gern visuell hervorgehoben (`<strong>`).\n\n## Sprache & Schreibweise\n\nPrimärsprache ist **Deutsch**: alle Customer-Pages, Marketing-Texte, UI-Labels, Komponenten-Beispieltexte und Design-System-Dokumentation. Englische Fachbegriffe (zum Beispiel Token-Namen, Komponenten-Klassen, Code-Beispiele) bleiben unverändert, im Fließtext wird der englische Begriff übersetzt oder erläutert. Lokalisierung in andere Sprachen ist nicht vorgesehen.\n\n### Anführungszeichen\n\nDeutsche Typografie-Konvention „99 … 66“: öffnend unten, schließend oben.\n\n| Zeichen | Unicode | Position |\n|---|---|---|\n| „ | U+201E | Öffnend, unten (sieht aus wie 99) |\n| “ | U+201C | Schließend, oben (sieht aus wie 66) |\n\nNicht verwenden: ASCII-`\"` (U+0022, gerade), `”` (U+201D, „99 oben“) oder die englische Konvention `“…”`. `npm run check:quotes` prüft das Gate, auch für nicht committete Dateien.\n\n### Keine Gedankenstriche\n\nEm-Dashes (U+2014) und En-Dashes (U+2013) in eigenen Copy-Texten vermeiden. Sie wirken im deutschen Lesefluss englisch-zitathaft und schwächen den ruhigen Markenton.\n\n| Statt | Lieber |\n|---|---|\n| Wir machen Software — und zwar gute. | Wir machen Software, und zwar gute. |\n| Drei Bereiche – ein Anspruch. | Drei Bereiche, ein Anspruch. |\n| Schau Dir an, wie wir arbeiten — oder buch direkt ein Erstgespräch. | Schau Dir an, wie wir arbeiten, oder buch direkt ein Erstgespräch. |\n\nErsatz: Komma, Doppelpunkt, Punkt oder Klammern. Der mittige Punkt `·` (U+00B7) bleibt als Trenner in Meta-Listen erlaubt („Bereich · Lesezeit“).\n\n### Schreibregeln aus der Mikrocopy\n\nAus `mikrocopy-conventions.md`, schärfer als die allgemeine Tonalität:\n\n- **Aktiv statt Passiv.** „Wir entwickeln Systeme, die halten“ statt „Es werden Systeme entwickelt, die halten“.\n- **Konkrete Verben statt Adjektiv-Nebel.** „Wir hören erst zu, dann bauen wir“ statt „Aufmerksamer, partnerschaftlicher Ansatz“.\n- **Kein Marketing-Sprech.** Vermeiden: „state-of-the-art“, „cutting-edge“, „next level“, „digital transformation“, „synergetische Lösungen“, Buzzwords ohne Substanz.\n- **Zahlen sprechen.** „120+ Projekte, 10 Jahre, 70+ Menschen“ statt „Langjährige Erfahrung mit zahlreichen Kunden“.\n\n## Tonalität: Du statt Sie\n\nAuf der gesamten Webseite spricht Conciso Leserinnen und Leser mit **Du** an. Diese Entscheidung ist keine Stilfrage, sondern fällt direkt aus dem Markenrad: Wer Gelassenheit erzeugen will, kann nicht in der Distanz des „Sie“ sprechen. Das Du ist der konsequenteste Weg, die drei Pfeiler in einem Wort zusammenzubringen, und bleibt höflich, weil die Tonalität ruhig, klar und ehrlich ist, nicht kumpelhaft.\n\n| Pfeiler | wird zu |\n|---|---|\n| Ruhig | Vertrauen ohne Distanz. Das Du nimmt das Förmliche heraus, ohne die Verlässlichkeit zu verlieren. |\n| Klar | Direktheit ohne Floskeln. Wir sagen, was Sache ist, kürzer, präziser, ohne Konjunktiv-Wolken. |\n| Energiegeladen | Persönlichkeit ohne Lautstärke. Das Du holt die Leser:innen ins Gespräch, nicht ins Auditorium. |\n\n**Anrede** (aus `mikrocopy-conventions.md`, schärfer als der allgemeine Grundsatz):\n\n- Du-Form durchgängig, kleingeschrieben im Fließtext: „Du schilderst Deine Situation.“\n- Großschreibung in der höflichen Anrede, in CTAs und Formularfeldern: „Wie können wir Dir helfen?“, „Dein Anliegen“.\n- Kein Mischen von Du- und Sie-Anreden auf einer Seite.\n- Das Du wird konsequent großgeschrieben (Du, Dir, Dein, Deinem): eine Stilentscheidung, kein Tippfehler.\n\n### Ausnahme: Wann das Sie gilt\n\nDas Du ist die Regel für alle öffentlichen und redaktionellen Texte. In der direkten Kommunikation zwischen Dienstleister und Kunde kann die Hierarchie ein Sie verlangen. Dann geht Angemessenheit vor Marke: im Zweifel lieber das Sie wählen, als die Anrede zu erzwingen. Das Du folgt, sobald das Gegenüber es anbietet oder selbst nutzt.\n\n- **E-Mail an Kund:innen.** Herrscht Unsicherheit über die passende Anrede, tendiert Conciso zum Sie. Ein zu früh gesetztes Du kann distanzlos wirken, gerade im schriftlichen Erstkontakt.\n- **Veranstaltungen mit Leadership-Fokus.** Bei Veranstaltungen, zu denen vorrangig Leadership- und Entscheider:innen-Positionen erwartet werden, erfolgt die Ansprache im Sie, in der Einladung wie vor Ort.\n\n## Was nicht geht\n\nAus `mikrocopy-conventions.md`:\n\n- Mischung Du / Sie auf einer Seite.\n- „Erfolgreich!“ als Bestätigungstext (Floskel).\n- Generische Button-Texte („Senden“, „OK“, „Weiter“).\n- Übertreibungen ohne Substanz.\n- Anglizismen, wo deutsche Worte präziser sind („Termin buchen“ statt „Slot booken“).\n",
|
|
12
|
+
"content": "import { Meta, Unstyled } from '@storybook/addon-docs/blocks';\n\n<Meta title=\"Marke/Markenrad\" name=\"Übersicht\" />\n\n# Markenrad\n\nDer Kernwert **Gelassenheit** entfaltet sich in drei Markenpfeilern (Ruhig, Klar, Energiegeladen) mit je drei charakterisierenden Eigenschaften. Das Unternehmen erzeugt Gelassenheit, auf ruhige, klare und energiegeladene Weise.\n\nDiese Seite ist die Begründungsschicht für die übrige Marke-Dokumentation (Brand Areas, Logo, Bildsprache): Wer eine dortige Regel hinterfragt, findet die Begründung hier.\n\n{/* Geometrie bewusst aus docs/index.html dupliziert: die Doku-Site ist eine statische\n Einzeldatei ohne Build, es gibt keinen gemeinsamen Import-Pfad für dieses SVG. Farben\n und Schriftgrößen kommen aus den .bw-*-Klassen in css/components.css und\n css/dark-mode.css, deshalb stimmt das Rad in Light und Dark automatisch mit der\n Doku-Site überein. */}\n\n<Unstyled>\n <div className=\"bw-wrap\">\n <svg viewBox=\"0 0 520 520\" className=\"bw-svg\" role=\"img\" aria-labelledby=\"bw-title bw-desc\">\n <title id=\"bw-title\">Markenrad: Ruhige Energie</title>\n <desc id=\"bw-desc\">Kreisdiagramm mit Kernwert Gelassenheit im Zentrum. Pfeiler Ruhig mit den Eigenschaften Verlässlich, Selbstsicher, Kompetent. Pfeiler Klar mit Aufmerksam, Präzise, Pragmatisch. Pfeiler Energiegeladen mit Kraftvoll, Agil, Leidenschaftlich.</desc>\n\n <path className=\"bw-outer\" d=\"M 73.8 367.5 A 215 215 0 0 1 260 45 L 260 100 A 160 160 0 0 0 121.4 340 Z\" />\n <path className=\"bw-outer\" d=\"M 260 45 A 215 215 0 0 1 446.2 367.5 L 398.6 340 A 160 160 0 0 0 260 100 Z\" />\n <path className=\"bw-outer\" d=\"M 446.2 367.5 A 215 215 0 0 1 73.8 367.5 L 121.4 340 A 160 160 0 0 0 398.6 340 Z\" />\n\n <path className=\"bw-middle\" d=\"M 121.4 340 A 160 160 0 0 1 260 100 L 260 175 A 85 85 0 0 0 186.4 302.5 Z\" />\n <path className=\"bw-middle\" d=\"M 260 100 A 160 160 0 0 1 398.6 340 L 333.6 302.5 A 85 85 0 0 0 260 175 Z\" />\n <path className=\"bw-middle\" d=\"M 398.6 340 A 160 160 0 0 1 121.4 340 L 186.4 302.5 A 85 85 0 0 0 333.6 302.5 Z\" />\n\n <circle className=\"bw-inner\" cx=\"260\" cy=\"260\" r=\"85\" />\n\n <line className=\"bw-divider\" x1=\"260\" y1=\"260\" x2=\"260\" y2=\"45\" />\n <line className=\"bw-divider\" x1=\"260\" y1=\"260\" x2=\"446.2\" y2=\"367.5\" />\n <line className=\"bw-divider\" x1=\"260\" y1=\"260\" x2=\"73.8\" y2=\"367.5\" />\n\n <circle className=\"bw-ring-outline\" cx=\"260\" cy=\"260\" r=\"215\" />\n\n <text className=\"bw-label-core\" x=\"260\" y=\"260\" textAnchor=\"middle\" dominantBaseline=\"middle\">GELASSENHEIT</text>\n\n <text className=\"bw-label-segment\" x=\"154\" y=\"199\" textAnchor=\"middle\" dominantBaseline=\"middle\">RUHIG</text>\n <text className=\"bw-label-segment\" x=\"366\" y=\"199\" textAnchor=\"middle\" dominantBaseline=\"middle\">KLAR</text>\n <text className=\"bw-label-segment\" x=\"260\" y=\"382\" textAnchor=\"middle\" dominantBaseline=\"middle\">ENERGIEGELADEN</text>\n\n <text className=\"bw-label-attr\" x=\"75.8\" y=\"292.5\" textAnchor=\"middle\" dominantBaseline=\"middle\">VERLÄSSLICH</text>\n <text className=\"bw-label-attr\" x=\"98\" y=\"166.5\" textAnchor=\"middle\" dominantBaseline=\"middle\">SELBSTSICHER</text>\n <text className=\"bw-label-attr\" x=\"196\" y=\"84\" textAnchor=\"middle\" dominantBaseline=\"middle\">KOMPETENT</text>\n\n <text className=\"bw-label-attr\" x=\"324\" y=\"84\" textAnchor=\"middle\" dominantBaseline=\"middle\">AUFMERKSAM</text>\n <text className=\"bw-label-attr\" x=\"422\" y=\"166.5\" textAnchor=\"middle\" dominantBaseline=\"middle\">PRÄZISE</text>\n <text className=\"bw-label-attr\" x=\"444\" y=\"292.5\" textAnchor=\"middle\" dominantBaseline=\"middle\">PRAGMATISCH</text>\n\n <text className=\"bw-label-attr\" x=\"380\" y=\"403\" textAnchor=\"middle\" dominantBaseline=\"middle\">KRAFTVOLL</text>\n <text className=\"bw-label-attr\" x=\"260\" y=\"447\" textAnchor=\"middle\" dominantBaseline=\"middle\">AGIL</text>\n <text className=\"bw-label-attr\" x=\"140\" y=\"403\" textAnchor=\"middle\" dominantBaseline=\"middle\">LEIDENSCHAFTLICH</text>\n </svg>\n </div>\n</Unstyled>\n\n## Drei Markenpfeiler\n\n| Pfeiler | Eigenschaften | Sprachliche Wirkung |\n|---|---|---|\n| Ruhig | Verlässlich · Selbstsicher · Kompetent | nicht aufgeregt, keine Verkaufs-Rhetorik, keine Übertreibungen |\n| Klar | Aufmerksam · Präzise · Pragmatisch | konkret statt blumig, kurze Sätze, eindeutige Verben |\n| Energiegeladen | Kraftvoll · Agil · Leidenschaftlich | aktive Verben, Tempo wo angemessen, Überzeugung statt Floskel |\n\nWirkt ein Text wie auf einer Beratungs-Mainstream-Seite („visionäre Lösungen für die digitale Transformation“), ist er nicht im Conciso-Ton.\n\nDie neun Eigenschaften (verlässlich, selbstsicher, kompetent, aufmerksam, präzise, pragmatisch, kraftvoll, agil, leidenschaftlich) sollen in Karten-Texten und längerer Copy spürbar werden, gern visuell hervorgehoben (`<strong>`).\n\n## Sprache & Schreibweise\n\nPrimärsprache ist **Deutsch**: alle Customer-Pages, Marketing-Texte, UI-Labels, Komponenten-Beispieltexte und Design-System-Dokumentation. Englische Fachbegriffe (zum Beispiel Token-Namen, Komponenten-Klassen, Code-Beispiele) bleiben unverändert, im Fließtext wird der englische Begriff übersetzt oder erläutert. Lokalisierung in andere Sprachen ist nicht vorgesehen.\n\n### Anführungszeichen\n\nDeutsche Typografie-Konvention „99 … 66“: öffnend unten, schließend oben.\n\n| Zeichen | Unicode | Position |\n|---|---|---|\n| „ | U+201E | Öffnend, unten (sieht aus wie 99) |\n| “ | U+201C | Schließend, oben (sieht aus wie 66) |\n\nNicht verwenden: ASCII-`\"` (U+0022, gerade), `”` (U+201D, „99 oben“) oder die englische Konvention `“…”`. `npm run check:quotes` prüft das Gate, auch für nicht committete Dateien.\n\n### Keine Gedankenstriche\n\nEm-Dashes (U+2014) und En-Dashes (U+2013) in eigenen Copy-Texten vermeiden. Sie wirken im deutschen Lesefluss englisch-zitathaft und schwächen den ruhigen Markenton.\n\n| Statt | Lieber |\n|---|---|\n| Wir machen Software — und zwar gute. | Wir machen Software, und zwar gute. |\n| Drei Bereiche – ein Anspruch. | Drei Bereiche, ein Anspruch. |\n| Schau Dir an, wie wir arbeiten — oder buch direkt ein Erstgespräch. | Schau Dir an, wie wir arbeiten, oder buch direkt ein Erstgespräch. |\n\nErsatz: Komma, Doppelpunkt, Punkt oder Klammern. Der mittige Punkt `·` (U+00B7) bleibt als Trenner in Meta-Listen erlaubt („Bereich · Lesezeit“).\n\n### Schreibregeln aus der Mikrocopy\n\nAus `docs/marke/mikrocopy-conventions.md`, schärfer als die allgemeine Tonalität:\n\n- **Aktiv statt Passiv.** „Wir entwickeln Systeme, die halten“ statt „Es werden Systeme entwickelt, die halten“.\n- **Konkrete Verben statt Adjektiv-Nebel.** „Wir hören erst zu, dann bauen wir“ statt „Aufmerksamer, partnerschaftlicher Ansatz“.\n- **Kein Marketing-Sprech.** Vermeiden: „state-of-the-art“, „cutting-edge“, „next level“, „digital transformation“, „synergetische Lösungen“, Buzzwords ohne Substanz.\n- **Zahlen sprechen.** „120+ Projekte, 10 Jahre, 70+ Menschen“ statt „Langjährige Erfahrung mit zahlreichen Kunden“.\n\n## Tonalität: Du statt Sie\n\nAuf der gesamten Webseite spricht Conciso Leserinnen und Leser mit **Du** an. Diese Entscheidung ist keine Stilfrage, sondern fällt direkt aus dem Markenrad: Wer Gelassenheit erzeugen will, kann nicht in der Distanz des „Sie“ sprechen. Das Du ist der konsequenteste Weg, die drei Pfeiler in einem Wort zusammenzubringen, und bleibt höflich, weil die Tonalität ruhig, klar und ehrlich ist, nicht kumpelhaft.\n\n| Pfeiler | wird zu |\n|---|---|\n| Ruhig | Vertrauen ohne Distanz. Das Du nimmt das Förmliche heraus, ohne die Verlässlichkeit zu verlieren. |\n| Klar | Direktheit ohne Floskeln. Wir sagen, was Sache ist, kürzer, präziser, ohne Konjunktiv-Wolken. |\n| Energiegeladen | Persönlichkeit ohne Lautstärke. Das Du holt die Leser:innen ins Gespräch, nicht ins Auditorium. |\n\n**Anrede** (aus `docs/marke/mikrocopy-conventions.md`, schärfer als der allgemeine Grundsatz):\n\n- Du-Form durchgängig, kleingeschrieben im Fließtext: „Du schilderst Deine Situation.“\n- Großschreibung in der höflichen Anrede, in CTAs und Formularfeldern: „Wie können wir Dir helfen?“, „Dein Anliegen“.\n- Kein Mischen von Du- und Sie-Anreden auf einer Seite.\n- Das Du wird konsequent großgeschrieben (Du, Dir, Dein, Deinem): eine Stilentscheidung, kein Tippfehler.\n\n### Ausnahme: Wann das Sie gilt\n\nDas Du ist die Regel für alle öffentlichen und redaktionellen Texte. In der direkten Kommunikation zwischen Dienstleister und Kunde kann die Hierarchie ein Sie verlangen. Dann geht Angemessenheit vor Marke: im Zweifel lieber das Sie wählen, als die Anrede zu erzwingen. Das Du folgt, sobald das Gegenüber es anbietet oder selbst nutzt.\n\n- **E-Mail an Kund:innen.** Herrscht Unsicherheit über die passende Anrede, tendiert Conciso zum Sie. Ein zu früh gesetztes Du kann distanzlos wirken, gerade im schriftlichen Erstkontakt.\n- **Veranstaltungen mit Leadership-Fokus.** Bei Veranstaltungen, zu denen vorrangig Leadership- und Entscheider:innen-Positionen erwartet werden, erfolgt die Ansprache im Sie, in der Einladung wie vor Ort.\n\n## Was nicht geht\n\nAus `docs/marke/mikrocopy-conventions.md`:\n\n- Mischung Du / Sie auf einer Seite.\n- „Erfolgreich!“ als Bestätigungstext (Floskel).\n- Generische Button-Texte („Senden“, „OK“, „Weiter“).\n- Übertreibungen ohne Substanz.\n- Anglizismen, wo deutsche Worte präziser sind („Termin buchen“ statt „Slot booken“).\n",
|
|
13
13
|
"summary": "# Markenrad Der Kernwert **Gelassenheit** entfaltet sich in drei Markenpfeilern (Ruhig, Kl..."
|
|
14
14
|
}
|
|
15
15
|
}
|
|
@@ -15,6 +15,11 @@
|
|
|
15
15
|
"name": "Deaktiviert",
|
|
16
16
|
"snippet": "import { Component } from '@angular/core';\nimport { RadioGroupComponent } from '@conciso/design-system-angular';\n\n@Component({\n selector: 'app-demo',\n imports: [RadioGroupComponent],\n template: `\n <cds-radio-group\n [legend]=\"'Bevorzugter Kontaktweg'\"\n [options]=\"['E-Mail', 'Telefon', 'Beides']\"\n [value]=\"'E-Mail'\"\n [required]=\"false\"\n [disabled]=\"true\"\n [area]=\"'co'\"\n (disabledChange)=\"disabledChange($event)\"\n (valueChange)=\"valueChange($event)\"\n />`,\n})\nexport class DemoComponent {\n disabledChange(event: unknown) {}\n valueChange(event: unknown) {}\n}"
|
|
17
17
|
},
|
|
18
|
+
"komponenten-inputs-forms-radio--pflichtfeld": {
|
|
19
|
+
"id": "komponenten-inputs-forms-radio--pflichtfeld",
|
|
20
|
+
"name": "Pflichtfeld",
|
|
21
|
+
"snippet": "import { Component } from '@angular/core';\nimport { RadioGroupComponent } from '@conciso/design-system-angular';\n\n@Component({\n selector: 'app-demo',\n imports: [RadioGroupComponent],\n template: `\n <cds-radio-group\n [legend]=\"'Bevorzugter Kontaktweg'\"\n [options]=\"['E-Mail', 'Telefon', 'Beides']\"\n [value]=\"'E-Mail'\"\n [required]=\"true\"\n [disabled]=\"false\"\n [area]=\"'co'\"\n (disabledChange)=\"disabledChange($event)\"\n (valueChange)=\"valueChange($event)\"\n />`,\n})\nexport class DemoComponent {\n disabledChange(event: unknown) {}\n valueChange(event: unknown) {}\n}"
|
|
22
|
+
},
|
|
18
23
|
"komponenten-inputs-forms-radio--tastatur": {
|
|
19
24
|
"id": "komponenten-inputs-forms-radio--tastatur",
|
|
20
25
|
"name": "Tastatur",
|
package/src/instructions.mjs
CHANGED
|
@@ -20,7 +20,15 @@ Feste Regeln für die Angular-Lib „@conciso/design-system-angular“:
|
|
|
20
20
|
1. CSS-Schicht und Fonts global einbinden, nicht pro Komponente. Ohne diesen Schritt bleiben die Wrapper-Komponenten ungestylt.
|
|
21
21
|
2. Kein eigenes CSS für DS-Komponenten schreiben und keine CSS-Klassen erfinden.
|
|
22
22
|
3. Nur Inputs und Outputs verwenden, die docs-show für die jeweilige Komponente liefert. Vorher nachsehen, nie raten.
|
|
23
|
-
4. Bei Fragen zur Einrichtung docs-show mit der ID „${EINRICHTUNG_DOC_ID}“ aufrufen (Storybook-Seite „Einrichtung“)
|
|
23
|
+
4. Bei Fragen zur Einrichtung docs-show mit der ID „${EINRICHTUNG_DOC_ID}“ aufrufen (Storybook-Seite „Einrichtung“).
|
|
24
|
+
5. Für Auswahl- und Gestaltungsfragen (welche Komponente, welche Variante, wo platzieren) zusätzlich die Verwendungsguidance heranziehen: Sie steht, wenn vorhanden, in der docs-show-Antwort der Komponente im Abschnitt „Docs“. Fehlt dieser Abschnitt, über docs-list nach einer Seite „Verwendung“ der Komponentengruppe suchen und sie mit docs-show laden.`;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Anzahl der oben nummerierten Regeln in OWN_INSTRUCTIONS. Exportiert, damit ein Test sie gegen
|
|
28
|
+
* die Regel-Liste in der Paket-README (mcp-server/README.md, Abschnitt „Was er kann“) absichern
|
|
29
|
+
* kann, ohne die Regeln selbst dafür zu duplizieren.
|
|
30
|
+
*/
|
|
31
|
+
export const OWN_RULE_COUNT = (OWN_INSTRUCTIONS.match(/^\d+\.\s/gm) ?? []).length;
|
|
24
32
|
|
|
25
33
|
/**
|
|
26
34
|
* Baut den vollständigen `instructions`-Text: eigene Regeln, optional die Versions-Notiz aus
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"components": {
|
|
3
|
-
"komponenten-buttons--verwendung": {
|
|
4
|
-
"id": "komponenten-buttons--verwendung",
|
|
5
|
-
"name": "komponenten-buttons--verwendung",
|
|
6
|
-
"docs": {
|
|
7
|
-
"komponenten-buttons--verwendung": {
|
|
8
|
-
"id": "komponenten-buttons--verwendung",
|
|
9
|
-
"name": "Verwendung",
|
|
10
|
-
"path": "./src/docs/komponenten/buttons-verwendung.mdx",
|
|
11
|
-
"title": "Komponenten/Buttons",
|
|
12
|
-
"content": "import { Meta, Unstyled } from '@storybook/addon-docs/blocks';\n\n<Meta title=\"Komponenten/Buttons\" name=\"Verwendung\" tags={['angular']} />\n\n# Verwendung\n\nButtons sind die primäre Aktions-Komponente des Systems: fünf Stilvarianten (Filled · Tonal · Elevated · Outlined · Text), drei Größen (Standard · Small · Large), der Ton-Modifier `.btn-err` für destruktive Aktionen und der Inversions-Modifier `.btn-on-band` für Buttons auf farbigen Bereichs-Bändern. Jede Variante steht in allen vier Brand Areas zur Verfügung (Bereichsreihenfolge co · ki · es · wo), das Mindestmaß für ein Touch-Target ist 44 Pixel.\n\n## Wann welche Variante\n\nDie Hierarchie ist verbindlich: Filled vor Tonal oder Outlined vor Text. Pro Kontext höchstens ein Filled-Button, sonst ist die Hauptaktion nicht mehr eindeutig erkennbar. Elevated steht außerhalb dieser Kette und markiert eine freistehende, vom Hintergrund abgehobene Aktion.\n\nSo löst sich die Hierarchie in typischen Kontexten auf: ein Dialog mit Text- neben Filled-Button, ein Formular mit Outlined- neben Filled-Button und eine Feature-Karte mit Text- neben Tonal-Button.\n\n<Unstyled>\n <div style={{ display: 'flex', flexDirection: 'column', gap: 'var(--s4)' }}>\n <div\n style={{\n border: 'var(--bd-strong)',\n borderRadius: 'var(--r-lg)',\n padding: 'var(--s5)',\n background: 'var(--bg-surface)',\n }}\n >\n <div style={{ font: '500 16px/24px var(--font)', color: 'var(--tx-primary)', marginBottom: 'var(--s2)' }}>\n Aktion bestätigen\n </div>\n <div style={{ font: '400 14px/20px var(--font)', color: 'var(--tx-secondary)', marginBottom: 'var(--s5)' }}>\n Möchtest du die Änderungen wirklich speichern?\n </div>\n <div style={{ display: 'flex', justifyContent: 'flex-end', gap: 'var(--s2)', marginBottom: 'var(--s3)' }}>\n <button className=\"btn btn-text btn-sm btn-co\">Abbrechen</button>\n <button className=\"btn btn-filled btn-sm btn-co\">Speichern</button>\n </div>\n <div style={{ font: '400 12px/16px var(--font)', color: 'var(--tx-secondary)', textAlign: 'right' }}>\n Text → Abbrechen · Filled → Hauptaktion\n </div>\n </div>\n <div\n style={{\n border: 'var(--bd-strong)',\n borderRadius: 'var(--r-lg)',\n padding: 'var(--s5)',\n background: 'var(--bg-surface)',\n }}\n >\n <div style={{ font: '500 16px/24px var(--font)', color: 'var(--tx-primary)', marginBottom: 'var(--s4)' }}>\n Formular einreichen\n </div>\n <div\n style={{\n height: '32px',\n background: 'var(--bg-overlay)',\n borderRadius: 'var(--r-sm)',\n border: 'var(--bd-strong)',\n marginBottom: 'var(--s5)',\n }}\n ></div>\n <div style={{ display: 'flex', gap: 'var(--s2)', marginBottom: 'var(--s3)' }}>\n <button className=\"btn btn-outlined btn-sm btn-co\">Vorschau</button>\n <button className=\"btn btn-filled btn-sm btn-co\">Absenden</button>\n </div>\n <div style={{ font: '400 12px/16px var(--font)', color: 'var(--tx-secondary)' }}>\n Outlined → Alternativaktion · Filled → Primäraktion\n </div>\n </div>\n <div\n style={{\n border: 'var(--bd-strong)',\n borderRadius: 'var(--r-lg)',\n padding: 'var(--s5)',\n background: 'var(--bg-surface)',\n }}\n >\n <div style={{ font: '500 16px/24px var(--font)', color: 'var(--tx-primary)', marginBottom: 'var(--s2)' }}>\n Feature entdecken\n </div>\n <div style={{ font: '400 14px/20px var(--font)', color: 'var(--tx-secondary)', marginBottom: 'var(--s5)' }}>\n Drei Bereiche, ein Ziel, Gelassenheit durch klare Struktur.\n </div>\n <div style={{ display: 'flex', alignItems: 'center', gap: 'var(--s2)', marginBottom: 'var(--s3)' }}>\n <button className=\"btn btn-text btn-sm btn-co\">Mehr erfahren</button>\n <button className=\"btn btn-tonal btn-sm btn-co\">Jetzt starten</button>\n </div>\n <div style={{ font: '400 12px/16px var(--font)', color: 'var(--tx-secondary)' }}>\n Text → Nebenaktion · Tonal → unterstützende Aktion\n </div>\n </div>\n </div>\n</Unstyled>\n\n| Variante | Rolle in der Hierarchie | Einsatz | Beispiele |\n|---|---|---|---|\n| Filled | 1. Primäre Hauptaktion | Max. 1 bis 2 pro Kontext | Speichern, Absenden, Starten |\n| Tonal | 2. Sekundäre Bestätigung | Neben Filled oder eigenständig | Weiter, Übernehmen |\n| Outlined | 2. Gleichwertige Alternative | Ohne Primärfokus | Vorschau, Exportieren |\n| Text | 3. Nebenaktion | Niedrigste Priorität, link-ähnliche Funktion | Abbrechen, Mehr erfahren |\n| Elevated | Außerhalb der Hierarchie | Freistehende Aktion, visuell vom Hintergrund getrennt | Schwebende Elemente, FAB |\n\n## Destruktive Aktionen\n\n`.btn-err` (Angular: `tone=\"err\"`) markiert eine Aktion, die sich nicht rückgängig machen lässt: Löschen, Verwerfen, Entfernen. Der Modifier **ersetzt** die Bereichsfarbe, er wird statt `.btn-co` gesetzt, nicht zusätzlich. Gedacht für Filled, Outlined und Text.\n\n<Unstyled>\n <div style={{ display: 'flex', gap: 'var(--s4)', flexWrap: 'wrap', alignItems: 'center', marginBottom: 'var(--s5)' }}>\n <button className=\"btn btn-filled btn-err\">Löschen</button>\n <button className=\"btn btn-outlined btn-err\">Verwerfen</button>\n <button className=\"btn btn-text btn-err\">Entfernen</button>\n </div>\n</Unstyled>\n\nWelcher Button gefüllt ist, entscheidet der Kontext:\n\n| Kontext | Beispiel | Hauptaktion (Filled) | Nebenaktion |\n|---|---|---|---|\n| Selbst ausgelöst | Klick auf „Löschen“, danach eine Rückfrage | „Löschen“ mit `.btn-err` | „Abbrechen“ als Text |\n| Unterbrechung | Ungespeicherte Änderungen beim Verlassen | „Weiter bearbeiten“ in der Bereichsfarbe | „Verwerfen“ als Outlined mit `.btn-err` |\n\nBei einer Unterbrechung wollte die Person etwas anderes, das Verwerfen ist Nebenwirkung. Deshalb bekommt dort der sichere Weg das Gewicht. Die Farbe ist nie der einzige Hinweis, das Label nennt immer die Folge.\n\n## Barrierefreiheit\n\n| Aspekt | Regel |\n|---|---|\n| Icon-only | Buttons ohne sichtbaren Text benötigen `aria-label`, der SVG-Inhalt allein reicht für Screenreader nicht aus |\n| Disabled | `aria-disabled=\"true\"` statt HTML `disabled`, wenn der Button im Fokus-Flow bleiben soll, `disabled` entfernt das Element aus der Tastaturreihenfolge |\n| Touch-Target | Mindestgröße 44 mal 44 Pixel für alle Button-Varianten (WCAG 2.5.5), `btn-sm` bei Bedarf mit zusätzlichem Padding kompensieren |\n| Focus-Ring | Nie `outline: none` ohne sichtbaren Ersatz, der Design-System-Focus-Ring (`--focus-aa`) muss für alle Buttons erhalten bleiben |\n| Filled auf Bereichs-Section | Filled-Buttons auf hellen Bereichs-Hintergründen (`--co-50`, `--ki-50`, `--wo-50`, `--es-50`) brauchen eine ausreichend dunkle Variante mit weißer Schrift, sonst fehlt der UI-Komponenten-Kontrast (WCAG 1.4.11, mindestens 3 zu 1) zwischen Button-Fläche und Section |\n\nDrei der vier Bereiche sind über die Modifier-Klasse bereits korrekt abgedeckt: `.btn-co` auf `--co-700`, `.btn-ki` auf `--ki-800`, `.btn-es` auf `--es-700`. Die Default-Farbe von `.btn-wo` (`--wo-700`) ist im Allgemeinen passend, verfehlt aber auf `--wo-50`-Sub-Streifen den Kontrast. Dort die Bereichs-Klasse mit einem minimalen Inline-Override kombinieren:\n\n```html\n<button class=\"btn btn-filled btn-wo\" style=\"--c500:var(--wo-600)\">\n```\n\n`--c50` erbt korrekt von `.btn-wo`, ein `color`-Override entfällt, weil der Default aus `.btn-filled` (Weiß) bereits greift.\n\n## Dos & Don'ts\n\n**Tun**\n\n- Pro Kontext maximal ein Filled Button, klare Priorisierung der Hauptaktion für die Nutzerin.\n- Verb-Labels: konkret und handlungsorientiert, „Starten“, „Speichern“, „Anfragen“, „Absenden“.\n- Hierarchie konsequent einhalten: Filled vor Tonal oder Outlined vor Text.\n- Bereichsklasse passend zum Seitenkontext: `.btn-co`, `.btn-ki`, `.btn-es`, `.btn-wo`.\n- Touch-Target mindestens 44 Pixel einhalten, auch im Small-Modus ausreichend groß für sichere Bedienung.\n- `.btn-err` nur für Aktionen, die sich nicht rückgängig machen lassen, höchstens einer pro Ansicht, mit einem Label, das die Folge nennt: „Löschen“, „Verwerfen“.\n\n**Nicht tun**\n\n- Mehrere Filled Buttons nebeneinander, das lässt keine klare Primäraktion erkennen.\n- Substantive oder lange Phrasen als Labels, „Antragsformular einreichen“ statt lieber „Absenden“.\n- Disabled-State ohne sichtbare Begründung, Helper-Text oder Tooltip nutzen, um zu erklären warum.\n- Bereichsfarbe willkürlich tauschen, Corporate-Kontext immer `.btn-co`, nie `.btn-ki`.\n- Filled-Button mit `--area-500` auf hellem Bereichs-Hintergrund (`--area-50`), stattdessen die dunklere Bereichs-Variante nutzen (siehe Barrierefreiheits-Tabelle oben).\n- `.btn-err` als Blickfang oder für umkehrbare Aktionen („Abmelden“, „Filter zurücksetzen“), und nie neben einer Bereichsklasse am selben Button.\n\n## Verwandte Seiten\n\n- Buttons (`Komponenten/Buttons/Button`), alle Stilvarianten, Größen und Zustände als Stories.\n",
|
|
13
|
-
"summary": "# Verwendung Buttons sind die primäre Aktions-Komponente des Systems: fünf Stilvarianten (..."
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
}
|