@conciso/design-system-mcp 2.5.0 → 2.7.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 +187 -27
- package/snapshot/manifests/docs.json +0 -128
- package/snapshot/services/addon-docs/mdx/komponenten-buchungsformular--/303/274bersicht.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 +10 -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": {
|
|
@@ -87,12 +97,22 @@
|
|
|
87
97
|
},
|
|
88
98
|
"stories": {
|
|
89
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
|
+
}
|
|
90
110
|
}
|
|
91
111
|
},
|
|
92
112
|
"komponenten-chips-badges-pills-status-badge": {
|
|
93
113
|
"id": "komponenten-chips-badges-pills-status-badge",
|
|
94
114
|
"name": "StatusBadgeComponent",
|
|
95
|
-
"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`).",
|
|
96
116
|
"docgen": {
|
|
97
117
|
"$ref": "../services/core/docgen/komponenten-chips-badges-pills-status-badge.json#/components/komponenten-chips-badges-pills-status-badge"
|
|
98
118
|
},
|
|
@@ -103,7 +123,7 @@
|
|
|
103
123
|
"komponenten-chips-badges-pills-bereichs-badge": {
|
|
104
124
|
"id": "komponenten-chips-badges-pills-bereichs-badge",
|
|
105
125
|
"name": "AreaBadgeComponent",
|
|
106
|
-
"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`).",
|
|
107
127
|
"docgen": {
|
|
108
128
|
"$ref": "../services/core/docgen/komponenten-chips-badges-pills-bereichs-badge.json#/components/komponenten-chips-badges-pills-bereichs-badge"
|
|
109
129
|
},
|
|
@@ -114,7 +134,7 @@
|
|
|
114
134
|
"komponenten-chips-badges-pills-pill": {
|
|
115
135
|
"id": "komponenten-chips-badges-pills-pill",
|
|
116
136
|
"name": "PillComponent",
|
|
117
|
-
"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`).",
|
|
118
138
|
"docgen": {
|
|
119
139
|
"$ref": "../services/core/docgen/komponenten-chips-badges-pills-pill.json#/components/komponenten-chips-badges-pills-pill"
|
|
120
140
|
},
|
|
@@ -131,12 +151,22 @@
|
|
|
131
151
|
},
|
|
132
152
|
"stories": {
|
|
133
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
|
+
}
|
|
134
164
|
}
|
|
135
165
|
},
|
|
136
166
|
"komponenten-inputs-forms-textbereich": {
|
|
137
167
|
"id": "komponenten-inputs-forms-textbereich",
|
|
138
168
|
"name": "TextareaFieldComponent",
|
|
139
|
-
"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`).",
|
|
140
170
|
"docgen": {
|
|
141
171
|
"$ref": "../services/core/docgen/komponenten-inputs-forms-textbereich.json#/components/komponenten-inputs-forms-textbereich"
|
|
142
172
|
},
|
|
@@ -147,7 +177,7 @@
|
|
|
147
177
|
"komponenten-inputs-forms-auswahlfeld": {
|
|
148
178
|
"id": "komponenten-inputs-forms-auswahlfeld",
|
|
149
179
|
"name": "SelectFieldComponent",
|
|
150
|
-
"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`).",
|
|
151
181
|
"docgen": {
|
|
152
182
|
"$ref": "../services/core/docgen/komponenten-inputs-forms-auswahlfeld.json#/components/komponenten-inputs-forms-auswahlfeld"
|
|
153
183
|
},
|
|
@@ -158,7 +188,7 @@
|
|
|
158
188
|
"komponenten-inputs-forms-radio": {
|
|
159
189
|
"id": "komponenten-inputs-forms-radio",
|
|
160
190
|
"name": "RadioGroupComponent",
|
|
161
|
-
"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`).",
|
|
162
192
|
"docgen": {
|
|
163
193
|
"$ref": "../services/core/docgen/komponenten-inputs-forms-radio.json#/components/komponenten-inputs-forms-radio"
|
|
164
194
|
},
|
|
@@ -169,7 +199,7 @@
|
|
|
169
199
|
"komponenten-inputs-forms-checkbox": {
|
|
170
200
|
"id": "komponenten-inputs-forms-checkbox",
|
|
171
201
|
"name": "CheckboxComponent",
|
|
172
|
-
"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`).",
|
|
173
203
|
"docgen": {
|
|
174
204
|
"$ref": "../services/core/docgen/komponenten-inputs-forms-checkbox.json#/components/komponenten-inputs-forms-checkbox"
|
|
175
205
|
},
|
|
@@ -180,7 +210,7 @@
|
|
|
180
210
|
"komponenten-inputs-forms-slider": {
|
|
181
211
|
"id": "komponenten-inputs-forms-slider",
|
|
182
212
|
"name": "SliderComponent",
|
|
183
|
-
"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`).",
|
|
184
214
|
"docgen": {
|
|
185
215
|
"$ref": "../services/core/docgen/komponenten-inputs-forms-slider.json#/components/komponenten-inputs-forms-slider"
|
|
186
216
|
},
|
|
@@ -191,7 +221,7 @@
|
|
|
191
221
|
"komponenten-inputs-forms-skala": {
|
|
192
222
|
"id": "komponenten-inputs-forms-skala",
|
|
193
223
|
"name": "ScaleComponent",
|
|
194
|
-
"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`).",
|
|
195
225
|
"docgen": {
|
|
196
226
|
"$ref": "../services/core/docgen/komponenten-inputs-forms-skala.json#/components/komponenten-inputs-forms-skala"
|
|
197
227
|
},
|
|
@@ -208,12 +238,22 @@
|
|
|
208
238
|
},
|
|
209
239
|
"stories": {
|
|
210
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
|
+
}
|
|
211
251
|
}
|
|
212
252
|
},
|
|
213
253
|
"komponenten-dropdowns-combobox": {
|
|
214
254
|
"id": "komponenten-dropdowns-combobox",
|
|
215
255
|
"name": "ComboboxComponent",
|
|
216
|
-
"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`).",
|
|
217
257
|
"docgen": {
|
|
218
258
|
"$ref": "../services/core/docgen/komponenten-dropdowns-combobox.json#/components/komponenten-dropdowns-combobox"
|
|
219
259
|
},
|
|
@@ -230,6 +270,16 @@
|
|
|
230
270
|
},
|
|
231
271
|
"stories": {
|
|
232
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
|
+
}
|
|
233
283
|
}
|
|
234
284
|
},
|
|
235
285
|
"komponenten-cards-teaser-card": {
|
|
@@ -241,12 +291,22 @@
|
|
|
241
291
|
},
|
|
242
292
|
"stories": {
|
|
243
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
|
+
}
|
|
244
304
|
}
|
|
245
305
|
},
|
|
246
306
|
"komponenten-cards-teaser-klickbare-karte": {
|
|
247
307
|
"id": "komponenten-cards-teaser-klickbare-karte",
|
|
248
308
|
"name": "LinkCardComponent",
|
|
249
|
-
"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`).",
|
|
250
310
|
"docgen": {
|
|
251
311
|
"$ref": "../services/core/docgen/komponenten-cards-teaser-klickbare-karte.json#/components/komponenten-cards-teaser-klickbare-karte"
|
|
252
312
|
},
|
|
@@ -257,7 +317,7 @@
|
|
|
257
317
|
"komponenten-cards-teaser-featured-karte": {
|
|
258
318
|
"id": "komponenten-cards-teaser-featured-karte",
|
|
259
319
|
"name": "FeaturedCardComponent",
|
|
260
|
-
"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`).",
|
|
261
321
|
"docgen": {
|
|
262
322
|
"$ref": "../services/core/docgen/komponenten-cards-teaser-featured-karte.json#/components/komponenten-cards-teaser-featured-karte"
|
|
263
323
|
},
|
|
@@ -268,7 +328,7 @@
|
|
|
268
328
|
"komponenten-cards-teaser-icon-karte": {
|
|
269
329
|
"id": "komponenten-cards-teaser-icon-karte",
|
|
270
330
|
"name": "IconCardComponent",
|
|
271
|
-
"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`).",
|
|
272
332
|
"docgen": {
|
|
273
333
|
"$ref": "../services/core/docgen/komponenten-cards-teaser-icon-karte.json#/components/komponenten-cards-teaser-icon-karte"
|
|
274
334
|
},
|
|
@@ -279,7 +339,7 @@
|
|
|
279
339
|
"komponenten-cards-teaser-feature-liste": {
|
|
280
340
|
"id": "komponenten-cards-teaser-feature-liste",
|
|
281
341
|
"name": "FeatureComponent",
|
|
282
|
-
"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`).",
|
|
283
343
|
"docgen": {
|
|
284
344
|
"$ref": "../services/core/docgen/komponenten-cards-teaser-feature-liste.json#/components/komponenten-cards-teaser-feature-liste"
|
|
285
345
|
},
|
|
@@ -290,7 +350,7 @@
|
|
|
290
350
|
"komponenten-cards-teaser-tier-trenner": {
|
|
291
351
|
"id": "komponenten-cards-teaser-tier-trenner",
|
|
292
352
|
"name": "TierComponent",
|
|
293
|
-
"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`).",
|
|
294
354
|
"docgen": {
|
|
295
355
|
"$ref": "../services/core/docgen/komponenten-cards-teaser-tier-trenner.json#/components/komponenten-cards-teaser-tier-trenner"
|
|
296
356
|
},
|
|
@@ -301,7 +361,7 @@
|
|
|
301
361
|
"komponenten-cards-teaser-statcard": {
|
|
302
362
|
"id": "komponenten-cards-teaser-statcard",
|
|
303
363
|
"name": "StatCardComponent",
|
|
304
|
-
"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`).",
|
|
305
365
|
"docgen": {
|
|
306
366
|
"$ref": "../services/core/docgen/komponenten-cards-teaser-statcard.json#/components/komponenten-cards-teaser-statcard"
|
|
307
367
|
},
|
|
@@ -312,7 +372,7 @@
|
|
|
312
372
|
"komponenten-cards-teaser-statstrip": {
|
|
313
373
|
"id": "komponenten-cards-teaser-statstrip",
|
|
314
374
|
"name": "StatStripComponent",
|
|
315
|
-
"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`).",
|
|
316
376
|
"docgen": {
|
|
317
377
|
"$ref": "../services/core/docgen/komponenten-cards-teaser-statstrip.json#/components/komponenten-cards-teaser-statstrip"
|
|
318
378
|
},
|
|
@@ -329,12 +389,22 @@
|
|
|
329
389
|
},
|
|
330
390
|
"stories": {
|
|
331
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
|
+
}
|
|
332
402
|
}
|
|
333
403
|
},
|
|
334
404
|
"komponenten-call-to-action-downloadcta": {
|
|
335
405
|
"id": "komponenten-call-to-action-downloadcta",
|
|
336
406
|
"name": "DownloadCtaComponent",
|
|
337
|
-
"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`).",
|
|
338
408
|
"docgen": {
|
|
339
409
|
"$ref": "../services/core/docgen/komponenten-call-to-action-downloadcta.json#/components/komponenten-call-to-action-downloadcta"
|
|
340
410
|
},
|
|
@@ -351,12 +421,22 @@
|
|
|
351
421
|
},
|
|
352
422
|
"stories": {
|
|
353
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
|
+
}
|
|
354
434
|
}
|
|
355
435
|
},
|
|
356
436
|
"komponenten-tabelle-vergleichstabelle": {
|
|
357
437
|
"id": "komponenten-tabelle-vergleichstabelle",
|
|
358
438
|
"name": "CompareComponent",
|
|
359
|
-
"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`).",
|
|
360
440
|
"docgen": {
|
|
361
441
|
"$ref": "../services/core/docgen/komponenten-tabelle-vergleichstabelle.json#/components/komponenten-tabelle-vergleichstabelle"
|
|
362
442
|
},
|
|
@@ -373,12 +453,22 @@
|
|
|
373
453
|
},
|
|
374
454
|
"stories": {
|
|
375
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
|
+
}
|
|
376
466
|
}
|
|
377
467
|
},
|
|
378
468
|
"komponenten-zitate-testimonials-testimonial": {
|
|
379
469
|
"id": "komponenten-zitate-testimonials-testimonial",
|
|
380
470
|
"name": "TestimonialComponent",
|
|
381
|
-
"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`).",
|
|
382
472
|
"docgen": {
|
|
383
473
|
"$ref": "../services/core/docgen/komponenten-zitate-testimonials-testimonial.json#/components/komponenten-zitate-testimonials-testimonial"
|
|
384
474
|
},
|
|
@@ -389,7 +479,7 @@
|
|
|
389
479
|
"komponenten-zitate-testimonials-teamvoice": {
|
|
390
480
|
"id": "komponenten-zitate-testimonials-teamvoice",
|
|
391
481
|
"name": "TeamVoiceComponent",
|
|
392
|
-
"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`).",
|
|
393
483
|
"docgen": {
|
|
394
484
|
"$ref": "../services/core/docgen/komponenten-zitate-testimonials-teamvoice.json#/components/komponenten-zitate-testimonials-teamvoice"
|
|
395
485
|
},
|
|
@@ -406,6 +496,16 @@
|
|
|
406
496
|
},
|
|
407
497
|
"stories": {
|
|
408
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
|
+
}
|
|
409
509
|
}
|
|
410
510
|
},
|
|
411
511
|
"komponenten-slider-carousel-carousel": {
|
|
@@ -417,12 +517,22 @@
|
|
|
417
517
|
},
|
|
418
518
|
"stories": {
|
|
419
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
|
+
}
|
|
420
530
|
}
|
|
421
531
|
},
|
|
422
532
|
"komponenten-slider-carousel-logocarousel": {
|
|
423
533
|
"id": "komponenten-slider-carousel-logocarousel",
|
|
424
534
|
"name": "LogoCarouselComponent",
|
|
425
|
-
"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`).",
|
|
426
536
|
"docgen": {
|
|
427
537
|
"$ref": "../services/core/docgen/komponenten-slider-carousel-logocarousel.json#/components/komponenten-slider-carousel-logocarousel"
|
|
428
538
|
},
|
|
@@ -439,6 +549,16 @@
|
|
|
439
549
|
},
|
|
440
550
|
"stories": {
|
|
441
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
|
+
}
|
|
442
562
|
}
|
|
443
563
|
},
|
|
444
564
|
"komponenten-navigation-topnav": {
|
|
@@ -450,6 +570,16 @@
|
|
|
450
570
|
},
|
|
451
571
|
"stories": {
|
|
452
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
|
+
}
|
|
453
583
|
}
|
|
454
584
|
},
|
|
455
585
|
"komponenten-hero-hero-bild": {
|
|
@@ -461,12 +591,22 @@
|
|
|
461
591
|
},
|
|
462
592
|
"stories": {
|
|
463
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
|
+
}
|
|
464
604
|
}
|
|
465
605
|
},
|
|
466
606
|
"komponenten-hero-störer": {
|
|
467
607
|
"id": "komponenten-hero-störer",
|
|
468
608
|
"name": "StoererSetComponent",
|
|
469
|
-
"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`).",
|
|
470
610
|
"docgen": {
|
|
471
611
|
"$ref": "../services/core/docgen/komponenten-hero-störer.json#/components/komponenten-hero-störer"
|
|
472
612
|
},
|
|
@@ -483,12 +623,22 @@
|
|
|
483
623
|
},
|
|
484
624
|
"stories": {
|
|
485
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
|
+
}
|
|
486
636
|
}
|
|
487
637
|
},
|
|
488
638
|
"komponenten-footer-oberer-teil": {
|
|
489
639
|
"id": "komponenten-footer-oberer-teil",
|
|
490
640
|
"name": "FooterMainComponent",
|
|
491
|
-
"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`).",
|
|
492
642
|
"docgen": {
|
|
493
643
|
"$ref": "../services/core/docgen/komponenten-footer-oberer-teil.json#/components/komponenten-footer-oberer-teil"
|
|
494
644
|
},
|
|
@@ -499,7 +649,7 @@
|
|
|
499
649
|
"komponenten-footer-unterer-teil": {
|
|
500
650
|
"id": "komponenten-footer-unterer-teil",
|
|
501
651
|
"name": "FooterBottomComponent",
|
|
502
|
-
"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`).",
|
|
503
653
|
"docgen": {
|
|
504
654
|
"$ref": "../services/core/docgen/komponenten-footer-unterer-teil.json#/components/komponenten-footer-unterer-teil"
|
|
505
655
|
},
|
|
@@ -516,12 +666,22 @@
|
|
|
516
666
|
},
|
|
517
667
|
"stories": {
|
|
518
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
|
+
}
|
|
519
679
|
}
|
|
520
680
|
},
|
|
521
681
|
"komponenten-theme-umschalter-segment": {
|
|
522
682
|
"id": "komponenten-theme-umschalter-segment",
|
|
523
683
|
"name": "ThemeSegmentComponent",
|
|
524
|
-
"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`).",
|
|
525
685
|
"docgen": {
|
|
526
686
|
"$ref": "../services/core/docgen/komponenten-theme-umschalter-segment.json#/components/komponenten-theme-umschalter-segment"
|
|
527
687
|
},
|
|
@@ -532,7 +692,7 @@
|
|
|
532
692
|
"komponenten-theme-umschalter-dropdown": {
|
|
533
693
|
"id": "komponenten-theme-umschalter-dropdown",
|
|
534
694
|
"name": "ThemeSelectComponent",
|
|
535
|
-
"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`).",
|
|
536
696
|
"docgen": {
|
|
537
697
|
"$ref": "../services/core/docgen/komponenten-theme-umschalter-dropdown.json#/components/komponenten-theme-umschalter-dropdown"
|
|
538
698
|
},
|