@conciso/design-system-mcp 0.0.0-bootstrap.0 → 2.3.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 CHANGED
@@ -1,34 +1,82 @@
1
1
  # @conciso/design-system-mcp
2
2
 
3
- MCP-Server für Consumer des Conciso Design System. Er beantwortet `docs-list`, `docs-show`
4
- und `docs-show-story` über stdio, mit den echten, dokumentierten Inputs und Outputs der
5
- [Angular-Lib](https://www.npmjs.com/package/@conciso/design-system-angular), nicht erfundenen.
6
- Die Daten stammen aus einem mitgelieferten Snapshot des Storybook-Builds derselben Version;
7
- der Server greift dafür nie auf ein Netzwerk zu. Beim Start vergleicht er seine Version mit der
8
- installierten Angular-Lib und warnt bei Abweichung, bricht aber nie ab.
3
+ MCP-Server für das Conciso Design System. Er gibt deinem KI-Assistenten (Claude Code,
4
+ GitHub Copilot in VS Code, Cursor und andere) die echte, dokumentierte API der
5
+ [Angular-Lib](https://www.npmjs.com/package/@conciso/design-system-angular) an die Hand,
6
+ passend zu der Version, die in deinem Projekt installiert ist.
7
+
8
+ ## Wozu?
9
+
10
+ KI-Assistenten kennen das Conciso Design System nicht. Fragst du nach einem Button mit Icon,
11
+ erfinden sie gern Inputs wie `icon` oder `iconPosition`, Elemente wie `<cds-icon>` oder
12
+ vergessen, dass die CSS-Schicht global eingebunden sein muss. Der Code sieht plausibel aus
13
+ und funktioniert nicht.
14
+
15
+ Mit diesem Server schlägt der Assistent nach, bevor er Code schreibt: welche Komponenten es
16
+ gibt, welche Inputs und Outputs sie haben, wie die Beispiele im Storybook aussehen. Gibt es
17
+ etwas nicht, sagt er das, statt es zu erfinden.
18
+
19
+ In unserem eigenen Test mit sechs typischen Fragen hat die KI ohne Server bei drei Fragen
20
+ Inputs oder Elemente erfunden, mit Server bei keiner.
21
+
22
+ ## Was er kann
23
+
24
+ | Werkzeug | Liefert |
25
+ |---|---|
26
+ | `docs-list` | alle Komponenten der Angular-Lib und alle Doku-Seiten des Storybooks mit ihren IDs |
27
+ | `docs-show` | zu einer Komponente die Inputs und Outputs mit Typen, Standardwerten und Beschreibung, dazu Code-Beispiele aus den Stories; zu einer Doku-Seite ihren vollständigen Text |
28
+ | `docs-show-story` | den Code einer einzelnen Story-Variante |
29
+
30
+ Beim Verbinden gibt der Server dem Assistenten außerdem feste Regeln mit:
31
+
32
+ 1. CSS-Schicht und Fonts global einbinden, sonst bleiben die Komponenten ungestylt.
33
+ 2. Kein eigenes CSS für Design-System-Komponenten, keine erfundenen CSS-Klassen.
34
+ 3. Nur Inputs und Outputs verwenden, die `docs-show` liefert. Vorher nachsehen, nie raten.
35
+ 4. Bei Fragen zur Einrichtung die Storybook-Seite „Einrichtung“ lesen.
36
+
37
+ Weitere Eigenschaften:
38
+
39
+ - **Offline.** Die Daten liegen als Snapshot des Storybook-Builds im Paket. Der Server
40
+ öffnet keinen Port und greift auf kein Netzwerk zu.
41
+ - **Versionsgenau.** Der Snapshot gehört zu genau einer Version des Design Systems. Beim
42
+ Start vergleicht der Server seine Version mit der installierten Angular-Lib und weist den
43
+ Assistenten bei Abweichung darauf hin. Er bricht dabei nie ab.
44
+
45
+ ## Beispiel
46
+
47
+ > Schreib mir einen Conciso-Button in der Variante „outlined“, Bereich „ki“, groß,
48
+ > deaktiviert, mit Icon links.
49
+
50
+ Der Assistent ruft `docs-list` und `docs-show` für den Button auf, findet dort die Inputs
51
+ `area`, `disabled`, `full`, `label`, `size`, `type` und `variant` und antwortet:
52
+
53
+ ```html
54
+ <cds-button label="Vorschau" variant="outlined" area="ki" size="lg" [disabled]="true" />
55
+ ```
56
+
57
+ Dazu der Hinweis, dass der Button keinen Input für ein Icon hat, statt eines erfundenen.
58
+
59
+ ## Voraussetzungen
60
+
61
+ - Node.js 20 oder neuer
62
+ - ein KI-Assistent, der MCP-Server über stdio einbinden kann
9
63
 
10
64
  ## Installation
11
65
 
12
- Zwei Wege: mit installiertem Paket, oder per `npx` ganz ohne Installation (etwa wenn dein
13
- Projekt die CSS-Schicht nur kopiert statt installiert hat, dann mit fester Version statt
14
- `latest`, passend zum kopierten Stand):
66
+ Empfohlen als Entwicklungsabhängigkeit, in derselben Version wie die Angular-Lib:
15
67
 
16
68
  ```bash
17
69
  npm i -D @conciso/design-system-mcp
18
70
  ```
19
71
 
20
- ```bash
21
- npx -y @conciso/design-system-mcp@<Version>
22
- ```
72
+ Hält dein Projekt das Design System nicht als Paket, sondern als kopierte Dateien, startest
73
+ du den Server ohne Installation über `npx` mit fester Version (siehe unten, „Versionen“).
23
74
 
24
- `<Version>` ist die Version der CSS-Schicht, die dein Projekt kopiert hat. Diesen
25
- MCP-Server gibt es erst ab einer späteren Version als die CSS-Schicht; welche Versionen
26
- existieren, zeigt `npm view @conciso/design-system-mcp versions`. Ist dein Stand älter, nimm
27
- die älteste verfügbare Version und aktualisiere die Kopie bei Gelegenheit.
75
+ ## Einbinden
28
76
 
29
- ## Einbinden in Claude Code
77
+ Die Konfiguration als Datei im Projekt committen, dann hat das ganze Team den Server.
30
78
 
31
- Mit installiertem Paket, als `.mcp.json` im Projekt committen:
79
+ **Claude Code**, `.mcp.json` im Projektordner:
32
80
 
33
81
  ```json
34
82
  {
@@ -41,19 +89,66 @@ Mit installiertem Paket, als `.mcp.json` im Projekt committen:
41
89
  }
42
90
  ```
43
91
 
44
- Ohne installiertes Paket dieselbe Datei, nur mit fester Version statt `cds-mcp`:
92
+ Oder per Befehl: `claude mcp add --scope project conciso-ds -- npx cds-mcp`
93
+
94
+ **VS Code / GitHub Copilot**, `.vscode/mcp.json`:
95
+
96
+ ```json
97
+ {
98
+ "servers": {
99
+ "conciso-ds": {
100
+ "type": "stdio",
101
+ "command": "npx",
102
+ "args": ["cds-mcp"]
103
+ }
104
+ }
105
+ }
106
+ ```
107
+
108
+ **Cursor**, `.cursor/mcp.json`:
45
109
 
46
110
  ```json
47
111
  {
48
112
  "mcpServers": {
49
113
  "conciso-ds": {
50
114
  "command": "npx",
51
- "args": ["-y", "@conciso/design-system-mcp@<Version>"]
115
+ "args": ["cds-mcp"]
52
116
  }
53
117
  }
54
118
  }
55
119
  ```
56
120
 
57
- Die vollständige Einrichtung, inklusive weiterer KI-Assistenten (VS Code, Cursor) und dem
58
- Weg ohne Angular, steht auf der Storybook-Seite
59
- [„Einrichtung“](https://conciso.github.io/conciso-design-system/?path=/docs/grundlagen-einrichtung--%C3%BCbersicht).
121
+ **Ohne installiertes Paket** ersetzt du in allen drei Varianten `"args": ["cds-mcp"]` durch
122
+ `"args": ["-y", "@conciso/design-system-mcp@<Version>"]`.
123
+
124
+ ## Versionen
125
+
126
+ Angular-Lib, CSS-Schicht und MCP-Server tragen immer dieselbe Versionsnummer. Aktualisierst
127
+ du die Lib, aktualisiere den Server mit, dann passt die Doku zum Code.
128
+
129
+ Nutzt du den Server ohne installiertes Paket, ist `<Version>` die Version der CSS-Schicht,
130
+ die dein Projekt verwendet. Den MCP-Server gibt es erst ab einer späteren Version als die
131
+ CSS-Schicht; welche Versionen existieren, zeigt `npm view @conciso/design-system-mcp versions`.
132
+ Ist dein Stand älter, nimm die älteste verfügbare Version und aktualisiere die Kopie bei
133
+ Gelegenheit. Die automatische Versionsprüfung greift in diesem Fall nicht, der Server nennt
134
+ dann nur, für welche Version sein Snapshot gilt.
135
+
136
+ ## Grenzen
137
+
138
+ - Die Werkzeuge beschreiben die **Angular-Lib**. Projekte ohne Angular (etwa Astro oder
139
+ statisches HTML) finden auf der Seite „Einrichtung“ und in den Komponenten-Beschreibungen
140
+ die CSS-Klassen, eigene HTML-Beispiele liefert der Server noch nicht.
141
+ - Design-Tokens und Icons lassen sich noch nicht direkt abfragen.
142
+ - Der Server sieht nur, was im Storybook dokumentiert ist. Was dort fehlt, gilt für ihn als
143
+ nicht vorhanden.
144
+
145
+ ## Mehr
146
+
147
+ - Storybook des Design Systems mit allen Komponenten:
148
+ <https://conciso.github.io/conciso-design-system/>
149
+ - Einrichtung Schritt für Schritt, mit und ohne Angular:
150
+ [Storybook-Seite „Einrichtung“](https://conciso.github.io/conciso-design-system/?path=/docs/grundlagen-einrichtung--%C3%BCbersicht)
151
+
152
+ ## Lizenz
153
+
154
+ MIT
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@conciso/design-system-mcp",
3
- "version": "0.0.0-bootstrap.0",
3
+ "version": "2.3.0",
4
4
  "description": "MCP-Server für Consumer des Conciso Design System, beantwortet docs-list, docs-show und docs-show-story über stdio aus einem mitgelieferten Storybook-Snapshot, ohne Netzzugriff.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -44,5 +44,19 @@
44
44
  "@eslint/js": "^10.0.1",
45
45
  "eslint": "^10.6.0",
46
46
  "globals": "^17.12.0"
47
- }
47
+ },
48
+ "homepage": "https://conciso.github.io/conciso-design-system/",
49
+ "keywords": [
50
+ "mcp",
51
+ "mcp-server",
52
+ "model-context-protocol",
53
+ "design-system",
54
+ "conciso",
55
+ "angular",
56
+ "storybook",
57
+ "claude",
58
+ "copilot",
59
+ "cursor",
60
+ "ai"
61
+ ]
48
62
  }
@@ -39,7 +39,7 @@
39
39
  "mdx": {
40
40
  "$ref": "../services/addon-docs/mdx/grundlagen-einrichtung--übersicht.json#/components/grundlagen-einrichtung--übersicht/docs/grundlagen-einrichtung--übersicht"
41
41
  },
42
- "summary": "# Einrichtung So bindest du das Conciso Design System in ein Angular-Projekt ein, von der ..."
42
+ "summary": "# Einrichtung So bindest du das Conciso Design System in ein Projekt ein, von der Installa..."
43
43
  },
44
44
  "grundlagen-spacing-grid--übersicht": {
45
45
  "id": "grundlagen-spacing-grid--übersicht",
@@ -9,8 +9,8 @@
9
9
  "name": "Übersicht",
10
10
  "path": "./src/docs/grundlagen/einrichtung.mdx",
11
11
  "title": "Grundlagen/Einrichtung",
12
- "content": "import { Meta } from '@storybook/addon-docs/blocks';\n\n<Meta title=\"Grundlagen/Einrichtung\" name=\"Übersicht\" />\n\n# Einrichtung\n\nSo bindest du das Conciso Design System in ein Angular-Projekt ein, von der Installation\nbis zur ersten Komponente, und schließt optional eine KI daran an.\n\n## Beide Pakete installieren\n\nAngular-Lib und CSS-Schicht tragen immer dieselbe Versionsnummer und liegen öffentlich auf\nnpmjs.org, du brauchst keinen Account und kein Token:\n\n```bash\nnpm i @conciso/design-system @conciso/design-system-angular\n```\n\n**Alternative: GitHub Packages.** Für Consumer innerhalb der GitHub-Organisation\n`conciso` liegen beide Pakete zusätzlich privat, org-scoped in GitHub Packages. Dafür\neine `.npmrc` im Projekt anlegen, die den `@conciso`-Scope umleitet, plus ein Token mit\nScope `read:packages` auch fürs Lesen (in GitHub Actions genügt `secrets.GITHUB_TOKEN`):\n\n```ini\n@conciso:registry=https://npm.pkg.github.com\n//npm.pkg.github.com/:_authToken=${GITHUB_TOKEN}\n```\n\nAusführliche Anleitung (Token-Beschaffung, CI vs. lokaler Rechner): README von\n`@conciso/design-system-angular` auf\n[npmjs.com](https://www.npmjs.com/package/@conciso/design-system-angular).\n\n## CSS und Fonts global einbinden\n\nDie Angular-Lib liefert **kein eigenes CSS**: Die Wrapper-Komponenten setzen nur die\nvorhandenen Klassen der CSS-Schicht zusammen, das Styling kommt aus einem globalen\nCascade, der sich nicht pro Komponente kapseln lässt. Fehlt dieser Schritt, erscheinen die\nKomponenten ungestylt.\n\n**`angular.json`** → `architect.build.options`, Eintrag `assets` ergänzen (`css` und\n`fonts` werden unverändert kopiert, kein CSS-Bundling durch den Angular-Build, deshalb\n`assets` statt `styles`):\n\n```jsonc\n{\n \"assets\": [\n // … bestehende Einträge (z. B. \"public\") …\n {\n \"glob\": \"**/*\",\n \"input\": \"node_modules/@conciso/design-system/css\",\n \"output\": \"conciso/css\"\n },\n {\n \"glob\": \"**/*\",\n \"input\": \"node_modules/@conciso/design-system/fonts\",\n \"output\": \"conciso/fonts\"\n }\n ]\n}\n```\n\n**`src/index.html`**, CSS in genau dieser Reihenfolge laden (fonts → tokens → dark-mode →\nbase → components; `fonts.css` referenziert die Font-Dateien relativ als `../fonts/*`,\n`conciso/css` und `conciso/fonts` müssen also Geschwisterordner bleiben):\n\n```html\n<link rel=\"stylesheet\" href=\"conciso/css/fonts.css\" />\n<link rel=\"stylesheet\" href=\"conciso/css/tokens.css\" />\n<link rel=\"stylesheet\" href=\"conciso/css/dark-mode.css\" />\n<link rel=\"stylesheet\" href=\"conciso/css/base.css\" />\n<link rel=\"stylesheet\" href=\"conciso/css/components.css\" />\n```\n\n**Kritisches CSS deaktivieren.** Der Angular-Production-Build versucht standardmäßig,\nreferenziertes CSS als kritisches CSS zu inlinen. Das über `assets` eingebundene CSS liegt\nzu diesem Zeitpunkt aber noch nicht im Ausgabeverzeichnis, das führt zu harmlosen, aber\nvermeidbaren Build-Warnungen. In `architect.build.configurations.production` ergänzen:\n\n```jsonc\n{\n \"optimization\": {\n \"scripts\": true,\n \"fonts\": true,\n \"styles\": { \"minify\": true, \"inlineCritical\": false }\n }\n}\n```\n\nWeitere Details: README von `@conciso/design-system-angular` auf\n[npmjs.com](https://www.npmjs.com/package/@conciso/design-system-angular).\n\n## Erste Komponente verwenden\n\n```ts\nimport { ButtonComponent } from '@conciso/design-system-angular';\n```\n\n```html\n<cds-button area=\"co\" variant=\"filled\" label=\"Kontakt\" />\n```\n\n`area` (Default `co`), `variant` (Default `filled`) und `label` (Default `Button`) sind die\ndokumentierten Inputs von `ButtonComponent`. Vollständige Liste mit allen Varianten:\n`Komponenten/Buttons/Button` in diesem Storybook, oder per KI-Assistent das Werkzeug\n`docs-show` (siehe unten).\n\n## KI-Assistenten anbinden\n\nDas Design System bringt einen eigenen MCP-Server mit: `@conciso/design-system-mcp`\n(`bin`: `cds-mcp`), Transport stdio, kein Port, nichts im Netz erreichbar. Er liefert\ndieselben Werkzeuge, mit denen auch diese Seite entstanden ist (`docs-list`, `docs-show`,\n`docs-show-story`), als mitgelieferten Snapshot passend zur installierten Version, ohne\nLive-Abruf von einer Website.\n\n```bash\nnpm i -D @conciso/design-system-mcp\n```\n\n**Versionen synchron halten.** Der Server vergleicht beim Start seine eigene Version mit\nder installierten Version der Angular-Lib und **warnt** bei Abweichung (in seinen\n`instructions` und auf stderr), bricht aber nicht ab. Am einfachsten: alle drei Pakete\ngemeinsam auf derselben Version installieren oder aktualisieren, zum Beispiel\n`npm i @conciso/design-system@X @conciso/design-system-angular@X\n@conciso/design-system-mcp@X`.\n\n### Claude Code\n\nEmpfohlen als committete Projektdatei `.mcp.json` im Repo-Root:\n\n```json\n{\n \"mcpServers\": {\n \"conciso-ds\": {\n \"command\": \"npx\",\n \"args\": [\"cds-mcp\"]\n }\n }\n}\n```\n\n### VS Code / GitHub Copilot\n\n`.vscode/mcp.json`, Schlüssel `servers`, mit explizitem `\"type\": \"stdio\"` (laut aktueller\nVS-Code-Doku ein Pflichtfeld für stdio-Server):\n\n```json\n{\n \"servers\": {\n \"conciso-ds\": {\n \"type\": \"stdio\",\n \"command\": \"npx\",\n \"args\": [\"cds-mcp\"]\n }\n }\n}\n```\n\n### Cursor\n\n`.cursor/mcp.json`, Schlüssel `mcpServers`:\n\n```json\n{\n \"mcpServers\": {\n \"conciso-ds\": {\n \"command\": \"npx\",\n \"args\": [\"cds-mcp\"]\n }\n }\n}\n```\n\nAlle drei Varianten starten denselben Prozess über stdio, ohne laufenden Dienst und ohne\nPort.\n\n## Siehe auch\n\n- `Komponenten/Buttons/Button` in diesem Storybook\n- README von `@conciso/design-system` auf\n [npmjs.com](https://www.npmjs.com/package/@conciso/design-system)\n- README von `@conciso/design-system-angular` auf\n [npmjs.com](https://www.npmjs.com/package/@conciso/design-system-angular)\n- README von `@conciso/design-system-mcp` auf\n [npmjs.com](https://www.npmjs.com/package/@conciso/design-system-mcp)\n",
13
- "summary": "# Einrichtung So bindest du das Conciso Design System in ein Angular-Projekt ein, von der ..."
12
+ "content": "import { Meta } from '@storybook/addon-docs/blocks';\n\n<Meta title=\"Grundlagen/Einrichtung\" name=\"Übersicht\" />\n\n# Einrichtung\n\nSo bindest du das Conciso Design System in ein Projekt ein, von der Installation bis zum\nersten Element, und schließt optional eine KI daran an. Zwei Wege stehen offen: mit\nAngular-Wrapper-Komponenten, oder rein über die CSS-Schicht, etwa in Astro oder einem\nstatischen HTML-Projekt.\n\n## Mit Angular einrichten\n\n### Beide Pakete installieren\n\nAngular-Lib und CSS-Schicht tragen immer dieselbe Versionsnummer und liegen öffentlich auf\nnpmjs.org, du brauchst keinen Account und kein Token:\n\n```bash\nnpm i @conciso/design-system @conciso/design-system-angular\n```\n\n**Alternative: GitHub Packages.** Für Consumer innerhalb der GitHub-Organisation\n`conciso` liegen beide Pakete zusätzlich privat, org-scoped in GitHub Packages. Dafür\neine `.npmrc` im Projekt anlegen, die den `@conciso`-Scope umleitet, plus ein Token mit\nScope `read:packages` auch fürs Lesen (in GitHub Actions genügt `secrets.GITHUB_TOKEN`):\n\n```ini\n@conciso:registry=https://npm.pkg.github.com\n//npm.pkg.github.com/:_authToken=${GITHUB_TOKEN}\n```\n\nAusführliche Anleitung (Token-Beschaffung, CI vs. lokaler Rechner): README von\n`@conciso/design-system-angular` auf\n[npmjs.com](https://www.npmjs.com/package/@conciso/design-system-angular).\n\n### CSS und Fonts global einbinden\n\nDie Angular-Lib liefert **kein eigenes CSS**: Die Wrapper-Komponenten setzen nur die\nvorhandenen Klassen der CSS-Schicht zusammen, das Styling kommt aus einem globalen\nCascade, der sich nicht pro Komponente kapseln lässt. Fehlt dieser Schritt, erscheinen die\nKomponenten ungestylt.\n\n**`angular.json`** → `architect.build.options`, Eintrag `assets` ergänzen (`css` und\n`fonts` werden unverändert kopiert, kein CSS-Bundling durch den Angular-Build, deshalb\n`assets` statt `styles`):\n\n```jsonc\n{\n \"assets\": [\n // … bestehende Einträge (z. B. \"public\") …\n {\n \"glob\": \"**/*\",\n \"input\": \"node_modules/@conciso/design-system/css\",\n \"output\": \"conciso/css\"\n },\n {\n \"glob\": \"**/*\",\n \"input\": \"node_modules/@conciso/design-system/fonts\",\n \"output\": \"conciso/fonts\"\n }\n ]\n}\n```\n\n**`src/index.html`**, CSS in genau dieser Reihenfolge laden (fonts → tokens → dark-mode →\nbase → components; `fonts.css` referenziert die Font-Dateien relativ als `../fonts/*`,\n`conciso/css` und `conciso/fonts` müssen also Geschwisterordner bleiben):\n\n```html\n<link rel=\"stylesheet\" href=\"conciso/css/fonts.css\" />\n<link rel=\"stylesheet\" href=\"conciso/css/tokens.css\" />\n<link rel=\"stylesheet\" href=\"conciso/css/dark-mode.css\" />\n<link rel=\"stylesheet\" href=\"conciso/css/base.css\" />\n<link rel=\"stylesheet\" href=\"conciso/css/components.css\" />\n```\n\n**Kritisches CSS deaktivieren.** Der Angular-Production-Build versucht standardmäßig,\nreferenziertes CSS als kritisches CSS zu inlinen. Das über `assets` eingebundene CSS liegt\nzu diesem Zeitpunkt aber noch nicht im Ausgabeverzeichnis, das führt zu harmlosen, aber\nvermeidbaren Build-Warnungen. In `architect.build.configurations.production` ergänzen:\n\n```jsonc\n{\n \"optimization\": {\n \"scripts\": true,\n \"fonts\": true,\n \"styles\": { \"minify\": true, \"inlineCritical\": false }\n }\n}\n```\n\nWeitere Details: README von `@conciso/design-system-angular` auf\n[npmjs.com](https://www.npmjs.com/package/@conciso/design-system-angular).\n\n### Erste Komponente verwenden\n\n```ts\nimport { ButtonComponent } from '@conciso/design-system-angular';\n```\n\n```html\n<cds-button area=\"co\" variant=\"filled\" label=\"Kontakt\" />\n```\n\n`area` (Default `co`), `variant` (Default `filled`) und `label` (Default `Button`) sind die\ndokumentierten Inputs von `ButtonComponent`. Vollständige Liste mit allen Varianten:\n`Komponenten/Buttons/Button` in diesem Storybook, oder per KI-Assistent das Werkzeug\n`docs-show` (siehe unten).\n\n## Ohne Angular einrichten\n\nKein Angular-Projekt, etwa Astro oder statisches HTML? Dann fällt der Angular-Lib-Teil\nweg, übrig bleibt die CSS-Schicht `@conciso/design-system` allein, dieselbe Quelle, die\nauch die Angular-Wrapper oben nutzen.\n\n### Paket installieren (empfohlen)\n\n```bash\nnpm i @conciso/design-system\n```\n\nAm einfachsten das gebündelte Einzel-CSS importieren (Ladereihenfolge und Fonts bereits\nenthalten):\n\n```js\nimport '@conciso/design-system';\n// entspricht: import '@conciso/design-system/dist/conciso-ds.css';\n```\n\nBrauchst du stattdessen nur einzelne Dateien, etwa nur `tokens.css` ohne die fertigen\nKomponentenklassen, importierst du sie einzeln, in genau dieser Reihenfolge (fonts →\ntokens → dark-mode → base → components):\n\n```js\nimport '@conciso/design-system/css/fonts.css';\nimport '@conciso/design-system/css/tokens.css';\nimport '@conciso/design-system/css/dark-mode.css';\nimport '@conciso/design-system/css/base.css';\nimport '@conciso/design-system/css/components.css';\n```\n\n### Dateien direkt kopieren\n\nHält dein Projekt die CSS-Schicht stattdessen als kopierte Dateien vor, ganz ohne\n`npm install` und ohne Build, gilt dieselbe Reihenfolge wie oben, nur als `<link>`-Tags\n(Tokens definieren Variablen, Dark-Mode überschreibt sie, Base setzt Grundlagen, Components\nnutzt alles):\n\n```html\n<link rel=\"stylesheet\" href=\"css/fonts.css\" />\n<link rel=\"stylesheet\" href=\"css/tokens.css\" />\n<link rel=\"stylesheet\" href=\"css/dark-mode.css\" />\n<link rel=\"stylesheet\" href=\"css/base.css\" />\n<link rel=\"stylesheet\" href=\"css/components.css\" />\n```\n\n`fonts.css` referenziert die Font-Dateien relativ als `../fonts/*`, der `fonts`-Ordner\nmuss also als Geschwisterordner neben `css` liegen, sonst brechen die `@font-face`-Regeln.\n\n**Alternative: ein einziges Bundle.** Statt der fünf Dateien reicht auch ein einzelner\nLink auf das gebündelte CSS (Reihenfolge und `@font-face`-Regeln bereits enthalten):\n\n```html\n<link rel=\"stylesheet\" href=\"dist/conciso-ds.css\" />\n```\n\nAuch hier muss `fonts` als Geschwisterordner neben `dist` liegen: Die `url(...)`-Pfade im\nBundle lösen relativ zur CSS-Datei auf.\n\n### Astro\n\nCSS aus einem npm-Paket bindest du in Astro am saubersten global in einem Layout ein: ein\nESM-`import` im Frontmatter der Layout-Komponente, oben bei den übrigen Imports. Am\neinfachsten mit dem gebündelten CSS:\n\n```astro\n---\nimport '@conciso/design-system';\n---\n```\n\nBrauchst du stattdessen nur einzelne Dateien, importierst du sie einzeln, in derselben\nReihenfolge wie oben (fonts → tokens → dark-mode → base → components):\n\n```astro\n---\nimport '@conciso/design-system/css/fonts.css';\nimport '@conciso/design-system/css/tokens.css';\nimport '@conciso/design-system/css/dark-mode.css';\nimport '@conciso/design-system/css/base.css';\nimport '@conciso/design-system/css/components.css';\n---\n```\n\nKopierte Dateien statt des npm-Pakets bindest du in Astro genauso über `<link>`-Tags im\nLayout ein, wie oben unter „Dateien direkt kopieren“ beschrieben.\n\n### Erstes Element verwenden\n\nKein Framework nötig, die Komponenten sind CSS-Klassen auf normalem HTML:\n\n```html\n<button type=\"button\" class=\"btn btn-filled btn-co\">Kontakt</button>\n```\n\nWelche Klassen zu welcher Variante gehören, zeigt die Storybook-Seite der jeweiligen\nKomponente (z. B. `Komponenten/Buttons/Button` in diesem Storybook), oder per KI-Assistent\ndas Werkzeug `docs-show` (siehe unten).\n\n## KI-Assistenten anbinden\n\nDas Design System bringt einen eigenen MCP-Server mit: `@conciso/design-system-mcp`\n(`bin`: `cds-mcp`), Transport stdio, kein Port, nichts im Netz erreichbar. Er liefert\ndieselben Werkzeuge, mit denen sich auch diese Seite abfragen lässt (`docs-list`,\n`docs-show`, `docs-show-story`), als mitgelieferten Snapshot passend zur installierten\nVersion, ohne Live-Abruf von einer Website. Zwei Wege, ihn einzubinden: mit installiertem\nPaket, oder per `npx` ganz ohne Installation, etwa wenn dein Projekt die CSS-Schicht nur\nkopiert statt installiert hat (siehe oben, „Dateien direkt kopieren“).\n\n### Mit installiertem Paket\n\n```bash\nnpm i -D @conciso/design-system-mcp\n```\n\n**Versionen synchron halten.** Der Server vergleicht beim Start seine eigene Version mit\nder installierten Version der Angular-Lib und **warnt** bei Abweichung (in seinen\n`instructions` und auf stderr), bricht aber nicht ab. Am einfachsten: alle drei Pakete\ngemeinsam auf derselben Version installieren oder aktualisieren, zum Beispiel\n`npm i @conciso/design-system@X @conciso/design-system-angular@X\n@conciso/design-system-mcp@X`. Ohne Angular-Projekt bleibt dieser automatische Abgleich\naus, auch mit installiertem `@conciso/design-system-mcp`: Die Prüfung vergleicht bislang\nnur gegen die Angular-Lib, nicht gegen die CSS-Schicht selbst.\n\n**Claude Code.** Empfohlen als committete Projektdatei `.mcp.json` im Repo-Root:\n\n```json\n{\n \"mcpServers\": {\n \"conciso-ds\": {\n \"command\": \"npx\",\n \"args\": [\"cds-mcp\"]\n }\n }\n}\n```\n\n**VS Code / GitHub Copilot.** `.vscode/mcp.json`, Schlüssel `servers`, mit explizitem\n`\"type\": \"stdio\"` (laut aktueller VS-Code-Doku ein Pflichtfeld für stdio-Server):\n\n```json\n{\n \"servers\": {\n \"conciso-ds\": {\n \"type\": \"stdio\",\n \"command\": \"npx\",\n \"args\": [\"cds-mcp\"]\n }\n }\n}\n```\n\n**Cursor.** `.cursor/mcp.json`, Schlüssel `mcpServers`:\n\n```json\n{\n \"mcpServers\": {\n \"conciso-ds\": {\n \"command\": \"npx\",\n \"args\": [\"cds-mcp\"]\n }\n }\n}\n```\n\nAlle drei Varianten starten denselben Prozess über stdio, ohne laufenden Dienst und ohne\nPort.\n\n### Ohne installiertes Paket\n\nIst `@conciso/design-system-mcp` im Projekt nicht installiert, startest du denselben\nServer trotzdem über `npx`, mit fester Versionsnummer statt `cds-mcp` und mit `-y`, damit\n`npx` das Paket ohne Rückfrage lädt:\n\n```json\n{\n \"mcpServers\": {\n \"conciso-ds\": {\n \"command\": \"npx\",\n \"args\": [\"-y\", \"@conciso/design-system-mcp@<Version>\"]\n }\n }\n}\n```\n\n`.vscode/mcp.json` (VS Code / GitHub Copilot), wieder mit `\"type\": \"stdio\"`:\n\n```json\n{\n \"servers\": {\n \"conciso-ds\": {\n \"type\": \"stdio\",\n \"command\": \"npx\",\n \"args\": [\"-y\", \"@conciso/design-system-mcp@<Version>\"]\n }\n }\n}\n```\n\n`.cursor/mcp.json` (Cursor):\n\n```json\n{\n \"mcpServers\": {\n \"conciso-ds\": {\n \"command\": \"npx\",\n \"args\": [\"-y\", \"@conciso/design-system-mcp@<Version>\"]\n }\n }\n}\n```\n\n**Version an den kopierten Stand binden.** `<Version>` ist die Version der CSS-Schicht,\ndie dein Projekt kopiert hat: Aktualisierst du die Kopie, ziehst du diese Versionsnummer\nmit, sonst dokumentiert der Server Komponenten, die dein kopierter Stand gar nicht kennt.\nDen MCP-Server gibt es erst ab einer späteren Version als die CSS-Schicht; welche Versionen\nexistieren, zeigt `npm view @conciso/design-system-mcp versions`. Ist dein Stand älter,\nnimmst du die älteste verfügbare Version. Die eingebaute Versionsprüfung greift hier\nohnehin nicht automatisch: Sie vergleicht sich beim Start mit der **installierten**\nVersion von\n`@conciso/design-system-angular` in `node_modules`. Ist nichts installiert, findet sie\nnichts zum Vergleichen und nennt stattdessen in ihren `instructions` nur, für welche\nVersion ihr eigener Snapshot gebaut wurde, den Rest prüfst du selbst gegen deinen\nkopierten Stand.\n\n## Siehe auch\n\n- `Komponenten/Buttons/Button` in diesem Storybook\n- README von `@conciso/design-system` auf\n [npmjs.com](https://www.npmjs.com/package/@conciso/design-system)\n- README von `@conciso/design-system-angular` auf\n [npmjs.com](https://www.npmjs.com/package/@conciso/design-system-angular)\n- README von `@conciso/design-system-mcp` auf\n [npmjs.com](https://www.npmjs.com/package/@conciso/design-system-mcp)\n",
13
+ "summary": "# Einrichtung So bindest du das Conciso Design System in ein Projekt ein, von der Installa..."
14
14
  }
15
15
  }
16
16
  }
@@ -9,7 +9,7 @@
9
9
  "name": "Verwendung",
10
10
  "path": "./src/docs/komponenten/buttons-verwendung.mdx",
11
11
  "title": "Komponenten/Buttons",
12
- "content": "import { Meta, Unstyled } from '@storybook/addon-docs/blocks';\n\n<Meta title=\"Komponenten/Buttons\" name=\"Verwendung\" tags={['angular']} />\n\n# Verwendung\n\nButtons sind die primäre Aktions-Komponente des Systems: fünf Stilvarianten (Filled · Tonal · Elevated · Outlined · Text), drei Größen (Standard · Small · Large) und der Inversions-Modifier `.btn-on-band` für Buttons auf farbigen Bereichs-Bändern. Jede Variante steht in allen vier Brand Areas zur Verfügung (Bereichsreihenfolge co · ki · es · wo), das Mindestmaß für ein Touch-Target ist 44 Pixel.\n\n## Wann welche Variante\n\nDie Hierarchie ist verbindlich: Filled vor Tonal oder Outlined vor Text. Pro Kontext höchstens ein Filled-Button, sonst ist die Hauptaktion nicht mehr eindeutig erkennbar. Elevated steht außerhalb dieser Kette und markiert eine freistehende, vom Hintergrund abgehobene Aktion.\n\nSo löst sich die Hierarchie in typischen Kontexten auf: ein Dialog mit Text- neben Filled-Button, ein Formular mit Outlined- neben Filled-Button und eine Feature-Karte mit Text- neben Tonal-Button.\n\n<Unstyled>\n <div style={{ display: 'flex', flexDirection: 'column', gap: 'var(--s4)' }}>\n <div\n style={{\n border: 'var(--bd-strong)',\n borderRadius: 'var(--r-lg)',\n padding: 'var(--s5)',\n background: 'var(--bg-surface)',\n }}\n >\n <div style={{ font: '500 16px/24px var(--font)', color: 'var(--tx-primary)', marginBottom: 'var(--s2)' }}>\n Aktion bestätigen\n </div>\n <div style={{ font: '400 14px/20px var(--font)', color: 'var(--tx-secondary)', marginBottom: 'var(--s5)' }}>\n Möchtest du die Änderungen wirklich speichern?\n </div>\n <div style={{ display: 'flex', justifyContent: 'flex-end', gap: 'var(--s2)', marginBottom: 'var(--s3)' }}>\n <button className=\"btn btn-text btn-sm btn-co\">Abbrechen</button>\n <button className=\"btn btn-filled btn-sm btn-co\">Speichern</button>\n </div>\n <div style={{ font: '400 12px/16px var(--font)', color: 'var(--tx-secondary)', textAlign: 'right' }}>\n Text → Abbrechen &nbsp;·&nbsp; Filled → Hauptaktion\n </div>\n </div>\n <div\n style={{\n border: 'var(--bd-strong)',\n borderRadius: 'var(--r-lg)',\n padding: 'var(--s5)',\n background: 'var(--bg-surface)',\n }}\n >\n <div style={{ font: '500 16px/24px var(--font)', color: 'var(--tx-primary)', marginBottom: 'var(--s4)' }}>\n Formular einreichen\n </div>\n <div\n style={{\n height: '32px',\n background: 'var(--bg-overlay)',\n borderRadius: 'var(--r-sm)',\n border: 'var(--bd-strong)',\n marginBottom: 'var(--s5)',\n }}\n ></div>\n <div style={{ display: 'flex', gap: 'var(--s2)', marginBottom: 'var(--s3)' }}>\n <button className=\"btn btn-outlined btn-sm btn-co\">Vorschau</button>\n <button className=\"btn btn-filled btn-sm btn-co\">Absenden</button>\n </div>\n <div style={{ font: '400 12px/16px var(--font)', color: 'var(--tx-secondary)' }}>\n Outlined → Alternativaktion &nbsp;·&nbsp; Filled → Primäraktion\n </div>\n </div>\n <div\n style={{\n border: 'var(--bd-strong)',\n borderRadius: 'var(--r-lg)',\n padding: 'var(--s5)',\n background: 'var(--bg-surface)',\n }}\n >\n <div style={{ font: '500 16px/24px var(--font)', color: 'var(--tx-primary)', marginBottom: 'var(--s2)' }}>\n Feature entdecken\n </div>\n <div style={{ font: '400 14px/20px var(--font)', color: 'var(--tx-secondary)', marginBottom: 'var(--s5)' }}>\n Drei Bereiche, ein Ziel, Gelassenheit durch klare Struktur.\n </div>\n <div style={{ display: 'flex', alignItems: 'center', gap: 'var(--s2)', marginBottom: 'var(--s3)' }}>\n <button className=\"btn btn-text btn-sm btn-co\">Mehr erfahren</button>\n <button className=\"btn btn-tonal btn-sm btn-co\">Jetzt starten</button>\n </div>\n <div style={{ font: '400 12px/16px var(--font)', color: 'var(--tx-secondary)' }}>\n Text → Nebenaktion &nbsp;·&nbsp; Tonal → unterstützende Aktion\n </div>\n </div>\n </div>\n</Unstyled>\n\n| Variante | Rolle in der Hierarchie | Einsatz | Beispiele |\n|---|---|---|---|\n| Filled | 1. Primäre Hauptaktion | Max. 1 bis 2 pro Kontext | Speichern, Absenden, Starten |\n| Tonal | 2. Sekundäre Bestätigung | Neben Filled oder eigenständig | Weiter, Übernehmen |\n| Outlined | 2. Gleichwertige Alternative | Ohne Primärfokus | Vorschau, Exportieren |\n| Text | 3. Nebenaktion | Niedrigste Priorität, link-ähnliche Funktion | Abbrechen, Mehr erfahren |\n| Elevated | Außerhalb der Hierarchie | Freistehende Aktion, visuell vom Hintergrund getrennt | Schwebende Elemente, FAB |\n\n## Barrierefreiheit\n\n| Aspekt | Regel |\n|---|---|\n| Icon-only | Buttons ohne sichtbaren Text benötigen `aria-label`, der SVG-Inhalt allein reicht für Screenreader nicht aus |\n| Disabled | `aria-disabled=\"true\"` statt HTML `disabled`, wenn der Button im Fokus-Flow bleiben soll, `disabled` entfernt das Element aus der Tastaturreihenfolge |\n| Touch-Target | Mindestgröße 44 mal 44 Pixel für alle Button-Varianten (WCAG 2.5.5), `btn-sm` bei Bedarf mit zusätzlichem Padding kompensieren |\n| Focus-Ring | Nie `outline: none` ohne sichtbaren Ersatz, der Design-System-Focus-Ring (`--focus-aa`) muss für alle Buttons erhalten bleiben |\n| Filled auf Bereichs-Section | Filled-Buttons auf hellen Bereichs-Hintergründen (`--co-50`, `--ki-50`, `--wo-50`, `--es-50`) brauchen eine ausreichend dunkle Variante mit weißer Schrift, sonst fehlt der UI-Komponenten-Kontrast (WCAG 1.4.11, mindestens 3 zu 1) zwischen Button-Fläche und Section |\n\nDrei der vier Bereiche sind über die Modifier-Klasse bereits korrekt abgedeckt: `.btn-co` auf `--co-700`, `.btn-ki` auf `--ki-800`, `.btn-es` auf `--es-700`. Die Default-Farbe von `.btn-wo` (`--wo-700`) ist im Allgemeinen passend, verfehlt aber auf `--wo-50`-Sub-Streifen den Kontrast. Dort die Bereichs-Klasse mit einem minimalen Inline-Override kombinieren:\n\n```html\n<button class=\"btn btn-filled btn-wo\" style=\"--c500:var(--wo-600)\">\n```\n\n`--c50` erbt korrekt von `.btn-wo`, ein `color`-Override entfällt, weil der Default aus `.btn-filled` (Weiß) bereits greift.\n\n## Dos & Don'ts\n\n**Tun**\n\n- Pro Kontext maximal ein Filled Button, klare Priorisierung der Hauptaktion für die Nutzerin.\n- Verb-Labels: konkret und handlungsorientiert, „Starten“, „Speichern“, „Anfragen“, „Absenden“.\n- Hierarchie konsequent einhalten: Filled vor Tonal oder Outlined vor Text.\n- Bereichsklasse passend zum Seitenkontext: `.btn-co`, `.btn-ki`, `.btn-es`, `.btn-wo`.\n- Touch-Target mindestens 44 Pixel einhalten, auch im Small-Modus ausreichend groß für sichere Bedienung.\n\n**Nicht tun**\n\n- Mehrere Filled Buttons nebeneinander, das lässt keine klare Primäraktion erkennen.\n- Substantive oder lange Phrasen als Labels, „Antragsformular einreichen“ statt lieber „Absenden“.\n- Disabled-State ohne sichtbare Begründung, Helper-Text oder Tooltip nutzen, um zu erklären warum.\n- Bereichsfarbe willkürlich tauschen, Corporate-Kontext immer `.btn-co`, nie `.btn-ki`.\n- Filled-Button mit `--area-500` auf hellem Bereichs-Hintergrund (`--area-50`), stattdessen die dunklere Bereichs-Variante nutzen (siehe Barrierefreiheits-Tabelle oben).\n\n## Verwandte Seiten\n\n- Buttons (`Komponenten/Buttons/Button`), alle Stilvarianten, Größen und Zustände als Stories.\n",
12
+ "content": "import { Meta, Unstyled } from '@storybook/addon-docs/blocks';\n\n<Meta title=\"Komponenten/Buttons\" name=\"Verwendung\" tags={['angular']} />\n\n# Verwendung\n\nButtons sind die primäre Aktions-Komponente des Systems: fünf Stilvarianten (Filled · Tonal · Elevated · Outlined · Text), drei Größen (Standard · Small · Large), der Ton-Modifier `.btn-err` für destruktive Aktionen und der Inversions-Modifier `.btn-on-band` für Buttons auf farbigen Bereichs-Bändern. Jede Variante steht in allen vier Brand Areas zur Verfügung (Bereichsreihenfolge co · ki · es · wo), das Mindestmaß für ein Touch-Target ist 44 Pixel.\n\n## Wann welche Variante\n\nDie Hierarchie ist verbindlich: Filled vor Tonal oder Outlined vor Text. Pro Kontext höchstens ein Filled-Button, sonst ist die Hauptaktion nicht mehr eindeutig erkennbar. Elevated steht außerhalb dieser Kette und markiert eine freistehende, vom Hintergrund abgehobene Aktion.\n\nSo löst sich die Hierarchie in typischen Kontexten auf: ein Dialog mit Text- neben Filled-Button, ein Formular mit Outlined- neben Filled-Button und eine Feature-Karte mit Text- neben Tonal-Button.\n\n<Unstyled>\n <div style={{ display: 'flex', flexDirection: 'column', gap: 'var(--s4)' }}>\n <div\n style={{\n border: 'var(--bd-strong)',\n borderRadius: 'var(--r-lg)',\n padding: 'var(--s5)',\n background: 'var(--bg-surface)',\n }}\n >\n <div style={{ font: '500 16px/24px var(--font)', color: 'var(--tx-primary)', marginBottom: 'var(--s2)' }}>\n Aktion bestätigen\n </div>\n <div style={{ font: '400 14px/20px var(--font)', color: 'var(--tx-secondary)', marginBottom: 'var(--s5)' }}>\n Möchtest du die Änderungen wirklich speichern?\n </div>\n <div style={{ display: 'flex', justifyContent: 'flex-end', gap: 'var(--s2)', marginBottom: 'var(--s3)' }}>\n <button className=\"btn btn-text btn-sm btn-co\">Abbrechen</button>\n <button className=\"btn btn-filled btn-sm btn-co\">Speichern</button>\n </div>\n <div style={{ font: '400 12px/16px var(--font)', color: 'var(--tx-secondary)', textAlign: 'right' }}>\n Text → Abbrechen &nbsp;·&nbsp; Filled → Hauptaktion\n </div>\n </div>\n <div\n style={{\n border: 'var(--bd-strong)',\n borderRadius: 'var(--r-lg)',\n padding: 'var(--s5)',\n background: 'var(--bg-surface)',\n }}\n >\n <div style={{ font: '500 16px/24px var(--font)', color: 'var(--tx-primary)', marginBottom: 'var(--s4)' }}>\n Formular einreichen\n </div>\n <div\n style={{\n height: '32px',\n background: 'var(--bg-overlay)',\n borderRadius: 'var(--r-sm)',\n border: 'var(--bd-strong)',\n marginBottom: 'var(--s5)',\n }}\n ></div>\n <div style={{ display: 'flex', gap: 'var(--s2)', marginBottom: 'var(--s3)' }}>\n <button className=\"btn btn-outlined btn-sm btn-co\">Vorschau</button>\n <button className=\"btn btn-filled btn-sm btn-co\">Absenden</button>\n </div>\n <div style={{ font: '400 12px/16px var(--font)', color: 'var(--tx-secondary)' }}>\n Outlined → Alternativaktion &nbsp;·&nbsp; Filled → Primäraktion\n </div>\n </div>\n <div\n style={{\n border: 'var(--bd-strong)',\n borderRadius: 'var(--r-lg)',\n padding: 'var(--s5)',\n background: 'var(--bg-surface)',\n }}\n >\n <div style={{ font: '500 16px/24px var(--font)', color: 'var(--tx-primary)', marginBottom: 'var(--s2)' }}>\n Feature entdecken\n </div>\n <div style={{ font: '400 14px/20px var(--font)', color: 'var(--tx-secondary)', marginBottom: 'var(--s5)' }}>\n Drei Bereiche, ein Ziel, Gelassenheit durch klare Struktur.\n </div>\n <div style={{ display: 'flex', alignItems: 'center', gap: 'var(--s2)', marginBottom: 'var(--s3)' }}>\n <button className=\"btn btn-text btn-sm btn-co\">Mehr erfahren</button>\n <button className=\"btn btn-tonal btn-sm btn-co\">Jetzt starten</button>\n </div>\n <div style={{ font: '400 12px/16px var(--font)', color: 'var(--tx-secondary)' }}>\n Text → Nebenaktion &nbsp;·&nbsp; Tonal → unterstützende Aktion\n </div>\n </div>\n </div>\n</Unstyled>\n\n| Variante | Rolle in der Hierarchie | Einsatz | Beispiele |\n|---|---|---|---|\n| Filled | 1. Primäre Hauptaktion | Max. 1 bis 2 pro Kontext | Speichern, Absenden, Starten |\n| Tonal | 2. Sekundäre Bestätigung | Neben Filled oder eigenständig | Weiter, Übernehmen |\n| Outlined | 2. Gleichwertige Alternative | Ohne Primärfokus | Vorschau, Exportieren |\n| Text | 3. Nebenaktion | Niedrigste Priorität, link-ähnliche Funktion | Abbrechen, Mehr erfahren |\n| Elevated | Außerhalb der Hierarchie | Freistehende Aktion, visuell vom Hintergrund getrennt | Schwebende Elemente, FAB |\n\n## Destruktive Aktionen\n\n`.btn-err` (Angular: `tone=\"err\"`) markiert eine Aktion, die sich nicht rückgängig machen lässt: Löschen, Verwerfen, Entfernen. Der Modifier **ersetzt** die Bereichsfarbe, er wird statt `.btn-co` gesetzt, nicht zusätzlich. Gedacht für Filled, Outlined und Text.\n\n<Unstyled>\n <div style={{ display: 'flex', gap: 'var(--s4)', flexWrap: 'wrap', alignItems: 'center', marginBottom: 'var(--s5)' }}>\n <button className=\"btn btn-filled btn-err\">Löschen</button>\n <button className=\"btn btn-outlined btn-err\">Verwerfen</button>\n <button className=\"btn btn-text btn-err\">Entfernen</button>\n </div>\n</Unstyled>\n\nWelcher Button gefüllt ist, entscheidet der Kontext:\n\n| Kontext | Beispiel | Hauptaktion (Filled) | Nebenaktion |\n|---|---|---|---|\n| Selbst ausgelöst | Klick auf „Löschen“, danach eine Rückfrage | „Löschen“ mit `.btn-err` | „Abbrechen“ als Text |\n| Unterbrechung | Ungespeicherte Änderungen beim Verlassen | „Weiter bearbeiten“ in der Bereichsfarbe | „Verwerfen“ als Outlined mit `.btn-err` |\n\nBei einer Unterbrechung wollte die Person etwas anderes, das Verwerfen ist Nebenwirkung. Deshalb bekommt dort der sichere Weg das Gewicht. Die Farbe ist nie der einzige Hinweis, das Label nennt immer die Folge.\n\n## Barrierefreiheit\n\n| Aspekt | Regel |\n|---|---|\n| Icon-only | Buttons ohne sichtbaren Text benötigen `aria-label`, der SVG-Inhalt allein reicht für Screenreader nicht aus |\n| Disabled | `aria-disabled=\"true\"` statt HTML `disabled`, wenn der Button im Fokus-Flow bleiben soll, `disabled` entfernt das Element aus der Tastaturreihenfolge |\n| Touch-Target | Mindestgröße 44 mal 44 Pixel für alle Button-Varianten (WCAG 2.5.5), `btn-sm` bei Bedarf mit zusätzlichem Padding kompensieren |\n| Focus-Ring | Nie `outline: none` ohne sichtbaren Ersatz, der Design-System-Focus-Ring (`--focus-aa`) muss für alle Buttons erhalten bleiben |\n| Filled auf Bereichs-Section | Filled-Buttons auf hellen Bereichs-Hintergründen (`--co-50`, `--ki-50`, `--wo-50`, `--es-50`) brauchen eine ausreichend dunkle Variante mit weißer Schrift, sonst fehlt der UI-Komponenten-Kontrast (WCAG 1.4.11, mindestens 3 zu 1) zwischen Button-Fläche und Section |\n\nDrei der vier Bereiche sind über die Modifier-Klasse bereits korrekt abgedeckt: `.btn-co` auf `--co-700`, `.btn-ki` auf `--ki-800`, `.btn-es` auf `--es-700`. Die Default-Farbe von `.btn-wo` (`--wo-700`) ist im Allgemeinen passend, verfehlt aber auf `--wo-50`-Sub-Streifen den Kontrast. Dort die Bereichs-Klasse mit einem minimalen Inline-Override kombinieren:\n\n```html\n<button class=\"btn btn-filled btn-wo\" style=\"--c500:var(--wo-600)\">\n```\n\n`--c50` erbt korrekt von `.btn-wo`, ein `color`-Override entfällt, weil der Default aus `.btn-filled` (Weiß) bereits greift.\n\n## Dos & Don'ts\n\n**Tun**\n\n- Pro Kontext maximal ein Filled Button, klare Priorisierung der Hauptaktion für die Nutzerin.\n- Verb-Labels: konkret und handlungsorientiert, „Starten“, „Speichern“, „Anfragen“, „Absenden“.\n- Hierarchie konsequent einhalten: Filled vor Tonal oder Outlined vor Text.\n- Bereichsklasse passend zum Seitenkontext: `.btn-co`, `.btn-ki`, `.btn-es`, `.btn-wo`.\n- Touch-Target mindestens 44 Pixel einhalten, auch im Small-Modus ausreichend groß für sichere Bedienung.\n- `.btn-err` nur für Aktionen, die sich nicht rückgängig machen lassen, höchstens einer pro Ansicht, mit einem Label, das die Folge nennt: „Löschen“, „Verwerfen“.\n\n**Nicht tun**\n\n- Mehrere Filled Buttons nebeneinander, das lässt keine klare Primäraktion erkennen.\n- Substantive oder lange Phrasen als Labels, „Antragsformular einreichen“ statt lieber „Absenden“.\n- Disabled-State ohne sichtbare Begründung, Helper-Text oder Tooltip nutzen, um zu erklären warum.\n- Bereichsfarbe willkürlich tauschen, Corporate-Kontext immer `.btn-co`, nie `.btn-ki`.\n- Filled-Button mit `--area-500` auf hellem Bereichs-Hintergrund (`--area-50`), stattdessen die dunklere Bereichs-Variante nutzen (siehe Barrierefreiheits-Tabelle oben).\n- `.btn-err` als Blickfang oder für umkehrbare Aktionen („Abmelden“, „Filter zurücksetzen“), und nie neben einer Bereichsklasse am selben Button.\n\n## Verwandte Seiten\n\n- Buttons (`Komponenten/Buttons/Button`), alle Stilvarianten, Größen und Zustände als Stories.\n",
13
13
  "summary": "# Verwendung Buttons sind die primäre Aktions-Komponente des Systems: fünf Stilvarianten (..."
14
14
  }
15
15
  }
@@ -9,7 +9,7 @@
9
9
  "argTypes": {
10
10
  "area": {
11
11
  "name": "area",
12
- "description": "Markenbereich → .btn-co / .btn-ki / .btn-es / .btn-wo",
12
+ "description": "Markenbereich → .btn-co / .btn-ki / .btn-es / .btn-wo. Wirkungslos bei `tone=\"err\"`.",
13
13
  "type": {
14
14
  "name": "enum",
15
15
  "value": [
@@ -97,6 +97,26 @@
97
97
  }
98
98
  }
99
99
  },
100
+ "tone": {
101
+ "name": "tone",
102
+ "description": "Ton → `err` setzt .btn-err (destruktive Aktion) statt der Bereichsklasse.",
103
+ "type": {
104
+ "name": "enum",
105
+ "value": [
106
+ "def",
107
+ "err"
108
+ ]
109
+ },
110
+ "table": {
111
+ "category": "inputs",
112
+ "type": {
113
+ "summary": "CdsButtonTone"
114
+ },
115
+ "defaultValue": {
116
+ "summary": "def"
117
+ }
118
+ }
119
+ },
100
120
  "type": {
101
121
  "name": "type",
102
122
  "type": {
@@ -158,7 +178,7 @@
158
178
  }
159
179
  }
160
180
  },
161
- "apiDescription": "## Inputs\n\n```\nexport type ButtonComponentInputs = {\n /**\n * Markenbereich → .btn-co / .btn-ki / .btn-es / .btn-wo\n *\n * @default co\n */\n area?: CdsArea;\n /** @default false */\n disabled?: boolean;\n /**\n * Volle Breite → .btn-full (Host wird block, damit 100% greifen).\n *\n * @default false\n */\n full?: boolean;\n /**\n * Sichtbarer Text des Buttons.\n *\n * @default Button\n */\n label?: string;\n /**\n * Größe → .btn-sm / (md = Default) / .btn-lg\n *\n * @default md\n */\n size?: CdsButtonSize;\n /** @default button */\n type?: \"button\" | \"submit\" | \"reset\";\n /**\n * Visuelle Variante → .btn-filled / .btn-tonal / .btn-elevated / .btn-outlined /\n * .btn-text; `filled-on-band` → .btn-filled + .btn-on-band (invertiert).\n *\n * @default filled\n */\n variant?: CdsButtonVariant;\n}\n```\n\n## Outputs\n\n```\nexport type ButtonComponentOutputs = {\n /** Klick auf den Button (feuert nicht, wenn `disabled`). */\n clicked: MouseEvent;\n}\n```",
181
+ "apiDescription": "## Inputs\n\n```\nexport type ButtonComponentInputs = {\n /**\n * Markenbereich → .btn-co / .btn-ki / .btn-es / .btn-wo. Wirkungslos bei `tone=\"err\"`.\n *\n * @default co\n */\n area?: CdsArea;\n /** @default false */\n disabled?: boolean;\n /**\n * Volle Breite → .btn-full (Host wird block, damit 100% greifen).\n *\n * @default false\n */\n full?: boolean;\n /**\n * Sichtbarer Text des Buttons.\n *\n * @default Button\n */\n label?: string;\n /**\n * Größe → .btn-sm / (md = Default) / .btn-lg\n *\n * @default md\n */\n size?: CdsButtonSize;\n /**\n * Ton → `err` setzt .btn-err (destruktive Aktion) statt der Bereichsklasse.\n *\n * @default def\n */\n tone?: CdsButtonTone;\n /** @default button */\n type?: \"button\" | \"submit\" | \"reset\";\n /**\n * Visuelle Variante → .btn-filled / .btn-tonal / .btn-elevated / .btn-outlined /\n * .btn-text; `filled-on-band` → .btn-filled + .btn-on-band (invertiert).\n *\n * @default filled\n */\n variant?: CdsButtonVariant;\n}\n```\n\n## Outputs\n\n```\nexport type ButtonComponentOutputs = {\n /** Klick auf den Button (feuert nicht, wenn `disabled`). */\n clicked: MouseEvent;\n}\n```",
162
182
  "renderer": "angular",
163
183
  "angularComponentMeta": {
164
184
  "name": "ButtonComponent",
@@ -170,6 +190,7 @@
170
190
  "full",
171
191
  "label",
172
192
  "size",
193
+ "tone",
173
194
  "type",
174
195
  "variant"
175
196
  ],
@@ -8,7 +8,7 @@
8
8
  "komponenten-buttons-button--interaktiv": {
9
9
  "id": "komponenten-buttons-button--interaktiv",
10
10
  "name": "Interaktiv",
11
- "snippet": "import { Component } from '@angular/core';\nimport { ButtonComponent } from '@conciso/design-system-angular';\n\n@Component({\n selector: 'app-demo',\n imports: [ButtonComponent],\n template: `\n @if (variant === 'filled-on-band') {\n <div\n [style.background]=\"'var(--' + area + (area === 'ki' ? '-800' : '-700') + ')'\"\n style=\"padding:24px;border-radius:var(--r-md)\">\n <cds-button\n [label]=\"label\"\n [variant]=\"variant\"\n [area]=\"area\"\n [size]=\"size\"\n [full]=\"full\"\n [disabled]=\"disabled\" />\n </div>\n } @else {\n <cds-button\n [label]=\"label\"\n [variant]=\"variant\"\n [area]=\"area\"\n [size]=\"size\"\n [full]=\"full\"\n [disabled]=\"disabled\" />\n }`,\n})\nexport class DemoComponent {\n label = 'Kontakt aufnehmen';\n variant = 'filled';\n area = 'co';\n size = 'md';\n full = false;\n disabled = false;\n}"
11
+ "snippet": "import { Component } from '@angular/core';\nimport { ButtonComponent } from '@conciso/design-system-angular';\n\n@Component({\n selector: 'app-demo',\n imports: [ButtonComponent],\n template: `\n @if (variant === 'filled-on-band') {\n <div\n [style.background]=\"'var(--' + area + (area === 'ki' ? '-800' : '-700') + ')'\"\n style=\"padding:24px;border-radius:var(--r-md)\">\n <cds-button\n [label]=\"label\"\n [variant]=\"variant\"\n [area]=\"area\"\n [tone]=\"tone\"\n [size]=\"size\"\n [full]=\"full\"\n [disabled]=\"disabled\" />\n </div>\n } @else {\n <cds-button\n [label]=\"label\"\n [variant]=\"variant\"\n [area]=\"area\"\n [tone]=\"tone\"\n [size]=\"size\"\n [full]=\"full\"\n [disabled]=\"disabled\" />\n }`,\n})\nexport class DemoComponent {\n label = 'Kontakt aufnehmen';\n variant = 'filled';\n area = 'co';\n tone = 'def';\n size = 'md';\n full = false;\n disabled = false;\n}"
12
12
  },
13
13
  "komponenten-buttons-button--varianten": {
14
14
  "id": "komponenten-buttons-button--varianten",
@@ -20,6 +20,11 @@
20
20
  "name": "Bereichsfarben",
21
21
  "snippet": "import { Component } from '@angular/core';\nimport { ButtonComponent } from '@conciso/design-system-angular';\n\n@Component({\n selector: 'app-demo',\n imports: [ButtonComponent],\n template: `\n <div style=\"display:flex;gap:16px;flex-wrap:wrap;align-items:center\">\n <cds-button area=\"co\" label=\"Corporate\"></cds-button>\n <cds-button area=\"ki\" label=\"AI.Applied\"></cds-button>\n <cds-button area=\"es\" label=\"Eff. Software\"></cds-button>\n <cds-button area=\"wo\" label=\"Wirks. Orga\"></cds-button>\n </div>`,\n})\nexport class DemoComponent {}"
22
22
  },
23
+ "komponenten-buttons-button--destruktiv": {
24
+ "id": "komponenten-buttons-button--destruktiv",
25
+ "name": "Destruktiv",
26
+ "snippet": "import { Component } from '@angular/core';\nimport { ButtonComponent } from '@conciso/design-system-angular';\n\n@Component({\n selector: 'app-demo',\n imports: [ButtonComponent],\n template: `\n <div style=\"display:flex;gap:16px;flex-wrap:wrap;align-items:center\">\n <cds-button tone=\"err\" label=\"Löschen\"></cds-button>\n <cds-button tone=\"err\" variant=\"outlined\" label=\"Verwerfen\"></cds-button>\n <cds-button tone=\"err\" variant=\"text\" label=\"Entfernen\"></cds-button>\n </div>`,\n})\nexport class DemoComponent {}"
27
+ },
23
28
  "komponenten-buttons-button--groessen": {
24
29
  "id": "komponenten-buttons-button--groessen",
25
30
  "name": "Größen",
@@ -33,13 +38,13 @@
33
38
  "komponenten-buttons-button--deaktiviert": {
34
39
  "id": "komponenten-buttons-button--deaktiviert",
35
40
  "name": "Deaktiviert",
36
- "snippet": "import { Component } from '@angular/core';\nimport { ButtonComponent } from '@conciso/design-system-angular';\n\n@Component({\n selector: 'app-demo',\n imports: [ButtonComponent],\n template: `\n <cds-button\n [label]=\"'Nicht verfügbar'\"\n [variant]=\"'filled'\"\n [area]=\"'co'\"\n [size]=\"'md'\"\n [full]=\"false\"\n [disabled]=\"true\"\n (clicked)=\"clicked($event)\"\n />`,\n})\nexport class DemoComponent {\n clicked(event: unknown) {}\n}",
41
+ "snippet": "import { Component } from '@angular/core';\nimport { ButtonComponent } from '@conciso/design-system-angular';\n\n@Component({\n selector: 'app-demo',\n imports: [ButtonComponent],\n template: `\n <cds-button\n [label]=\"'Nicht verfügbar'\"\n [variant]=\"'filled'\"\n [area]=\"'co'\"\n [tone]=\"'def'\"\n [size]=\"'md'\"\n [full]=\"false\"\n [disabled]=\"true\"\n (clicked)=\"clicked($event)\"\n />`,\n})\nexport class DemoComponent {\n clicked(event: unknown) {}\n}",
37
42
  "warning": "Incomplete snippet: `fn()` could not be resolved statically."
38
43
  },
39
44
  "komponenten-buttons-button--klick-verhalten": {
40
45
  "id": "komponenten-buttons-button--klick-verhalten",
41
46
  "name": "Klick-Verhalten",
42
- "snippet": "import { Component } from '@angular/core';\nimport { ButtonComponent } from '@conciso/design-system-angular';\n\n@Component({\n selector: 'app-demo',\n imports: [ButtonComponent],\n template: `\n <cds-button\n [label]=\"'Kontakt aufnehmen'\"\n [variant]=\"'filled'\"\n [area]=\"'co'\"\n [size]=\"'md'\"\n [full]=\"false\"\n [disabled]=\"false\"\n (clicked)=\"clicked($event)\"\n />`,\n})\nexport class DemoComponent {\n clicked(event: unknown) {}\n}",
47
+ "snippet": "import { Component } from '@angular/core';\nimport { ButtonComponent } from '@conciso/design-system-angular';\n\n@Component({\n selector: 'app-demo',\n imports: [ButtonComponent],\n template: `\n <cds-button\n [label]=\"'Kontakt aufnehmen'\"\n [variant]=\"'filled'\"\n [area]=\"'co'\"\n [tone]=\"'def'\"\n [size]=\"'md'\"\n [full]=\"false\"\n [disabled]=\"false\"\n (clicked)=\"clicked($event)\"\n />`,\n})\nexport class DemoComponent {\n clicked(event: unknown) {}\n}",
43
48
  "warning": "Incomplete snippet: `fn()` could not be resolved statically."
44
49
  }
45
50
  }