@conciso/design-system-mcp 2.4.0 → 2.6.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 +207 -27
- package/snapshot/manifests/docs.json +0 -128
- 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-buchungsformular--/303/274bersicht.json +1 -1
- package/snapshot/services/addon-docs/mdx/komponenten-buttons-button.json +1 -1
- package/snapshot/services/addon-docs/mdx/komponenten-call-to-action-cta-band.json +18 -0
- package/snapshot/services/addon-docs/mdx/komponenten-cards-teaser-card.json +18 -0
- package/snapshot/services/addon-docs/mdx/komponenten-chips-badges-pills-chip.json +18 -0
- package/snapshot/services/addon-docs/mdx/komponenten-code-block-code-block.json +18 -0
- package/snapshot/services/addon-docs/mdx/komponenten-dropdowns-custom-select.json +18 -0
- package/snapshot/services/addon-docs/mdx/komponenten-feedback-snackbar.json +18 -0
- package/snapshot/services/addon-docs/mdx/komponenten-footer-komplett.json +18 -0
- package/snapshot/services/addon-docs/mdx/komponenten-hero-hero-bild.json +18 -0
- package/snapshot/services/addon-docs/mdx/komponenten-inputs-forms-textfeld.json +18 -0
- package/snapshot/services/addon-docs/mdx/komponenten-navigation-topnav.json +18 -0
- package/snapshot/services/addon-docs/mdx/komponenten-sektion-sektion.json +18 -0
- package/snapshot/services/addon-docs/mdx/komponenten-slider-carousel-carousel.json +18 -0
- package/snapshot/services/addon-docs/mdx/komponenten-tabelle-tabelle.json +18 -0
- package/snapshot/services/addon-docs/mdx/komponenten-theme-umschalter-cycle-button.json +18 -0
- package/snapshot/services/addon-docs/mdx/komponenten-zitate-testimonials-blockquote.json +18 -0
- package/snapshot/services/addon-docs/mdx/marke-logo-logo.json +18 -0
- package/snapshot/services/core/docgen/komponenten-call-to-action-downloadcta.json +1 -1
- package/snapshot/services/core/docgen/komponenten-cards-teaser-feature-liste.json +1 -1
- package/snapshot/services/core/docgen/komponenten-cards-teaser-featured-karte.json +1 -1
- package/snapshot/services/core/docgen/komponenten-cards-teaser-icon-karte.json +1 -1
- package/snapshot/services/core/docgen/komponenten-cards-teaser-klickbare-karte.json +1 -1
- package/snapshot/services/core/docgen/komponenten-cards-teaser-statcard.json +1 -1
- package/snapshot/services/core/docgen/komponenten-cards-teaser-statstrip.json +1 -1
- package/snapshot/services/core/docgen/komponenten-cards-teaser-tier-trenner.json +1 -1
- package/snapshot/services/core/docgen/komponenten-chips-badges-pills-bereichs-badge.json +1 -1
- package/snapshot/services/core/docgen/komponenten-chips-badges-pills-pill.json +1 -1
- package/snapshot/services/core/docgen/komponenten-chips-badges-pills-status-badge.json +1 -1
- package/snapshot/services/core/docgen/komponenten-dropdowns-combobox.json +1 -1
- package/snapshot/services/core/docgen/komponenten-footer-oberer-teil.json +1 -1
- package/snapshot/services/core/docgen/komponenten-footer-unterer-teil.json +1 -1
- package/snapshot/services/core/docgen/komponenten-hero-st/303/266rer.json +1 -1
- package/snapshot/services/core/docgen/komponenten-inputs-forms-auswahlfeld.json +1 -1
- package/snapshot/services/core/docgen/komponenten-inputs-forms-checkbox.json +1 -1
- package/snapshot/services/core/docgen/komponenten-inputs-forms-radio.json +1 -1
- package/snapshot/services/core/docgen/komponenten-inputs-forms-skala.json +1 -1
- package/snapshot/services/core/docgen/komponenten-inputs-forms-slider.json +1 -1
- package/snapshot/services/core/docgen/komponenten-inputs-forms-textbereich.json +1 -1
- package/snapshot/services/core/docgen/komponenten-slider-carousel-logocarousel.json +1 -1
- package/snapshot/services/core/docgen/komponenten-tabelle-vergleichstabelle.json +1 -1
- package/snapshot/services/core/docgen/komponenten-theme-umschalter-dropdown.json +1 -1
- package/snapshot/services/core/docgen/komponenten-theme-umschalter-segment.json +1 -1
- package/snapshot/services/core/docgen/komponenten-zitate-testimonials-teamvoice.json +1 -1
- package/snapshot/services/core/docgen/komponenten-zitate-testimonials-testimonial.json +1 -1
- package/src/instructions.mjs +9 -1
- package/snapshot/services/addon-docs/mdx/komponenten-call-to-action--verwendung.json +0 -18
- package/snapshot/services/addon-docs/mdx/komponenten-cards-teaser--verwendung.json +0 -18
- package/snapshot/services/addon-docs/mdx/komponenten-chips-badges-pills--verwendung.json +0 -18
- package/snapshot/services/addon-docs/mdx/komponenten-code-block--verwendung.json +0 -18
- package/snapshot/services/addon-docs/mdx/komponenten-dropdowns--verwendung.json +0 -18
- package/snapshot/services/addon-docs/mdx/komponenten-feedback--verwendung.json +0 -18
- package/snapshot/services/addon-docs/mdx/komponenten-footer--verwendung.json +0 -18
- package/snapshot/services/addon-docs/mdx/komponenten-hero--/303/274bersicht.json +0 -18
- package/snapshot/services/addon-docs/mdx/komponenten-inputs-forms--verwendung.json +0 -18
- package/snapshot/services/addon-docs/mdx/komponenten-navigation--verwendung.json +0 -18
- package/snapshot/services/addon-docs/mdx/komponenten-sektion--/303/274bersicht.json +0 -18
- package/snapshot/services/addon-docs/mdx/komponenten-slider-carousel--verwendung.json +0 -18
- package/snapshot/services/addon-docs/mdx/komponenten-tabelle--/303/274bersicht.json +0 -18
- package/snapshot/services/addon-docs/mdx/komponenten-theme-umschalter--verwendung.json +0 -18
- package/snapshot/services/addon-docs/mdx/komponenten-zitate-testimonials--verwendung.json +0 -18
- package/snapshot/services/addon-docs/mdx/marke-logo--verwendung.json +0 -18
|
@@ -21,6 +21,16 @@
|
|
|
21
21
|
},
|
|
22
22
|
"stories": {
|
|
23
23
|
"$ref": "../services/core/story-docs/marke-logo-logo.json#/components/marke-logo-logo"
|
|
24
|
+
},
|
|
25
|
+
"docs": {
|
|
26
|
+
"marke-logo-logo--verwendung": {
|
|
27
|
+
"id": "marke-logo-logo--verwendung",
|
|
28
|
+
"name": "Verwendung",
|
|
29
|
+
"mdx": {
|
|
30
|
+
"$ref": "../services/addon-docs/mdx/marke-logo-logo.json#/components/marke-logo-logo/docs/marke-logo-logo--verwendung"
|
|
31
|
+
},
|
|
32
|
+
"summary": "# Verwendung Verwendungsregeln zum Logo: Größen, Schutzraum, Einsatz nach Hintergrund, Bar..."
|
|
33
|
+
}
|
|
24
34
|
}
|
|
25
35
|
},
|
|
26
36
|
"grundlagen-farben": {
|
|
@@ -28,6 +38,16 @@
|
|
|
28
38
|
"name": "grundlagen-farben",
|
|
29
39
|
"stories": {
|
|
30
40
|
"$ref": "../services/core/story-docs/grundlagen-farben.json#/components/grundlagen-farben"
|
|
41
|
+
},
|
|
42
|
+
"docs": {
|
|
43
|
+
"grundlagen-farben--verwendung": {
|
|
44
|
+
"id": "grundlagen-farben--verwendung",
|
|
45
|
+
"name": "Verwendung",
|
|
46
|
+
"mdx": {
|
|
47
|
+
"$ref": "../services/addon-docs/mdx/grundlagen-farben.json#/components/grundlagen-farben/docs/grundlagen-farben--verwendung"
|
|
48
|
+
},
|
|
49
|
+
"summary": "# Verwendung Vier Bereichspaletten (Corporate, Angewandte KI, Effektive Software, Wirksame..."
|
|
50
|
+
}
|
|
31
51
|
}
|
|
32
52
|
},
|
|
33
53
|
"grundlagen-typografie": {
|
|
@@ -35,6 +55,16 @@
|
|
|
35
55
|
"name": "grundlagen-typografie",
|
|
36
56
|
"stories": {
|
|
37
57
|
"$ref": "../services/core/story-docs/grundlagen-typografie.json#/components/grundlagen-typografie"
|
|
58
|
+
},
|
|
59
|
+
"docs": {
|
|
60
|
+
"grundlagen-typografie--verwendung": {
|
|
61
|
+
"id": "grundlagen-typografie--verwendung",
|
|
62
|
+
"name": "Verwendung",
|
|
63
|
+
"mdx": {
|
|
64
|
+
"$ref": "../services/addon-docs/mdx/grundlagen-typografie.json#/components/grundlagen-typografie/docs/grundlagen-typografie--verwendung"
|
|
65
|
+
},
|
|
66
|
+
"summary": "# Verwendung Zwei Schriften tragen zwei unterschiedliche Aufgaben. Libre Baskerville (Seri..."
|
|
67
|
+
}
|
|
38
68
|
}
|
|
39
69
|
},
|
|
40
70
|
"komponenten-buttons-button": {
|
|
@@ -67,12 +97,22 @@
|
|
|
67
97
|
},
|
|
68
98
|
"stories": {
|
|
69
99
|
"$ref": "../services/core/story-docs/komponenten-chips-badges-pills-chip.json#/components/komponenten-chips-badges-pills-chip"
|
|
100
|
+
},
|
|
101
|
+
"docs": {
|
|
102
|
+
"komponenten-chips-badges-pills-chip--verwendung": {
|
|
103
|
+
"id": "komponenten-chips-badges-pills-chip--verwendung",
|
|
104
|
+
"name": "Verwendung",
|
|
105
|
+
"mdx": {
|
|
106
|
+
"$ref": "../services/addon-docs/mdx/komponenten-chips-badges-pills-chip.json#/components/komponenten-chips-badges-pills-chip/docs/komponenten-chips-badges-pills-chip--verwendung"
|
|
107
|
+
},
|
|
108
|
+
"summary": "# Verwendung Drei Formen, die leicht verwechselt werden: interaktive Filter-Chips (Toggle)..."
|
|
109
|
+
}
|
|
70
110
|
}
|
|
71
111
|
},
|
|
72
112
|
"komponenten-chips-badges-pills-status-badge": {
|
|
73
113
|
"id": "komponenten-chips-badges-pills-status-badge",
|
|
74
114
|
"name": "StatusBadgeComponent",
|
|
75
|
-
"description": "Status-Badge — passive Zustands-Kennzeichnung auf Basis von `.badge` +\n`.badge-{ok|warn|err|neu}` aus css/components.css.\n\nTrägt einen Zustand über semantische Farben (OK, Warnung, Fehler, Neutral) —\nz. B. „Live“, „Beta“, „Deprecated“, „Draft“. Nicht interaktiv. Für die\nZuordnung zu einer Brand Area die Bereichs-Badge, für einen redaktionellen\nAnker im Lesefluss die Pill nutzen; für interaktive Filter den Chip.",
|
|
115
|
+
"description": "Status-Badge — passive Zustands-Kennzeichnung auf Basis von `.badge` +\n`.badge-{ok|warn|err|neu}` aus css/components.css.\n\nTrägt einen Zustand über semantische Farben (OK, Warnung, Fehler, Neutral) —\nz. B. „Live“, „Beta“, „Deprecated“, „Draft“. Nicht interaktiv. Für die\nZuordnung zu einer Brand Area die Bereichs-Badge, für einen redaktionellen\nAnker im Lesefluss die Pill nutzen; für interaktive Filter den Chip.\n\nVerwendungsguidance dieser Gruppe: siehe Chip (`komponenten-chips-badges-pills-chip--verwendung`).",
|
|
76
116
|
"docgen": {
|
|
77
117
|
"$ref": "../services/core/docgen/komponenten-chips-badges-pills-status-badge.json#/components/komponenten-chips-badges-pills-status-badge"
|
|
78
118
|
},
|
|
@@ -83,7 +123,7 @@
|
|
|
83
123
|
"komponenten-chips-badges-pills-bereichs-badge": {
|
|
84
124
|
"id": "komponenten-chips-badges-pills-bereichs-badge",
|
|
85
125
|
"name": "AreaBadgeComponent",
|
|
86
|
-
"description": "Bereichs-Badge — passive Bereichs-Kennzeichnung auf Basis von `.badge` +\n`[data-area]` aus css/components.css.\n\nOrdnet ein Element einer der vier Brand Areas zu (50er-Grund, 800er-Text).\nNicht interaktiv. Für Zustände die Status-Badge, für einen redaktionellen\nAnker im Lesefluss die Pill nutzen; für interaktive Filter den Chip.",
|
|
126
|
+
"description": "Bereichs-Badge — passive Bereichs-Kennzeichnung auf Basis von `.badge` +\n`[data-area]` aus css/components.css.\n\nOrdnet ein Element einer der vier Brand Areas zu (50er-Grund, 800er-Text).\nNicht interaktiv. Für Zustände die Status-Badge, für einen redaktionellen\nAnker im Lesefluss die Pill nutzen; für interaktive Filter den Chip.\n\nVerwendungsguidance dieser Gruppe: siehe Chip (`komponenten-chips-badges-pills-chip--verwendung`).",
|
|
87
127
|
"docgen": {
|
|
88
128
|
"$ref": "../services/core/docgen/komponenten-chips-badges-pills-bereichs-badge.json#/components/komponenten-chips-badges-pills-bereichs-badge"
|
|
89
129
|
},
|
|
@@ -94,7 +134,7 @@
|
|
|
94
134
|
"komponenten-chips-badges-pills-pill": {
|
|
95
135
|
"id": "komponenten-chips-badges-pills-pill",
|
|
96
136
|
"name": "PillComponent",
|
|
97
|
-
"description": "Pill — Wrapper um `.pill` aus css/components.css → „Badges & Chips“ (Pill).\n\nPassive, redaktionelle Bereichs-Markierung, typografisch als Eyebrow (uppercase,\nletter-spacing .09em, label-xs) — sitzt typischerweise oberhalb eines Titels und\nordnet einen Inhalt einer Brand Area zu. Abgrenzung zur Badge: die Pill ist der\nthematische „Was für ein Inhalt ist das?“-Anker im Lesefluss; die Badge die\npunktuelle Status-/Bereichs-Kennzeichnung neben Elementen. Nicht interaktiv.\n\na11y: Der reine Bereichsname klingt im Screenreader-Fluss leicht wie eine\nÜberschrift — daher trägt die Pill ein explizites `aria-label` (Default\n„Bereich <label>“, überschreibbar), genau wie in der Doku vorgegeben.",
|
|
137
|
+
"description": "Pill — Wrapper um `.pill` aus css/components.css → „Badges & Chips“ (Pill).\n\nPassive, redaktionelle Bereichs-Markierung, typografisch als Eyebrow (uppercase,\nletter-spacing .09em, label-xs) — sitzt typischerweise oberhalb eines Titels und\nordnet einen Inhalt einer Brand Area zu. Abgrenzung zur Badge: die Pill ist der\nthematische „Was für ein Inhalt ist das?“-Anker im Lesefluss; die Badge die\npunktuelle Status-/Bereichs-Kennzeichnung neben Elementen. Nicht interaktiv.\n\na11y: Der reine Bereichsname klingt im Screenreader-Fluss leicht wie eine\nÜberschrift — daher trägt die Pill ein explizites `aria-label` (Default\n„Bereich <label>“, überschreibbar), genau wie in der Doku vorgegeben.\n\nVerwendungsguidance dieser Gruppe: siehe Chip (`komponenten-chips-badges-pills-chip--verwendung`).",
|
|
98
138
|
"docgen": {
|
|
99
139
|
"$ref": "../services/core/docgen/komponenten-chips-badges-pills-pill.json#/components/komponenten-chips-badges-pills-pill"
|
|
100
140
|
},
|
|
@@ -111,12 +151,22 @@
|
|
|
111
151
|
},
|
|
112
152
|
"stories": {
|
|
113
153
|
"$ref": "../services/core/story-docs/komponenten-inputs-forms-textfeld.json#/components/komponenten-inputs-forms-textfeld"
|
|
154
|
+
},
|
|
155
|
+
"docs": {
|
|
156
|
+
"komponenten-inputs-forms-textfeld--verwendung": {
|
|
157
|
+
"id": "komponenten-inputs-forms-textfeld--verwendung",
|
|
158
|
+
"name": "Verwendung",
|
|
159
|
+
"mdx": {
|
|
160
|
+
"$ref": "../services/addon-docs/mdx/komponenten-inputs-forms-textfeld.json#/components/komponenten-inputs-forms-textfeld/docs/komponenten-inputs-forms-textfeld--verwendung"
|
|
161
|
+
},
|
|
162
|
+
"summary": "# Verwendung Feldkomponenten (Text · E-Mail · Select · Textarea · Checkbox · Radio), berei..."
|
|
163
|
+
}
|
|
114
164
|
}
|
|
115
165
|
},
|
|
116
166
|
"komponenten-inputs-forms-textbereich": {
|
|
117
167
|
"id": "komponenten-inputs-forms-textbereich",
|
|
118
168
|
"name": "TextareaFieldComponent",
|
|
119
|
-
"description": "Textbereich — mehrzeiliges `<textarea>` im `.field`-Gerüst. Gleiche a11y-\nVerdrahtung wie das Textfeld (aria-required/-invalid/-describedby).\n\nAls `ControlValueAccessor` (siehe FieldBase) direkt an Angular-Formulare\nanbindbar (`[(ngModel)]`, `formControlName`) bzw. ohne Formular per `[(value)]
|
|
169
|
+
"description": "Textbereich — mehrzeiliges `<textarea>` im `.field`-Gerüst. Gleiche a11y-\nVerdrahtung wie das Textfeld (aria-required/-invalid/-describedby).\n\nAls `ControlValueAccessor` (siehe FieldBase) direkt an Angular-Formulare\nanbindbar (`[(ngModel)]`, `formControlName`) bzw. ohne Formular per `[(value)]`.\n\nVerwendungsguidance dieser Gruppe: siehe Textfeld (`komponenten-inputs-forms-textfeld--verwendung`).",
|
|
120
170
|
"docgen": {
|
|
121
171
|
"$ref": "../services/core/docgen/komponenten-inputs-forms-textbereich.json#/components/komponenten-inputs-forms-textbereich"
|
|
122
172
|
},
|
|
@@ -127,7 +177,7 @@
|
|
|
127
177
|
"komponenten-inputs-forms-auswahlfeld": {
|
|
128
178
|
"id": "komponenten-inputs-forms-auswahlfeld",
|
|
129
179
|
"name": "SelectFieldComponent",
|
|
130
|
-
"description": "Auswahlfeld — `<select>` im `.field`-Gerüst. Die Optionen kommen über `options`;\na11y-Verdrahtung wie beim Textfeld (aria-required/-invalid/-describedby).\n\nAls `ControlValueAccessor` (siehe FieldBase) direkt an Angular-Formulare\nanbindbar (`[(ngModel)]`, `formControlName`) bzw. ohne Formular per `[(value)]
|
|
180
|
+
"description": "Auswahlfeld — `<select>` im `.field`-Gerüst. Die Optionen kommen über `options`;\na11y-Verdrahtung wie beim Textfeld (aria-required/-invalid/-describedby).\n\nAls `ControlValueAccessor` (siehe FieldBase) direkt an Angular-Formulare\nanbindbar (`[(ngModel)]`, `formControlName`) bzw. ohne Formular per `[(value)]`.\n\nVerwendungsguidance dieser Gruppe: siehe Textfeld (`komponenten-inputs-forms-textfeld--verwendung`).",
|
|
131
181
|
"docgen": {
|
|
132
182
|
"$ref": "../services/core/docgen/komponenten-inputs-forms-auswahlfeld.json#/components/komponenten-inputs-forms-auswahlfeld"
|
|
133
183
|
},
|
|
@@ -138,7 +188,7 @@
|
|
|
138
188
|
"komponenten-inputs-forms-radio": {
|
|
139
189
|
"id": "komponenten-inputs-forms-radio",
|
|
140
190
|
"name": "RadioGroupComponent",
|
|
141
|
-
"description": "Radio-Gruppe (Optionsfelder) nach docs/index.html („Forms“).\n\nFür 2–6 sich gegenseitig ausschließende Optionen (mehr → Select). Bewusst KEIN\nnachgebauter Kreis: native `<input type=\"radio\">` mit `accent-color` in der\nBereichsfarbe, gruppiert in `<fieldset>`/`<legend>` (Gruppen-Label wie ein\nFeld-Label), alle Optionen teilen denselben `name`.\n\nAls `ControlValueAccessor` direkt an Angular-Formulare anbindbar (`[(ngModel)]`,\n`formControlName`); ohne Formular geht `[(value)]` (valueChange via model()).",
|
|
191
|
+
"description": "Radio-Gruppe (Optionsfelder) nach docs/index.html („Forms“).\n\nFür 2–6 sich gegenseitig ausschließende Optionen (mehr → Select). Bewusst KEIN\nnachgebauter Kreis: native `<input type=\"radio\">` mit `accent-color` in der\nBereichsfarbe, gruppiert in `<fieldset>`/`<legend>` (Gruppen-Label wie ein\nFeld-Label), alle Optionen teilen denselben `name`.\n\nAls `ControlValueAccessor` direkt an Angular-Formulare anbindbar (`[(ngModel)]`,\n`formControlName`); ohne Formular geht `[(value)]` (valueChange via model()).\n\nVerwendungsguidance dieser Gruppe: siehe Textfeld (`komponenten-inputs-forms-textfeld--verwendung`).",
|
|
142
192
|
"docgen": {
|
|
143
193
|
"$ref": "../services/core/docgen/komponenten-inputs-forms-radio.json#/components/komponenten-inputs-forms-radio"
|
|
144
194
|
},
|
|
@@ -149,7 +199,7 @@
|
|
|
149
199
|
"komponenten-inputs-forms-checkbox": {
|
|
150
200
|
"id": "komponenten-inputs-forms-checkbox",
|
|
151
201
|
"name": "CheckboxComponent",
|
|
152
|
-
"description": "Checkbox — Einwilligungs-/Consent-Feld nach docs/index.html („Forms“).\n\nBewusst KEIN nachgebautes Kästchen: ein natives `<input type=\"checkbox\">` mit\n`accent-color` in der Bereichsfarbe (genau wie die Doku), umschlossen von einem\n`<label>` mit dem Einwilligungstext und optional verlinktem Datenschutzhinweis.\nDokumentierte Verwendung: Newsletter-/DSGVO-Einwilligung, i. d. R. `required`.\n\nAls `ControlValueAccessor` direkt an Angular-Formulare anbindbar (`[(ngModel)]`,\n`formControlName`); ohne Formular geht `[(checked)]` (checkedChange via model()).",
|
|
202
|
+
"description": "Checkbox — Einwilligungs-/Consent-Feld nach docs/index.html („Forms“).\n\nBewusst KEIN nachgebautes Kästchen: ein natives `<input type=\"checkbox\">` mit\n`accent-color` in der Bereichsfarbe (genau wie die Doku), umschlossen von einem\n`<label>` mit dem Einwilligungstext und optional verlinktem Datenschutzhinweis.\nDokumentierte Verwendung: Newsletter-/DSGVO-Einwilligung, i. d. R. `required`.\n\nAls `ControlValueAccessor` direkt an Angular-Formulare anbindbar (`[(ngModel)]`,\n`formControlName`); ohne Formular geht `[(checked)]` (checkedChange via model()).\n\nVerwendungsguidance dieser Gruppe: siehe Textfeld (`komponenten-inputs-forms-textfeld--verwendung`).",
|
|
153
203
|
"docgen": {
|
|
154
204
|
"$ref": "../services/core/docgen/komponenten-inputs-forms-checkbox.json#/components/komponenten-inputs-forms-checkbox"
|
|
155
205
|
},
|
|
@@ -160,7 +210,7 @@
|
|
|
160
210
|
"komponenten-inputs-forms-slider": {
|
|
161
211
|
"id": "komponenten-inputs-forms-slider",
|
|
162
212
|
"name": "SliderComponent",
|
|
163
|
-
"description": "Slider — Wrapper um `.field-slider` / `.slider` aus css/components.css → „Slider“.\n\nRange-Eingabe mit Label + Live-Ausgabe, bereichsgefärbtem Thumb/Output\n(.slider-<area> setzt --sl-color), automatisch berechneten Ticks und Helper-Text.\n\nTicks: Es wird nur eine gewünschte ANZAHL (`tickCount`) angegeben; die Positionen/\nLabels werden gleichmäßig aus [min, max] berechnet (space-between wie das CSS-\nLayout). Wird der Slider zu schmal, reduziert die Komponente die Tick-Zahl reaktiv\n(ResizeObserver), sodass die Labels nicht überlappen — Endpunkte bleiben erhalten.\n\nAls `ControlValueAccessor` direkt an Angular-Formulare anbindbar (`[(ngModel)]`,\n`formControlName`); ohne Formular geht `[(value)]` (valueChange via model()).",
|
|
213
|
+
"description": "Slider — Wrapper um `.field-slider` / `.slider` aus css/components.css → „Slider“.\n\nRange-Eingabe mit Label + Live-Ausgabe, bereichsgefärbtem Thumb/Output\n(.slider-<area> setzt --sl-color), automatisch berechneten Ticks und Helper-Text.\n\nTicks: Es wird nur eine gewünschte ANZAHL (`tickCount`) angegeben; die Positionen/\nLabels werden gleichmäßig aus [min, max] berechnet (space-between wie das CSS-\nLayout). Wird der Slider zu schmal, reduziert die Komponente die Tick-Zahl reaktiv\n(ResizeObserver), sodass die Labels nicht überlappen — Endpunkte bleiben erhalten.\n\nAls `ControlValueAccessor` direkt an Angular-Formulare anbindbar (`[(ngModel)]`,\n`formControlName`); ohne Formular geht `[(value)]` (valueChange via model()).\n\nVerwendungsguidance dieser Gruppe: siehe Textfeld (`komponenten-inputs-forms-textfeld--verwendung`).",
|
|
164
214
|
"docgen": {
|
|
165
215
|
"$ref": "../services/core/docgen/komponenten-inputs-forms-slider.json#/components/komponenten-inputs-forms-slider"
|
|
166
216
|
},
|
|
@@ -171,7 +221,7 @@
|
|
|
171
221
|
"komponenten-inputs-forms-skala": {
|
|
172
222
|
"id": "komponenten-inputs-forms-skala",
|
|
173
223
|
"name": "ScaleComponent",
|
|
174
|
-
"description": "Skala (cds-scale) — Slider für GEORDNETE (ordinale) Kategorien, deren Labels die\nWerte SIND (z. B. Niedrig < Mittel < Hoch, nie < selten < oft < immer).\n\nBasiert auf dem nativen <input type=\"range\">; min=0, max=labels.length-1, step=1\nwerden intern abgeleitet und NICHT exponiert. Der aktuelle Wert erscheint als\nLABEL im <output> und wird Screenreadern über `aria-valuetext` als Text gemeldet\n(nicht als Zahl) — das anerkannte APG-Muster für ordinale Slider. Die Skalenpunkte\nzeigen alle Labels, exakt auf ihre Position ausgerichtet und bewusst OHNE\nReduktion (jedes Label ist eine wählbare Stufe).\n\nNUR für geordnete Kategorien. Ungeordnete/gleichrangige Optionen (ohne natürliche\nReihenfolge) gehören NICHT auf einen Slider → cds-radio-group oder cds-area-tabs.\n\nAls `ControlValueAccessor` direkt an Angular-Formulare anbindbar (`[(ngModel)]`,\n`formControlName`); der Formularwert ist der Stufen-INDEX. Ohne Formular geht\n`[(value)]` (valueChange via model()).",
|
|
224
|
+
"description": "Skala (cds-scale) — Slider für GEORDNETE (ordinale) Kategorien, deren Labels die\nWerte SIND (z. B. Niedrig < Mittel < Hoch, nie < selten < oft < immer).\n\nBasiert auf dem nativen <input type=\"range\">; min=0, max=labels.length-1, step=1\nwerden intern abgeleitet und NICHT exponiert. Der aktuelle Wert erscheint als\nLABEL im <output> und wird Screenreadern über `aria-valuetext` als Text gemeldet\n(nicht als Zahl) — das anerkannte APG-Muster für ordinale Slider. Die Skalenpunkte\nzeigen alle Labels, exakt auf ihre Position ausgerichtet und bewusst OHNE\nReduktion (jedes Label ist eine wählbare Stufe).\n\nNUR für geordnete Kategorien. Ungeordnete/gleichrangige Optionen (ohne natürliche\nReihenfolge) gehören NICHT auf einen Slider → cds-radio-group oder cds-area-tabs.\n\nAls `ControlValueAccessor` direkt an Angular-Formulare anbindbar (`[(ngModel)]`,\n`formControlName`); der Formularwert ist der Stufen-INDEX. Ohne Formular geht\n`[(value)]` (valueChange via model()).\n\nVerwendungsguidance dieser Gruppe: siehe Textfeld (`komponenten-inputs-forms-textfeld--verwendung`).",
|
|
175
225
|
"docgen": {
|
|
176
226
|
"$ref": "../services/core/docgen/komponenten-inputs-forms-skala.json#/components/komponenten-inputs-forms-skala"
|
|
177
227
|
},
|
|
@@ -188,12 +238,22 @@
|
|
|
188
238
|
},
|
|
189
239
|
"stories": {
|
|
190
240
|
"$ref": "../services/core/story-docs/komponenten-dropdowns-custom-select.json#/components/komponenten-dropdowns-custom-select"
|
|
241
|
+
},
|
|
242
|
+
"docs": {
|
|
243
|
+
"komponenten-dropdowns-custom-select--verwendung": {
|
|
244
|
+
"id": "komponenten-dropdowns-custom-select--verwendung",
|
|
245
|
+
"name": "Verwendung",
|
|
246
|
+
"mdx": {
|
|
247
|
+
"$ref": "../services/addon-docs/mdx/komponenten-dropdowns-custom-select.json#/components/komponenten-dropdowns-custom-select/docs/komponenten-dropdowns-custom-select--verwendung"
|
|
248
|
+
},
|
|
249
|
+
"summary": "# Verwendung Auswahl-Komponenten über das native `` hinaus: Custom Select (gestylte Einzel..."
|
|
250
|
+
}
|
|
191
251
|
}
|
|
192
252
|
},
|
|
193
253
|
"komponenten-dropdowns-combobox": {
|
|
194
254
|
"id": "komponenten-dropdowns-combobox",
|
|
195
255
|
"name": "ComboboxComponent",
|
|
196
|
-
"description": "Combobox (cds-combobox) — Tipp-Filter über `.ep-combobox` aus css/components.css\n→ Doku „Dropdowns“. Wie der Custom Select, aber mit Substring-Filter im Feld (für\nlange Listen). Optional Multi-Select mit Chips (`multi`).\n\nVerhalten/a11y selbst getragen: Input mit role=combobox (dort ist\naria-activedescendant erlaubt), aria-expanded/-controls/-autocomplete; Listbox mit\nrole=listbox/option; ↓ öffnet/navigiert, Enter wählt, Esc schließt, Rücktaste bei\nleerem Feld entfernt im Multi-Modus den letzten Chip. Beim Schließen ohne Auswahl\nfällt die Einzelauswahl auf das gewählte Label zurück (kein loser Filtertext).\n\nAls `ControlValueAccessor` direkt an Angular-Formulare anbindbar (`[(ngModel)]`,\n`formControlName`); der Formularwert ist im Multi-Modus `string[]`, sonst `string`.\nOhne Formular gehen `[(value)]` / `[(values)]` (valueChange/valuesChange via model()).",
|
|
256
|
+
"description": "Combobox (cds-combobox) — Tipp-Filter über `.ep-combobox` aus css/components.css\n→ Doku „Dropdowns“. Wie der Custom Select, aber mit Substring-Filter im Feld (für\nlange Listen). Optional Multi-Select mit Chips (`multi`).\n\nVerhalten/a11y selbst getragen: Input mit role=combobox (dort ist\naria-activedescendant erlaubt), aria-expanded/-controls/-autocomplete; Listbox mit\nrole=listbox/option; ↓ öffnet/navigiert, Enter wählt, Esc schließt, Rücktaste bei\nleerem Feld entfernt im Multi-Modus den letzten Chip. Beim Schließen ohne Auswahl\nfällt die Einzelauswahl auf das gewählte Label zurück (kein loser Filtertext).\n\nAls `ControlValueAccessor` direkt an Angular-Formulare anbindbar (`[(ngModel)]`,\n`formControlName`); der Formularwert ist im Multi-Modus `string[]`, sonst `string`.\nOhne Formular gehen `[(value)]` / `[(values)]` (valueChange/valuesChange via model()).\n\nVerwendungsguidance dieser Gruppe: siehe Custom Select (`komponenten-dropdowns-custom-select--verwendung`).",
|
|
197
257
|
"docgen": {
|
|
198
258
|
"$ref": "../services/core/docgen/komponenten-dropdowns-combobox.json#/components/komponenten-dropdowns-combobox"
|
|
199
259
|
},
|
|
@@ -210,6 +270,16 @@
|
|
|
210
270
|
},
|
|
211
271
|
"stories": {
|
|
212
272
|
"$ref": "../services/core/story-docs/komponenten-feedback-snackbar.json#/components/komponenten-feedback-snackbar"
|
|
273
|
+
},
|
|
274
|
+
"docs": {
|
|
275
|
+
"komponenten-feedback-snackbar--verwendung": {
|
|
276
|
+
"id": "komponenten-feedback-snackbar--verwendung",
|
|
277
|
+
"name": "Verwendung",
|
|
278
|
+
"mdx": {
|
|
279
|
+
"$ref": "../services/addon-docs/mdx/komponenten-feedback-snackbar.json#/components/komponenten-feedback-snackbar/docs/komponenten-feedback-snackbar--verwendung"
|
|
280
|
+
},
|
|
281
|
+
"summary": "# Verwendung Drei Snackbar-Varianten (Default, OK, Fehler) für Kontaktformular, Newsletter..."
|
|
282
|
+
}
|
|
213
283
|
}
|
|
214
284
|
},
|
|
215
285
|
"komponenten-cards-teaser-card": {
|
|
@@ -221,12 +291,22 @@
|
|
|
221
291
|
},
|
|
222
292
|
"stories": {
|
|
223
293
|
"$ref": "../services/core/story-docs/komponenten-cards-teaser-card.json#/components/komponenten-cards-teaser-card"
|
|
294
|
+
},
|
|
295
|
+
"docs": {
|
|
296
|
+
"komponenten-cards-teaser-card--verwendung": {
|
|
297
|
+
"id": "komponenten-cards-teaser-card--verwendung",
|
|
298
|
+
"name": "Verwendung",
|
|
299
|
+
"mdx": {
|
|
300
|
+
"$ref": "../services/addon-docs/mdx/komponenten-cards-teaser-card.json#/components/komponenten-cards-teaser-card/docs/komponenten-cards-teaser-card--verwendung"
|
|
301
|
+
},
|
|
302
|
+
"summary": "# Verwendung Generische Karten (statisch, Link-Karte) und Inhaltskarten (Stat), alle Brand..."
|
|
303
|
+
}
|
|
224
304
|
}
|
|
225
305
|
},
|
|
226
306
|
"komponenten-cards-teaser-klickbare-karte": {
|
|
227
307
|
"id": "komponenten-cards-teaser-klickbare-karte",
|
|
228
308
|
"name": "LinkCardComponent",
|
|
229
|
-
"description": "LinkCard (cds-link-card) — Wrapper um `a.card.card-elevated` aus css/components.css\n(css/components.css:147–154) samt `.card-cta-link` (css/components.css:1347–1356).\n\nDie Lücke, die `CardComponent` bewusst offen lässt (siehe deren Klassendoku):\n`.card-elevated` wirkt im CSS ausschließlich auf `a.card-elevated` (Riegel aus\n`CONTRIBUTING.md` §4, „Elevation = Interaktivität“) — eine `<article>`/`<div>`-Karte\nbekommt den Schatten auch mit gesetzter Klasse nicht. Diese Komponente rendert\ndeshalb ein echtes `<a>`, die ganze Fläche ist der Link, kein Klick-Handler auf\neinem nicht-interaktiven Element.\n\nStruktur wie `CardComponent`: optionale bereichsgefärbte `.card-media` mit der\nechten Bereichs-Glyphe, `.card-body` mit `.card-eyebrow` / `.card-title` /\n`.card-text`. Neu ist der Fuß `.card-cta-link`, optional unten angeheftet\n(`--pinned`, für gleich hohe Karten im Raster über `.card-body{flex:1}`).\n\n**Entscheidung — Fuß ist ein `<span>`, kein zweites `<a>`.** Die ganze Karte ist\nbereits `a.card-elevated`; ein verschachteltes `<a>` im Fuß wäre ungültiges HTML\n(der Browser schließt es beim Parsen vorzeitig) und würde zwei Klickziele auf\nderselben Fläche erzeugen. `docs/index.html:4707–4716` zeigt exakt dieses Muster:\n`<span class=\"card-cta-link card-cta-link--pinned\">…</span>` innerhalb von\n`a.card.card-elevated`. `.card-cta-link` selbst ist nicht auf `a.` gescoped (anders\nals `.card-elevated`), der Span trägt Farbe und Typografie also unverändert.\n\n**Entscheidung — Pfeil-Suffix wird von der Komponente ergänzt, nicht Teil von\n`ctaLabel`.** Der Pfeil ist reine visuelle Affordanz, kein Inhalt — `docs/index.html`\n(Abschnitt „Klickbare Karte“) kapselt ihn deshalb selbst in ein\n`aria-hidden`-Span. Läge das Zeichen im `ctaLabel`-Text, müsste jeder Aufrufer\nselbst an das `aria-hidden` denken; das wird hier stattdessen einmalig in der\nKomponente erledigt.\n\n**Entscheidung — kein `data-area` auf `.card-cta-link`.** Die Doku hält die\nCTA-Farbe in gemischten Bereichs-Listen bewusst einheitlich Corporate-Petrol\n(`docs/index.html:8762`: „CTA-Farbe einheitlich `--co-700`“), unabhängig vom\n`area` der Karte. Der Fuß bleibt deshalb ohne `data-area`-Bindung.\n\n**Entscheidung — Host als Flex-Container.** Im Raster ist der Host das\nGrid-Kind, das `align-items:stretch` auf Zeilenhöhe zieht, nicht `a.card`. Ohne\neigene Regel blieb die Karte auf Inhaltshöhe, und eine Karte ohne Eyebrow endete\nsamt `--pinned`-Fuß höher als ihre Nachbarn. `:host{display:flex}` mit\n`flex:1` an der Karte gibt die gestreckte Höhe an `a.card` weiter; Story\n„Im Raster“ pinnt das.",
|
|
309
|
+
"description": "LinkCard (cds-link-card) — Wrapper um `a.card.card-elevated` aus css/components.css\n(css/components.css:147–154) samt `.card-cta-link` (css/components.css:1347–1356).\n\nDie Lücke, die `CardComponent` bewusst offen lässt (siehe deren Klassendoku):\n`.card-elevated` wirkt im CSS ausschließlich auf `a.card-elevated` (Riegel aus\n`CONTRIBUTING.md` §4, „Elevation = Interaktivität“) — eine `<article>`/`<div>`-Karte\nbekommt den Schatten auch mit gesetzter Klasse nicht. Diese Komponente rendert\ndeshalb ein echtes `<a>`, die ganze Fläche ist der Link, kein Klick-Handler auf\neinem nicht-interaktiven Element.\n\nStruktur wie `CardComponent`: optionale bereichsgefärbte `.card-media` mit der\nechten Bereichs-Glyphe, `.card-body` mit `.card-eyebrow` / `.card-title` /\n`.card-text`. Neu ist der Fuß `.card-cta-link`, optional unten angeheftet\n(`--pinned`, für gleich hohe Karten im Raster über `.card-body{flex:1}`).\n\n**Entscheidung — Fuß ist ein `<span>`, kein zweites `<a>`.** Die ganze Karte ist\nbereits `a.card-elevated`; ein verschachteltes `<a>` im Fuß wäre ungültiges HTML\n(der Browser schließt es beim Parsen vorzeitig) und würde zwei Klickziele auf\nderselben Fläche erzeugen. `docs/index.html:4707–4716` zeigt exakt dieses Muster:\n`<span class=\"card-cta-link card-cta-link--pinned\">…</span>` innerhalb von\n`a.card.card-elevated`. `.card-cta-link` selbst ist nicht auf `a.` gescoped (anders\nals `.card-elevated`), der Span trägt Farbe und Typografie also unverändert.\n\n**Entscheidung — Pfeil-Suffix wird von der Komponente ergänzt, nicht Teil von\n`ctaLabel`.** Der Pfeil ist reine visuelle Affordanz, kein Inhalt — `docs/index.html`\n(Abschnitt „Klickbare Karte“) kapselt ihn deshalb selbst in ein\n`aria-hidden`-Span. Läge das Zeichen im `ctaLabel`-Text, müsste jeder Aufrufer\nselbst an das `aria-hidden` denken; das wird hier stattdessen einmalig in der\nKomponente erledigt.\n\n**Entscheidung — kein `data-area` auf `.card-cta-link`.** Die Doku hält die\nCTA-Farbe in gemischten Bereichs-Listen bewusst einheitlich Corporate-Petrol\n(`docs/index.html:8762`: „CTA-Farbe einheitlich `--co-700`“), unabhängig vom\n`area` der Karte. Der Fuß bleibt deshalb ohne `data-area`-Bindung.\n\n**Entscheidung — Host als Flex-Container.** Im Raster ist der Host das\nGrid-Kind, das `align-items:stretch` auf Zeilenhöhe zieht, nicht `a.card`. Ohne\neigene Regel blieb die Karte auf Inhaltshöhe, und eine Karte ohne Eyebrow endete\nsamt `--pinned`-Fuß höher als ihre Nachbarn. `:host{display:flex}` mit\n`flex:1` an der Karte gibt die gestreckte Höhe an `a.card` weiter; Story\n„Im Raster“ pinnt das.\n\nVerwendungsguidance dieser Gruppe: siehe Card (`komponenten-cards-teaser-card--verwendung`).",
|
|
230
310
|
"docgen": {
|
|
231
311
|
"$ref": "../services/core/docgen/komponenten-cards-teaser-klickbare-karte.json#/components/komponenten-cards-teaser-klickbare-karte"
|
|
232
312
|
},
|
|
@@ -237,7 +317,7 @@
|
|
|
237
317
|
"komponenten-cards-teaser-featured-karte": {
|
|
238
318
|
"id": "komponenten-cards-teaser-featured-karte",
|
|
239
319
|
"name": "FeaturedCardComponent",
|
|
240
|
-
"description": "FeaturedCard (cds-featured-card) — Wrapper um `.card-featured` aus\ncss/components.css (css/components.css:230–249): die horizontale Großkarte für\n**genau einen** hervorgehobenen Beitrag oder Termin (Bild links 60 %, Textspalte\nrechts 40 % als absolut positioniertes Overlay), siehe `docs/index.html`\nAbschnitt „Featured · horizontale Großkarte“ (`#gt-events-featured`).\n\n**Entscheidung 1 — `href` entscheidet zwischen `<a>` und `<article>`.** Die\nDoku-Beispiele zeigen die Featured-Card ausschließlich als Link\n(`a.card.card-elevated.card-featured`), das Ticket verlangt aber ausdrücklich eine\nVariante ohne `<a>`. `.card-elevated` ist nach `CONTRIBUTING.md` §4 („Elevation =\nInteraktivität“) im CSS auf `a.card-elevated` gescoped — eine `<article>` bekäme\nden Schatten mit gesetzter Klasse ohnehin nicht. Die Komponente führt die Klasse\ndeshalb nur mit, wenn sie auch wirkt: mit `href` ein `<a class=\"card card-elevated\ncard-featured\">`, ohne `href` ein `<article class=\"card card-featured\">` (ruht\nflach mit dem `--bd-strong`-Rahmen aus `.card`, wie jede statische Fläche). Media\nund Body stehen dafür einmal in einem gemeinsamen `<ng-template>` und werden in\nbeiden Zweigen per `<ng-container [ngTemplateOutlet]>` eingesetzt — dasselbe\nMuster wie `SectionComponent` (`section.component.ts`) für „zwei Wurzelelemente,\nein Körper“. `<ng-container>` rendert selbst kein Element, die Kindselektoren aus\nEntscheidung 2 bleiben also unberührt: im laufenden Storybook erneut per\n`querySelector`/`getBoundingClientRect` gemessen (siehe Play-Funktionen), Ergebnis\nunverändert zur vorherigen, noch duplizierten Fassung.\n\n**Entscheidung 2 — die Pill ist direkt komponiertes Markup, kein `<cds-pill>`.**\nDas CSS arbeitet mit direkten Kindselektoren: `.card-featured>.card-media`,\n`.card-featured-body>.pill`, `.card-featured-body>.card-text`,\n`.card-featured-body>.card-title-hero` (jeweils mit `margin`/`min-height`/\n`line-clamp`-Übernahmen, siehe CSS-Kommentare dort). `<cds-pill>` rendert sein\n`.pill`-`<span>` nicht auf dem eigenen Host-Element, sondern eine Ebene tiefer\n(`pill.component.ts`: Host ist `<cds-pill>`, `.pill` sitzt im Template darunter) —\nprojiziert als `<cds-pill class=\"pill\">` stünde die Pille damit als\n`.card-featured-body>cds-pill>.pill`, zwei Ebenen statt einer, und die\nKindselektoren griffen nicht mehr (leise: kein Fehler, nur falsches Layout).\nDieselbe Abwägung wie in `download-cta.component.ts` (Kommentar über den\nButtons): dort verhindert `.cta-dl-actions`, das seine Kinder per Flex streckt,\ndass ein `<cds-button>`-Host mitstreckt; hier verhindert ein Kindselektor, dass\nirgendein zusätzliches Host-Element dazwischentritt. In beiden Fällen werden die\nKlassen direkt komponiert statt eine Wrapper-Komponente zu verwenden. Geprüft im\nlaufenden Storybook (`Komponenten/Cards & Teaser/Featured-Karte`): die gerenderte\nKette ist `.card-featured>.card-media` und `.card-featured-body` mit `.pill`,\n`.card-text`, `.card-title-hero` als direkten Kindern, kein zusätzliches Element\ndazwischen (siehe Play-Funktionen der Stories).\n\nWeil die Pille direkt komponiert wird, übernimmt diese Komponente auch die\n`aria-label`-Regel von `PillComponent` (`pill.component.ts`) von Hand nach:\nDefault „Bereich `<pill>`“, überschreibbar über `pillAriaLabel` — nötig, weil die\nPille nicht immer einen Bereich benennt (siehe `pillAriaLabel`-Doku unten).\n\n**Entscheidung 3 — kein separates `data-area` für die Pille.** Die Doku setzt\nKarte und Pille immer auf denselben Bereich (`docs/index.html:8979`: Karte\n`data-area=\"es\"`, Pille `data-area=\"es\"`). Die Komponente bindet deshalb `area`\nauf beide, statt einen zweiten Bereichs-Input zu erfinden.\n\n**Entscheidung 4 — kein CTA- und kein Meta-Input.** Die Doku-Vorlage zeigt\nzusätzlich einen Meta-Strip (Datum/Ort/Format) und einen `.card-cta-link`-Fuß;\ndas Ticket benennt als API aber nur `title`/`text`/`imageSrc`/`imageAlt`/`href`/\n`pill`/`area`. Diese Komponente bildet exakt diese Fläche ab, ohne Inputs zu\nerfinden, die das Ticket nicht vorsieht — ein Meta-Strip oder ein CTA-Fuß wären\neine spätere, eigene Erweiterung.",
|
|
320
|
+
"description": "FeaturedCard (cds-featured-card) — Wrapper um `.card-featured` aus\ncss/components.css (css/components.css:230–249): die horizontale Großkarte für\n**genau einen** hervorgehobenen Beitrag oder Termin (Bild links 60 %, Textspalte\nrechts 40 % als absolut positioniertes Overlay), siehe `docs/index.html`\nAbschnitt „Featured · horizontale Großkarte“ (`#gt-events-featured`).\n\n**Entscheidung 1 — `href` entscheidet zwischen `<a>` und `<article>`.** Die\nDoku-Beispiele zeigen die Featured-Card ausschließlich als Link\n(`a.card.card-elevated.card-featured`), das Ticket verlangt aber ausdrücklich eine\nVariante ohne `<a>`. `.card-elevated` ist nach `CONTRIBUTING.md` §4 („Elevation =\nInteraktivität“) im CSS auf `a.card-elevated` gescoped — eine `<article>` bekäme\nden Schatten mit gesetzter Klasse ohnehin nicht. Die Komponente führt die Klasse\ndeshalb nur mit, wenn sie auch wirkt: mit `href` ein `<a class=\"card card-elevated\ncard-featured\">`, ohne `href` ein `<article class=\"card card-featured\">` (ruht\nflach mit dem `--bd-strong`-Rahmen aus `.card`, wie jede statische Fläche). Media\nund Body stehen dafür einmal in einem gemeinsamen `<ng-template>` und werden in\nbeiden Zweigen per `<ng-container [ngTemplateOutlet]>` eingesetzt — dasselbe\nMuster wie `SectionComponent` (`section.component.ts`) für „zwei Wurzelelemente,\nein Körper“. `<ng-container>` rendert selbst kein Element, die Kindselektoren aus\nEntscheidung 2 bleiben also unberührt: im laufenden Storybook erneut per\n`querySelector`/`getBoundingClientRect` gemessen (siehe Play-Funktionen), Ergebnis\nunverändert zur vorherigen, noch duplizierten Fassung.\n\n**Entscheidung 2 — die Pill ist direkt komponiertes Markup, kein `<cds-pill>`.**\nDas CSS arbeitet mit direkten Kindselektoren: `.card-featured>.card-media`,\n`.card-featured-body>.pill`, `.card-featured-body>.card-text`,\n`.card-featured-body>.card-title-hero` (jeweils mit `margin`/`min-height`/\n`line-clamp`-Übernahmen, siehe CSS-Kommentare dort). `<cds-pill>` rendert sein\n`.pill`-`<span>` nicht auf dem eigenen Host-Element, sondern eine Ebene tiefer\n(`pill.component.ts`: Host ist `<cds-pill>`, `.pill` sitzt im Template darunter) —\nprojiziert als `<cds-pill class=\"pill\">` stünde die Pille damit als\n`.card-featured-body>cds-pill>.pill`, zwei Ebenen statt einer, und die\nKindselektoren griffen nicht mehr (leise: kein Fehler, nur falsches Layout).\nDieselbe Abwägung wie in `download-cta.component.ts` (Kommentar über den\nButtons): dort verhindert `.cta-dl-actions`, das seine Kinder per Flex streckt,\ndass ein `<cds-button>`-Host mitstreckt; hier verhindert ein Kindselektor, dass\nirgendein zusätzliches Host-Element dazwischentritt. In beiden Fällen werden die\nKlassen direkt komponiert statt eine Wrapper-Komponente zu verwenden. Geprüft im\nlaufenden Storybook (`Komponenten/Cards & Teaser/Featured-Karte`): die gerenderte\nKette ist `.card-featured>.card-media` und `.card-featured-body` mit `.pill`,\n`.card-text`, `.card-title-hero` als direkten Kindern, kein zusätzliches Element\ndazwischen (siehe Play-Funktionen der Stories).\n\nWeil die Pille direkt komponiert wird, übernimmt diese Komponente auch die\n`aria-label`-Regel von `PillComponent` (`pill.component.ts`) von Hand nach:\nDefault „Bereich `<pill>`“, überschreibbar über `pillAriaLabel` — nötig, weil die\nPille nicht immer einen Bereich benennt (siehe `pillAriaLabel`-Doku unten).\n\n**Entscheidung 3 — kein separates `data-area` für die Pille.** Die Doku setzt\nKarte und Pille immer auf denselben Bereich (`docs/index.html:8979`: Karte\n`data-area=\"es\"`, Pille `data-area=\"es\"`). Die Komponente bindet deshalb `area`\nauf beide, statt einen zweiten Bereichs-Input zu erfinden.\n\n**Entscheidung 4 — kein CTA- und kein Meta-Input.** Die Doku-Vorlage zeigt\nzusätzlich einen Meta-Strip (Datum/Ort/Format) und einen `.card-cta-link`-Fuß;\ndas Ticket benennt als API aber nur `title`/`text`/`imageSrc`/`imageAlt`/`href`/\n`pill`/`area`. Diese Komponente bildet exakt diese Fläche ab, ohne Inputs zu\nerfinden, die das Ticket nicht vorsieht — ein Meta-Strip oder ein CTA-Fuß wären\neine spätere, eigene Erweiterung.\n\nVerwendungsguidance dieser Gruppe: siehe Card (`komponenten-cards-teaser-card--verwendung`).",
|
|
241
321
|
"docgen": {
|
|
242
322
|
"$ref": "../services/core/docgen/komponenten-cards-teaser-featured-karte.json#/components/komponenten-cards-teaser-featured-karte"
|
|
243
323
|
},
|
|
@@ -248,7 +328,7 @@
|
|
|
248
328
|
"komponenten-cards-teaser-icon-karte": {
|
|
249
329
|
"id": "komponenten-cards-teaser-icon-karte",
|
|
250
330
|
"name": "IconCardComponent",
|
|
251
|
-
"description": "IconCard (`[cdsIconCard]`) — Wrapper um `.ep-card` aus css/components.css\n(css/components.css:1298–1340): die Icon-Kachel mit farbiger Icon-Fläche, Eyebrow,\nTitel, Text und optionaler Pfeil-CTA-Zeile, die auf den Beispielseiten Bereichs-\nund Angebots-Einstiege trägt (`docs/index.html:9401–9420` u. a., 81 Vorkommen).\n\n**Entscheidung 1 — Attributselektor, kein Element-Selektor.** Erste Fassung dieser\nKomponente war `cds-icon-card` als eigenes Element mit `href`-Input, das intern\nzwischen `<a class=\"ep-card ep-card-link\">` und `<div class=\"ep-card\">` wählte\n(`@if`/`@else` + `<ng-template>`). Gemessen im laufenden Storybook: zwei Karten mit\nunterschiedlich langem Text ergaben im `.ep-cards`-Grid ungleiche `.ep-card`-Höhen\n(174px/270px), weil `align-items:stretch` nur den unsichtbaren `<cds-icon-card>`-Host\nstreckt, nicht das `.ep-card`-Element eine Ebene darunter. Dieselbe Messung mit\n`.ep-card` OHNE Host-Wrapper (rohes Markup direkt in `.ep-cards`) ergab 306px/306px,\nCTA-Unterkanten auf identischer Y-Koordinate — das CSS gleicht die Höhen korrekt aus,\nsobald `.ep-card` selbst das Grid-Kind ist. Der Fehler saß also im Wrapper-Element,\nnicht in der CSS-Schicht (siehe „Im Raster“-Story, dort dieselbe Messung als\nPlay-Funktion gepinnt).\n\nDie Lösung, analog zu Angular Materials `a[mat-button], button[mat-button]`: die\nKomponente hängt sich als Attribut an ein vom Konsumenten geschriebenes `<a>` oder\n`<div>`, statt ein eigenes Element zu sein. Dadurch trägt **derselbe** native Knoten,\nden der Konsument in sein Grid schreibt, sowohl die Komponentenlogik als auch die\n`.ep-card`-Klasse — kein Host-Element dazwischen, `align-items:stretch` trifft direkt\nauf `.ep-card`.\n\n**`href` ist deshalb kein Input mehr.** Ob die Karte ein Link ist, entscheidet der\nKonsument über das gewählte Tag (`<a cdsIconCard href=\"…\">` vs. `<div cdsIconCard>`)\nund setzt `href` als natives Attribut direkt am `<a>` — Angular muss dafür nichts\nverwalten. `.ep-card-link` (nur auf `a.ep-card-link` wirksam, `CONTRIBUTING.md` §4)\nwird deshalb vom Host-Tag abgeleitet, nicht mehr per Verzweigung im Template\ngerendert.\n\n**`.ep-card-link` hängt an `<a>` UND `href`, nicht am Tag allein.** Ein `<a\ncdsIconCard>` ohne `href` ist weder fokussierbar noch hat es eine Link-Rolle —\n`.ep-card-link` (Schatten, Hover-Anhebung, Cursor) nur am Tag festzumachen hätte\neine Karte erzeugt, die aussieht wie ein Link, aber keiner ist, und genau die\nGarantie aufgegeben, die die frühere `href`-Input-Fassung strukturell hatte (leerer\nString → zwingend der `<div>`-Zweig). `isLink()` prüft deshalb beides.\n\n**`isLink()` ist eine Methode im Host-Binding, kein einmalig berechnetes Feld.**\n`href` kann nach dem Erstellen zur Laufzeit gesetzt/entfernt werden (z. B.\n`<a cdsIconCard [attr.href]=\"urlSignal()\">`). Ein Host-Binding-Ausdruck\n(`'[class.ep-card-link]': 'isLink()'`) wird bei JEDEM Refresh der DECLARING VIEW\nneu ausgewertet — also der Elternvorlage, die `<a cdsIconCard>` schreibt —, nicht\nnur bei einem Refresh der eigenen (OnPush-gesteuerten) Kindvorlage dieser\nKomponente. Das ist kein Sonderfall wie bei einem in ADR-0007 §3 verworfenen\nGetter (dort ging es um einen Getter in einer INTERPOLATION der eigenen\nKindvorlage, die unter OnPush nur bei eigenen Signal-Änderungen neu läuft):\nHost-Bindings werden unabhängig vom OnPush-Status der Komponente selbst\nmitgeführt, wenn die Elternansicht aktualisiert wird — reagiert also auf\n`[attr.href]`/`[href]`-Bindungen des Konsumenten, ob Signal- oder\nZone.js-getrieben, ohne `effect()` (ADR-0007 §4) und ohne `MutationObserver`.\nEmpirisch geprüft (Spike-Story mit `[attr.href]=\"signal()\"`-Toggle zur Laufzeit,\nseither wieder gelöscht): Setzen des Signals nach Erstrender schaltet\n`.ep-card-link` zuverlässig um. Einzige Grenze: eine Änderung, die AUSSERHALB von\nAngular direkt am nativen Element vorgenommen wird (z. B. `el.setAttribute\n('href', …)` von Fremdcode), löst keinen Refresh aus — das gilt aber für jede\nAngular-Bindung gleichermaßen und ist kein Sonderfall dieser Komponente.\n\n**Entscheidung 2 — Icon als projizierter Inhalt, OHNE dass das SVG eine eigene\nGrößenklasse tragen muss.** Wie bei `cds-stoerer` (siehe dessen Klassendoku) sind\ndie Icons auf den Beispielseiten wechselnde Heroicons, keine DS-Bereichsglyphen aus\nder Registry `icons/cds-icons.ts` — Inhalt, nicht Chrom. Deshalb Projektion über\n`<ng-content select=\"[cdsIcon]\">` statt eines `icon`-Strings. Anders als beim Störer\nist `.ep-card-icon` hier aber ein echter CONTAINER: css/components.css:1310+1318\nsetzt Maße und Stroke über den Nachfahren-Selektor `.ep-card-icon svg{width:32px;\nheight:32px;stroke-width:var(--icon-stroke-sm)}`, nicht über eine Klasse auf dem\nSVG selbst. Der Konsument liefert deshalb ein unverändertes `<svg cdsIcon\nviewBox=\"…\" aria-hidden=\"true\" focusable=\"false\">…</svg>` OHNE zusätzliche Klasse —\ndas Verhältnis Größe/Stroke kommt allein aus dem Container. Geprüft an\ncss/components.css:1298–1318 (Kommentar dort: „Farbe kommt aus der Komponente,\nnicht aus … inline gesetzten style-Attributen“) und in der Story „Interaktiv“\ngepinnt (Play-Funktion misst die gerenderte SVG-Breite).\n\n**`data-area` sitzt auf drei Elementen** (`.ep-card` (Host), `.ep-card-icon`,\n`.ep-card-eyebrow`, wie im Mockup, `docs/index.html:4681–4686`): die CTA-Farbe\nbraucht dagegen KEIN eigenes `data-area`, sie kommt über den Nachfahren-Selektor\n`.ep-card[data-area=\"…\"] .ep-card-cta` (css/components.css:1336–1339) vom\n`data-area` der Karte selbst.\n\n**Kein erfundener `aria-label`.** Der Pfeil-Suffix der CTA-Zeile ist reine visuelle\nAffordanz (`docs/index.html:4686`: `<span aria-hidden=\"true\">→</span>`) und steht\ndeshalb `aria-hidden`, unverändert zum Mockup — kein zusätzlicher, selbst\nausgedachter zugänglicher Name.\n\n**Entscheidung 3 — kein `cdsIconCards`-Raster.** `.ep-cards` ist ein reines\n`display:grid` ohne Struktur oder Verhalten (dieselbe Begründung wie beim Verzicht\nauf einen `layout-grid`-Wrapper, siehe `spec.md`). Konsumenten schreiben\n`<div class=\"ep-cards\">` von Hand (siehe Story „Im Raster“).",
|
|
331
|
+
"description": "IconCard (`[cdsIconCard]`) — Wrapper um `.ep-card` aus css/components.css\n(css/components.css:1298–1340): die Icon-Kachel mit farbiger Icon-Fläche, Eyebrow,\nTitel, Text und optionaler Pfeil-CTA-Zeile, die auf den Beispielseiten Bereichs-\nund Angebots-Einstiege trägt (`docs/index.html:9401–9420` u. a., 81 Vorkommen).\n\n**Entscheidung 1 — Attributselektor, kein Element-Selektor.** Erste Fassung dieser\nKomponente war `cds-icon-card` als eigenes Element mit `href`-Input, das intern\nzwischen `<a class=\"ep-card ep-card-link\">` und `<div class=\"ep-card\">` wählte\n(`@if`/`@else` + `<ng-template>`). Gemessen im laufenden Storybook: zwei Karten mit\nunterschiedlich langem Text ergaben im `.ep-cards`-Grid ungleiche `.ep-card`-Höhen\n(174px/270px), weil `align-items:stretch` nur den unsichtbaren `<cds-icon-card>`-Host\nstreckt, nicht das `.ep-card`-Element eine Ebene darunter. Dieselbe Messung mit\n`.ep-card` OHNE Host-Wrapper (rohes Markup direkt in `.ep-cards`) ergab 306px/306px,\nCTA-Unterkanten auf identischer Y-Koordinate — das CSS gleicht die Höhen korrekt aus,\nsobald `.ep-card` selbst das Grid-Kind ist. Der Fehler saß also im Wrapper-Element,\nnicht in der CSS-Schicht (siehe „Im Raster“-Story, dort dieselbe Messung als\nPlay-Funktion gepinnt).\n\nDie Lösung, analog zu Angular Materials `a[mat-button], button[mat-button]`: die\nKomponente hängt sich als Attribut an ein vom Konsumenten geschriebenes `<a>` oder\n`<div>`, statt ein eigenes Element zu sein. Dadurch trägt **derselbe** native Knoten,\nden der Konsument in sein Grid schreibt, sowohl die Komponentenlogik als auch die\n`.ep-card`-Klasse — kein Host-Element dazwischen, `align-items:stretch` trifft direkt\nauf `.ep-card`.\n\n**`href` ist deshalb kein Input mehr.** Ob die Karte ein Link ist, entscheidet der\nKonsument über das gewählte Tag (`<a cdsIconCard href=\"…\">` vs. `<div cdsIconCard>`)\nund setzt `href` als natives Attribut direkt am `<a>` — Angular muss dafür nichts\nverwalten. `.ep-card-link` (nur auf `a.ep-card-link` wirksam, `CONTRIBUTING.md` §4)\nwird deshalb vom Host-Tag abgeleitet, nicht mehr per Verzweigung im Template\ngerendert.\n\n**`.ep-card-link` hängt an `<a>` UND `href`, nicht am Tag allein.** Ein `<a\ncdsIconCard>` ohne `href` ist weder fokussierbar noch hat es eine Link-Rolle —\n`.ep-card-link` (Schatten, Hover-Anhebung, Cursor) nur am Tag festzumachen hätte\neine Karte erzeugt, die aussieht wie ein Link, aber keiner ist, und genau die\nGarantie aufgegeben, die die frühere `href`-Input-Fassung strukturell hatte (leerer\nString → zwingend der `<div>`-Zweig). `isLink()` prüft deshalb beides.\n\n**`isLink()` ist eine Methode im Host-Binding, kein einmalig berechnetes Feld.**\n`href` kann nach dem Erstellen zur Laufzeit gesetzt/entfernt werden (z. B.\n`<a cdsIconCard [attr.href]=\"urlSignal()\">`). Ein Host-Binding-Ausdruck\n(`'[class.ep-card-link]': 'isLink()'`) wird bei JEDEM Refresh der DECLARING VIEW\nneu ausgewertet — also der Elternvorlage, die `<a cdsIconCard>` schreibt —, nicht\nnur bei einem Refresh der eigenen (OnPush-gesteuerten) Kindvorlage dieser\nKomponente. Das ist kein Sonderfall wie bei einem in ADR-0007 §3 verworfenen\nGetter (dort ging es um einen Getter in einer INTERPOLATION der eigenen\nKindvorlage, die unter OnPush nur bei eigenen Signal-Änderungen neu läuft):\nHost-Bindings werden unabhängig vom OnPush-Status der Komponente selbst\nmitgeführt, wenn die Elternansicht aktualisiert wird — reagiert also auf\n`[attr.href]`/`[href]`-Bindungen des Konsumenten, ob Signal- oder\nZone.js-getrieben, ohne `effect()` (ADR-0007 §4) und ohne `MutationObserver`.\nEmpirisch geprüft (Spike-Story mit `[attr.href]=\"signal()\"`-Toggle zur Laufzeit,\nseither wieder gelöscht): Setzen des Signals nach Erstrender schaltet\n`.ep-card-link` zuverlässig um. Einzige Grenze: eine Änderung, die AUSSERHALB von\nAngular direkt am nativen Element vorgenommen wird (z. B. `el.setAttribute\n('href', …)` von Fremdcode), löst keinen Refresh aus — das gilt aber für jede\nAngular-Bindung gleichermaßen und ist kein Sonderfall dieser Komponente.\n\n**Entscheidung 2 — Icon als projizierter Inhalt, OHNE dass das SVG eine eigene\nGrößenklasse tragen muss.** Wie bei `cds-stoerer` (siehe dessen Klassendoku) sind\ndie Icons auf den Beispielseiten wechselnde Heroicons, keine DS-Bereichsglyphen aus\nder Registry `icons/cds-icons.ts` — Inhalt, nicht Chrom. Deshalb Projektion über\n`<ng-content select=\"[cdsIcon]\">` statt eines `icon`-Strings. Anders als beim Störer\nist `.ep-card-icon` hier aber ein echter CONTAINER: css/components.css:1310+1318\nsetzt Maße und Stroke über den Nachfahren-Selektor `.ep-card-icon svg{width:32px;\nheight:32px;stroke-width:var(--icon-stroke-sm)}`, nicht über eine Klasse auf dem\nSVG selbst. Der Konsument liefert deshalb ein unverändertes `<svg cdsIcon\nviewBox=\"…\" aria-hidden=\"true\" focusable=\"false\">…</svg>` OHNE zusätzliche Klasse —\ndas Verhältnis Größe/Stroke kommt allein aus dem Container. Geprüft an\ncss/components.css:1298–1318 (Kommentar dort: „Farbe kommt aus der Komponente,\nnicht aus … inline gesetzten style-Attributen“) und in der Story „Interaktiv“\ngepinnt (Play-Funktion misst die gerenderte SVG-Breite).\n\n**`data-area` sitzt auf drei Elementen** (`.ep-card` (Host), `.ep-card-icon`,\n`.ep-card-eyebrow`, wie im Mockup, `docs/index.html:4681–4686`): die CTA-Farbe\nbraucht dagegen KEIN eigenes `data-area`, sie kommt über den Nachfahren-Selektor\n`.ep-card[data-area=\"…\"] .ep-card-cta` (css/components.css:1336–1339) vom\n`data-area` der Karte selbst.\n\n**Kein erfundener `aria-label`.** Der Pfeil-Suffix der CTA-Zeile ist reine visuelle\nAffordanz (`docs/index.html:4686`: `<span aria-hidden=\"true\">→</span>`) und steht\ndeshalb `aria-hidden`, unverändert zum Mockup — kein zusätzlicher, selbst\nausgedachter zugänglicher Name.\n\n**Entscheidung 3 — kein `cdsIconCards`-Raster.** `.ep-cards` ist ein reines\n`display:grid` ohne Struktur oder Verhalten (dieselbe Begründung wie beim Verzicht\nauf einen `layout-grid`-Wrapper, siehe `spec.md`). Konsumenten schreiben\n`<div class=\"ep-cards\">` von Hand (siehe Story „Im Raster“).\n\nVerwendungsguidance dieser Gruppe: siehe Card (`komponenten-cards-teaser-card--verwendung`).",
|
|
252
332
|
"docgen": {
|
|
253
333
|
"$ref": "../services/core/docgen/komponenten-cards-teaser-icon-karte.json#/components/komponenten-cards-teaser-icon-karte"
|
|
254
334
|
},
|
|
@@ -259,7 +339,7 @@
|
|
|
259
339
|
"komponenten-cards-teaser-feature-liste": {
|
|
260
340
|
"id": "komponenten-cards-teaser-feature-liste",
|
|
261
341
|
"name": "FeatureComponent",
|
|
262
|
-
"description": "Feature (`[cdsFeature]`) — Wrapper um `.ep-feature` aus css/components.css\n(css/components.css:1363–1379): die flache Feature-Zeile ohne Box und ohne\nSchatten (Icon-Kachel links, Titel/Text rechts) — die „Offene Feature-Liste“ der\nBeispielseiten (Doku-Sektion `docs/index.html:4882` ff., Beispielseiten u. a.\n`docs/index.html:10405–10415`, `11582–11588`; 40 Vorkommen als\n`class=\"ep-feature col-4\"` im `.layout-grid`).\n\n**Attributselektor, kein eigenes Element (ADR-0008).** Das Mockup setzt die\nSpaltenklasse am selben Element wie `.ep-feature` (`class=\"ep-feature col-4\"`).\nDas Bauteil ist damit selbst Grid-Kind UND Ziel einer Layout-Klasse des\nKonsumenten — exakt das Kriterium aus\n[ADR-0008](../../../../../../docs/adr/0008-selektortyp-der-wrapper-komponenten.md).\nEin eigenes `<cds-feature>`-Element mit innerem `<div class=\"ep-feature\">` würde\n`.layout-grid>[class*=\"col-\"]` (css/base.css:214) brechen: der `col-*`-Selektor\nträfe den unsichtbaren Host, nicht `.ep-feature`, das `.layout-grid` gibt seinem\nKind (dem Host) dann zwar per `align-items:stretch` (Grid-Default) die volle\nZeilenhöhe, aber `.ep-feature` darunter bliebe auf Inhaltshöhe — derselbe Fehler,\nden ADR-0008 Fall 1 für `.ep-card`/`.ep-cards` gemessen hat (174px/270px statt\n306px/306px). Die Komponente hängt sich deshalb als Attribut an ein vom\nKonsumenten geschriebenes `<div>` (`<div cdsFeature class=\"col-4\">`), analog zu\n`cds-icon-card` (siehe dessen Klassendoku). Gemessen für dieses Bauteil in der\nStory „Dreispalter“ (Play-Funktion): drei `.ep-feature` mit stark\nunterschiedlich langem Text als `col-4`-Geschwister in einem `.layout-grid`\nergeben identische Höhen und deckungsgleiche Unterkanten (Messwerte in der\nStory-Doku dort).\n\n**Icon-Kontrakt: `.ep-feature-icon` ist ein Container, keine Klasse auf dem\nSVG — UND reicht zusätzlich die Farbe durch, anders als `.ep-card-icon`.** Wie\n`.ep-card-icon` (siehe `icon-card.component.ts`, Entscheidung 2) setzt\ncss/components.css:1369 Maße und Stroke über den Nachfahren-Selektor\n`.ep-feature-icon svg{width:26px;height:26px;stroke-width:var(--icon-stroke-md)}`\n— NICHT über eine Klasse auf dem SVG selbst, anders als `.stoerer-icon`\n(`stoerer.component.ts`), das direkt auf dem projizierten `<svg>` sitzt. Der\nKonsument liefert deshalb ein unverändertes\n`<svg cdsIcon viewBox=\"…\" aria-hidden=\"true\" focusable=\"false\">…</svg>` OHNE\nzusätzliche Größenklasse, projiziert über `<ng-content select=\"[cdsIcon]\">`\n(Kontrakt in der Story „Interaktiv“ per `getBoundingClientRect()` gepinnt).\nAnders als `.ep-card-icon` (nur `background`, kein `color`) setzt\n`.ep-feature-icon` UND ihre vier `[data-area]`-Varianten (css/components.css:\n1367–1372) zusätzlich `color` auf dem Container selbst. Das Mockup nutzt das\naktiv aus: die projizierten SVGs dort (`docs/index.html:10406` u. a.) tragen\n`stroke=\"currentColor\"` statt eines hart codierten Bereichstons — die Farbe\nkommt allein aus dem Container, ein Icon-Autor muss den Bereich der Kachel gar\nnicht kennen. Bei `cds-icon-card` ist das nicht möglich (kein `color` am\nContainer), dort trägt jedes Icon seinen Bereichston selbst im `stroke`-Attribut.\nStory „Interaktiv“ demonstriert das mit `stroke=\"currentColor\"` und prüft die\ngeerbte Farbe per `getComputedStyle()`. Die Icon-Kachel selbst ist im Mockup\n(`docs/index.html:4883` u. a.) ein `<span aria-hidden=\"true\">`, kein `<div>` —\nrein dekorativ, das SVG trägt bereits sein eigenes `aria-hidden`; die Komponente\nübernimmt beides unverändert.\n\n**CTA: `<a>` mit `href`, sonst `<span>` — nie ein `<a>` ohne `href`.**\ncss/components.css:1376 zielt mit `.ep-feature-body>.card-cta-link` auf den\ndirekten Nachfahren; Angulars `@if`/`@else` fügt dafür kein Wrapper-Element ein\n(kompiliert zu Kommentar-Ankern, kein Element), der Kindselektor bleibt also in\nbeiden Zweigen erhalten. Ausgezählt in `docs/index.html`: alle 13 Vorkommen von\n`.card-cta-link` innerhalb von `.ep-feature-body` sind entweder ein `<a\nhref=\"…\">` (12×) oder ein `<span>` (1×, `docs/index.html:13216`,\n„Landingpage folgt“ — Platzhalter für ein Ziel, das noch fehlt). Ein `<a>` OHNE\n`href` kommt kein einziges Mal vor — dieselbe Falle, die `cds-icon-card` über\n`isLink()` schließt (ein Link-Tag ohne `href` ist weder fokussierbar noch hat\nes eine Link-Rolle, sieht mit der `.card-cta-link`-Optik aber trotzdem wie ein\nbedienbares Element aus). Hier entscheidet sich das nicht am Host-Tag (der ist\nbei `cdsFeature` immer `<div>`), sondern strukturell im eigenen Template:\n`ctaHref` gesetzt → `<a class=\"card-cta-link\" [href]=\"ctaHref()\">`, leer →\n`<span class=\"card-cta-link\">` mit identischer Optik und identischem Pfeil,\naber ohne Link-Rolle (siehe Story „Ohne Href“). Ein `[attr.href]`-Nullwert wäre\ndieselbe Krücke gewesen wie ein `<a>` ohne `href` zu tolerieren; der\n`@if`/`@else`-Zweig macht den Fall stattdessen unmöglich, statt ihn nur\nabzufedern. `data-area` sitzt auf beiden Zweigen, weil `.card-cta-link[data-area]`\n(css/components.css:1363–1366) ein direkter Attributselektor ist, keine\nNachfahren-Regel wie `.ep-card[data-area] .ep-card-cta` bei der Icon-Karte —\nohne eigenes `data-area` bliebe der Link/Span auf der CSS-Vorgabefarbe, auch bei\ngesetztem `area`.\n\n**`ctaAriaLabel` — der zugängliche Name ist im Mockup die Regel, nicht die\nAusnahme.** Erster Anlauf dieser Komponente hatte keinen solchen Input, mit der\n(falschen) Annahme, das Mockup verzichte meist auf einen zusätzlichen\n`aria-label`. Ausgezählt: von den 12 `<a class=\"card-cta-link\">` in\n`.ep-feature-body` tragen 11 einen `aria-label`, nur einer nicht\n(„Contentletter abonnieren“, `docs/index.html:15203` — der sichtbare Text ist\ndort bereits eindeutig). Grund: nur 3 verschiedene sichtbare Texte verteilen\nsich auf diese 12 Links, „Zur Landingpage“ allein zehnmal\n(`docs/index.html:11587` u. a.) — eine Screenreader-Linkliste hörte sonst\nzehnmal denselben Namen ohne Unterscheidung. Das Mockup disambiguiert\ndurchgängig mit der Form `<sichtbarer Text>: <Ziel>`\n(`aria-label=\"Zur Landingpage: KI Kickstart Workshops\"`). `ctaAriaLabel` ist\ndeshalb Beiwerk (Default `''`): leer bleibt der sichtbare `ctaLabel`-Text der\nzugängliche Name (passt für einen eindeutigen CTA-Text wie „Contentletter\nabonnieren“), gesetzt überschreibt er ihn — Konsumenten mit einer Liste\ngleichlautender CTA-Texte (wie den zehn „Zur Landingpage“ im Mockup) setzen ihn\npro Instanz auf `<ctaLabel>: <Ziel>`. Wirkt nur am `<a>`-Zweig: `aria-label` an\neinem `<span>` ohne Rolle hat keinen verlässlichen Effekt im\nAccessibility-Baum, und der `<span>`-Zweig ist ohnehin nicht interaktiv.",
|
|
342
|
+
"description": "Feature (`[cdsFeature]`) — Wrapper um `.ep-feature` aus css/components.css\n(css/components.css:1363–1379): die flache Feature-Zeile ohne Box und ohne\nSchatten (Icon-Kachel links, Titel/Text rechts) — die „Offene Feature-Liste“ der\nBeispielseiten (Doku-Sektion `docs/index.html:4882` ff., Beispielseiten u. a.\n`docs/index.html:10405–10415`, `11582–11588`; 40 Vorkommen als\n`class=\"ep-feature col-4\"` im `.layout-grid`).\n\n**Attributselektor, kein eigenes Element (ADR-0008).** Das Mockup setzt die\nSpaltenklasse am selben Element wie `.ep-feature` (`class=\"ep-feature col-4\"`).\nDas Bauteil ist damit selbst Grid-Kind UND Ziel einer Layout-Klasse des\nKonsumenten — exakt das Kriterium aus\n[ADR-0008](../../../../../../docs/adr/0008-selektortyp-der-wrapper-komponenten.md).\nEin eigenes `<cds-feature>`-Element mit innerem `<div class=\"ep-feature\">` würde\n`.layout-grid>[class*=\"col-\"]` (css/base.css:214) brechen: der `col-*`-Selektor\nträfe den unsichtbaren Host, nicht `.ep-feature`, das `.layout-grid` gibt seinem\nKind (dem Host) dann zwar per `align-items:stretch` (Grid-Default) die volle\nZeilenhöhe, aber `.ep-feature` darunter bliebe auf Inhaltshöhe — derselbe Fehler,\nden ADR-0008 Fall 1 für `.ep-card`/`.ep-cards` gemessen hat (174px/270px statt\n306px/306px). Die Komponente hängt sich deshalb als Attribut an ein vom\nKonsumenten geschriebenes `<div>` (`<div cdsFeature class=\"col-4\">`), analog zu\n`cds-icon-card` (siehe dessen Klassendoku). Gemessen für dieses Bauteil in der\nStory „Dreispalter“ (Play-Funktion): drei `.ep-feature` mit stark\nunterschiedlich langem Text als `col-4`-Geschwister in einem `.layout-grid`\nergeben identische Höhen und deckungsgleiche Unterkanten (Messwerte in der\nStory-Doku dort).\n\n**Icon-Kontrakt: `.ep-feature-icon` ist ein Container, keine Klasse auf dem\nSVG — UND reicht zusätzlich die Farbe durch, anders als `.ep-card-icon`.** Wie\n`.ep-card-icon` (siehe `icon-card.component.ts`, Entscheidung 2) setzt\ncss/components.css:1369 Maße und Stroke über den Nachfahren-Selektor\n`.ep-feature-icon svg{width:26px;height:26px;stroke-width:var(--icon-stroke-md)}`\n— NICHT über eine Klasse auf dem SVG selbst, anders als `.stoerer-icon`\n(`stoerer.component.ts`), das direkt auf dem projizierten `<svg>` sitzt. Der\nKonsument liefert deshalb ein unverändertes\n`<svg cdsIcon viewBox=\"…\" aria-hidden=\"true\" focusable=\"false\">…</svg>` OHNE\nzusätzliche Größenklasse, projiziert über `<ng-content select=\"[cdsIcon]\">`\n(Kontrakt in der Story „Interaktiv“ per `getBoundingClientRect()` gepinnt).\nAnders als `.ep-card-icon` (nur `background`, kein `color`) setzt\n`.ep-feature-icon` UND ihre vier `[data-area]`-Varianten (css/components.css:\n1367–1372) zusätzlich `color` auf dem Container selbst. Das Mockup nutzt das\naktiv aus: die projizierten SVGs dort (`docs/index.html:10406` u. a.) tragen\n`stroke=\"currentColor\"` statt eines hart codierten Bereichstons — die Farbe\nkommt allein aus dem Container, ein Icon-Autor muss den Bereich der Kachel gar\nnicht kennen. Bei `cds-icon-card` ist das nicht möglich (kein `color` am\nContainer), dort trägt jedes Icon seinen Bereichston selbst im `stroke`-Attribut.\nStory „Interaktiv“ demonstriert das mit `stroke=\"currentColor\"` und prüft die\ngeerbte Farbe per `getComputedStyle()`. Die Icon-Kachel selbst ist im Mockup\n(`docs/index.html:4883` u. a.) ein `<span aria-hidden=\"true\">`, kein `<div>` —\nrein dekorativ, das SVG trägt bereits sein eigenes `aria-hidden`; die Komponente\nübernimmt beides unverändert.\n\n**CTA: `<a>` mit `href`, sonst `<span>` — nie ein `<a>` ohne `href`.**\ncss/components.css:1376 zielt mit `.ep-feature-body>.card-cta-link` auf den\ndirekten Nachfahren; Angulars `@if`/`@else` fügt dafür kein Wrapper-Element ein\n(kompiliert zu Kommentar-Ankern, kein Element), der Kindselektor bleibt also in\nbeiden Zweigen erhalten. Ausgezählt in `docs/index.html`: alle 13 Vorkommen von\n`.card-cta-link` innerhalb von `.ep-feature-body` sind entweder ein `<a\nhref=\"…\">` (12×) oder ein `<span>` (1×, `docs/index.html:13216`,\n„Landingpage folgt“ — Platzhalter für ein Ziel, das noch fehlt). Ein `<a>` OHNE\n`href` kommt kein einziges Mal vor — dieselbe Falle, die `cds-icon-card` über\n`isLink()` schließt (ein Link-Tag ohne `href` ist weder fokussierbar noch hat\nes eine Link-Rolle, sieht mit der `.card-cta-link`-Optik aber trotzdem wie ein\nbedienbares Element aus). Hier entscheidet sich das nicht am Host-Tag (der ist\nbei `cdsFeature` immer `<div>`), sondern strukturell im eigenen Template:\n`ctaHref` gesetzt → `<a class=\"card-cta-link\" [href]=\"ctaHref()\">`, leer →\n`<span class=\"card-cta-link\">` mit identischer Optik und identischem Pfeil,\naber ohne Link-Rolle (siehe Story „Ohne Href“). Ein `[attr.href]`-Nullwert wäre\ndieselbe Krücke gewesen wie ein `<a>` ohne `href` zu tolerieren; der\n`@if`/`@else`-Zweig macht den Fall stattdessen unmöglich, statt ihn nur\nabzufedern. `data-area` sitzt auf beiden Zweigen, weil `.card-cta-link[data-area]`\n(css/components.css:1363–1366) ein direkter Attributselektor ist, keine\nNachfahren-Regel wie `.ep-card[data-area] .ep-card-cta` bei der Icon-Karte —\nohne eigenes `data-area` bliebe der Link/Span auf der CSS-Vorgabefarbe, auch bei\ngesetztem `area`.\n\n**`ctaAriaLabel` — der zugängliche Name ist im Mockup die Regel, nicht die\nAusnahme.** Erster Anlauf dieser Komponente hatte keinen solchen Input, mit der\n(falschen) Annahme, das Mockup verzichte meist auf einen zusätzlichen\n`aria-label`. Ausgezählt: von den 12 `<a class=\"card-cta-link\">` in\n`.ep-feature-body` tragen 11 einen `aria-label`, nur einer nicht\n(„Contentletter abonnieren“, `docs/index.html:15203` — der sichtbare Text ist\ndort bereits eindeutig). Grund: nur 3 verschiedene sichtbare Texte verteilen\nsich auf diese 12 Links, „Zur Landingpage“ allein zehnmal\n(`docs/index.html:11587` u. a.) — eine Screenreader-Linkliste hörte sonst\nzehnmal denselben Namen ohne Unterscheidung. Das Mockup disambiguiert\ndurchgängig mit der Form `<sichtbarer Text>: <Ziel>`\n(`aria-label=\"Zur Landingpage: KI Kickstart Workshops\"`). `ctaAriaLabel` ist\ndeshalb Beiwerk (Default `''`): leer bleibt der sichtbare `ctaLabel`-Text der\nzugängliche Name (passt für einen eindeutigen CTA-Text wie „Contentletter\nabonnieren“), gesetzt überschreibt er ihn — Konsumenten mit einer Liste\ngleichlautender CTA-Texte (wie den zehn „Zur Landingpage“ im Mockup) setzen ihn\npro Instanz auf `<ctaLabel>: <Ziel>`. Wirkt nur am `<a>`-Zweig: `aria-label` an\neinem `<span>` ohne Rolle hat keinen verlässlichen Effekt im\nAccessibility-Baum, und der `<span>`-Zweig ist ohnehin nicht interaktiv.\n\nVerwendungsguidance dieser Gruppe: siehe Card (`komponenten-cards-teaser-card--verwendung`).",
|
|
263
343
|
"docgen": {
|
|
264
344
|
"$ref": "../services/core/docgen/komponenten-cards-teaser-feature-liste.json#/components/komponenten-cards-teaser-feature-liste"
|
|
265
345
|
},
|
|
@@ -270,7 +350,7 @@
|
|
|
270
350
|
"komponenten-cards-teaser-tier-trenner": {
|
|
271
351
|
"id": "komponenten-cards-teaser-tier-trenner",
|
|
272
352
|
"name": "TierComponent",
|
|
273
|
-
"description": "Tier (`cds-tier`) — Wrapper um `.ep-tier` aus css/components.css\n(css/components.css:1381–1384): der Stufen-Trenner (Label + Haarlinie), der eine\nOffene Feature-Liste in Pakete gliedert (z. B. „In jedem Paket enthalten“ /\n„Zusätzlich mit Pro“, Doku-Sektion `docs/index.html:4880`, Beispielseiten\n`docs/index.html:11855–11857`, `11883–11885`, `12576–12578`).\n\n**Element-Selektor, kein Attribut (ADR-0008-Standardfall).** Ausgezählt: alle 4\n`.ep-tier`-Vorkommen in `docs/index.html` stehen als eigenständiger `<div>` VOR\neinem `.layout-grid` oder einer Karten-Reihe, nie als deren Kind — keines trägt\neine `col-*`-Spaltenklasse, keines liegt in einem Grid/Flex, das seine Kinder\ndehnt. Das Tag variiert ebenfalls nicht (immer `<div>`). Keines der drei\nADR-0008-Kriterien (Grid-/Flex-Kind, Ziel einer Layout-Klasse, wechselndes Tag)\ntrifft zu, der Element-Selektor bleibt deshalb der Standardfall. `.ep-tier{\ndisplay:flex}` sitzt direkt auf dem Host (`host: { class: 'ep-tier' }`), kein\ninneres Wrapper-Element darunter — anders als bei `cds-section` (ADR-0008 Fall 2)\nist hier nichts von außen auf eine bestimmte DOM-Tiefe angewiesen: kein\nNachfahren-Selektor zielt auf `.ep-tier`, keine Fläche hängt am Host.\n\n**`area` ist auf `'ki'` typisiert, nicht auf `CdsArea`.** `css/components.css:1383`\nkennt nur die eine Regel `.ep-tier-label[data-area=\"ki\"]` (Dark-Override\n`css/dark-mode.css:476`) — für `co`/`es`/`wo` existiert keine einzige\n`[data-area]`-Regel auf `.ep-tier-label`, per Grep über `css/*.css` geprüft.\nAusgezählt in `docs/index.html`: von 4 `.ep-tier-label`-Vorkommen tragen 3\n`data-area=\"ki\"` (4880, 11884, 12577), eines trägt gar kein `data-area` (11856),\nkeines der Werte `co`/`es`/`wo` kommt vor. Ein `area`-Input vom Typ `CdsArea`\nwürde für drei von vier gültigen Werten ein `data-area`-Attribut schreiben, das\nim CSS folgenlos bleibt — die Falle, die genau dann entsteht, wenn eine Eingabe\nmehr verspricht, als die Stilschicht einlöst. Der Typ ist deshalb auf den einen\nWert eingeschränkt, den das CSS tatsächlich kennt; der Compiler verhindert damit\nstrukturell, dass jemand `co`/`es`/`wo` setzt und ein wirkungsloses Attribut\nbekommt, statt es nur im JSDoc zu behaupten.",
|
|
353
|
+
"description": "Tier (`cds-tier`) — Wrapper um `.ep-tier` aus css/components.css\n(css/components.css:1381–1384): der Stufen-Trenner (Label + Haarlinie), der eine\nOffene Feature-Liste in Pakete gliedert (z. B. „In jedem Paket enthalten“ /\n„Zusätzlich mit Pro“, Doku-Sektion `docs/index.html:4880`, Beispielseiten\n`docs/index.html:11855–11857`, `11883–11885`, `12576–12578`).\n\n**Element-Selektor, kein Attribut (ADR-0008-Standardfall).** Ausgezählt: alle 4\n`.ep-tier`-Vorkommen in `docs/index.html` stehen als eigenständiger `<div>` VOR\neinem `.layout-grid` oder einer Karten-Reihe, nie als deren Kind — keines trägt\neine `col-*`-Spaltenklasse, keines liegt in einem Grid/Flex, das seine Kinder\ndehnt. Das Tag variiert ebenfalls nicht (immer `<div>`). Keines der drei\nADR-0008-Kriterien (Grid-/Flex-Kind, Ziel einer Layout-Klasse, wechselndes Tag)\ntrifft zu, der Element-Selektor bleibt deshalb der Standardfall. `.ep-tier{\ndisplay:flex}` sitzt direkt auf dem Host (`host: { class: 'ep-tier' }`), kein\ninneres Wrapper-Element darunter — anders als bei `cds-section` (ADR-0008 Fall 2)\nist hier nichts von außen auf eine bestimmte DOM-Tiefe angewiesen: kein\nNachfahren-Selektor zielt auf `.ep-tier`, keine Fläche hängt am Host.\n\n**`area` ist auf `'ki'` typisiert, nicht auf `CdsArea`.** `css/components.css:1383`\nkennt nur die eine Regel `.ep-tier-label[data-area=\"ki\"]` (Dark-Override\n`css/dark-mode.css:476`) — für `co`/`es`/`wo` existiert keine einzige\n`[data-area]`-Regel auf `.ep-tier-label`, per Grep über `css/*.css` geprüft.\nAusgezählt in `docs/index.html`: von 4 `.ep-tier-label`-Vorkommen tragen 3\n`data-area=\"ki\"` (4880, 11884, 12577), eines trägt gar kein `data-area` (11856),\nkeines der Werte `co`/`es`/`wo` kommt vor. Ein `area`-Input vom Typ `CdsArea`\nwürde für drei von vier gültigen Werten ein `data-area`-Attribut schreiben, das\nim CSS folgenlos bleibt — die Falle, die genau dann entsteht, wenn eine Eingabe\nmehr verspricht, als die Stilschicht einlöst. Der Typ ist deshalb auf den einen\nWert eingeschränkt, den das CSS tatsächlich kennt; der Compiler verhindert damit\nstrukturell, dass jemand `co`/`es`/`wo` setzt und ein wirkungsloses Attribut\nbekommt, statt es nur im JSDoc zu behaupten.\n\nVerwendungsguidance dieser Gruppe: siehe Card (`komponenten-cards-teaser-card--verwendung`).",
|
|
274
354
|
"docgen": {
|
|
275
355
|
"$ref": "../services/core/docgen/komponenten-cards-teaser-tier-trenner.json#/components/komponenten-cards-teaser-tier-trenner"
|
|
276
356
|
},
|
|
@@ -281,7 +361,7 @@
|
|
|
281
361
|
"komponenten-cards-teaser-statcard": {
|
|
282
362
|
"id": "komponenten-cards-teaser-statcard",
|
|
283
363
|
"name": "StatCardComponent",
|
|
284
|
-
"description": "StatCard — Wrapper um `.card-stat` aus css/components.css → „Stat Card“.\n\nFlache, statische Kennzahlen-Karte mit bereichsgefärbtem Top-Akzent (data-area),\ngroßem Wert (.card-stat-value), Label (.card-stat-label) und optionalem\nTrend-Pill (.card-stat-trend.up/.down) inkl. Richtungs-Pfeil — wie docs/index.html.",
|
|
364
|
+
"description": "StatCard — Wrapper um `.card-stat` aus css/components.css → „Stat Card“.\n\nFlache, statische Kennzahlen-Karte mit bereichsgefärbtem Top-Akzent (data-area),\ngroßem Wert (.card-stat-value), Label (.card-stat-label) und optionalem\nTrend-Pill (.card-stat-trend.up/.down) inkl. Richtungs-Pfeil — wie docs/index.html.\n\nVerwendungsguidance dieser Gruppe: siehe Card (`komponenten-cards-teaser-card--verwendung`).",
|
|
285
365
|
"docgen": {
|
|
286
366
|
"$ref": "../services/core/docgen/komponenten-cards-teaser-statcard.json#/components/komponenten-cards-teaser-statcard"
|
|
287
367
|
},
|
|
@@ -292,7 +372,7 @@
|
|
|
292
372
|
"komponenten-cards-teaser-statstrip": {
|
|
293
373
|
"id": "komponenten-cards-teaser-statstrip",
|
|
294
374
|
"name": "StatStripComponent",
|
|
295
|
-
"description": "StatStrip — Wrapper um `.card-stat-strip` + `.card-stat-flat` aus\ncss/components.css → „Stat-Strip“. Flacher Bandstreifen (auto-fit-Grid auf\n--n-50-Grund) mit zentrierten Kennzahlen ohne Rahmen/Schatten; Wert je\nBereich getönt via [data-area]. Genau wie docs/index.html.",
|
|
375
|
+
"description": "StatStrip — Wrapper um `.card-stat-strip` + `.card-stat-flat` aus\ncss/components.css → „Stat-Strip“. Flacher Bandstreifen (auto-fit-Grid auf\n--n-50-Grund) mit zentrierten Kennzahlen ohne Rahmen/Schatten; Wert je\nBereich getönt via [data-area]. Genau wie docs/index.html.\n\nVerwendungsguidance dieser Gruppe: siehe Card (`komponenten-cards-teaser-card--verwendung`).",
|
|
296
376
|
"docgen": {
|
|
297
377
|
"$ref": "../services/core/docgen/komponenten-cards-teaser-statstrip.json#/components/komponenten-cards-teaser-statstrip"
|
|
298
378
|
},
|
|
@@ -309,12 +389,22 @@
|
|
|
309
389
|
},
|
|
310
390
|
"stories": {
|
|
311
391
|
"$ref": "../services/core/story-docs/komponenten-call-to-action-cta-band.json#/components/komponenten-call-to-action-cta-band"
|
|
392
|
+
},
|
|
393
|
+
"docs": {
|
|
394
|
+
"komponenten-call-to-action-cta-band--verwendung": {
|
|
395
|
+
"id": "komponenten-call-to-action-cta-band--verwendung",
|
|
396
|
+
"name": "Verwendung",
|
|
397
|
+
"mdx": {
|
|
398
|
+
"$ref": "../services/addon-docs/mdx/komponenten-call-to-action-cta-band.json#/components/komponenten-call-to-action-cta-band/docs/komponenten-call-to-action-cta-band--verwendung"
|
|
399
|
+
},
|
|
400
|
+
"summary": "# Verwendung Call to Action deckt zwei Pattern-Familien ab: das Page-End-CTA-Band als letz..."
|
|
401
|
+
}
|
|
312
402
|
}
|
|
313
403
|
},
|
|
314
404
|
"komponenten-call-to-action-downloadcta": {
|
|
315
405
|
"id": "komponenten-call-to-action-downloadcta",
|
|
316
406
|
"name": "DownloadCtaComponent",
|
|
317
|
-
"description": "DownloadCta — Wrapper um `.cta-dl` aus css/components.css → „Download CTA“.\n\nAufmerksamkeitsstarker Download-Block mit bereichsgefärbtem Top-Akzent + Icon\n(data-area), Eyebrow/Titel/Beschreibung/Meta und zwei Aktionen (primär/sekundär,\nüber die bestehenden `.btn`-Klassen). Konsumiert nur vorhandene Styles.",
|
|
407
|
+
"description": "DownloadCta — Wrapper um `.cta-dl` aus css/components.css → „Download CTA“.\n\nAufmerksamkeitsstarker Download-Block mit bereichsgefärbtem Top-Akzent + Icon\n(data-area), Eyebrow/Titel/Beschreibung/Meta und zwei Aktionen (primär/sekundär,\nüber die bestehenden `.btn`-Klassen). Konsumiert nur vorhandene Styles.\n\nVerwendungsguidance dieser Gruppe: siehe CTA-Band (`komponenten-call-to-action-cta-band--verwendung`).",
|
|
318
408
|
"docgen": {
|
|
319
409
|
"$ref": "../services/core/docgen/komponenten-call-to-action-downloadcta.json#/components/komponenten-call-to-action-downloadcta"
|
|
320
410
|
},
|
|
@@ -331,12 +421,22 @@
|
|
|
331
421
|
},
|
|
332
422
|
"stories": {
|
|
333
423
|
"$ref": "../services/core/story-docs/komponenten-tabelle-tabelle.json#/components/komponenten-tabelle-tabelle"
|
|
424
|
+
},
|
|
425
|
+
"docs": {
|
|
426
|
+
"komponenten-tabelle-tabelle--verwendung": {
|
|
427
|
+
"id": "komponenten-tabelle-tabelle--verwendung",
|
|
428
|
+
"name": "Verwendung",
|
|
429
|
+
"mdx": {
|
|
430
|
+
"$ref": "../services/addon-docs/mdx/komponenten-tabelle-tabelle.json#/components/komponenten-tabelle-tabelle/docs/komponenten-tabelle-tabelle--verwendung"
|
|
431
|
+
},
|
|
432
|
+
"summary": "# Tabelle Barrierefreie Datentabellen mit ``, `scope`-Attributen und Tastaturnavigation, i..."
|
|
433
|
+
}
|
|
334
434
|
}
|
|
335
435
|
},
|
|
336
436
|
"komponenten-tabelle-vergleichstabelle": {
|
|
337
437
|
"id": "komponenten-tabelle-vergleichstabelle",
|
|
338
438
|
"name": "CompareComponent",
|
|
339
|
-
"description": "Compare (`cds-compare`) — Wrapper um `.ep-compare*` aus css/components.css\n(css/components.css:1275–1294): die aufklappbare Vergleichstabelle für den zeilenweisen\nDirektvergleich mehrerer Pakete/Tarife (Doku-Site `sec-table`, Nav-Eintrag\n„Vergleichstabelle (aufklappbar)“, `docs/index.html:5182–5204`). Zehntes Ticket der\nSeitenbausteine-Serie, nach `cds-table` (Ticket 09).\n\n**Mit Daten-Input, anders als `cds-table`.** `cds-table` projiziert `<thead>`/`<tbody>`\nunverändert per `<ng-content>`, weil seine Zellen Badges, Links und `data-num` tragen können\n(siehe dessen Klassendoku). Hier ist der Zellinhalt strukturell auf Ja/Nein oder eine kurze\nAngabe begrenzt — ausgezählt: alle 22 Datenzellen des einzigen realen Vorkommens\n(`docs/index.html:11970–12038`, 11 Zeilen × 2 Spalten, ohne die Zeilenüberschriften) sind\nentweder ein `.ep-compare-yes`/`-no`-Marker (18×, davon 14× „Ja“, 4× „Nein“) oder ein kurzer\nText wie „bis 70 Mrd. Param.“ bzw. „30 Min.“ (4×) — nie ein Badge, Link oder anderes Markup.\nWeil Spaltenzahl, `pro`-Spalte und Zellinhalt damit vollständig aus zwei Arrays (`columns`,\n`rows`) hervorgehen, würde `<ng-content>` beim Konsumenten nur denselben `@for`-Code\nduplizieren, ohne eine Freiheit zu gewinnen, die die Zell-Typisierung (`boolean | string`)\nohnehin ausschließt.\n\n**Ja/Nein-Zellen tragen einen Screenreader-Text, übernommen statt erfunden.** Im einzigen\nrealen Vorkommen steht hinter jeder Glyphe ein `.sr-only`-Text, ausnahmslos:\n`<span class=\"ep-compare-yes\" aria-hidden=\"true\">✓</span><span class=\"sr-only\">Enthalten</span>`\n(14×) bzw. `<span class=\"ep-compare-no\" aria-hidden=\"true\">−</span><span class=\"sr-only\">Nicht\nenthalten</span>` (4×, „−“ ist U+2212 Minus, kein Bindestrich). Genau diese Zeichen und dieser\nWortlaut, keine eigene Formulierung — Farbe und Glyphe allein tragen keine Bedeutung\n(WCAG 1.4.1), der `.sr-only`-Text ist deshalb kein optionaler Zusatz, sondern fest verdrahtet,\nnicht per Input überschreibbar.\n\n**`caption` ist Pflicht (`input.required<string>()`), abweichend von der Ticket-Skizze (dort\nkein Input dafür vorgesehen) — dieselbe Begründung wie bei `cds-table`.** Die eigene Doku\n(`storybook-angular/src/docs/komponenten/tabelle.mdx:91`) nennt `<caption class=\"sr-only\">`\nausdrücklich als Teil des Bauteils, und das einzige reale Vorkommen hat eine. Anders als bei\n`cds-table` ist sie hier `.sr-only`, nicht sichtbar: der Klartext steht schon im `<summary>`\n(`summary`-Input), die `<caption>` wiederholt ihn nur für Screenreader, die nach dem Aufklappen\ndirekt in die Tabelle springen, ohne den Summary-Text erneut vorgelesen zu bekommen.\n\n**`rowsLabel` (erste Kopfzelle, `<th scope=\"col\">Funktion</th>` im Mockup) ist dagegen Beiwerk,\noptional mit Default `''`.** Auch dafür sieht die Ticket-Skizze keinen Input vor. Den Text fest\nim Template zu verdrahten hieße, AI.Box-Copy in einen wiederverwendbaren Wrapper zu backen\n(ADR-0007 §2); ihn ganz wegzulassen wich ohne CSS-Befund vom einzigen Beleg ab, ohne dass die\nDoku das verlangt. Anders als `caption` ist die Kopfzelle nicht barrierefreiheitsrelevant\nPflicht: ein leeres `<th scope=\"col\">` bleibt eine gültige, in Vergleichsmatrizen verbreitete\nEcke ohne eigenen Namen. Deshalb Beiwerk, kein Inhalt — das Beispielwort „Funktion“ steht in\nder Story, nicht in der Klasse.\n\n**Natives `<details>`/`<summary>` bleibt erhalten, kein nachgebautes Disclosure** (Ticket-\nVorgabe, analog `cds-faq`): Tastaturbedienung und Toggle-Verhalten kommen vom Browser, das CSS\nhängt direkt an `[open]` (`.ep-compare[open] .ep-compare-caret`). `<details class=\"ep-compare\">`\nsitzt deshalb im TEMPLATE, nicht am Host — derselbe Grund wie bei `cds-table`s\n`.tbl-wrap`/`.tbl`: ein `<cds-compare>`-Host ist ein unbekanntes Custom Element, kein echtes\n`<details>`, und kann dessen native Disclosure-Semantik nicht annehmen.\n\n**Element-Selektor (ADR-0008-Standardfall).** `.ep-compare` sitzt im einzigen realen Vorkommen\nals gewöhnlicher Block-Nachfahre in `.ep-section` (`docs/index.html:11969`) — kein Grid-/\nFlex-Kind, keine `col-*`-Klasse vom Konsumenten, kein Tag-Wechsel (immer `<details>`). Keines\nder drei ADR-0008-Kriterien greift, ein Attributselektor brächte hier nichts.\n\n**`open` ist ein reiner Anfangszustand, keine Zwei-Wege-Bindung.** Gebunden über\n`[attr.open]=\"open() ? '' : null\"`: Angular schreibt das Attribut nur, wenn sich der GEPRÜFTE\nAusdruckswert seit dem letzten Change-Detection-Lauf ändert. `open()` bleibt nach dem ersten\nRendern konstant (die Komponente schreibt nie in dieses Signal zurück), ein nachfolgender\nnativer Toggle wird deshalb nicht rückgängig gemacht — geprüft in der Story „Interaktiv“\n(Play-Funktion: Klick öffnet, `toggled` feuert `true`, ein zweiter, vom Toggle unabhängiger\nInteraktionsschritt lässt die Tabelle weiterhin offen).",
|
|
439
|
+
"description": "Compare (`cds-compare`) — Wrapper um `.ep-compare*` aus css/components.css\n(css/components.css:1275–1294): die aufklappbare Vergleichstabelle für den zeilenweisen\nDirektvergleich mehrerer Pakete/Tarife (Doku-Site `sec-table`, Nav-Eintrag\n„Vergleichstabelle (aufklappbar)“, `docs/index.html:5182–5204`). Zehntes Ticket der\nSeitenbausteine-Serie, nach `cds-table` (Ticket 09).\n\n**Mit Daten-Input, anders als `cds-table`.** `cds-table` projiziert `<thead>`/`<tbody>`\nunverändert per `<ng-content>`, weil seine Zellen Badges, Links und `data-num` tragen können\n(siehe dessen Klassendoku). Hier ist der Zellinhalt strukturell auf Ja/Nein oder eine kurze\nAngabe begrenzt — ausgezählt: alle 22 Datenzellen des einzigen realen Vorkommens\n(`docs/index.html:11970–12038`, 11 Zeilen × 2 Spalten, ohne die Zeilenüberschriften) sind\nentweder ein `.ep-compare-yes`/`-no`-Marker (18×, davon 14× „Ja“, 4× „Nein“) oder ein kurzer\nText wie „bis 70 Mrd. Param.“ bzw. „30 Min.“ (4×) — nie ein Badge, Link oder anderes Markup.\nWeil Spaltenzahl, `pro`-Spalte und Zellinhalt damit vollständig aus zwei Arrays (`columns`,\n`rows`) hervorgehen, würde `<ng-content>` beim Konsumenten nur denselben `@for`-Code\nduplizieren, ohne eine Freiheit zu gewinnen, die die Zell-Typisierung (`boolean | string`)\nohnehin ausschließt.\n\n**Ja/Nein-Zellen tragen einen Screenreader-Text, übernommen statt erfunden.** Im einzigen\nrealen Vorkommen steht hinter jeder Glyphe ein `.sr-only`-Text, ausnahmslos:\n`<span class=\"ep-compare-yes\" aria-hidden=\"true\">✓</span><span class=\"sr-only\">Enthalten</span>`\n(14×) bzw. `<span class=\"ep-compare-no\" aria-hidden=\"true\">−</span><span class=\"sr-only\">Nicht\nenthalten</span>` (4×, „−“ ist U+2212 Minus, kein Bindestrich). Genau diese Zeichen und dieser\nWortlaut, keine eigene Formulierung — Farbe und Glyphe allein tragen keine Bedeutung\n(WCAG 1.4.1), der `.sr-only`-Text ist deshalb kein optionaler Zusatz, sondern fest verdrahtet,\nnicht per Input überschreibbar.\n\n**`caption` ist Pflicht (`input.required<string>()`), abweichend von der Ticket-Skizze (dort\nkein Input dafür vorgesehen) — dieselbe Begründung wie bei `cds-table`.** Die eigene Doku\n(`storybook-angular/src/docs/komponenten/tabelle.mdx:91`) nennt `<caption class=\"sr-only\">`\nausdrücklich als Teil des Bauteils, und das einzige reale Vorkommen hat eine. Anders als bei\n`cds-table` ist sie hier `.sr-only`, nicht sichtbar: der Klartext steht schon im `<summary>`\n(`summary`-Input), die `<caption>` wiederholt ihn nur für Screenreader, die nach dem Aufklappen\ndirekt in die Tabelle springen, ohne den Summary-Text erneut vorgelesen zu bekommen.\n\n**`rowsLabel` (erste Kopfzelle, `<th scope=\"col\">Funktion</th>` im Mockup) ist dagegen Beiwerk,\noptional mit Default `''`.** Auch dafür sieht die Ticket-Skizze keinen Input vor. Den Text fest\nim Template zu verdrahten hieße, AI.Box-Copy in einen wiederverwendbaren Wrapper zu backen\n(ADR-0007 §2); ihn ganz wegzulassen wich ohne CSS-Befund vom einzigen Beleg ab, ohne dass die\nDoku das verlangt. Anders als `caption` ist die Kopfzelle nicht barrierefreiheitsrelevant\nPflicht: ein leeres `<th scope=\"col\">` bleibt eine gültige, in Vergleichsmatrizen verbreitete\nEcke ohne eigenen Namen. Deshalb Beiwerk, kein Inhalt — das Beispielwort „Funktion“ steht in\nder Story, nicht in der Klasse.\n\n**Natives `<details>`/`<summary>` bleibt erhalten, kein nachgebautes Disclosure** (Ticket-\nVorgabe, analog `cds-faq`): Tastaturbedienung und Toggle-Verhalten kommen vom Browser, das CSS\nhängt direkt an `[open]` (`.ep-compare[open] .ep-compare-caret`). `<details class=\"ep-compare\">`\nsitzt deshalb im TEMPLATE, nicht am Host — derselbe Grund wie bei `cds-table`s\n`.tbl-wrap`/`.tbl`: ein `<cds-compare>`-Host ist ein unbekanntes Custom Element, kein echtes\n`<details>`, und kann dessen native Disclosure-Semantik nicht annehmen.\n\n**Element-Selektor (ADR-0008-Standardfall).** `.ep-compare` sitzt im einzigen realen Vorkommen\nals gewöhnlicher Block-Nachfahre in `.ep-section` (`docs/index.html:11969`) — kein Grid-/\nFlex-Kind, keine `col-*`-Klasse vom Konsumenten, kein Tag-Wechsel (immer `<details>`). Keines\nder drei ADR-0008-Kriterien greift, ein Attributselektor brächte hier nichts.\n\n**`open` ist ein reiner Anfangszustand, keine Zwei-Wege-Bindung.** Gebunden über\n`[attr.open]=\"open() ? '' : null\"`: Angular schreibt das Attribut nur, wenn sich der GEPRÜFTE\nAusdruckswert seit dem letzten Change-Detection-Lauf ändert. `open()` bleibt nach dem ersten\nRendern konstant (die Komponente schreibt nie in dieses Signal zurück), ein nachfolgender\nnativer Toggle wird deshalb nicht rückgängig gemacht — geprüft in der Story „Interaktiv“\n(Play-Funktion: Klick öffnet, `toggled` feuert `true`, ein zweiter, vom Toggle unabhängiger\nInteraktionsschritt lässt die Tabelle weiterhin offen).\n\nVerwendungsguidance dieser Gruppe: siehe Tabelle (`komponenten-tabelle-tabelle--verwendung`).",
|
|
340
440
|
"docgen": {
|
|
341
441
|
"$ref": "../services/core/docgen/komponenten-tabelle-vergleichstabelle.json#/components/komponenten-tabelle-vergleichstabelle"
|
|
342
442
|
},
|
|
@@ -353,12 +453,22 @@
|
|
|
353
453
|
},
|
|
354
454
|
"stories": {
|
|
355
455
|
"$ref": "../services/core/story-docs/komponenten-zitate-testimonials-blockquote.json#/components/komponenten-zitate-testimonials-blockquote"
|
|
456
|
+
},
|
|
457
|
+
"docs": {
|
|
458
|
+
"komponenten-zitate-testimonials-blockquote--verwendung": {
|
|
459
|
+
"id": "komponenten-zitate-testimonials-blockquote--verwendung",
|
|
460
|
+
"name": "Verwendung",
|
|
461
|
+
"mdx": {
|
|
462
|
+
"$ref": "../services/addon-docs/mdx/komponenten-zitate-testimonials-blockquote.json#/components/komponenten-zitate-testimonials-blockquote/docs/komponenten-zitate-testimonials-blockquote--verwendung"
|
|
463
|
+
},
|
|
464
|
+
"summary": "# Verwendung Zitate & Testimonials führt vier Formen: Blockquote, Testimonial-Card, Team-S..."
|
|
465
|
+
}
|
|
356
466
|
}
|
|
357
467
|
},
|
|
358
468
|
"komponenten-zitate-testimonials-testimonial": {
|
|
359
469
|
"id": "komponenten-zitate-testimonials-testimonial",
|
|
360
470
|
"name": "TestimonialComponent",
|
|
361
|
-
"description": "Testimonial — Wrapper um `.testimonial` aus css/components.css → „Testimonial Card“.\n\nStatische Zitat-Karte mit bereichsgefärbtem Top-Akzent (data-area), Quote-Icon\n(.testimonial-icon, fill:currentColor), Zitat (blockquote) und Footer mit Name/Rolle.\nNur bestehende Klassen — kein eigenes CSS.",
|
|
471
|
+
"description": "Testimonial — Wrapper um `.testimonial` aus css/components.css → „Testimonial Card“.\n\nStatische Zitat-Karte mit bereichsgefärbtem Top-Akzent (data-area), Quote-Icon\n(.testimonial-icon, fill:currentColor), Zitat (blockquote) und Footer mit Name/Rolle.\nNur bestehende Klassen — kein eigenes CSS.\n\nVerwendungsguidance dieser Gruppe: siehe Blockquote (`komponenten-zitate-testimonials-blockquote--verwendung`).",
|
|
362
472
|
"docgen": {
|
|
363
473
|
"$ref": "../services/core/docgen/komponenten-zitate-testimonials-testimonial.json#/components/komponenten-zitate-testimonials-testimonial"
|
|
364
474
|
},
|
|
@@ -369,7 +479,7 @@
|
|
|
369
479
|
"komponenten-zitate-testimonials-teamvoice": {
|
|
370
480
|
"id": "komponenten-zitate-testimonials-teamvoice",
|
|
371
481
|
"name": "TeamVoiceComponent",
|
|
372
|
-
"description": "TeamVoice — Wrapper um `.team-voice` aus css/components.css → „Team-Stimmen“.\n\nEditoriale Zitat-Reihe mit seitlichem Foto (im Grid abwechselnd links/rechts,\ngesteuert per :nth-child innerhalb von `.team-voices`), bereichsgefärbtem\nAkzent (data-area), Quote-Icon (ui-quote), Zitat und Name/Rolle. Mehrere\nKomponenten in einen `<div class=\"team-voices\">` legen, damit das alternierende\nLayout greift (siehe Story).",
|
|
482
|
+
"description": "TeamVoice — Wrapper um `.team-voice` aus css/components.css → „Team-Stimmen“.\n\nEditoriale Zitat-Reihe mit seitlichem Foto (im Grid abwechselnd links/rechts,\ngesteuert per :nth-child innerhalb von `.team-voices`), bereichsgefärbtem\nAkzent (data-area), Quote-Icon (ui-quote), Zitat und Name/Rolle. Mehrere\nKomponenten in einen `<div class=\"team-voices\">` legen, damit das alternierende\nLayout greift (siehe Story).\n\nVerwendungsguidance dieser Gruppe: siehe Blockquote (`komponenten-zitate-testimonials-blockquote--verwendung`).",
|
|
373
483
|
"docgen": {
|
|
374
484
|
"$ref": "../services/core/docgen/komponenten-zitate-testimonials-teamvoice.json#/components/komponenten-zitate-testimonials-teamvoice"
|
|
375
485
|
},
|
|
@@ -386,6 +496,16 @@
|
|
|
386
496
|
},
|
|
387
497
|
"stories": {
|
|
388
498
|
"$ref": "../services/core/story-docs/komponenten-code-block-code-block.json#/components/komponenten-code-block-code-block"
|
|
499
|
+
},
|
|
500
|
+
"docs": {
|
|
501
|
+
"komponenten-code-block-code-block--verwendung": {
|
|
502
|
+
"id": "komponenten-code-block-code-block--verwendung",
|
|
503
|
+
"name": "Verwendung",
|
|
504
|
+
"mdx": {
|
|
505
|
+
"$ref": "../services/addon-docs/mdx/komponenten-code-block-code-block.json#/components/komponenten-code-block-code-block/docs/komponenten-code-block-code-block--verwendung"
|
|
506
|
+
},
|
|
507
|
+
"summary": "# Verwendung Code-Block stellt Quellcode und Terminal-Ausgaben für Wissens- und Technikbei..."
|
|
508
|
+
}
|
|
389
509
|
}
|
|
390
510
|
},
|
|
391
511
|
"komponenten-slider-carousel-carousel": {
|
|
@@ -397,12 +517,22 @@
|
|
|
397
517
|
},
|
|
398
518
|
"stories": {
|
|
399
519
|
"$ref": "../services/core/story-docs/komponenten-slider-carousel-carousel.json#/components/komponenten-slider-carousel-carousel"
|
|
520
|
+
},
|
|
521
|
+
"docs": {
|
|
522
|
+
"komponenten-slider-carousel-carousel--verwendung": {
|
|
523
|
+
"id": "komponenten-slider-carousel-carousel--verwendung",
|
|
524
|
+
"name": "Verwendung",
|
|
525
|
+
"mdx": {
|
|
526
|
+
"$ref": "../services/addon-docs/mdx/komponenten-slider-carousel-carousel.json#/components/komponenten-slider-carousel-carousel/docs/komponenten-slider-carousel-carousel--verwendung"
|
|
527
|
+
},
|
|
528
|
+
"summary": "# Verwendung Slider & Carousel führt zwei getrennte Formen: das Bild-Carousel zur Seiten-I..."
|
|
529
|
+
}
|
|
400
530
|
}
|
|
401
531
|
},
|
|
402
532
|
"komponenten-slider-carousel-logocarousel": {
|
|
403
533
|
"id": "komponenten-slider-carousel-logocarousel",
|
|
404
534
|
"name": "LogoCarouselComponent",
|
|
405
|
-
"description": "LogoCarousel — Wrapper um `.logo-carousel` aus css/components.css → „Logo-Carousel“.\n\nDiskrete Sets von je fünf Logos, die automatisch per Crossfade wechseln\n(`[aria-hidden]` je Slide). Das Autoplay pausiert bei Maus-Hover und Tastatur-Fokus\n(damit Nutzer in Ruhe lesen/bedienen können), zusätzlich dauerhaft über den\nPause-Button (.logo-carousel-pause, sichtbar bei Hover/Fokus bzw. im .paused-Zustand);\nDots wählen ein Set direkt. Autoplay respektiert prefers-reduced-motion.\n\nDer Timer wird zentral über ein `effect` gesteuert: er läuft nur, wenn NICHT\npausiert, NICHT gehovert, NICHT fokussiert und reduzierte Bewegung nicht gewünscht\nist. Eine Änderung des `interval` startet ihn automatisch neu.\n\nJede Kachel ist ein `cds-logo`: bevorzugt ein Bild (`src`), sonst der Text als\nPlatzhalter/Fallback. Standardmäßig sind reine Text-Platzhalter gesetzt – reale\nAnwendungen übergeben ihre Kundenlogos als Bilder.",
|
|
535
|
+
"description": "LogoCarousel — Wrapper um `.logo-carousel` aus css/components.css → „Logo-Carousel“.\n\nDiskrete Sets von je fünf Logos, die automatisch per Crossfade wechseln\n(`[aria-hidden]` je Slide). Das Autoplay pausiert bei Maus-Hover und Tastatur-Fokus\n(damit Nutzer in Ruhe lesen/bedienen können), zusätzlich dauerhaft über den\nPause-Button (.logo-carousel-pause, sichtbar bei Hover/Fokus bzw. im .paused-Zustand);\nDots wählen ein Set direkt. Autoplay respektiert prefers-reduced-motion.\n\nDer Timer wird zentral über ein `effect` gesteuert: er läuft nur, wenn NICHT\npausiert, NICHT gehovert, NICHT fokussiert und reduzierte Bewegung nicht gewünscht\nist. Eine Änderung des `interval` startet ihn automatisch neu.\n\nJede Kachel ist ein `cds-logo`: bevorzugt ein Bild (`src`), sonst der Text als\nPlatzhalter/Fallback. Standardmäßig sind reine Text-Platzhalter gesetzt – reale\nAnwendungen übergeben ihre Kundenlogos als Bilder.\n\nVerwendungsguidance dieser Gruppe: siehe Carousel (`komponenten-slider-carousel-carousel--verwendung`).",
|
|
406
536
|
"docgen": {
|
|
407
537
|
"$ref": "../services/core/docgen/komponenten-slider-carousel-logocarousel.json#/components/komponenten-slider-carousel-logocarousel"
|
|
408
538
|
},
|
|
@@ -419,6 +549,16 @@
|
|
|
419
549
|
},
|
|
420
550
|
"stories": {
|
|
421
551
|
"$ref": "../services/core/story-docs/komponenten-sektion-sektion.json#/components/komponenten-sektion-sektion"
|
|
552
|
+
},
|
|
553
|
+
"docs": {
|
|
554
|
+
"komponenten-sektion-sektion--verwendung": {
|
|
555
|
+
"id": "komponenten-sektion-sektion--verwendung",
|
|
556
|
+
"name": "Verwendung",
|
|
557
|
+
"mdx": {
|
|
558
|
+
"$ref": "../services/addon-docs/mdx/komponenten-sektion-sektion.json#/components/komponenten-sektion-sektion/docs/komponenten-sektion-sektion--verwendung"
|
|
559
|
+
},
|
|
560
|
+
"summary": "# Sektion Das strukturelle Gerüst, in dem auf den Beispielseiten praktisch jeder andere Ba..."
|
|
561
|
+
}
|
|
422
562
|
}
|
|
423
563
|
},
|
|
424
564
|
"komponenten-navigation-topnav": {
|
|
@@ -430,6 +570,16 @@
|
|
|
430
570
|
},
|
|
431
571
|
"stories": {
|
|
432
572
|
"$ref": "../services/core/story-docs/komponenten-navigation-topnav.json#/components/komponenten-navigation-topnav"
|
|
573
|
+
},
|
|
574
|
+
"docs": {
|
|
575
|
+
"komponenten-navigation-topnav--verwendung": {
|
|
576
|
+
"id": "komponenten-navigation-topnav--verwendung",
|
|
577
|
+
"name": "Verwendung",
|
|
578
|
+
"mdx": {
|
|
579
|
+
"$ref": "../services/addon-docs/mdx/komponenten-navigation-topnav.json#/components/komponenten-navigation-topnav/docs/komponenten-navigation-topnav--verwendung"
|
|
580
|
+
},
|
|
581
|
+
"summary": "# Verwendung Navigation führt drei Elemente: Topnav, Breadcrumb und Back-to-Top-Button. Nu..."
|
|
582
|
+
}
|
|
433
583
|
}
|
|
434
584
|
},
|
|
435
585
|
"komponenten-hero-hero-bild": {
|
|
@@ -441,12 +591,22 @@
|
|
|
441
591
|
},
|
|
442
592
|
"stories": {
|
|
443
593
|
"$ref": "../services/core/story-docs/komponenten-hero-hero-bild.json#/components/komponenten-hero-hero-bild"
|
|
594
|
+
},
|
|
595
|
+
"docs": {
|
|
596
|
+
"komponenten-hero-hero-bild--verwendung": {
|
|
597
|
+
"id": "komponenten-hero-hero-bild--verwendung",
|
|
598
|
+
"name": "Verwendung",
|
|
599
|
+
"mdx": {
|
|
600
|
+
"$ref": "../services/addon-docs/mdx/komponenten-hero-hero-bild.json#/components/komponenten-hero-hero-bild/docs/komponenten-hero-hero-bild--verwendung"
|
|
601
|
+
},
|
|
602
|
+
"summary": "# Hero Drei Hero-Varianten für den Seitenkopf: Hero-Image mit Caption-Overlay (21:9, Stand..."
|
|
603
|
+
}
|
|
444
604
|
}
|
|
445
605
|
},
|
|
446
606
|
"komponenten-hero-störer": {
|
|
447
607
|
"id": "komponenten-hero-störer",
|
|
448
608
|
"name": "StoererSetComponent",
|
|
449
|
-
"description": "StoererSet (cds-stoerer-set) — Wrapper um `.stoerer-set` / `.stoerer-list` aus\ncss/components.css (css/components.css:926–974): das Set aus ein bis drei\n`<cds-stoerer>`-Kacheln, das auf der Startseite oben rechts über dem Hero-Bild\nliegt. Der Positionsrahmen `.stoerer-hero` (umschließt Hero-Bild UND Set,\n`container-type:inline-size` für die Container-Query-Schwelle) ist bewusst NICHT\nTeil dieser Komponente, sondern bleibt beim Konsumenten (siehe\n`.scratch/angular-seitenbausteine/issues/03-stoerer.md`): er umschließt Hero UND\nSet gemeinsam, das könnte diese Komponente als internes Detail nicht leisten, ohne\ndas Hero-Bild selbst zu kennen.\n\n**Entscheidung — `<li>` ohne strukturelles Wrapper-Element.** `.stoerer-list` ist\nein `<ul>`; nach HTML-AAM bekommt ein `<li>` die implizite Rolle `listitem` nur als\ndirektes Kind eines `<ul>`/`<ol>`/`<menu>` — Screenreader kündigen die Liste sonst\nnicht mit Anzahl an. Ein einfaches `<ng-content>` hätte `<cds-stoerer>` selbst\nzwischen `<ul>` und `<li>` geschoben (kein direktes Kind mehr), und ein\n`display:contents`-Wrapper verbietet sich als neues CSS (ADR-0001). Gelöst über\ndasselbe Muster, das `cds-area-tabs`/`cds-area-tab` bereits für „projizierte\nKind-Komponente, deren Markup an einer selbst bestimmten Stelle im eigenen Template\nlandet“ etabliert (`area-tabs/area-tabs.component.ts`): `cds-stoerer` rendert nicht\nin sich selbst, sondern in ein `<ng-template>` und liefert es als `TemplateRef`\n(`stoerer.component.ts`). Diese Komponente liest die projizierten `<cds-stoerer>`\nüber `contentChildren()` und setzt ihr Template per `ngTemplateOutlet` direkt in\nein selbst gerendertes `<li>` ein. Im laufenden Storybook geprüft (`Komponenten/Hero/\nStörer` → Story „Interaktiv“, DOM live im Browser per `querySelector` abgefragt,\nzusätzlich in der Play-Funktion der Story gepinnt): `<ul class=\"stoerer-list\">`\nhat ausschließlich `<li>` als direkte Kinder (`ul.stoerer-list > *` → `[\"LI\",\"LI\"]`),\n`<cds-stoerer>` selbst taucht im gerenderten DOM nirgends auf — Angular hängt\nunprojizierten Content ohne passendes `<ng-content>`-Ziel gar nicht erst ein, exakt\nwie bei `<cds-area-tab>` innerhalb von `<cds-area-tabs>`. Ein `items`-Array (die im\nTicket vermerkte Alternative) hätte denselben DOM-Baum ergeben, aber den\nKonsumenten gezwungen, das projizierte Icon jeder Kachel in ein Datenobjekt\numzuziehen; mit dieser Lösung bleibt die deklarative, Content-projizierende API\nerhalten.",
|
|
609
|
+
"description": "StoererSet (cds-stoerer-set) — Wrapper um `.stoerer-set` / `.stoerer-list` aus\ncss/components.css (css/components.css:926–974): das Set aus ein bis drei\n`<cds-stoerer>`-Kacheln, das auf der Startseite oben rechts über dem Hero-Bild\nliegt. Der Positionsrahmen `.stoerer-hero` (umschließt Hero-Bild UND Set,\n`container-type:inline-size` für die Container-Query-Schwelle) ist bewusst NICHT\nTeil dieser Komponente, sondern bleibt beim Konsumenten (siehe\n`.scratch/angular-seitenbausteine/issues/03-stoerer.md`): er umschließt Hero UND\nSet gemeinsam, das könnte diese Komponente als internes Detail nicht leisten, ohne\ndas Hero-Bild selbst zu kennen.\n\n**Entscheidung — `<li>` ohne strukturelles Wrapper-Element.** `.stoerer-list` ist\nein `<ul>`; nach HTML-AAM bekommt ein `<li>` die implizite Rolle `listitem` nur als\ndirektes Kind eines `<ul>`/`<ol>`/`<menu>` — Screenreader kündigen die Liste sonst\nnicht mit Anzahl an. Ein einfaches `<ng-content>` hätte `<cds-stoerer>` selbst\nzwischen `<ul>` und `<li>` geschoben (kein direktes Kind mehr), und ein\n`display:contents`-Wrapper verbietet sich als neues CSS (ADR-0001). Gelöst über\ndasselbe Muster, das `cds-area-tabs`/`cds-area-tab` bereits für „projizierte\nKind-Komponente, deren Markup an einer selbst bestimmten Stelle im eigenen Template\nlandet“ etabliert (`area-tabs/area-tabs.component.ts`): `cds-stoerer` rendert nicht\nin sich selbst, sondern in ein `<ng-template>` und liefert es als `TemplateRef`\n(`stoerer.component.ts`). Diese Komponente liest die projizierten `<cds-stoerer>`\nüber `contentChildren()` und setzt ihr Template per `ngTemplateOutlet` direkt in\nein selbst gerendertes `<li>` ein. Im laufenden Storybook geprüft (`Komponenten/Hero/\nStörer` → Story „Interaktiv“, DOM live im Browser per `querySelector` abgefragt,\nzusätzlich in der Play-Funktion der Story gepinnt): `<ul class=\"stoerer-list\">`\nhat ausschließlich `<li>` als direkte Kinder (`ul.stoerer-list > *` → `[\"LI\",\"LI\"]`),\n`<cds-stoerer>` selbst taucht im gerenderten DOM nirgends auf — Angular hängt\nunprojizierten Content ohne passendes `<ng-content>`-Ziel gar nicht erst ein, exakt\nwie bei `<cds-area-tab>` innerhalb von `<cds-area-tabs>`. Ein `items`-Array (die im\nTicket vermerkte Alternative) hätte denselben DOM-Baum ergeben, aber den\nKonsumenten gezwungen, das projizierte Icon jeder Kachel in ein Datenobjekt\numzuziehen; mit dieser Lösung bleibt die deklarative, Content-projizierende API\nerhalten.\n\nVerwendungsguidance dieser Gruppe: siehe Hero-Bild (`komponenten-hero-hero-bild--verwendung`).",
|
|
450
610
|
"docgen": {
|
|
451
611
|
"$ref": "../services/core/docgen/komponenten-hero-störer.json#/components/komponenten-hero-störer"
|
|
452
612
|
},
|
|
@@ -463,12 +623,22 @@
|
|
|
463
623
|
},
|
|
464
624
|
"stories": {
|
|
465
625
|
"$ref": "../services/core/story-docs/komponenten-footer-komplett.json#/components/komponenten-footer-komplett"
|
|
626
|
+
},
|
|
627
|
+
"docs": {
|
|
628
|
+
"komponenten-footer-komplett--verwendung": {
|
|
629
|
+
"id": "komponenten-footer-komplett--verwendung",
|
|
630
|
+
"name": "Verwendung",
|
|
631
|
+
"mdx": {
|
|
632
|
+
"$ref": "../services/addon-docs/mdx/komponenten-footer-komplett.json#/components/komponenten-footer-komplett/docs/komponenten-footer-komplett--verwendung"
|
|
633
|
+
},
|
|
634
|
+
"summary": "# Verwendung Footer ist ein Zwei-Band-Layout: heller Main-Bereich mit Spalten-Grid (Brand ..."
|
|
635
|
+
}
|
|
466
636
|
}
|
|
467
637
|
},
|
|
468
638
|
"komponenten-footer-oberer-teil": {
|
|
469
639
|
"id": "komponenten-footer-oberer-teil",
|
|
470
640
|
"name": "FooterMainComponent",
|
|
471
|
-
"description": "Footer — oberer Teil (`.footer-main`): helles Band als **generisches Spalten-Layout**.\nDer Inhalt wird als beliebige Spalten projiziert (jedes Top-Level-Kind = eine\nGrid-Spalte), statt fester Adresse/Nav/Newsletter-Struktur — so eignet es sich für\nWebsite- UND App-Footer ohne Marketing-Lock-in.\n\n```html\n<cds-footer-main>\n <div>…Spalte 1…</div>\n <div>…Spalte 2…</div>\n</cds-footer-main>\n```\n\nDie Host-Klasse `footer-main` trägt Hintergrund/Padding aus css/components.css;\n`:host{display:block}` macht das Band auch standalone zum Block. Spaltenanzahl/-breiten\nüber `columns` (grid-template-columns); ohne Angabe gilt das 3-Spalten-Default.",
|
|
641
|
+
"description": "Footer — oberer Teil (`.footer-main`): helles Band als **generisches Spalten-Layout**.\nDer Inhalt wird als beliebige Spalten projiziert (jedes Top-Level-Kind = eine\nGrid-Spalte), statt fester Adresse/Nav/Newsletter-Struktur — so eignet es sich für\nWebsite- UND App-Footer ohne Marketing-Lock-in.\n\n```html\n<cds-footer-main>\n <div>…Spalte 1…</div>\n <div>…Spalte 2…</div>\n</cds-footer-main>\n```\n\nDie Host-Klasse `footer-main` trägt Hintergrund/Padding aus css/components.css;\n`:host{display:block}` macht das Band auch standalone zum Block. Spaltenanzahl/-breiten\nüber `columns` (grid-template-columns); ohne Angabe gilt das 3-Spalten-Default.\n\nVerwendungsguidance dieser Gruppe: siehe Footer, Komplett (`komponenten-footer-komplett--verwendung`).",
|
|
472
642
|
"docgen": {
|
|
473
643
|
"$ref": "../services/core/docgen/komponenten-footer-oberer-teil.json#/components/komponenten-footer-oberer-teil"
|
|
474
644
|
},
|
|
@@ -479,7 +649,7 @@
|
|
|
479
649
|
"komponenten-footer-unterer-teil": {
|
|
480
650
|
"id": "komponenten-footer-unterer-teil",
|
|
481
651
|
"name": "FooterBottomComponent",
|
|
482
|
-
"description": "Footer — unterer Teil (`.footer-btm`): dunkler Streifen mit Copyright, Rechts-Links\nund Social-Profilen. Die Host-Klasse `footer-btm` trägt Hintergrund/Flex-Layout aus\ncss/components.css. Social-Glyphen sind schlanke Inline-SVGs in Weiß; verifizierte\nBuilt-in-Icons (linkedin, youtube) via `platform`, beliebige weitere via `iconPath
|
|
652
|
+
"description": "Footer — unterer Teil (`.footer-btm`): dunkler Streifen mit Copyright, Rechts-Links\nund Social-Profilen. Die Host-Klasse `footer-btm` trägt Hintergrund/Flex-Layout aus\ncss/components.css. Social-Glyphen sind schlanke Inline-SVGs in Weiß; verifizierte\nBuilt-in-Icons (linkedin, youtube) via `platform`, beliebige weitere via `iconPath`.\n\nVerwendungsguidance dieser Gruppe: siehe Footer, Komplett (`komponenten-footer-komplett--verwendung`).",
|
|
483
653
|
"docgen": {
|
|
484
654
|
"$ref": "../services/core/docgen/komponenten-footer-unterer-teil.json#/components/komponenten-footer-unterer-teil"
|
|
485
655
|
},
|
|
@@ -496,12 +666,22 @@
|
|
|
496
666
|
},
|
|
497
667
|
"stories": {
|
|
498
668
|
"$ref": "../services/core/story-docs/komponenten-theme-umschalter-cycle-button.json#/components/komponenten-theme-umschalter-cycle-button"
|
|
669
|
+
},
|
|
670
|
+
"docs": {
|
|
671
|
+
"komponenten-theme-umschalter-cycle-button--verwendung": {
|
|
672
|
+
"id": "komponenten-theme-umschalter-cycle-button--verwendung",
|
|
673
|
+
"name": "Verwendung",
|
|
674
|
+
"mdx": {
|
|
675
|
+
"$ref": "../services/addon-docs/mdx/komponenten-theme-umschalter-cycle-button.json#/components/komponenten-theme-umschalter-cycle-button/docs/komponenten-theme-umschalter-cycle-button--verwendung"
|
|
676
|
+
},
|
|
677
|
+
"summary": "# Theme-Umschalter · Verwendung `docs/index.html` hat für den Theme-Umschalter eine eigene..."
|
|
678
|
+
}
|
|
499
679
|
}
|
|
500
680
|
},
|
|
501
681
|
"komponenten-theme-umschalter-segment": {
|
|
502
682
|
"id": "komponenten-theme-umschalter-segment",
|
|
503
683
|
"name": "ThemeSegmentComponent",
|
|
504
|
-
"description": "Theme-Segment — Segment-Switch für das Farbthema. Vorgesehener Einsatz: als\neigenständiges Element zum Hovern. Ist daher IMMER responsiv (unter 640px\nIcon-only) und IMMER animiert (Aktiv-Markierung gleitet als Thumb) — beides\nfest, nicht konfigurierbar. Icon + Textlabel stehen immer nebeneinander.\n\nEinzige Konfiguration: `showSystem` (tri Hell/Dunkel/System vs. binär Hell/Dunkel).\n\nBaut auf den CSS-Kern-Klassen `.theme-bar`/`.tbtn` auf. Jeder Button trägt ein\n`aria-label`, ist also auch im Icon-only-Modus benannt. Der Thumb wird per\ngetBoundingClientRect an die aktive Zelle gesetzt (ResizeObserver misst bei\nBreakpoint-/Font-Änderungen nach).",
|
|
684
|
+
"description": "Theme-Segment — Segment-Switch für das Farbthema. Vorgesehener Einsatz: als\neigenständiges Element zum Hovern. Ist daher IMMER responsiv (unter 640px\nIcon-only) und IMMER animiert (Aktiv-Markierung gleitet als Thumb) — beides\nfest, nicht konfigurierbar. Icon + Textlabel stehen immer nebeneinander.\n\nEinzige Konfiguration: `showSystem` (tri Hell/Dunkel/System vs. binär Hell/Dunkel).\n\nBaut auf den CSS-Kern-Klassen `.theme-bar`/`.tbtn` auf. Jeder Button trägt ein\n`aria-label`, ist also auch im Icon-only-Modus benannt. Der Thumb wird per\ngetBoundingClientRect an die aktive Zelle gesetzt (ResizeObserver misst bei\nBreakpoint-/Font-Änderungen nach).\n\nVerwendungsguidance dieser Gruppe: siehe Cycle-Button (`komponenten-theme-umschalter-cycle-button--verwendung`).",
|
|
505
685
|
"docgen": {
|
|
506
686
|
"$ref": "../services/core/docgen/komponenten-theme-umschalter-segment.json#/components/komponenten-theme-umschalter-segment"
|
|
507
687
|
},
|
|
@@ -512,7 +692,7 @@
|
|
|
512
692
|
"komponenten-theme-umschalter-dropdown": {
|
|
513
693
|
"id": "komponenten-theme-umschalter-dropdown",
|
|
514
694
|
"name": "ThemeSelectComponent",
|
|
515
|
-
"description": "Theme-Dropdown — Theme-Umschalter auf Basis unseres Custom Select (cds-select):\ngestylte Einzelauswahl mit Listbox-Popup und Häkchen. Vorgesehener Einsatz: nur in\nden Einstellungen (Settings), NICHT als persistentes Element auf allen Seiten.\n\n`showSystem` schaltet zwischen Hell/Dunkel/System und binär Hell/Dunkel.",
|
|
695
|
+
"description": "Theme-Dropdown — Theme-Umschalter auf Basis unseres Custom Select (cds-select):\ngestylte Einzelauswahl mit Listbox-Popup und Häkchen. Vorgesehener Einsatz: nur in\nden Einstellungen (Settings), NICHT als persistentes Element auf allen Seiten.\n\n`showSystem` schaltet zwischen Hell/Dunkel/System und binär Hell/Dunkel.\n\nVerwendungsguidance dieser Gruppe: siehe Cycle-Button (`komponenten-theme-umschalter-cycle-button--verwendung`).",
|
|
516
696
|
"docgen": {
|
|
517
697
|
"$ref": "../services/core/docgen/komponenten-theme-umschalter-dropdown.json#/components/komponenten-theme-umschalter-dropdown"
|
|
518
698
|
},
|