@revikornmann/muka-ui 0.18.0 → 0.20.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 (195) hide show
  1. package/README.md +81 -60
  2. package/cli/bin/muka-ui.js +12 -5
  3. package/cli/commands/brand.js +33 -14
  4. package/cli/commands/init.js +21 -17
  5. package/cli/commands/install-skill.js +84 -26
  6. package/cli/templates/AGENTS.md +128 -0
  7. package/cli/templates/CLAUDE.md +8 -88
  8. package/cli/templates/muka-ui-guidelines.md +50 -14
  9. package/dist/cjs/components/ActionSheet/ActionSheet.css +4 -4
  10. package/dist/cjs/components/BottomBar/BottomBar.css +0 -3
  11. package/dist/cjs/components/Breadcrumb/Breadcrumb.css +26 -2
  12. package/dist/cjs/components/Combobox/Combobox.css +116 -132
  13. package/dist/cjs/components/Combobox/Combobox.js +175 -52
  14. package/dist/cjs/components/Combobox/Combobox.js.map +1 -1
  15. package/dist/cjs/components/Combobox/index.js.map +1 -1
  16. package/dist/cjs/components/ContextSelect/ContextSelect.css +4 -4
  17. package/dist/cjs/components/DocumentViewer/DocumentViewer.css +2 -2
  18. package/dist/cjs/components/DropdownSelect/DropdownSelect.css +225 -0
  19. package/dist/cjs/components/DropdownSelect/DropdownSelect.js +106 -0
  20. package/dist/cjs/components/DropdownSelect/DropdownSelect.js.map +1 -0
  21. package/dist/cjs/components/DropdownSelect/index.js +6 -0
  22. package/dist/cjs/components/DropdownSelect/index.js.map +1 -0
  23. package/dist/cjs/components/EmptyState/EmptyState.css +8 -8
  24. package/dist/cjs/components/FAB/FAB.css +1 -1
  25. package/dist/cjs/components/FileUpload/FileUpload.css +10 -10
  26. package/dist/cjs/components/Icon/custom/ArrowReturnIcon.js +11 -0
  27. package/dist/cjs/components/Icon/custom/ArrowReturnIcon.js.map +1 -0
  28. package/dist/cjs/components/Icon/iconRegistry.js +14 -1
  29. package/dist/cjs/components/Icon/iconRegistry.js.map +1 -1
  30. package/dist/cjs/components/Input/Input.css +47 -10
  31. package/dist/cjs/components/Input/Input.js +14 -3
  32. package/dist/cjs/components/Input/Input.js.map +1 -1
  33. package/dist/cjs/components/Label/Label.css +1 -1
  34. package/dist/cjs/components/LicensePlateInput/LicensePlateInput.css +1 -1
  35. package/dist/cjs/components/Menu/Menu.css +124 -38
  36. package/dist/cjs/components/Menu/Menu.js +283 -25
  37. package/dist/cjs/components/Menu/Menu.js.map +1 -1
  38. package/dist/cjs/components/Pagination/Pagination.css +15 -15
  39. package/dist/cjs/components/PhotoUploader/PhotoUploader.css +4 -4
  40. package/dist/cjs/components/ProgressAccordeon/ProgressAccordeon.css +10 -6
  41. package/dist/cjs/components/ProgressAccordeon/ProgressAccordeon.js +27 -16
  42. package/dist/cjs/components/ProgressAccordeon/ProgressAccordeon.js.map +1 -1
  43. package/dist/cjs/components/ProgressTracker/ProgressTracker.css +273 -22
  44. package/dist/cjs/components/ProgressTracker/ProgressTracker.js +109 -9
  45. package/dist/cjs/components/ProgressTracker/ProgressTracker.js.map +1 -1
  46. package/dist/cjs/components/Scrollbar/Scrollbar.css +7 -6
  47. package/dist/cjs/components/SearchInput/SearchInput.css +4 -4
  48. package/dist/cjs/components/Select/Select.css +2 -2
  49. package/dist/cjs/components/SmsOtpField/SmsOtpField.css +2 -2
  50. package/dist/cjs/components/SpecList/SpecList.css +8 -8
  51. package/dist/cjs/components/Spinner/Spinner.css +1 -1
  52. package/dist/cjs/components/SwipeActions/SwipeActions.css +6 -6
  53. package/dist/cjs/components/Table/Table.css +3 -3
  54. package/dist/cjs/components/Table/TablePagination.css +1 -1
  55. package/dist/cjs/components/Tabs/Tabs.css +6 -6
  56. package/dist/cjs/components/Textarea/Textarea.css +2 -2
  57. package/dist/cjs/components/Waveform/Waveform.css +1 -1
  58. package/dist/cjs/components/index.js +5 -3
  59. package/dist/cjs/components/index.js.map +1 -1
  60. package/dist/esm/components/ActionSheet/ActionSheet.css +4 -4
  61. package/dist/esm/components/BottomBar/BottomBar.css +0 -3
  62. package/dist/esm/components/Breadcrumb/Breadcrumb.css +26 -2
  63. package/dist/esm/components/Combobox/Combobox.css +116 -132
  64. package/dist/esm/components/Combobox/Combobox.js +177 -54
  65. package/dist/esm/components/Combobox/Combobox.js.map +1 -1
  66. package/dist/esm/components/Combobox/index.js +1 -1
  67. package/dist/esm/components/Combobox/index.js.map +1 -1
  68. package/dist/esm/components/ContextSelect/ContextSelect.css +4 -4
  69. package/dist/esm/components/DocumentViewer/DocumentViewer.css +2 -2
  70. package/dist/esm/components/DropdownSelect/DropdownSelect.css +225 -0
  71. package/dist/esm/components/DropdownSelect/DropdownSelect.js +102 -0
  72. package/dist/esm/components/DropdownSelect/DropdownSelect.js.map +1 -0
  73. package/dist/esm/components/DropdownSelect/index.js +2 -0
  74. package/dist/esm/components/DropdownSelect/index.js.map +1 -0
  75. package/dist/esm/components/EmptyState/EmptyState.css +8 -8
  76. package/dist/esm/components/FAB/FAB.css +1 -1
  77. package/dist/esm/components/FileUpload/FileUpload.css +10 -10
  78. package/dist/esm/components/Icon/custom/ArrowReturnIcon.js +7 -0
  79. package/dist/esm/components/Icon/custom/ArrowReturnIcon.js.map +1 -0
  80. package/dist/esm/components/Icon/iconRegistry.js +14 -1
  81. package/dist/esm/components/Icon/iconRegistry.js.map +1 -1
  82. package/dist/esm/components/Input/Input.css +47 -10
  83. package/dist/esm/components/Input/Input.js +14 -3
  84. package/dist/esm/components/Input/Input.js.map +1 -1
  85. package/dist/esm/components/Label/Label.css +1 -1
  86. package/dist/esm/components/LicensePlateInput/LicensePlateInput.css +1 -1
  87. package/dist/esm/components/Menu/Menu.css +124 -38
  88. package/dist/esm/components/Menu/Menu.js +284 -26
  89. package/dist/esm/components/Menu/Menu.js.map +1 -1
  90. package/dist/esm/components/Pagination/Pagination.css +15 -15
  91. package/dist/esm/components/PhotoUploader/PhotoUploader.css +4 -4
  92. package/dist/esm/components/ProgressAccordeon/ProgressAccordeon.css +10 -6
  93. package/dist/esm/components/ProgressAccordeon/ProgressAccordeon.js +27 -16
  94. package/dist/esm/components/ProgressAccordeon/ProgressAccordeon.js.map +1 -1
  95. package/dist/esm/components/ProgressTracker/ProgressTracker.css +273 -22
  96. package/dist/esm/components/ProgressTracker/ProgressTracker.js +110 -10
  97. package/dist/esm/components/ProgressTracker/ProgressTracker.js.map +1 -1
  98. package/dist/esm/components/Scrollbar/Scrollbar.css +7 -6
  99. package/dist/esm/components/SearchInput/SearchInput.css +4 -4
  100. package/dist/esm/components/Select/Select.css +2 -2
  101. package/dist/esm/components/SmsOtpField/SmsOtpField.css +2 -2
  102. package/dist/esm/components/SpecList/SpecList.css +8 -8
  103. package/dist/esm/components/Spinner/Spinner.css +1 -1
  104. package/dist/esm/components/SwipeActions/SwipeActions.css +6 -6
  105. package/dist/esm/components/Table/Table.css +3 -3
  106. package/dist/esm/components/Table/TablePagination.css +1 -1
  107. package/dist/esm/components/Tabs/Tabs.css +6 -6
  108. package/dist/esm/components/Textarea/Textarea.css +2 -2
  109. package/dist/esm/components/Waveform/Waveform.css +1 -1
  110. package/dist/esm/components/index.js +1 -0
  111. package/dist/esm/components/index.js.map +1 -1
  112. package/dist/styles/components/ActionSheet.css +4 -4
  113. package/dist/styles/components/BottomBar.css +0 -3
  114. package/dist/styles/components/Breadcrumb.css +26 -2
  115. package/dist/styles/components/Combobox.css +116 -132
  116. package/dist/styles/components/ContextSelect.css +4 -4
  117. package/dist/styles/components/DocumentViewer.css +2 -2
  118. package/dist/styles/components/DropdownSelect.css +225 -0
  119. package/dist/styles/components/EmptyState.css +8 -8
  120. package/dist/styles/components/FAB.css +1 -1
  121. package/dist/styles/components/FileUpload.css +10 -10
  122. package/dist/styles/components/Input.css +47 -10
  123. package/dist/styles/components/Label.css +1 -1
  124. package/dist/styles/components/LicensePlateInput.css +1 -1
  125. package/dist/styles/components/Menu.css +124 -38
  126. package/dist/styles/components/Pagination.css +15 -15
  127. package/dist/styles/components/PhotoUploader.css +4 -4
  128. package/dist/styles/components/ProgressAccordeon.css +10 -6
  129. package/dist/styles/components/ProgressTracker.css +273 -22
  130. package/dist/styles/components/Scrollbar.css +7 -6
  131. package/dist/styles/components/SearchInput.css +4 -4
  132. package/dist/styles/components/Select.css +2 -2
  133. package/dist/styles/components/SmsOtpField.css +2 -2
  134. package/dist/styles/components/SpecList.css +8 -8
  135. package/dist/styles/components/Spinner.css +1 -1
  136. package/dist/styles/components/SwipeActions.css +6 -6
  137. package/dist/styles/components/Table.css +3 -3
  138. package/dist/styles/components/Tabs.css +6 -6
  139. package/dist/styles/components/Textarea.css +2 -2
  140. package/dist/styles/components/Typography.css +89 -0
  141. package/dist/styles/components/Waveform.css +1 -1
  142. package/dist/styles/index.css +1167 -462
  143. package/dist/styles/muka-dark.css +1167 -462
  144. package/dist/styles/muka-light.css +1167 -462
  145. package/dist/styles/tokens-bouwplan-dark.css +5 -4
  146. package/dist/styles/tokens-bouwplan-light.css +5 -4
  147. package/dist/styles/tokens-fscl-dark.css +25 -24
  148. package/dist/styles/tokens-fscl-light.css +25 -24
  149. package/dist/styles/tokens-grip-dark.css +4 -3
  150. package/dist/styles/tokens-grip-light.css +4 -3
  151. package/dist/styles/tokens-muka-dark.css +4 -3
  152. package/dist/styles/tokens-muka-light.css +4 -3
  153. package/dist/styles/tokens-wireframe-dark.css +49 -48
  154. package/dist/styles/tokens-wireframe-light.css +49 -48
  155. package/dist/styles/wireframe-dark.css +1212 -507
  156. package/dist/styles/wireframe-light.css +1212 -507
  157. package/dist/types/components/Combobox/Combobox.d.ts +38 -38
  158. package/dist/types/components/Combobox/Combobox.d.ts.map +1 -1
  159. package/dist/types/components/Combobox/index.d.ts +1 -1
  160. package/dist/types/components/Combobox/index.d.ts.map +1 -1
  161. package/dist/types/components/DropdownSelect/DropdownSelect.d.ts +71 -0
  162. package/dist/types/components/DropdownSelect/DropdownSelect.d.ts.map +1 -0
  163. package/dist/types/components/DropdownSelect/index.d.ts +2 -0
  164. package/dist/types/components/DropdownSelect/index.d.ts.map +1 -0
  165. package/dist/types/components/Icon/custom/ArrowReturnIcon.d.ts +9 -0
  166. package/dist/types/components/Icon/custom/ArrowReturnIcon.d.ts.map +1 -0
  167. package/dist/types/components/Icon/iconRegistry.d.ts.map +1 -1
  168. package/dist/types/components/Input/Input.d.ts +5 -0
  169. package/dist/types/components/Input/Input.d.ts.map +1 -1
  170. package/dist/types/components/Menu/Menu.d.ts +42 -2
  171. package/dist/types/components/Menu/Menu.d.ts.map +1 -1
  172. package/dist/types/components/ProgressAccordeon/ProgressAccordeon.d.ts +17 -12
  173. package/dist/types/components/ProgressAccordeon/ProgressAccordeon.d.ts.map +1 -1
  174. package/dist/types/components/ProgressTracker/ProgressTracker.d.ts +29 -8
  175. package/dist/types/components/ProgressTracker/ProgressTracker.d.ts.map +1 -1
  176. package/dist/types/components/index.d.ts +1 -0
  177. package/dist/types/components/index.d.ts.map +1 -1
  178. package/docs/consumers/README.md +116 -37
  179. package/docs/consumers/brand.md +261 -0
  180. package/docs/consumers/figma-console-mcp.md +116 -0
  181. package/docs/consumers/setup-instructions.md +98 -12
  182. package/docs/consumers/skills.md +79 -0
  183. package/package.json +5 -6
  184. package/scripts/postinstall-nudge.js +8 -4
  185. package/skills/add-brand/SKILL.md +204 -0
  186. package/skills/add-brand/reference.md +160 -0
  187. package/skills/figma-to-code/SKILL.md +127 -0
  188. package/skills/pull-from-figma/SKILL.md +123 -0
  189. package/skills/push-to-figma/SKILL.md +172 -0
  190. package/skills/setup-muka/SKILL.md +73 -13
  191. package/tokens/README.md +39 -17
  192. package/tokens/t2-alias/brand/bouwplan/fonts.json +1 -1
  193. package/tokens/t2-alias/brand/fscl/fonts.json +3 -3
  194. package/tokens/t2-alias/brand/wireframe/fonts.json +2 -2
  195. package/tokens/t4-components/menu.json +8 -3
@@ -1,61 +1,140 @@
1
- # Consuming Muka UI in another repo
1
+ # Using Muka UI in your app
2
2
 
3
- Muka UI is published as a **public package on npm** and released on a tag-gated
4
- cadence. Consumers install a specific version and stay current via an automated
5
- update workflow driven by GitHub Releases. Installing needs no registry config
6
- or auth token.
3
+ Muka UI is a multi-brand, multi-theme React design system published as a
4
+ **public package on npm**. Installing it needs no registry config or auth token.
7
5
 
8
- ## Quick start
6
+ These docs are for building an app **with** Muka. To work **on** Muka itself, see
7
+ [`DEVELOPMENT.md`](../../DEVELOPMENT.md).
9
8
 
10
- The fastest path is the `/setup-muka` skill. Make it discoverable, then run it:
9
+ ## The workflow
10
+
11
+ Five steps from an empty repo to a branded, designed, working app. Each one is a
12
+ skill or a single command.
13
+
14
+ ```mermaid
15
+ flowchart TD
16
+ repo["1. Create your repo"] --> install["2. Install Muka UI<br/>/setup-muka"]
17
+ install --> brand["3. Add your brand<br/>/add-brand"]
18
+ brand --> design["4. Design in Figma<br/>Muka UI Figma Library"]
19
+ design --> handover["5. Hand the Figma link to your agent<br/>/figma-to-code"]
20
+ handover --> app["A branded app built from<br/>Muka components"]
21
+ brand -.->|"designers need your brand"| push["/push-to-figma"]
22
+ push -.-> design
23
+ design -.->|"designer retunes the brand"| pull["/pull-from-figma"]
24
+ pull -.-> brand
25
+ ```
26
+
27
+ ### 1. Create your repo
28
+
29
+ Any React app with a bundler that can import CSS — Vite, Next.js, Remix,
30
+ webpack. React `>=16.8` is the only peer requirement.
31
+
32
+ ### 2. Install Muka UI
11
33
 
12
34
  ```bash
13
- npx muka-ui install-skill # copies /setup-muka into .claude/skills
14
- # then in Claude Code / Cursor:
35
+ npm install @revikornmann/muka-ui@latest
36
+ npx muka-ui install-skill # make the skills discoverable
37
+ # then, in your agent:
15
38
  /setup-muka [brand]
16
39
  ```
17
40
 
18
- It installs Muka, sets up styles, adds the update workflow, and opens the
19
- consumer-registration PR for you.
41
+ `/setup-muka` installs the package, imports the right stylesheet and fonts, adds
42
+ the release auto-update workflow, and opens the PR that registers your repo as a
43
+ consumer. Doing it by hand instead: [`setup-instructions.md`](setup-instructions.md).
20
44
 
21
- To do it by hand, follow [setup-instructions.md](setup-instructions.md):
45
+ Muka ships five brands — `muka`, `wireframe`, `grip`, `fscl`, `bouwplan` — each
46
+ in light and dark. If one of them fits, you can stop here.
22
47
 
23
- 1. `npm install @revikornmann/muka-ui@latest`.
24
- 2. Import `@revikornmann/muka-ui/styles` (+ brand token CSS) in your app root.
25
- 3. Copy `templates/update-muka.yml` into `.github/workflows/`.
26
- 4. Add the repo to [`.github/consumers.txt`](../../.github/consumers.txt).
48
+ ### 3. Add your brand
27
49
 
28
- ## Release-gated update flow
50
+ ```
51
+ /add-brand acme
52
+ ```
53
+
54
+ This scaffolds a brand layer **in your repo** that overrides Muka's. You author
55
+ about 78 colour references and four font families; primitives, semantics, and
56
+ every component token keep coming from the package. One file of colour references
57
+ restyles the entire component library, and there is no component code to change.
58
+
59
+ Details and the token map: [`brand.md`](brand.md).
60
+
61
+ ### 4. Design in Figma
62
+
63
+ Design against the [Muka UI Figma
64
+ Library](https://www.figma.com/design/RL5IFLUJk4yeAFNXlsX4b5/Muka-UI-Figma-Library),
65
+ so screens are assembled from the same components the code has, bound to the same
66
+ variables the tokens generate.
67
+
68
+ To let designers work in **your** brand, publish it to Figma as variables:
69
+
70
+ ```
71
+ /push-to-figma
72
+ ```
29
73
 
30
- When a maintainer publishes a GitHub Release, [publish.yml](../../.github/workflows/publish.yml)
31
- builds and publishes the package to the public npm registry, then fires a
32
- `muka-released` `repository_dispatch` (carrying the version) to every repo in
33
- [`.github/consumers.txt`](../../.github/consumers.txt). Each consumer's
74
+ When a designer retunes the brand there, bring it back with `/pull-from-figma`.
75
+ Both need [Figma Console MCP](figma-console-mcp.md).
76
+
77
+ ### 5. Hand the Figma link to your agent
78
+
79
+ ```
80
+ /figma-to-code https://figma.com/design/…?node-id=472-4248
81
+ ```
82
+
83
+ Because the design is made of Muka components and the code has those same
84
+ components, the agent's job is mapping rather than reinventing: it reads the Code
85
+ Connect mapping, composes the screen from real components, and styles the gaps
86
+ with token custom properties. The result inherits your brand and both themes for
87
+ free.
88
+
89
+ ### And voilà
90
+
91
+ A branded app built from a component library you did not have to write, that
92
+ follows brand changes centrally and updates itself on each Muka release.
93
+
94
+ ## Reference
95
+
96
+ | Doc | Contents |
97
+ |---|---|
98
+ | [`setup-instructions.md`](setup-instructions.md) | Canonical install, styles, fonts, theming, and auto-update setup |
99
+ | [`brand.md`](brand.md) | Building your own brand on top of Muka's token layers |
100
+ | [`skills.md`](skills.md) | Every shipped skill and what it is for |
101
+ | [`figma-console-mcp.md`](figma-console-mcp.md) | One-time setup for the token-sync skills |
102
+
103
+ Component APIs, live Playgrounds, and token documentation are in the Storybook at
104
+ **<https://muka.kornmann.com>**.
105
+
106
+ ## Staying up to date
107
+
108
+ When a maintainer publishes a GitHub Release,
109
+ [`publish.yml`](../../.github/workflows/publish.yml) publishes to npm and fires a
110
+ `muka-released` `repository_dispatch` (carrying the version) to every repo listed
111
+ in [`.github/consumers.txt`](../../.github/consumers.txt). Your
34
112
  `update-muka.yml` installs that exact version and commits the lockfile bump.
35
113
 
36
114
  ```mermaid
37
115
  flowchart LR
38
116
  tag["Maintainer tags release"] --> publish["publish.yml builds + npm publish"]
39
- publish --> pkg["npm registry (npmjs.org)"]
40
- publish --> dispatch["repository_dispatch: muka-released (version)"]
41
- dispatch --> update["consumer update-muka.yml"]
117
+ publish --> pkg["npm registry"]
118
+ publish --> dispatch["repository_dispatch: muka-released"]
119
+ dispatch --> update["your update-muka.yml"]
42
120
  update --> install["npm install @revikornmann/muka-ui@version"]
43
121
  install --> commit["Commit + push lockfile"]
44
- commit --> deploy["Host redeploys (e.g. Vercel)"]
122
+ commit --> deploy["Host redeploys"]
45
123
  ```
46
124
 
47
- ## Versioning
48
-
49
- - Consumers typically pin a caret range, e.g. `"@revikornmann/muka-ui": "^1.4.0"`.
50
- - The dispatch installs the **exact** published version, so bumps are predictable.
125
+ - Pin a caret range, e.g. `"@revikornmann/muka-ui": "^0.18.0"`. The dispatch
126
+ installs the **exact** published version, so bumps are predictable.
51
127
  - Manual `workflow_dispatch` runs install `@latest`.
52
- - Develop freely on `main` — consumers are only notified on a published release.
53
-
54
- ## Notes
55
-
56
- - The update only changes `package.json` + `package-lock.json`, so it never
128
+ - The update only touches `package.json` and `package-lock.json`, so it never
57
129
  conflicts with app source.
58
- - `dist/` is built at publish time and shipped inside the tarball; it is not
130
+ - `dist/` is built at publish time and shipped in the tarball; it is not
59
131
  committed to the Muka repo.
60
- - If you deploy on Vercel/Netlify, the push to your default branch triggers the
61
- redeploy. The package is public, so the host needs no auth to install it.
132
+
133
+ > **Muka is under active development.** A release can bring breaking changes —
134
+ > visual shifts, changed component APIs, altered token values. Treat the update
135
+ > workflow as a trigger to **re-test your app**, not a guarantee of stability.
136
+ > Keep CI checks and visual review on the bump PR.
137
+ >
138
+ > If you maintain a custom brand, rebuild it after every upgrade: your brand CSS
139
+ > is generated against the package's primitives and component tokens. See
140
+ > [`brand.md`](brand.md#keeping-your-brand-current).
@@ -0,0 +1,261 @@
1
+ # Building your own brand
2
+
3
+ Muka ships five brands. When none of them is yours, you can add your own **in
4
+ your repo** without forking Muka: you author one layer of the token system and
5
+ inherit the rest from the package.
6
+
7
+ The fastest path is the [`/add-brand`](skills.md) skill, which walks an agent
8
+ through everything below:
9
+
10
+ ```
11
+ /add-brand acme
12
+ ```
13
+
14
+ This document is the reference behind it.
15
+
16
+ ## What you own, and what you don't
17
+
18
+ Muka's tokens are four layers deep. A brand is defined entirely by the second
19
+ one:
20
+
21
+ | Layer | Owner | Example |
22
+ |---|---|---|
23
+ | **T1 Primitives** | Package | `color.violet.9`, `spacing.4`, `size.md` |
24
+ | **T2 Alias — base** | Package | brand-agnostic defaults |
25
+ | **T2 Alias — brand** | **You** | `alias.color.accent.default` → `{color.violet.9}` |
26
+ | **T3 Semantics** | Package | `color.surface.level1`, `color.action.default` |
27
+ | **T4 Components** | Package | `button.color.primary.background.default` |
28
+
29
+ Components read T3 and T4. Those resolve through T2. So repointing
30
+ `alias.color.accent.default` at a different primitive changes every button, link,
31
+ focus ring, and selection highlight in the library at once — with no component
32
+ code, and no fork to maintain.
33
+
34
+ It also means **you should never edit T3 or T4**. They come from `node_modules`
35
+ and are replaced on every upgrade.
36
+
37
+ ## Scaffold it
38
+
39
+ ```bash
40
+ npx muka-ui brand init acme
41
+ ```
42
+
43
+ Brand names are lowercase, start with a letter, and contain only letters,
44
+ numbers, and hyphens. This writes, prompting before overwriting anything:
45
+
46
+ | Path | Contents |
47
+ |---|---|
48
+ | `brand/light.json` | Light-mode colour aliases — 78 tokens |
49
+ | `brand/dark.json` | Dark-mode colour aliases |
50
+ | `brand/fonts.json` | Font families and weights for four roles |
51
+ | `brand/muka.brand.json` | Build manifest: your files plus the package's token globs |
52
+ | `brand/build.js` | Build entry using `TokenBuilder` from the package |
53
+
54
+ It also adds a `build:tokens` script to `package.json` if there isn't one.
55
+
56
+ The files start as copies of Muka's `wireframe` brand, so they are complete and
57
+ buildable rather than empty. Prove the pipeline before editing:
58
+
59
+ ```bash
60
+ npm run build:tokens
61
+ ```
62
+
63
+ Expect `All theme combinations built successfully!` and two new files in
64
+ `styles/`. Debugging is far easier against known-good values.
65
+
66
+ ## The token groups
67
+
68
+ All 78 colour tokens live under `alias.color`:
69
+
70
+ | Group | Tokens | Effect |
71
+ |---|---|---|
72
+ | `neutral` | `1`–`12` plus `alphaHued.1`–`12` | Every surface, border, and text colour. The widest-reaching choice in the file. |
73
+ | `accent` | `default`, `hover`, `pressed`, `contrast`, `muted`, and an `inverse.*` set | The interactive colour: buttons, links, focus rings, selection. Change this first. |
74
+ | `brand` | `primary.*`, `secondary.*` | Identity colours for marketing surfaces, distinct from ordinary controls. |
75
+ | `state` | `success`, `warning`, `error`, `info` — each with `contrast`/`default`/`muted` and four `surface` levels | Feedback colours. Keep the hues conventional. |
76
+ | `conversation` | `own`, `peer`, `agent` surfaces and borders, plus `meta` | Chat components. Leave as scaffolded if your app has no chat — they still need to resolve. |
77
+
78
+ ## Write references, not colours
79
+
80
+ Every value is a reference to a T1 primitive:
81
+
82
+ ```json
83
+ "accent": {
84
+ "default": { "$type": "color", "$value": "{color.violet.9}" },
85
+ "hover": { "$type": "color", "$value": "{color.violet.10}" },
86
+ "pressed": { "$type": "color", "$value": "{color.violet.11}" },
87
+ "contrast": { "$type": "color", "$value": "{color.violet.12}" },
88
+ "muted": { "$type": "color", "$value": "{color.violet.8}" }
89
+ }
90
+ ```
91
+
92
+ A raw hex works, but opts that token out of the system: it gains no dark-mode
93
+ counterpart and stops tracking the ramp. Use references.
94
+
95
+ ### Available palettes
96
+
97
+ 12-step ramps. Light mode uses the base name; dark mode appends **camelCase
98
+ `Dark`**, and references are case-sensitive — `{color.violetdark.9}` resolves to
99
+ nothing.
100
+
101
+ - **Neutrals:** `gray`, `mauve`, `slate`, `sage`, `olive`, `sand`
102
+ - **Colours:** `tomato`, `red`, `ruby`, `crimson`, `pink`, `plum`, `purple`,
103
+ `violet`, `iris`, `indigo`, `blue`, `cyan`, `teal`, `jade`, `green`, `grass`,
104
+ `bronze`, `gold`, `brown`, `orange`, `amber`, `yellow`, `lime`, `mint`, `sky`
105
+ - **Absolutes:** `white`, `black`, `black-alpha`, `white-alpha`
106
+ - **Hued neutral alphas:** `mauveA`, `grayA`, `sandA`, `sageA` (and their `Dark`
107
+ variants) back `neutral.alphaHued.*`
108
+
109
+ Full values:
110
+ `node_modules/@revikornmann/muka-ui/tokens/t1-primitives/color.json`.
111
+
112
+ ### What the steps mean
113
+
114
+ | Steps | Use |
115
+ |---|---|
116
+ | 1–2 | App and component backgrounds |
117
+ | 3–5 | Subtle backgrounds: hover, selected, muted fills |
118
+ | 6–8 | Borders and separators — 8 is the strongest |
119
+ | 9–10 | Solid fills — 9 is the most saturated, 10 its hover |
120
+ | 11 | Low-contrast text |
121
+ | 12 | High-contrast text and headings |
122
+
123
+ Put `accent.default` at 9, `hover` at 10, `pressed` at 11, `contrast` at 12
124
+ unless you have a reason not to. Every shipped brand follows this.
125
+
126
+ ### Mirror it for dark mode
127
+
128
+ `brand/dark.json` repeats the structure using the `Dark` ramps, keeping the
129
+ **same step numbers**:
130
+
131
+ ```json
132
+ "accent": {
133
+ "default": { "$type": "color", "$value": "{color.violetDark.9}" }
134
+ }
135
+ ```
136
+
137
+ The ramps are built so equal steps read as equal emphasis in either mode, which
138
+ is what makes the mirror work.
139
+
140
+ ## Typography
141
+
142
+ `brand/fonts.json` sets four roles:
143
+
144
+ | Role | Used for |
145
+ |---|---|
146
+ | `brand` | Headings, buttons, labels |
147
+ | `plain` | Body copy and UI text |
148
+ | `mono` | Code and numeric tables |
149
+ | `script` | Decorative accents only |
150
+
151
+ `family` values must be the **exact `@font-face` family name** that gets loaded —
152
+ the generated CSS passes the literal through to `font-family`. List only weights
153
+ the font actually provides; naming an absent weight makes the browser synthesise
154
+ it, which looks wrong at display sizes.
155
+
156
+ ### Loading the fonts
157
+
158
+ Muka self-hosts its own brands' fonts, but that pipeline does not extend to your
159
+ brand. You have three options:
160
+
161
+ 1. **Reuse a font Muka already bundles** — import that brand's fonts file and you
162
+ are done:
163
+ ```ts
164
+ import '@revikornmann/muka-ui/styles/fonts-muka.css';
165
+ ```
166
+ | Family | Import this brand's fonts file |
167
+ |---|---|
168
+ | `Funnel Display`, `Funnel Sans` | `fonts-muka.css` |
169
+ | `Quicksand` | `fonts-grip.css` |
170
+ | `IBM Plex Sans`, `Lora` | `fonts-fscl.css` |
171
+ | `Red Hat Display`, `Red Hat Text` | `fonts-bouwplan.css` |
172
+ | `Yesteryear` (script role) | `fonts-muka.css`, `fonts-grip.css`, or `fonts-bouwplan.css` |
173
+
174
+ `fonts-wireframe.css` is empty — that brand uses system fonts only.
175
+ 2. **Use a system font** — `Helvetica`, `Arial`, `Menlo`, `Georgia`,
176
+ `system-ui`, and friends need no loading.
177
+ 3. **Bring your own** — self-host it with your own `@font-face` under the exact
178
+ family name from `fonts.json`. Don't use a Google Fonts `<link>`: it breaks
179
+ offline and air-gapped installs and adds a render-blocking request.
180
+
181
+ ## Build and load the CSS
182
+
183
+ ```bash
184
+ npm run build:tokens
185
+ ```
186
+
187
+ This writes `styles/tokens-acme-light.css` and `styles/tokens-acme-dark.css` —
188
+ complete stylesheets with every resolved token, around 2,200 custom properties
189
+ each.
190
+
191
+ Import your brand CSS **after** Muka's component and reset layer:
192
+
193
+ ```ts
194
+ import '@revikornmann/muka-ui/styles/base.css';
195
+ import './styles/tokens-acme-light.css';
196
+ import '@revikornmann/muka-ui/styles/fonts-muka.css'; // or your own @font-face
197
+ ```
198
+
199
+ Use `base.css`, **not** `@revikornmann/muka-ui/styles`. The latter is the bundled
200
+ `muka-light` theme: it contains a full token set that will fight your brand
201
+ depending on import order.
202
+
203
+ ### Switching brand and theme
204
+
205
+ Every token stylesheet declares its variables on `:root`. There are **no
206
+ `[data-brand]` or `[data-theme]` selectors**, so the active theme is simply
207
+ whichever stylesheet loaded last. Adding `data-brand` / `data-theme` attributes
208
+ does nothing.
209
+
210
+ For a runtime light/dark toggle, swap a `<link>` rather than importing both:
211
+
212
+ ```ts
213
+ const link = document.getElementById('muka-theme') as HTMLLinkElement;
214
+ link.href = `/styles/tokens-acme-${mode}.css`;
215
+ ```
216
+
217
+ Copy the generated CSS into your static/public directory so those hrefs resolve.
218
+ This is exactly how Muka's own Storybook switches between its ten themes.
219
+
220
+ ## Keeping your brand current
221
+
222
+ Your brand CSS is generated against the package's primitives, semantics, and
223
+ component tokens, so it goes stale when Muka publishes new ones — a new component
224
+ in a release has tokens your last build never saw.
225
+
226
+ Wire the rebuild into your pipeline so it can't be forgotten:
227
+
228
+ ```json
229
+ "scripts": {
230
+ "build": "npm run build:tokens && vite build",
231
+ "postinstall": "npm run build:tokens"
232
+ }
233
+ ```
234
+
235
+ Commit `brand/**`. Generated `styles/tokens-*.css` can be committed or
236
+ gitignored — commit it if your host has no build step.
237
+
238
+ ## Verify
239
+
240
+ - Both CSS files exist and were rebuilt after your last edit.
241
+ - Neither contains `undefined` — that is an unresolved reference, usually a
242
+ typo'd palette or a missing `Dark` suffix.
243
+ - Your accent colour is really there:
244
+ ```bash
245
+ grep -- '--alias-color-accent-default' styles/tokens-acme-light.css
246
+ ```
247
+ - A primary `<Button>` renders in your accent colour and body text in your
248
+ typeface, in both light and dark.
249
+ - Dark mode changes surfaces without leaving text unreadable.
250
+
251
+ ## Troubleshooting
252
+
253
+ | Symptom | Cause |
254
+ |---|---|
255
+ | `undefined` in the generated CSS | Unresolved `{reference}` — typo'd palette name or missing `Dark` suffix |
256
+ | Dark mode looks like light mode | `dark.json` still references light ramps |
257
+ | Colours unchanged after rebuilding | Brand CSS imported before Muka's token bundle. Import `base.css`, then your brand last |
258
+ | Text unreadable on accent fills | `accent.contrast` too close to `accent.default` — move it to step 12 or `white` |
259
+ | Fonts fall back to a system face | No `@font-face` loaded for that family, or the name doesn't match byte-for-byte |
260
+ | `Cannot find module '…/build'` | Regenerate with `npx muka-ui brand init` from a current version; older scaffolds wrote an unscoped package name |
261
+ | New components look unstyled after an upgrade | Brand CSS predates the release. Re-run `npm run build:tokens` |
@@ -0,0 +1,116 @@
1
+ # Figma Console MCP — one-time setup
2
+
3
+ The [`/push-to-figma`](../../skills/push-to-figma/SKILL.md) and
4
+ [`/pull-from-figma`](../../skills/pull-from-figma/SKILL.md) skills sync your
5
+ brand's design tokens between your repo and Figma. Both talk to Figma through
6
+ **Figma Console MCP**, which relays commands to a **Desktop Bridge** plugin
7
+ running inside Figma Desktop. This guide gets that pipeline working.
8
+
9
+ ```
10
+ Your agent ──(MCP: figma-console)──► Desktop Bridge plugin ──► Figma Desktop (variables)
11
+ ```
12
+
13
+ > **Credits:** [Figma Console MCP](https://github.com/southleft/figma-console-mcp)
14
+ > is an open-source (MIT) MCP server by **[Southleft](https://southleft.com)**,
15
+ > published on npm as
16
+ > [`figma-console-mcp`](https://www.npmjs.com/package/figma-console-mcp). It is
17
+ > not a Muka project — Muka only ships the skills that drive it. Please raise
18
+ > issues with the server itself
19
+ > [upstream](https://github.com/southleft/figma-console-mcp/issues).
20
+
21
+ This is only needed for the two token-sync skills. `/setup-muka`, `/add-brand`,
22
+ and `/figma-to-code` do not require it — `/figma-to-code` works with Figma's own
23
+ official MCP server, which is a separate thing.
24
+
25
+ ## 1. Get a Figma access token
26
+
27
+ Create a personal access token in Figma (**Settings → Security → Personal access
28
+ tokens**) with **Variables** read/write scope. It looks like `figd_…`.
29
+
30
+ **Do not paste it into any file.** Keep it in your shell environment:
31
+
32
+ ```bash
33
+ # ~/.zshrc (or ~/.bashrc)
34
+ export FIGMA_ACCESS_TOKEN="figd_your_token_here"
35
+ ```
36
+
37
+ Open a new shell (or `source` the file) so the variable is set.
38
+
39
+ ## 2. Register the server
40
+
41
+ Add a project-scoped `.mcp.json` at your repo root. It uses **env expansion**, so
42
+ no secret lives in the file and it is safe to commit:
43
+
44
+ ```json
45
+ {
46
+ "mcpServers": {
47
+ "figma-console": {
48
+ "command": "npx",
49
+ "args": ["-y", "figma-console-mcp@latest"],
50
+ "env": {
51
+ "FIGMA_ACCESS_TOKEN": "${FIGMA_ACCESS_TOKEN}",
52
+ "ENABLE_MCP_APPS": "true"
53
+ }
54
+ }
55
+ }
56
+ }
57
+ ```
58
+
59
+ Because it is project-scoped, **Claude Code asks you to approve the
60
+ `figma-console` server** the first time it reads `.mcp.json` (run `/mcp` to
61
+ review and approve). Approve it, then **restart the session** — `.mcp.json` is
62
+ only read at startup, so adding or editing it mid-session will not surface the
63
+ tools.
64
+
65
+ Need machine-specific overrides? Put them in `.mcp.local.json` and gitignore
66
+ that path. Never inline a `figd_…` token in a committed file.
67
+
68
+ ## 3. Install the Desktop Bridge plugin
69
+
70
+ The plugin files are written to `~/.figma-console-mcp/plugin/` the first time the
71
+ server runs. Find the exact path with:
72
+
73
+ ```bash
74
+ npx figma-console-mcp@latest --print-path
75
+ ```
76
+
77
+ In **Figma Desktop**: `Plugins → Development → Import plugin from manifest…` →
78
+ select `~/.figma-console-mcp/plugin/manifest.json`. Then open the file you want
79
+ to edit and run `Plugins → Development → Figma Desktop Bridge` to connect it.
80
+
81
+ The bridge needs **Figma Desktop**; it does not work in the browser.
82
+
83
+ ## 4. Verify
84
+
85
+ From your agent, once the server is loaded:
86
+
87
+ ```
88
+ figma_get_status { probe: true }
89
+ ```
90
+
91
+ A healthy result reports `setup.valid: true`, `probeResult.success: true`, and
92
+ the connected file name. `figma_list_open_files` shows which file the plugin is
93
+ bridged to.
94
+
95
+ ## Which Figma file to connect
96
+
97
+ Point the bridge at **your own copy or branch** of the Muka UI Figma Library, not
98
+ the shared library itself. Your brand is your brand — pushing modes into the
99
+ upstream library affects every other consumer.
100
+
101
+ Duplicate the [Muka UI Figma
102
+ Library](https://www.figma.com/design/RL5IFLUJk4yeAFNXlsX4b5/Muka-UI-Figma-Library)
103
+ into your own team, or work on a branch of it, then connect the bridge there.
104
+
105
+ The skills discover collections and modes **by name**, so a duplicate works
106
+ without any ID configuration.
107
+
108
+ ## Troubleshooting
109
+
110
+ | Symptom | Fix |
111
+ |---|---|
112
+ | `figma-console` tools don't appear | The session predates `.mcp.json`. Approve it via `/mcp` and restart the session. |
113
+ | `FIGMA_ACCESS_TOKEN` unset | `${FIGMA_ACCESS_TOKEN}` expanded to empty. Export it and restart the session. |
114
+ | Probe fails / no connected file | Open the target file in Figma Desktop and run the Desktop Bridge plugin, then re-check `figma_get_status { probe: true }`. |
115
+ | Permission error writing variables | The token lacks Variables write scope, or you only have view access to the file. |
116
+ | Pushed values show as raw swatches | They were written as hex instead of variable aliases. See Step 4 and Step 6 of `/push-to-figma`. |