@conciso/design-system-mcp 0.0.0-bootstrap.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.
Files changed (157) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +59 -0
  3. package/bin/cds-mcp.mjs +9 -0
  4. package/package.json +48 -0
  5. package/snapshot/manifests/components.json +617 -0
  6. package/snapshot/manifests/docs.json +293 -0
  7. package/snapshot/services/addon-docs/mdx/beispielseiten-/303/274bersicht--/303/274bersicht.json +18 -0
  8. package/snapshot/services/addon-docs/mdx/grundlagen-barrierefreiheit--/303/274bersicht.json +18 -0
  9. package/snapshot/services/addon-docs/mdx/grundlagen-design-tokens--/303/274bersicht.json +18 -0
  10. package/snapshot/services/addon-docs/mdx/grundlagen-einrichtung--/303/274bersicht.json +18 -0
  11. package/snapshot/services/addon-docs/mdx/grundlagen-elevation--/303/274bersicht.json +18 -0
  12. package/snapshot/services/addon-docs/mdx/grundlagen-icons--/303/274bersicht.json +18 -0
  13. package/snapshot/services/addon-docs/mdx/grundlagen-responsive--/303/274bersicht.json +18 -0
  14. package/snapshot/services/addon-docs/mdx/grundlagen-spacing-grid--/303/274bersicht.json +18 -0
  15. package/snapshot/services/addon-docs/mdx/komponenten-buchungsformular--/303/274bersicht.json +18 -0
  16. package/snapshot/services/addon-docs/mdx/komponenten-buttons--verwendung.json +18 -0
  17. package/snapshot/services/addon-docs/mdx/komponenten-call-to-action--verwendung.json +18 -0
  18. package/snapshot/services/addon-docs/mdx/komponenten-cards-teaser--verwendung.json +18 -0
  19. package/snapshot/services/addon-docs/mdx/komponenten-chips-badges-pills--verwendung.json +18 -0
  20. package/snapshot/services/addon-docs/mdx/komponenten-code-block--verwendung.json +18 -0
  21. package/snapshot/services/addon-docs/mdx/komponenten-dropdowns--verwendung.json +18 -0
  22. package/snapshot/services/addon-docs/mdx/komponenten-feedback--verwendung.json +18 -0
  23. package/snapshot/services/addon-docs/mdx/komponenten-footer--verwendung.json +18 -0
  24. package/snapshot/services/addon-docs/mdx/komponenten-hero--/303/274bersicht.json +18 -0
  25. package/snapshot/services/addon-docs/mdx/komponenten-inputs-forms--verwendung.json +18 -0
  26. package/snapshot/services/addon-docs/mdx/komponenten-navigation--verwendung.json +18 -0
  27. package/snapshot/services/addon-docs/mdx/komponenten-sektion--/303/274bersicht.json +18 -0
  28. package/snapshot/services/addon-docs/mdx/komponenten-slider-carousel--verwendung.json +18 -0
  29. package/snapshot/services/addon-docs/mdx/komponenten-tabelle--/303/274bersicht.json +18 -0
  30. package/snapshot/services/addon-docs/mdx/komponenten-theme-umschalter--verwendung.json +18 -0
  31. package/snapshot/services/addon-docs/mdx/komponenten-zitate-testimonials--verwendung.json +18 -0
  32. package/snapshot/services/addon-docs/mdx/marke-bildsprache--/303/274bersicht.json +18 -0
  33. package/snapshot/services/addon-docs/mdx/marke-brand-areas--/303/274bersicht.json +18 -0
  34. package/snapshot/services/addon-docs/mdx/marke-logo--verwendung.json +18 -0
  35. package/snapshot/services/addon-docs/mdx/marke-markenrad--/303/274bersicht.json +18 -0
  36. package/snapshot/services/addon-docs/mdx/referenzen-quellen--/303/274bersicht.json +18 -0
  37. package/snapshot/services/addon-docs/mdx/seitenmuster-angebots-detailseite--/303/274bersicht.json +18 -0
  38. package/snapshot/services/addon-docs/mdx/seitenmuster-beitrags/303/274bersicht--/303/274bersicht.json +18 -0
  39. package/snapshot/services/addon-docs/mdx/seitenmuster-seminar-/302/267-training--/303/274bersicht.json +18 -0
  40. package/snapshot/services/addon-docs/mdx/seitenmuster-veranstaltung--/303/274bersicht.json +18 -0
  41. package/snapshot/services/addon-docs/mdx/seitenmuster-veranstaltungs/303/274bersicht--/303/274bersicht.json +18 -0
  42. package/snapshot/services/addon-docs/mdx/seitenmuster-wissensbeitrag--/303/274bersicht.json +18 -0
  43. package/snapshot/services/core/docgen/grundlagen-farben.json +3 -0
  44. package/snapshot/services/core/docgen/grundlagen-typografie.json +3 -0
  45. package/snapshot/services/core/docgen/komponenten-buttons-button.json +183 -0
  46. package/snapshot/services/core/docgen/komponenten-call-to-action-cta-band.json +131 -0
  47. package/snapshot/services/core/docgen/komponenten-call-to-action-downloadcta.json +182 -0
  48. package/snapshot/services/core/docgen/komponenten-cards-teaser-card.json +146 -0
  49. package/snapshot/services/core/docgen/komponenten-cards-teaser-feature-liste.json +128 -0
  50. package/snapshot/services/core/docgen/komponenten-cards-teaser-featured-karte.json +158 -0
  51. package/snapshot/services/core/docgen/komponenten-cards-teaser-icon-karte.json +111 -0
  52. package/snapshot/services/core/docgen/komponenten-cards-teaser-klickbare-karte.json +161 -0
  53. package/snapshot/services/core/docgen/komponenten-cards-teaser-statcard.json +115 -0
  54. package/snapshot/services/core/docgen/komponenten-cards-teaser-statstrip.json +58 -0
  55. package/snapshot/services/core/docgen/komponenten-cards-teaser-tier-trenner.json +56 -0
  56. package/snapshot/services/core/docgen/komponenten-chips-badges-pills-bereichs-badge.json +63 -0
  57. package/snapshot/services/core/docgen/komponenten-chips-badges-pills-chip.json +95 -0
  58. package/snapshot/services/core/docgen/komponenten-chips-badges-pills-pill.json +78 -0
  59. package/snapshot/services/core/docgen/komponenten-chips-badges-pills-status-badge.json +63 -0
  60. package/snapshot/services/core/docgen/komponenten-code-block-code-block.json +91 -0
  61. package/snapshot/services/core/docgen/komponenten-dropdowns-combobox.json +224 -0
  62. package/snapshot/services/core/docgen/komponenten-dropdowns-custom-select.json +173 -0
  63. package/snapshot/services/core/docgen/komponenten-feedback-snackbar.json +97 -0
  64. package/snapshot/services/core/docgen/komponenten-footer-komplett.json +21 -0
  65. package/snapshot/services/core/docgen/komponenten-footer-oberer-teil.json +39 -0
  66. package/snapshot/services/core/docgen/komponenten-footer-unterer-teil.json +105 -0
  67. package/snapshot/services/core/docgen/komponenten-hero-hero-bild.json +162 -0
  68. package/snapshot/services/core/docgen/komponenten-hero-st/303/266rer.json +41 -0
  69. package/snapshot/services/core/docgen/komponenten-inputs-forms-auswahlfeld.json +192 -0
  70. package/snapshot/services/core/docgen/komponenten-inputs-forms-checkbox.json +182 -0
  71. package/snapshot/services/core/docgen/komponenten-inputs-forms-radio.json +181 -0
  72. package/snapshot/services/core/docgen/komponenten-inputs-forms-skala.json +179 -0
  73. package/snapshot/services/core/docgen/komponenten-inputs-forms-slider.json +259 -0
  74. package/snapshot/services/core/docgen/komponenten-inputs-forms-textbereich.json +190 -0
  75. package/snapshot/services/core/docgen/komponenten-inputs-forms-textfeld.json +207 -0
  76. package/snapshot/services/core/docgen/komponenten-navigation-topnav.json +186 -0
  77. package/snapshot/services/core/docgen/komponenten-sektion-sektion.json +113 -0
  78. package/snapshot/services/core/docgen/komponenten-slider-carousel-carousel.json +92 -0
  79. package/snapshot/services/core/docgen/komponenten-slider-carousel-logocarousel.json +92 -0
  80. package/snapshot/services/core/docgen/komponenten-tabelle-tabelle.json +74 -0
  81. package/snapshot/services/core/docgen/komponenten-tabelle-vergleichstabelle.json +142 -0
  82. package/snapshot/services/core/docgen/komponenten-theme-umschalter-cycle-button.json +41 -0
  83. package/snapshot/services/core/docgen/komponenten-theme-umschalter-dropdown.json +41 -0
  84. package/snapshot/services/core/docgen/komponenten-theme-umschalter-segment.json +41 -0
  85. package/snapshot/services/core/docgen/komponenten-zitate-testimonials-blockquote.json +96 -0
  86. package/snapshot/services/core/docgen/komponenten-zitate-testimonials-teamvoice.json +130 -0
  87. package/snapshot/services/core/docgen/komponenten-zitate-testimonials-testimonial.json +96 -0
  88. package/snapshot/services/core/docgen/marke-brand-areas-areatabs.json +75 -0
  89. package/snapshot/services/core/docgen/marke-logo-logo.json +71 -0
  90. package/snapshot/services/core/docgen/seitenmuster-seminar-/302/267-training-fakten-liste.json +79 -0
  91. package/snapshot/services/core/docgen/seitenmuster-wissensbeitrag-article-header.json +196 -0
  92. package/snapshot/services/core/docgen/seitenmuster-wissensbeitrag-author-card.json +91 -0
  93. package/snapshot/services/core/docgen/seitenmuster-wissensbeitrag-avatar.json +100 -0
  94. package/snapshot/services/core/docgen/seitenmuster-wissensbeitrag-callout.json +64 -0
  95. package/snapshot/services/core/docgen/seitenmuster-wissensbeitrag-faq.json +41 -0
  96. package/snapshot/services/core/docgen/seitenmuster-wissensbeitrag-figure.json +73 -0
  97. package/snapshot/services/core/docgen/seitenmuster-wissensbeitrag-inhaltsverzeichnis.json +75 -0
  98. package/snapshot/services/core/docgen/seitenmuster-wissensbeitrag-pull-quote.json +63 -0
  99. package/snapshot/services/core/story-docs/grundlagen-farben.json +19 -0
  100. package/snapshot/services/core/story-docs/grundlagen-typografie.json +25 -0
  101. package/snapshot/services/core/story-docs/komponenten-buttons-button.json +48 -0
  102. package/snapshot/services/core/story-docs/komponenten-call-to-action-cta-band.json +27 -0
  103. package/snapshot/services/core/story-docs/komponenten-call-to-action-downloadcta.json +17 -0
  104. package/snapshot/services/core/story-docs/komponenten-cards-teaser-card.json +37 -0
  105. package/snapshot/services/core/story-docs/komponenten-cards-teaser-feature-liste.json +37 -0
  106. package/snapshot/services/core/story-docs/komponenten-cards-teaser-featured-karte.json +36 -0
  107. package/snapshot/services/core/story-docs/komponenten-cards-teaser-icon-karte.json +41 -0
  108. package/snapshot/services/core/story-docs/komponenten-cards-teaser-klickbare-karte.json +26 -0
  109. package/snapshot/services/core/story-docs/komponenten-cards-teaser-statcard.json +21 -0
  110. package/snapshot/services/core/story-docs/komponenten-cards-teaser-statstrip.json +21 -0
  111. package/snapshot/services/core/story-docs/komponenten-cards-teaser-tier-trenner.json +22 -0
  112. package/snapshot/services/core/story-docs/komponenten-chips-badges-pills-bereichs-badge.json +21 -0
  113. package/snapshot/services/core/story-docs/komponenten-chips-badges-pills-chip.json +27 -0
  114. package/snapshot/services/core/story-docs/komponenten-chips-badges-pills-pill.json +21 -0
  115. package/snapshot/services/core/story-docs/komponenten-chips-badges-pills-status-badge.json +21 -0
  116. package/snapshot/services/core/story-docs/komponenten-code-block-code-block.json +26 -0
  117. package/snapshot/services/core/story-docs/komponenten-dropdowns-combobox.json +37 -0
  118. package/snapshot/services/core/story-docs/komponenten-dropdowns-custom-select.json +37 -0
  119. package/snapshot/services/core/story-docs/komponenten-feedback-snackbar.json +27 -0
  120. package/snapshot/services/core/story-docs/komponenten-footer-komplett.json +22 -0
  121. package/snapshot/services/core/story-docs/komponenten-footer-oberer-teil.json +21 -0
  122. package/snapshot/services/core/story-docs/komponenten-footer-unterer-teil.json +32 -0
  123. package/snapshot/services/core/story-docs/komponenten-hero-hero-bild.json +37 -0
  124. package/snapshot/services/core/story-docs/komponenten-hero-st/303/266rer.json +26 -0
  125. package/snapshot/services/core/story-docs/komponenten-inputs-forms-auswahlfeld.json +32 -0
  126. package/snapshot/services/core/story-docs/komponenten-inputs-forms-checkbox.json +32 -0
  127. package/snapshot/services/core/story-docs/komponenten-inputs-forms-radio.json +32 -0
  128. package/snapshot/services/core/story-docs/komponenten-inputs-forms-skala.json +42 -0
  129. package/snapshot/services/core/story-docs/komponenten-inputs-forms-slider.json +37 -0
  130. package/snapshot/services/core/story-docs/komponenten-inputs-forms-textbereich.json +27 -0
  131. package/snapshot/services/core/story-docs/komponenten-inputs-forms-textfeld.json +32 -0
  132. package/snapshot/services/core/story-docs/komponenten-navigation-topnav.json +26 -0
  133. package/snapshot/services/core/story-docs/komponenten-sektion-sektion.json +41 -0
  134. package/snapshot/services/core/story-docs/komponenten-slider-carousel-carousel.json +31 -0
  135. package/snapshot/services/core/story-docs/komponenten-slider-carousel-logocarousel.json +27 -0
  136. package/snapshot/services/core/story-docs/komponenten-tabelle-tabelle.json +36 -0
  137. package/snapshot/services/core/story-docs/komponenten-tabelle-vergleichstabelle.json +32 -0
  138. package/snapshot/services/core/story-docs/komponenten-theme-umschalter-cycle-button.json +31 -0
  139. package/snapshot/services/core/story-docs/komponenten-theme-umschalter-dropdown.json +26 -0
  140. package/snapshot/services/core/story-docs/komponenten-theme-umschalter-segment.json +26 -0
  141. package/snapshot/services/core/story-docs/komponenten-zitate-testimonials-blockquote.json +21 -0
  142. package/snapshot/services/core/story-docs/komponenten-zitate-testimonials-teamvoice.json +21 -0
  143. package/snapshot/services/core/story-docs/komponenten-zitate-testimonials-testimonial.json +21 -0
  144. package/snapshot/services/core/story-docs/marke-brand-areas-areatabs.json +26 -0
  145. package/snapshot/services/core/story-docs/marke-logo-logo.json +23 -0
  146. package/snapshot/services/core/story-docs/seitenmuster-seminar-/302/267-training-fakten-liste.json +21 -0
  147. package/snapshot/services/core/story-docs/seitenmuster-wissensbeitrag-article-header.json +37 -0
  148. package/snapshot/services/core/story-docs/seitenmuster-wissensbeitrag-author-card.json +31 -0
  149. package/snapshot/services/core/story-docs/seitenmuster-wissensbeitrag-avatar.json +32 -0
  150. package/snapshot/services/core/story-docs/seitenmuster-wissensbeitrag-callout.json +26 -0
  151. package/snapshot/services/core/story-docs/seitenmuster-wissensbeitrag-faq.json +27 -0
  152. package/snapshot/services/core/story-docs/seitenmuster-wissensbeitrag-figure.json +22 -0
  153. package/snapshot/services/core/story-docs/seitenmuster-wissensbeitrag-inhaltsverzeichnis.json +27 -0
  154. package/snapshot/services/core/story-docs/seitenmuster-wissensbeitrag-pull-quote.json +21 -0
  155. package/src/instructions.mjs +38 -0
  156. package/src/server.mjs +111 -0
  157. package/src/version-check.mjs +80 -0
@@ -0,0 +1,146 @@
1
+ {
2
+ "components": {
3
+ "komponenten-cards-teaser-card": {
4
+ "id": "komponenten-cards-teaser-card",
5
+ "name": "CardComponent",
6
+ "path": "./src/lib/card/card.stories.ts",
7
+ "description": "Card — Wrapper um `.card` aus css/components.css → „Cards“.\n\nDie Karte rendert `<article class=\"card\">` und ruht damit flach mit Rahmen. Das folgt der\nKonvention „Elevation = Interaktivität“: Schatten trägt eine Karte nur, wenn die Karte selbst\nder klickbare Bereich ist. Hier liegt die Interaktion in der Footer-Aktion, nicht in der Fläche.\n`.card-elevated` wirkt im CSS ausschließlich auf `a.card-elevated`; eine Link-Karten-Variante\n(`<a>` mit Ziel statt `<article>` mit Button) ist deshalb eine eigene Komponente/Variante.\n\nBildet die im CSS vorgesehene Struktur ab: .card-media (bereichsgefärbt via\n[data-area]) mit der echten Bereichs-Glyphe, .card-body mit .card-eyebrow /\n.card-title / .card-text und ein optionales .card-footer mit einer Text-Aktion.\n\nAlle Textteile sind optional (leer = ausgeblendet); zusätzlich nimmt `.card-body`\nbeliebigen projizierten Inhalt via `<ng-content>` auf — so eignet sich die Karte\nauch für freie Listen-/Detail-Inhalte in SPAs, nicht nur die Marketing-Struktur.\nDie Footer-Aktion meldet Klicks über `actionClick`.",
8
+ "jsDocTags": {},
9
+ "argTypes": {
10
+ "actionLabel": {
11
+ "name": "actionLabel",
12
+ "description": "Kompakte Text-Aktion im Footer (leer = kein Footer).",
13
+ "type": {
14
+ "name": "string"
15
+ },
16
+ "table": {
17
+ "category": "inputs",
18
+ "type": {
19
+ "summary": "string"
20
+ },
21
+ "defaultValue": {
22
+ "summary": ""
23
+ }
24
+ }
25
+ },
26
+ "area": {
27
+ "name": "area",
28
+ "description": "Markenbereich → data-area (färbt Media-Glyphe + Eyebrow).",
29
+ "type": {
30
+ "name": "enum",
31
+ "value": [
32
+ "co",
33
+ "ki",
34
+ "es",
35
+ "wo"
36
+ ]
37
+ },
38
+ "table": {
39
+ "category": "inputs",
40
+ "type": {
41
+ "summary": "CdsArea"
42
+ },
43
+ "defaultValue": {}
44
+ }
45
+ },
46
+ "eyebrow": {
47
+ "name": "eyebrow",
48
+ "description": "Kicker-Text oberhalb des Titels (leer = keine Eyebrow-Zeile).",
49
+ "type": {
50
+ "name": "string"
51
+ },
52
+ "table": {
53
+ "category": "inputs",
54
+ "type": {
55
+ "summary": "string"
56
+ },
57
+ "defaultValue": {
58
+ "summary": ""
59
+ }
60
+ }
61
+ },
62
+ "showMedia": {
63
+ "name": "showMedia",
64
+ "description": "Bereichsgefärbte Medienfläche mit Bereichs-Glyphe anzeigen.",
65
+ "type": {
66
+ "name": "boolean"
67
+ },
68
+ "table": {
69
+ "category": "inputs",
70
+ "type": {
71
+ "summary": "boolean"
72
+ },
73
+ "defaultValue": {
74
+ "summary": true
75
+ }
76
+ }
77
+ },
78
+ "text": {
79
+ "name": "text",
80
+ "description": "Anreißer-/Beschreibungstext der Karte.",
81
+ "type": {
82
+ "name": "string",
83
+ "required": true
84
+ },
85
+ "table": {
86
+ "category": "inputs",
87
+ "type": {
88
+ "summary": "string"
89
+ },
90
+ "defaultValue": {}
91
+ }
92
+ },
93
+ "title": {
94
+ "name": "title",
95
+ "description": "Kartentitel.",
96
+ "type": {
97
+ "name": "string",
98
+ "required": true
99
+ },
100
+ "table": {
101
+ "category": "inputs",
102
+ "type": {
103
+ "summary": "string"
104
+ },
105
+ "defaultValue": {}
106
+ }
107
+ },
108
+ "actionClick": {
109
+ "name": "actionClick",
110
+ "description": "Klick auf die Footer-Aktion.",
111
+ "type": {
112
+ "name": "other",
113
+ "value": "void"
114
+ },
115
+ "action": "actionClick",
116
+ "table": {
117
+ "category": "outputs",
118
+ "type": {
119
+ "summary": "void"
120
+ },
121
+ "defaultValue": {}
122
+ }
123
+ }
124
+ },
125
+ "apiDescription": "## Inputs\n\n```\nexport type CardComponentInputs = {\n /**\n * Kompakte Text-Aktion im Footer (leer = kein Footer).\n *\n * @default ''\n */\n actionLabel?: string;\n /** Markenbereich → data-area (färbt Media-Glyphe + Eyebrow). */\n area?: CdsArea;\n /**\n * Kicker-Text oberhalb des Titels (leer = keine Eyebrow-Zeile).\n *\n * @default ''\n */\n eyebrow?: string;\n /**\n * Bereichsgefärbte Medienfläche mit Bereichs-Glyphe anzeigen.\n *\n * @default true\n */\n showMedia?: boolean;\n /** Anreißer-/Beschreibungstext der Karte. */\n text: string;\n /** Kartentitel. */\n title: string;\n}\n```\n\n## Outputs\n\n```\nexport type CardComponentOutputs = {\n /** Klick auf die Footer-Aktion. */\n actionClick: void;\n}\n```",
126
+ "renderer": "angular",
127
+ "angularComponentMeta": {
128
+ "name": "CardComponent",
129
+ "selector": "cds-card",
130
+ "standalone": true,
131
+ "inputs": [
132
+ "actionLabel",
133
+ "area",
134
+ "eyebrow",
135
+ "showMedia",
136
+ "text",
137
+ "title"
138
+ ],
139
+ "outputs": [
140
+ "actionClick"
141
+ ],
142
+ "enums": []
143
+ }
144
+ }
145
+ }
146
+ }
@@ -0,0 +1,128 @@
1
+ {
2
+ "components": {
3
+ "komponenten-cards-teaser-feature-liste": {
4
+ "id": "komponenten-cards-teaser-feature-liste",
5
+ "name": "FeatureComponent",
6
+ "path": "./src/lib/feature/feature.stories.ts",
7
+ "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.",
8
+ "jsDocTags": {},
9
+ "argTypes": {
10
+ "area": {
11
+ "name": "area",
12
+ "description": "Markenbereich → `data-area` auf Icon-Kachel und CTA-Link.",
13
+ "type": {
14
+ "name": "enum",
15
+ "value": [
16
+ "co",
17
+ "ki",
18
+ "es",
19
+ "wo"
20
+ ]
21
+ },
22
+ "table": {
23
+ "category": "inputs",
24
+ "type": {
25
+ "summary": "CdsArea"
26
+ },
27
+ "defaultValue": {}
28
+ }
29
+ },
30
+ "ctaAriaLabel": {
31
+ "name": "ctaAriaLabel",
32
+ "description": "Zugänglicher Name des CTA-Links, überschreibt den sichtbaren `ctaLabel`-Text.\nNötig, wenn derselbe sichtbare CTA-Text mehrfach auf einer Seite steht (siehe\nKlassendoku); Form aus dem Mockup: `<ctaLabel>: <Ziel>`. Leer (Default) = kein\n`aria-label`, der sichtbare `ctaLabel`-Text bleibt der zugängliche Name. Wirkt\nnur, wenn `ctaHref` gesetzt ist (nur der `<a>`-Zweig hat eine Link-Rolle).",
33
+ "type": {
34
+ "name": "string"
35
+ },
36
+ "table": {
37
+ "category": "inputs",
38
+ "type": {
39
+ "summary": "string"
40
+ },
41
+ "defaultValue": {
42
+ "summary": ""
43
+ }
44
+ }
45
+ },
46
+ "ctaHref": {
47
+ "name": "ctaHref",
48
+ "description": "CTA-Linkziel; gesetzt → `<a href>`, leer → `<span>` ohne Link-Rolle (siehe Klassendoku).",
49
+ "type": {
50
+ "name": "string"
51
+ },
52
+ "table": {
53
+ "category": "inputs",
54
+ "type": {
55
+ "summary": "string"
56
+ },
57
+ "defaultValue": {
58
+ "summary": ""
59
+ }
60
+ }
61
+ },
62
+ "ctaLabel": {
63
+ "name": "ctaLabel",
64
+ "description": "CTA-Linktext (`.card-cta-link` als direktes Kind von `.ep-feature-body`, leer = kein CTA).",
65
+ "type": {
66
+ "name": "string"
67
+ },
68
+ "table": {
69
+ "category": "inputs",
70
+ "type": {
71
+ "summary": "string"
72
+ },
73
+ "defaultValue": {
74
+ "summary": ""
75
+ }
76
+ }
77
+ },
78
+ "text": {
79
+ "name": "text",
80
+ "description": "Beschreibungstext (`.ep-feature-text`).",
81
+ "type": {
82
+ "name": "string",
83
+ "required": true
84
+ },
85
+ "table": {
86
+ "category": "inputs",
87
+ "type": {
88
+ "summary": "string"
89
+ },
90
+ "defaultValue": {}
91
+ }
92
+ },
93
+ "title": {
94
+ "name": "title",
95
+ "description": "Titel (`.ep-feature-title`).",
96
+ "type": {
97
+ "name": "string",
98
+ "required": true
99
+ },
100
+ "table": {
101
+ "category": "inputs",
102
+ "type": {
103
+ "summary": "string"
104
+ },
105
+ "defaultValue": {}
106
+ }
107
+ }
108
+ },
109
+ "apiDescription": "## Inputs\n\n```\nexport type FeatureComponentInputs = {\n /** Markenbereich → `data-area` auf Icon-Kachel und CTA-Link. */\n area?: CdsArea;\n /**\n * Zugänglicher Name des CTA-Links, überschreibt den sichtbaren `ctaLabel`-Text.\n * Nötig, wenn derselbe sichtbare CTA-Text mehrfach auf einer Seite steht (siehe\n * Klassendoku); Form aus dem Mockup: `<ctaLabel>: <Ziel>`. Leer (Default) = kein\n * `aria-label`, der sichtbare `ctaLabel`-Text bleibt der zugängliche Name. Wirkt\n * nur, wenn `ctaHref` gesetzt ist (nur der `<a>`-Zweig hat eine Link-Rolle).\n *\n * @default ''\n */\n ctaAriaLabel?: string;\n /**\n * CTA-Linkziel; gesetzt → `<a href>`, leer → `<span>` ohne Link-Rolle (siehe Klassendoku).\n *\n * @default ''\n */\n ctaHref?: string;\n /**\n * CTA-Linktext (`.card-cta-link` als direktes Kind von `.ep-feature-body`, leer = kein CTA).\n *\n * @default ''\n */\n ctaLabel?: string;\n /** Beschreibungstext (`.ep-feature-text`). */\n text: string;\n /** Titel (`.ep-feature-title`). */\n title: string;\n}\n```",
110
+ "renderer": "angular",
111
+ "angularComponentMeta": {
112
+ "name": "FeatureComponent",
113
+ "selector": "div[cdsFeature]",
114
+ "standalone": true,
115
+ "inputs": [
116
+ "area",
117
+ "ctaAriaLabel",
118
+ "ctaHref",
119
+ "ctaLabel",
120
+ "text",
121
+ "title"
122
+ ],
123
+ "outputs": [],
124
+ "enums": []
125
+ }
126
+ }
127
+ }
128
+ }
@@ -0,0 +1,158 @@
1
+ {
2
+ "components": {
3
+ "komponenten-cards-teaser-featured-karte": {
4
+ "id": "komponenten-cards-teaser-featured-karte",
5
+ "name": "FeaturedCardComponent",
6
+ "path": "./src/lib/featured-card/featured-card.stories.ts",
7
+ "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.",
8
+ "jsDocTags": {},
9
+ "argTypes": {
10
+ "area": {
11
+ "name": "area",
12
+ "description": "Markenbereich → `data-area` auf Karte und Pille.",
13
+ "type": {
14
+ "name": "enum",
15
+ "value": [
16
+ "co",
17
+ "ki",
18
+ "es",
19
+ "wo"
20
+ ]
21
+ },
22
+ "table": {
23
+ "category": "inputs",
24
+ "type": {
25
+ "summary": "CdsArea"
26
+ },
27
+ "defaultValue": {}
28
+ }
29
+ },
30
+ "href": {
31
+ "name": "href",
32
+ "description": "Linkziel; gesetzt → `<a>` (ganze Fläche klickbar), leer → `<article>` (statisch, kein Schatten).",
33
+ "type": {
34
+ "name": "string"
35
+ },
36
+ "table": {
37
+ "category": "inputs",
38
+ "type": {
39
+ "summary": "string"
40
+ },
41
+ "defaultValue": {
42
+ "summary": ""
43
+ }
44
+ }
45
+ },
46
+ "imageAlt": {
47
+ "name": "imageAlt",
48
+ "description": "Alternativtext des Bildes — Pflicht, das Bild trägt Bedeutung.",
49
+ "type": {
50
+ "name": "string",
51
+ "required": true
52
+ },
53
+ "table": {
54
+ "category": "inputs",
55
+ "type": {
56
+ "summary": "string"
57
+ },
58
+ "defaultValue": {}
59
+ }
60
+ },
61
+ "imageSrc": {
62
+ "name": "imageSrc",
63
+ "description": "Bildquelle der 16:9-Medienfläche.",
64
+ "type": {
65
+ "name": "string",
66
+ "required": true
67
+ },
68
+ "table": {
69
+ "category": "inputs",
70
+ "type": {
71
+ "summary": "string"
72
+ },
73
+ "defaultValue": {}
74
+ }
75
+ },
76
+ "pill": {
77
+ "name": "pill",
78
+ "description": "Bereichs-Pille über dem Titel (`.pill`, leer = keine Pille).",
79
+ "type": {
80
+ "name": "string"
81
+ },
82
+ "table": {
83
+ "category": "inputs",
84
+ "type": {
85
+ "summary": "string"
86
+ },
87
+ "defaultValue": {
88
+ "summary": ""
89
+ }
90
+ }
91
+ },
92
+ "pillAriaLabel": {
93
+ "name": "pillAriaLabel",
94
+ "description": "`aria-label` der Pille überschreiben; Default „Bereich `<pill>`“, wie\n`PillComponent` (`pill.component.ts`). Nötig, weil `pill` nicht immer einen\nBereich benennt — das Mockup zeigt neben `aria-label=\"Bereich Corporate\"` auch\n`aria-label=\"Lesezeit 12 Minuten\"` für dieselbe Klasse.",
95
+ "type": {
96
+ "name": "string"
97
+ },
98
+ "table": {
99
+ "category": "inputs",
100
+ "type": {
101
+ "summary": "string"
102
+ },
103
+ "defaultValue": {}
104
+ }
105
+ },
106
+ "text": {
107
+ "name": "text",
108
+ "description": "Anreißer-/Beschreibungstext (`.card-text`).",
109
+ "type": {
110
+ "name": "string",
111
+ "required": true
112
+ },
113
+ "table": {
114
+ "category": "inputs",
115
+ "type": {
116
+ "summary": "string"
117
+ },
118
+ "defaultValue": {}
119
+ }
120
+ },
121
+ "title": {
122
+ "name": "title",
123
+ "description": "Titel (`.card-title-hero`).",
124
+ "type": {
125
+ "name": "string",
126
+ "required": true
127
+ },
128
+ "table": {
129
+ "category": "inputs",
130
+ "type": {
131
+ "summary": "string"
132
+ },
133
+ "defaultValue": {}
134
+ }
135
+ }
136
+ },
137
+ "apiDescription": "## Inputs\n\n```\nexport type FeaturedCardComponentInputs = {\n /** Markenbereich → `data-area` auf Karte und Pille. */\n area?: CdsArea;\n /**\n * Linkziel; gesetzt → `<a>` (ganze Fläche klickbar), leer → `<article>` (statisch, kein Schatten).\n *\n * @default ''\n */\n href?: string;\n /** Alternativtext des Bildes — Pflicht, das Bild trägt Bedeutung. */\n imageAlt: string;\n /** Bildquelle der 16:9-Medienfläche. */\n imageSrc: string;\n /**\n * Bereichs-Pille über dem Titel (`.pill`, leer = keine Pille).\n *\n * @default ''\n */\n pill?: string;\n /**\n * `aria-label` der Pille überschreiben; Default „Bereich `<pill>`“, wie\n * `PillComponent` (`pill.component.ts`). Nötig, weil `pill` nicht immer einen\n * Bereich benennt — das Mockup zeigt neben `aria-label=\"Bereich Corporate\"` auch\n * `aria-label=\"Lesezeit 12 Minuten\"` für dieselbe Klasse.\n */\n pillAriaLabel?: string;\n /** Anreißer-/Beschreibungstext (`.card-text`). */\n text: string;\n /** Titel (`.card-title-hero`). */\n title: string;\n}\n```",
138
+ "renderer": "angular",
139
+ "angularComponentMeta": {
140
+ "name": "FeaturedCardComponent",
141
+ "selector": "cds-featured-card",
142
+ "standalone": true,
143
+ "inputs": [
144
+ "area",
145
+ "href",
146
+ "imageAlt",
147
+ "imageSrc",
148
+ "pill",
149
+ "pillAriaLabel",
150
+ "text",
151
+ "title"
152
+ ],
153
+ "outputs": [],
154
+ "enums": []
155
+ }
156
+ }
157
+ }
158
+ }
@@ -0,0 +1,111 @@
1
+ {
2
+ "components": {
3
+ "komponenten-cards-teaser-icon-karte": {
4
+ "id": "komponenten-cards-teaser-icon-karte",
5
+ "name": "IconCardComponent",
6
+ "path": "./src/lib/icon-card/icon-card.stories.ts",
7
+ "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“).",
8
+ "jsDocTags": {},
9
+ "argTypes": {
10
+ "area": {
11
+ "name": "area",
12
+ "description": "Markenbereich → `data-area` auf Karte, Icon-Kachel und Eyebrow.",
13
+ "type": {
14
+ "name": "enum",
15
+ "value": [
16
+ "co",
17
+ "ki",
18
+ "es",
19
+ "wo"
20
+ ]
21
+ },
22
+ "table": {
23
+ "category": "inputs",
24
+ "type": {
25
+ "summary": "CdsArea"
26
+ },
27
+ "defaultValue": {}
28
+ }
29
+ },
30
+ "ctaLabel": {
31
+ "name": "ctaLabel",
32
+ "description": "CTA-Zeile am Kartenfuß (`.ep-card-cta`, leer = keine CTA-Zeile).",
33
+ "type": {
34
+ "name": "string"
35
+ },
36
+ "table": {
37
+ "category": "inputs",
38
+ "type": {
39
+ "summary": "string"
40
+ },
41
+ "defaultValue": {
42
+ "summary": ""
43
+ }
44
+ }
45
+ },
46
+ "eyebrow": {
47
+ "name": "eyebrow",
48
+ "description": "Kicker-Text oberhalb des Titels (`.ep-card-eyebrow`, leer = keine Eyebrow-Zeile).",
49
+ "type": {
50
+ "name": "string"
51
+ },
52
+ "table": {
53
+ "category": "inputs",
54
+ "type": {
55
+ "summary": "string"
56
+ },
57
+ "defaultValue": {
58
+ "summary": ""
59
+ }
60
+ }
61
+ },
62
+ "text": {
63
+ "name": "text",
64
+ "description": "Anreißer-/Beschreibungstext (`.ep-card-text`).",
65
+ "type": {
66
+ "name": "string",
67
+ "required": true
68
+ },
69
+ "table": {
70
+ "category": "inputs",
71
+ "type": {
72
+ "summary": "string"
73
+ },
74
+ "defaultValue": {}
75
+ }
76
+ },
77
+ "title": {
78
+ "name": "title",
79
+ "description": "Kartentitel (`.ep-card-title`).",
80
+ "type": {
81
+ "name": "string",
82
+ "required": true
83
+ },
84
+ "table": {
85
+ "category": "inputs",
86
+ "type": {
87
+ "summary": "string"
88
+ },
89
+ "defaultValue": {}
90
+ }
91
+ }
92
+ },
93
+ "apiDescription": "## Inputs\n\n```\nexport type IconCardComponentInputs = {\n /** Markenbereich → `data-area` auf Karte, Icon-Kachel und Eyebrow. */\n area?: CdsArea;\n /**\n * CTA-Zeile am Kartenfuß (`.ep-card-cta`, leer = keine CTA-Zeile).\n *\n * @default ''\n */\n ctaLabel?: string;\n /**\n * Kicker-Text oberhalb des Titels (`.ep-card-eyebrow`, leer = keine Eyebrow-Zeile).\n *\n * @default ''\n */\n eyebrow?: string;\n /** Anreißer-/Beschreibungstext (`.ep-card-text`). */\n text: string;\n /** Kartentitel (`.ep-card-title`). */\n title: string;\n}\n```",
94
+ "renderer": "angular",
95
+ "angularComponentMeta": {
96
+ "name": "IconCardComponent",
97
+ "selector": "a[cdsIconCard], div[cdsIconCard]",
98
+ "standalone": true,
99
+ "inputs": [
100
+ "area",
101
+ "ctaLabel",
102
+ "eyebrow",
103
+ "text",
104
+ "title"
105
+ ],
106
+ "outputs": [],
107
+ "enums": []
108
+ }
109
+ }
110
+ }
111
+ }