@revikornmann/muka-ui 0.17.0 → 0.19.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 +81 -60
- package/cli/bin/muka-ui.js +12 -5
- package/cli/commands/brand.js +33 -14
- package/cli/commands/init.js +21 -17
- package/cli/commands/install-skill.js +84 -26
- package/cli/templates/AGENTS.md +128 -0
- package/cli/templates/CLAUDE.md +8 -88
- package/cli/templates/muka-ui-guidelines.md +50 -14
- package/dist/cjs/components/ActionSheet/ActionSheet.js +1 -1
- package/dist/cjs/components/Breadcrumb/Breadcrumb.css +11 -3
- package/dist/cjs/components/Breadcrumb/Breadcrumb.js +19 -1
- package/dist/cjs/components/Breadcrumb/Breadcrumb.js.map +1 -1
- package/dist/cjs/components/Combobox/Combobox.css +116 -132
- package/dist/cjs/components/Combobox/Combobox.js +175 -52
- package/dist/cjs/components/Combobox/Combobox.js.map +1 -1
- package/dist/cjs/components/Combobox/index.js.map +1 -1
- package/dist/cjs/components/ContextSelect/ContextSelect.css +117 -0
- package/dist/cjs/components/ContextSelect/ContextSelect.js +49 -0
- package/dist/cjs/components/ContextSelect/ContextSelect.js.map +1 -0
- package/dist/cjs/components/ContextSelect/index.js +11 -0
- package/dist/cjs/components/ContextSelect/index.js.map +1 -0
- package/dist/cjs/components/DropdownSelect/DropdownSelect.css +225 -0
- package/dist/cjs/components/DropdownSelect/DropdownSelect.js +106 -0
- package/dist/cjs/components/DropdownSelect/DropdownSelect.js.map +1 -0
- package/dist/cjs/components/DropdownSelect/index.js +6 -0
- package/dist/cjs/components/DropdownSelect/index.js.map +1 -0
- package/dist/cjs/components/Icon/custom/ArrowDropUpDownIcon.js +11 -0
- package/dist/cjs/components/Icon/custom/ArrowDropUpDownIcon.js.map +1 -0
- package/dist/cjs/components/Icon/custom/ArrowReturnIcon.js +11 -0
- package/dist/cjs/components/Icon/custom/ArrowReturnIcon.js.map +1 -0
- package/dist/cjs/components/Icon/iconRegistry.js +11 -0
- package/dist/cjs/components/Icon/iconRegistry.js.map +1 -1
- package/dist/cjs/components/Input/Input.css +45 -8
- package/dist/cjs/components/Input/Input.js +14 -3
- package/dist/cjs/components/Input/Input.js.map +1 -1
- package/dist/cjs/components/Menu/Menu.css +213 -17
- package/dist/cjs/components/Menu/Menu.js +429 -39
- package/dist/cjs/components/Menu/Menu.js.map +1 -1
- package/dist/cjs/components/Menu/index.js +5 -1
- package/dist/cjs/components/Menu/index.js.map +1 -1
- package/dist/cjs/components/ProgressTracker/ProgressTracker.css +273 -22
- package/dist/cjs/components/ProgressTracker/ProgressTracker.js +109 -9
- package/dist/cjs/components/ProgressTracker/ProgressTracker.js.map +1 -1
- package/dist/cjs/components/Scrollbar/Scrollbar.css +124 -0
- package/dist/cjs/components/Scrollbar/Scrollbar.js +118 -0
- package/dist/cjs/components/Scrollbar/Scrollbar.js.map +1 -0
- package/dist/cjs/components/Scrollbar/index.js +11 -0
- package/dist/cjs/components/Scrollbar/index.js.map +1 -0
- package/dist/cjs/components/index.js +13 -16
- package/dist/cjs/components/index.js.map +1 -1
- package/dist/esm/components/ActionSheet/ActionSheet.js +1 -1
- package/dist/esm/components/Breadcrumb/Breadcrumb.css +11 -3
- package/dist/esm/components/Breadcrumb/Breadcrumb.js +19 -1
- package/dist/esm/components/Breadcrumb/Breadcrumb.js.map +1 -1
- package/dist/esm/components/Combobox/Combobox.css +116 -132
- package/dist/esm/components/Combobox/Combobox.js +177 -54
- package/dist/esm/components/Combobox/Combobox.js.map +1 -1
- package/dist/esm/components/Combobox/index.js +1 -1
- package/dist/esm/components/Combobox/index.js.map +1 -1
- package/dist/esm/components/ContextSelect/ContextSelect.css +117 -0
- package/dist/esm/components/ContextSelect/ContextSelect.js +45 -0
- package/dist/esm/components/ContextSelect/ContextSelect.js.map +1 -0
- package/dist/esm/components/ContextSelect/index.js +3 -0
- package/dist/esm/components/ContextSelect/index.js.map +1 -0
- package/dist/esm/components/DropdownSelect/DropdownSelect.css +225 -0
- package/dist/esm/components/DropdownSelect/DropdownSelect.js +102 -0
- package/dist/esm/components/DropdownSelect/DropdownSelect.js.map +1 -0
- package/dist/esm/components/DropdownSelect/index.js +2 -0
- package/dist/esm/components/DropdownSelect/index.js.map +1 -0
- package/dist/esm/components/Icon/custom/ArrowDropUpDownIcon.js +7 -0
- package/dist/esm/components/Icon/custom/ArrowDropUpDownIcon.js.map +1 -0
- package/dist/esm/components/Icon/custom/ArrowReturnIcon.js +7 -0
- package/dist/esm/components/Icon/custom/ArrowReturnIcon.js.map +1 -0
- package/dist/esm/components/Icon/iconRegistry.js +11 -0
- package/dist/esm/components/Icon/iconRegistry.js.map +1 -1
- package/dist/esm/components/Input/Input.css +45 -8
- package/dist/esm/components/Input/Input.js +14 -3
- package/dist/esm/components/Input/Input.js.map +1 -1
- package/dist/esm/components/Menu/Menu.css +213 -17
- package/dist/esm/components/Menu/Menu.js +428 -40
- package/dist/esm/components/Menu/Menu.js.map +1 -1
- package/dist/esm/components/Menu/index.js +1 -1
- package/dist/esm/components/Menu/index.js.map +1 -1
- package/dist/esm/components/ProgressTracker/ProgressTracker.css +273 -22
- package/dist/esm/components/ProgressTracker/ProgressTracker.js +110 -10
- package/dist/esm/components/ProgressTracker/ProgressTracker.js.map +1 -1
- package/dist/esm/components/Scrollbar/Scrollbar.css +124 -0
- package/dist/esm/components/Scrollbar/Scrollbar.js +114 -0
- package/dist/esm/components/Scrollbar/Scrollbar.js.map +1 -0
- package/dist/esm/components/Scrollbar/index.js +3 -0
- package/dist/esm/components/Scrollbar/index.js.map +1 -0
- package/dist/esm/components/index.js +4 -2
- package/dist/esm/components/index.js.map +1 -1
- package/dist/styles/components/Breadcrumb.css +11 -3
- package/dist/styles/components/Combobox.css +116 -132
- package/dist/styles/components/ContextSelect.css +117 -0
- package/dist/styles/components/DropdownSelect.css +225 -0
- package/dist/styles/components/Input.css +45 -8
- package/dist/styles/components/Menu.css +213 -17
- package/dist/styles/components/ProgressTracker.css +273 -22
- package/dist/styles/components/Scrollbar.css +124 -0
- package/dist/styles/components/Typography.css +89 -0
- package/dist/styles/index.css +1526 -480
- package/dist/styles/muka-dark.css +1526 -480
- package/dist/styles/muka-light.css +1526 -480
- package/dist/styles/tokens-bouwplan-dark.css +9 -6
- package/dist/styles/tokens-bouwplan-light.css +9 -6
- package/dist/styles/tokens-fscl-dark.css +29 -26
- package/dist/styles/tokens-fscl-light.css +29 -26
- package/dist/styles/tokens-grip-dark.css +8 -5
- package/dist/styles/tokens-grip-light.css +8 -5
- package/dist/styles/tokens-muka-dark.css +8 -5
- package/dist/styles/tokens-muka-light.css +8 -5
- package/dist/styles/tokens-wireframe-dark.css +53 -50
- package/dist/styles/tokens-wireframe-light.css +53 -50
- package/dist/styles/wireframe-dark.css +1571 -525
- package/dist/styles/wireframe-light.css +1571 -525
- package/dist/types/components/ActionSheet/ActionSheet.d.ts +1 -1
- package/dist/types/components/Breadcrumb/Breadcrumb.d.ts +27 -3
- package/dist/types/components/Breadcrumb/Breadcrumb.d.ts.map +1 -1
- package/dist/types/components/Combobox/Combobox.d.ts +38 -38
- package/dist/types/components/Combobox/Combobox.d.ts.map +1 -1
- package/dist/types/components/Combobox/index.d.ts +1 -1
- package/dist/types/components/Combobox/index.d.ts.map +1 -1
- package/dist/types/components/ContextSelect/ContextSelect.d.ts +62 -0
- package/dist/types/components/ContextSelect/ContextSelect.d.ts.map +1 -0
- package/dist/types/components/ContextSelect/index.d.ts +3 -0
- package/dist/types/components/ContextSelect/index.d.ts.map +1 -0
- package/dist/types/components/DataTable/DataTable.d.ts +1 -1
- package/dist/types/components/DropdownSelect/DropdownSelect.d.ts +71 -0
- package/dist/types/components/DropdownSelect/DropdownSelect.d.ts.map +1 -0
- package/dist/types/components/DropdownSelect/index.d.ts +2 -0
- package/dist/types/components/DropdownSelect/index.d.ts.map +1 -0
- package/dist/types/components/Icon/custom/ArrowDropUpDownIcon.d.ts +9 -0
- package/dist/types/components/Icon/custom/ArrowDropUpDownIcon.d.ts.map +1 -0
- package/dist/types/components/Icon/custom/ArrowReturnIcon.d.ts +9 -0
- package/dist/types/components/Icon/custom/ArrowReturnIcon.d.ts.map +1 -0
- package/dist/types/components/Icon/iconRegistry.d.ts.map +1 -1
- package/dist/types/components/Input/Input.d.ts +5 -0
- package/dist/types/components/Input/Input.d.ts.map +1 -1
- package/dist/types/components/Menu/Menu.d.ts +99 -29
- package/dist/types/components/Menu/Menu.d.ts.map +1 -1
- package/dist/types/components/Menu/index.d.ts +2 -2
- package/dist/types/components/Menu/index.d.ts.map +1 -1
- package/dist/types/components/ProgressTracker/ProgressTracker.d.ts +29 -8
- package/dist/types/components/ProgressTracker/ProgressTracker.d.ts.map +1 -1
- package/dist/types/components/Scrollbar/Scrollbar.d.ts +19 -0
- package/dist/types/components/Scrollbar/Scrollbar.d.ts.map +1 -0
- package/dist/types/components/Scrollbar/index.d.ts +3 -0
- package/dist/types/components/Scrollbar/index.d.ts.map +1 -0
- package/dist/types/components/index.d.ts +5 -4
- package/dist/types/components/index.d.ts.map +1 -1
- package/docs/consumers/README.md +116 -37
- package/docs/consumers/brand.md +261 -0
- package/docs/consumers/figma-console-mcp.md +116 -0
- package/docs/consumers/setup-instructions.md +98 -12
- package/docs/consumers/skills.md +79 -0
- package/package.json +4 -6
- package/scripts/postinstall-nudge.js +8 -4
- package/skills/add-brand/SKILL.md +204 -0
- package/skills/add-brand/reference.md +160 -0
- package/skills/figma-to-code/SKILL.md +127 -0
- package/skills/pull-from-figma/SKILL.md +123 -0
- package/skills/push-to-figma/SKILL.md +172 -0
- package/skills/setup-muka/SKILL.md +73 -13
- package/tokens/README.md +40 -18
- package/tokens/t2-alias/brand/bouwplan/fonts.json +1 -1
- package/tokens/t2-alias/brand/fscl/fonts.json +3 -3
- package/tokens/t2-alias/brand/wireframe/fonts.json +2 -2
- package/tokens/t4-components/menu.json +20 -5
- package/dist/cjs/components/ContextMenu/ContextMenu.js +0 -186
- package/dist/cjs/components/ContextMenu/ContextMenu.js.map +0 -1
- package/dist/cjs/components/ContextMenu/index.js +0 -17
- package/dist/cjs/components/ContextMenu/index.js.map +0 -1
- package/dist/esm/components/ContextMenu/ContextMenu.js +0 -145
- package/dist/esm/components/ContextMenu/ContextMenu.js.map +0 -1
- package/dist/esm/components/ContextMenu/index.js +0 -2
- package/dist/esm/components/ContextMenu/index.js.map +0 -1
- package/dist/types/components/ContextMenu/ContextMenu.d.ts +0 -188
- package/dist/types/components/ContextMenu/ContextMenu.d.ts.map +0 -1
- package/dist/types/components/ContextMenu/index.d.ts +0 -3
- package/dist/types/components/ContextMenu/index.d.ts.map +0 -1
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: add-brand
|
|
3
|
+
description: Create a custom brand in this repo that overrides Muka UI's brand layer, so every Muka component picks up your colours and typography.
|
|
4
|
+
disable-model-invocation: true
|
|
5
|
+
argument-hint: "[brand-name]"
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Add your own brand
|
|
9
|
+
|
|
10
|
+
Give this repo its own brand without forking Muka UI. You author **only the T2
|
|
11
|
+
brand layer**; primitives, semantics, and all component tokens keep coming from
|
|
12
|
+
the installed package, so every Muka component restyles itself with no component
|
|
13
|
+
code changes.
|
|
14
|
+
|
|
15
|
+
`$ARGUMENTS` is the brand name — lowercase, starting with a letter, letters,
|
|
16
|
+
numbers and hyphens only (e.g. `acme`, `northwind`, `blue-harbour`).
|
|
17
|
+
|
|
18
|
+
**Prerequisite:** `@revikornmann/muka-ui` is installed. If not, run
|
|
19
|
+
`/setup-muka` first.
|
|
20
|
+
|
|
21
|
+
See [`reference.md`](reference.md) for the full token map, the available
|
|
22
|
+
primitive palettes, and the colour-scale conventions.
|
|
23
|
+
|
|
24
|
+
## How the override works
|
|
25
|
+
|
|
26
|
+
```
|
|
27
|
+
T1 Primitives (package) raw ramps: color.indigo.9, spacing.4, size.md
|
|
28
|
+
T2 Alias base (package) brand-agnostic defaults
|
|
29
|
+
T2 Alias brand ← YOU brand/light.json, brand/dark.json, brand/fonts.json
|
|
30
|
+
T3 Semantics (package) color.surface.level1, color.action.default
|
|
31
|
+
T4 Components (package) button.color.primary.background.default
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Your three files replace the brand slice of T2. Everything above resolves
|
|
35
|
+
through them, which is why one file of colour references repaints the whole
|
|
36
|
+
library.
|
|
37
|
+
|
|
38
|
+
## Step 1: Scaffold the brand
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
npx muka-ui brand init $ARGUMENTS
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
This creates, prompting before overwriting anything that exists:
|
|
45
|
+
|
|
46
|
+
| Path | Contents |
|
|
47
|
+
|---|---|
|
|
48
|
+
| `brand/fonts.json` | Font families and weights for the `brand`, `plain`, `mono`, `script` roles |
|
|
49
|
+
| `brand/light.json` | Light-mode colour aliases (78 tokens) |
|
|
50
|
+
| `brand/dark.json` | Dark-mode colour aliases |
|
|
51
|
+
| `brand/muka.brand.json` | Build manifest — your brand files plus package 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 one is not there.
|
|
55
|
+
|
|
56
|
+
The scaffolded files are copies of Muka's `wireframe` brand, so they are a
|
|
57
|
+
complete, valid, buildable starting point rather than empty stubs. Confirm the
|
|
58
|
+
build works before editing anything:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
npm run build:tokens
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
That must print `All theme combinations built successfully!` and produce
|
|
65
|
+
`styles/tokens-$ARGUMENTS-light.css` and `styles/tokens-$ARGUMENTS-dark.css`.
|
|
66
|
+
Fix any failure here before moving on — it is much easier to debug against
|
|
67
|
+
known-good token values.
|
|
68
|
+
|
|
69
|
+
## Step 2: Decide the brand identity
|
|
70
|
+
|
|
71
|
+
Before editing, settle these and write them down in the conversation:
|
|
72
|
+
|
|
73
|
+
| Decision | Feeds |
|
|
74
|
+
|---|---|
|
|
75
|
+
| Neutral ramp | `alias.color.neutral.*` — every surface, border, and text colour |
|
|
76
|
+
| Accent colour | `alias.color.accent.*` — buttons, links, focus rings, selection |
|
|
77
|
+
| Primary / secondary brand colours | `alias.color.brand.*` — logos, marketing accents |
|
|
78
|
+
| State colours | `alias.color.state.{success,warning,error,info}` |
|
|
79
|
+
| Brand and body typefaces | `alias.font.brand.family`, `alias.font.plain.family` |
|
|
80
|
+
|
|
81
|
+
Pick a **hue-matched pair** of primitive ramps for light and dark: light mode
|
|
82
|
+
uses `{color.<name>.N}`, dark mode uses `{color.<name>dark.N}`. Ask the user for
|
|
83
|
+
the brand's colours if they have not supplied them; do not invent a palette.
|
|
84
|
+
|
|
85
|
+
## Step 3: Edit the colour aliases
|
|
86
|
+
|
|
87
|
+
Edit `brand/light.json`. Every value is a **reference to a T1 primitive**, never
|
|
88
|
+
a raw hex — that is what keeps the ramp coherent and lets dark mode mirror it:
|
|
89
|
+
|
|
90
|
+
```json
|
|
91
|
+
"neutral": {
|
|
92
|
+
"1": { "$type": "color", "$value": "{color.slate.1}" },
|
|
93
|
+
"12": { "$type": "color", "$value": "{color.slate.12}" }
|
|
94
|
+
},
|
|
95
|
+
"accent": {
|
|
96
|
+
"default": { "$type": "color", "$value": "{color.violet.9}" },
|
|
97
|
+
"hover": { "$type": "color", "$value": "{color.violet.10}" },
|
|
98
|
+
"pressed": { "$type": "color", "$value": "{color.violet.11}" },
|
|
99
|
+
"contrast": { "$type": "color", "$value": "{color.violet.12}" },
|
|
100
|
+
"muted": { "$type": "color", "$value": "{color.violet.8}" }
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Then mirror it in `brand/dark.json` using the `Dark` ramps —
|
|
105
|
+
`{color.slateDark.1}`, `{color.violetDark.9}`. The suffix is **camelCase
|
|
106
|
+
`Dark`**, and references are case-sensitive: `{color.slatedark.1}` resolves to
|
|
107
|
+
nothing. Keep the **same step numbers** in both files; the ramps are designed so
|
|
108
|
+
equal steps read as equal emphasis in either mode.
|
|
109
|
+
|
|
110
|
+
Rules that matter:
|
|
111
|
+
|
|
112
|
+
- **Reference primitives, never hex.** A raw hex silently opts that token out of
|
|
113
|
+
the system and will not have a dark-mode counterpart.
|
|
114
|
+
- **Keep every key.** Deleting a token leaves the semantic layer resolving to
|
|
115
|
+
the base alias value, which is rarely what you want. Repoint it instead.
|
|
116
|
+
- **Do not edit anything above T2.** Semantics and component tokens come from
|
|
117
|
+
the package and are overwritten on every upgrade.
|
|
118
|
+
- Only `alias.*` belongs in these files.
|
|
119
|
+
|
|
120
|
+
Available palettes and the meaning of each step are in
|
|
121
|
+
[`reference.md`](reference.md).
|
|
122
|
+
|
|
123
|
+
## Step 4: Set the typography
|
|
124
|
+
|
|
125
|
+
Edit `brand/fonts.json`. The `family` values must be the **exact `@font-face`
|
|
126
|
+
family name** that will be loaded, because the generated CSS passes the literal
|
|
127
|
+
through to `font-family`.
|
|
128
|
+
|
|
129
|
+
- **Reusing a font Muka already bundles** (Funnel Display, Funnel Sans, Red Hat
|
|
130
|
+
Display, Red Hat Text, Quicksand, IBM Plex Sans, Lora, Yesteryear) — import
|
|
131
|
+
that brand's fonts file and you are done:
|
|
132
|
+
```ts
|
|
133
|
+
import '@revikornmann/muka-ui/styles/fonts-muka.css';
|
|
134
|
+
```
|
|
135
|
+
- **Using a system font** (Helvetica, Arial, Menlo, Georgia, …) — nothing to
|
|
136
|
+
load.
|
|
137
|
+
- **Bringing your own font** — self-host it with your own `@font-face` under the
|
|
138
|
+
exact family name you put in `fonts.json`. Do not use a Google Fonts `<link>`:
|
|
139
|
+
it breaks offline and air-gapped installs and adds a render-blocking request.
|
|
140
|
+
Muka's own font pipeline is not available to consumer brands, so this
|
|
141
|
+
`@font-face` block is yours to own.
|
|
142
|
+
|
|
143
|
+
## Step 5: Build and wire up the CSS
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
npm run build:tokens
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
Import your brand CSS **after** Muka's base and component styles so your `:root`
|
|
150
|
+
block wins the cascade:
|
|
151
|
+
|
|
152
|
+
```ts
|
|
153
|
+
import '@revikornmann/muka-ui/styles/base.css';
|
|
154
|
+
import './styles/tokens-acme-light.css';
|
|
155
|
+
import '@revikornmann/muka-ui/styles/fonts-muka.css'; // or your own @font-face
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Do **not** import `@revikornmann/muka-ui/styles` as well — that bundle contains
|
|
159
|
+
the full muka-light token set and, depending on import order, will fight your
|
|
160
|
+
brand. Use `base.css` instead, which is the component and reset layer only.
|
|
161
|
+
|
|
162
|
+
There are no `[data-brand]` / `[data-theme]` selectors; to toggle light/dark at
|
|
163
|
+
runtime, swap the stylesheet rather than importing both:
|
|
164
|
+
|
|
165
|
+
```ts
|
|
166
|
+
link.href = `/styles/tokens-acme-${mode}.css`;
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
## Step 6: Rebuild on every Muka upgrade
|
|
170
|
+
|
|
171
|
+
Your brand CSS is generated against the package's primitives, semantics, and
|
|
172
|
+
component tokens, so it goes stale when Muka publishes new ones. Add the build
|
|
173
|
+
to the existing pipeline so it cannot be forgotten:
|
|
174
|
+
|
|
175
|
+
```json
|
|
176
|
+
"scripts": {
|
|
177
|
+
"build": "npm run build:tokens && <your existing build>",
|
|
178
|
+
"postinstall": "npm run build:tokens"
|
|
179
|
+
}
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
Commit `brand/**`. Generated CSS under `styles/tokens-*.css` can be committed or
|
|
183
|
+
gitignored — commit it if your host does not run a build step.
|
|
184
|
+
|
|
185
|
+
## Verify
|
|
186
|
+
|
|
187
|
+
- `styles/tokens-$ARGUMENTS-light.css` and `-dark.css` exist and were rebuilt
|
|
188
|
+
after your last edit.
|
|
189
|
+
- Neither file contains `undefined` — that means an unresolved `{reference}`,
|
|
190
|
+
usually a typo'd primitive name.
|
|
191
|
+
- Your accent colour appears as a real value:
|
|
192
|
+
```bash
|
|
193
|
+
grep -- '--alias-color-accent-default' styles/tokens-$ARGUMENTS-light.css
|
|
194
|
+
```
|
|
195
|
+
- A primary `<Button>` renders in your accent colour and body text in your
|
|
196
|
+
typeface, in both light and dark.
|
|
197
|
+
- Toggling to dark mode changes surfaces without leaving light-mode text
|
|
198
|
+
unreadable.
|
|
199
|
+
|
|
200
|
+
## Next
|
|
201
|
+
|
|
202
|
+
- `/push-to-figma` — publish this brand to Figma as variables, so designers can
|
|
203
|
+
design in your brand.
|
|
204
|
+
- `/figma-to-code` — turn a Figma link into a screen built from Muka components.
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
# Brand token reference
|
|
2
|
+
|
|
3
|
+
Everything you need while editing `brand/light.json`, `brand/dark.json`, and
|
|
4
|
+
`brand/fonts.json`. The authoritative values live in
|
|
5
|
+
`node_modules/@revikornmann/muka-ui/tokens/t1-primitives/color.json`.
|
|
6
|
+
|
|
7
|
+
## Available primitive palettes
|
|
8
|
+
|
|
9
|
+
Each palette is a 12-step ramp. Light-mode references use the base name; dark
|
|
10
|
+
mode appends **camelCase `Dark`** (`{color.violet.9}` → `{color.violetDark.9}`).
|
|
11
|
+
References are case-sensitive.
|
|
12
|
+
|
|
13
|
+
**Neutrals** — `gray`, `mauve`, `slate`, `sage`, `olive`, `sand`
|
|
14
|
+
|
|
15
|
+
**Colours** — `tomato`, `red`, `ruby`, `crimson`, `pink`, `plum`, `purple`,
|
|
16
|
+
`violet`, `iris`, `indigo`, `blue`, `cyan`, `teal`, `jade`, `green`, `grass`,
|
|
17
|
+
`bronze`, `gold`, `brown`, `orange`, `amber`, `yellow`, `lime`, `mint`, `sky`
|
|
18
|
+
|
|
19
|
+
**Absolutes** — `white`, `black`, and the transparency ramps `black-alpha`,
|
|
20
|
+
`white-alpha`
|
|
21
|
+
|
|
22
|
+
**Hued neutral alphas** — `mauveA`, `grayA`, `sandA`, `sageA` (and
|
|
23
|
+
`mauveDarkA`, `grayDarkA`, `sandDarkA`, `sageDarkA`) back
|
|
24
|
+
`alias.color.neutral.alphaHued.*`, which is used for overlays and scrims that
|
|
25
|
+
must tint rather than cover. Match these to whichever neutral ramp you chose.
|
|
26
|
+
|
|
27
|
+
Every palette has a dark counterpart except `white`, `black`, and the alpha
|
|
28
|
+
ramps, which are mode-independent.
|
|
29
|
+
|
|
30
|
+
## What each step in a 12-step ramp is for
|
|
31
|
+
|
|
32
|
+
| Steps | Use |
|
|
33
|
+
|---|---|
|
|
34
|
+
| 1–2 | App and component backgrounds |
|
|
35
|
+
| 3–5 | Subtle backgrounds: hover, selected, muted fills |
|
|
36
|
+
| 6–8 | Borders and separators (8 is the strongest border / focus ring) |
|
|
37
|
+
| 9–10 | Solid fills — 9 is the palette's most saturated step, 10 is its hover |
|
|
38
|
+
| 11 | Low-contrast text, and text on light backgrounds |
|
|
39
|
+
| 12 | High-contrast text and headings |
|
|
40
|
+
|
|
41
|
+
Pick `accent.default` at step **9**, `hover` at **10**, `pressed` at **11**, and
|
|
42
|
+
`contrast` at **12** unless you have a reason not to. This pattern is what every
|
|
43
|
+
shipped brand uses.
|
|
44
|
+
|
|
45
|
+
## Token groups in `light.json` / `dark.json`
|
|
46
|
+
|
|
47
|
+
78 tokens across five groups. All are `$type: "color"`.
|
|
48
|
+
|
|
49
|
+
### `alias.color.neutral`
|
|
50
|
+
|
|
51
|
+
- `1`–`12` — the neutral ramp. Drives every surface level, border, and text
|
|
52
|
+
colour in the semantic layer, so this choice has the widest visual effect of
|
|
53
|
+
anything in the file.
|
|
54
|
+
- `alphaHued.1`–`12` — translucent neutrals for overlays and scrims.
|
|
55
|
+
|
|
56
|
+
### `alias.color.brand`
|
|
57
|
+
|
|
58
|
+
- `primary.{regular,contrast,muted}`
|
|
59
|
+
- `secondary.{regular,contrast,muted}`
|
|
60
|
+
|
|
61
|
+
Brand identity colours. Used for marketing surfaces and accents rather than
|
|
62
|
+
ordinary controls — controls read from `accent`.
|
|
63
|
+
|
|
64
|
+
### `alias.color.accent`
|
|
65
|
+
|
|
66
|
+
- `{default,hover,pressed,contrast,muted}`
|
|
67
|
+
- `inverse.{default,hover,pressed,contrast,muted}`
|
|
68
|
+
|
|
69
|
+
The interactive colour: primary buttons, links, focus rings, selection,
|
|
70
|
+
active navigation. `inverse` is the same role on top of an accent-filled
|
|
71
|
+
surface, so it usually runs from step 1 up to `white`.
|
|
72
|
+
|
|
73
|
+
If you only change one thing, change this.
|
|
74
|
+
|
|
75
|
+
### `alias.color.state`
|
|
76
|
+
|
|
77
|
+
For each of `success`, `warning`, `error`, `info`:
|
|
78
|
+
|
|
79
|
+
- `{contrast,default,muted}`
|
|
80
|
+
- `surface.{level0,level1,level2,level3}`
|
|
81
|
+
|
|
82
|
+
Keep the hues conventional — green for success, red for error, amber for
|
|
83
|
+
warning. `default` is the solid step 9, `contrast` the readable step 11, `muted`
|
|
84
|
+
a step 3 fill, and the `surface` levels are the elevation ramp for banners and
|
|
85
|
+
alerts.
|
|
86
|
+
|
|
87
|
+
### `alias.color.conversation`
|
|
88
|
+
|
|
89
|
+
For each of `own`, `peer`, `agent`:
|
|
90
|
+
|
|
91
|
+
- `surface.{default,raised}`
|
|
92
|
+
- `border`
|
|
93
|
+
|
|
94
|
+
Plus `meta` for timestamps and read receipts. These back the chat components. If
|
|
95
|
+
your app has no chat surface, leave them as scaffolded — they still need to
|
|
96
|
+
resolve.
|
|
97
|
+
|
|
98
|
+
## `fonts.json` roles
|
|
99
|
+
|
|
100
|
+
| Role | Used for |
|
|
101
|
+
|---|---|
|
|
102
|
+
| `brand` | Headings, buttons, labels — the expressive typeface |
|
|
103
|
+
| `plain` | Body copy and UI text — the readable typeface |
|
|
104
|
+
| `mono` | Code, numeric tables, anything needing fixed advance |
|
|
105
|
+
| `script` | Decorative accents only |
|
|
106
|
+
|
|
107
|
+
Each role has `family` plus a `weight` map. `brand` and `plain` carry
|
|
108
|
+
`regular` / `medium` / `semibold` / `bold`; `mono` carries `regular` / `bold`;
|
|
109
|
+
`script` is `family` only.
|
|
110
|
+
|
|
111
|
+
Weights are CSS numerics as strings (`"400"`, `"600"`). Only list weights the
|
|
112
|
+
font actually provides — naming a weight the file lacks makes the browser
|
|
113
|
+
synthesise it, which looks wrong at large sizes.
|
|
114
|
+
|
|
115
|
+
Pointing `brand` and `plain` at the same family is normal and is what the
|
|
116
|
+
`wireframe` and `fscl` brands do.
|
|
117
|
+
|
|
118
|
+
## Fonts Muka already bundles
|
|
119
|
+
|
|
120
|
+
Reference any of these and you get a real self-hosted face by importing the
|
|
121
|
+
matching `fonts-<brand>.css`:
|
|
122
|
+
|
|
123
|
+
| Family | Import this brand's fonts file |
|
|
124
|
+
|---|---|
|
|
125
|
+
| `Funnel Display`, `Funnel Sans` | `fonts-muka.css` |
|
|
126
|
+
| `Quicksand` | `fonts-grip.css` |
|
|
127
|
+
| `IBM Plex Sans`, `Lora` | `fonts-fscl.css` |
|
|
128
|
+
| `Red Hat Display`, `Red Hat Text` | `fonts-bouwplan.css` |
|
|
129
|
+
| `Yesteryear` (script role) | `fonts-muka.css`, `fonts-grip.css`, or `fonts-bouwplan.css` |
|
|
130
|
+
|
|
131
|
+
`fonts-wireframe.css` is empty — that brand is system fonts only.
|
|
132
|
+
|
|
133
|
+
System families need no loading: `Helvetica`, `Arial`, `Menlo`,
|
|
134
|
+
`Lucida Console`, `Times New Roman`, `Courier New`, `Georgia`, `Verdana`,
|
|
135
|
+
`Tahoma`, `Trebuchet MS`, `system-ui`, `ui-sans-serif`, `ui-serif`,
|
|
136
|
+
`ui-monospace`, and the generic `sans-serif` / `serif` / `monospace`.
|
|
137
|
+
|
|
138
|
+
## Generated CSS names
|
|
139
|
+
|
|
140
|
+
Token paths become custom properties by flattening on `-`:
|
|
141
|
+
|
|
142
|
+
| Token | Custom property |
|
|
143
|
+
|---|---|
|
|
144
|
+
| `alias.color.accent.default` | `--alias-color-accent-default` |
|
|
145
|
+
| `alias.color.neutral.3` | `--alias-color-neutral-3` |
|
|
146
|
+
| `alias.font.brand.family` | `--alias-font-brand-family` |
|
|
147
|
+
|
|
148
|
+
You will rarely reference these directly — components read T3/T4 properties like
|
|
149
|
+
`--color-action-default` and `--button-color-primary-background-default`, which
|
|
150
|
+
resolve through your aliases. Grep for `--alias-` only when debugging.
|
|
151
|
+
|
|
152
|
+
## Debugging
|
|
153
|
+
|
|
154
|
+
| Symptom | Cause |
|
|
155
|
+
|---|---|
|
|
156
|
+
| `undefined` in the generated CSS | An unresolved `{reference}` — usually a typo'd palette name or a missing `Dark` suffix |
|
|
157
|
+
| Dark mode looks identical to light | `dark.json` still references light ramps |
|
|
158
|
+
| Text unreadable on accent fills | `accent.contrast` is too close to `accent.default`; move it to step 12 or `white` |
|
|
159
|
+
| Fonts fall back to a system face | No `@font-face` is loaded for that family name, or the name does not match byte-for-byte |
|
|
160
|
+
| Colours unchanged after a rebuild | The brand CSS is imported before Muka's token bundle, so the bundle wins. Import `base.css` instead of `styles`, and your brand CSS last |
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: figma-to-code
|
|
3
|
+
description: Build a screen in this app from a Figma link, composing Muka UI components and design tokens instead of writing new styled markup.
|
|
4
|
+
disable-model-invocation: true
|
|
5
|
+
argument-hint: "[figma-url]"
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Figma link → Muka UI screen
|
|
9
|
+
|
|
10
|
+
Turn a Figma design into working code in **this app** by assembling it from Muka
|
|
11
|
+
UI components. `$ARGUMENTS` is the Figma URL.
|
|
12
|
+
|
|
13
|
+
The goal is assembly, not reproduction. A Figma frame drawn with the Muka UI
|
|
14
|
+
Figma Library is already made of Muka components, so the right output is those
|
|
15
|
+
same components with props — not a pixel-matched rebuild in bespoke CSS. If the
|
|
16
|
+
result is a pile of `<div>`s with hardcoded colours, the design was
|
|
17
|
+
re-implemented instead of mapped, and it will not follow brand or theme changes.
|
|
18
|
+
|
|
19
|
+
**Prerequisite:** `@revikornmann/muka-ui` is installed (`/setup-muka`) and a
|
|
20
|
+
Figma MCP server is connected.
|
|
21
|
+
|
|
22
|
+
## Step 1: Read the design
|
|
23
|
+
|
|
24
|
+
Extract `fileKey` and `nodeId` from the URL:
|
|
25
|
+
|
|
26
|
+
- `figma.com/design/:fileKey/:fileName?node-id=:nodeId` — convert `-` to `:` in
|
|
27
|
+
the nodeId (`472-4248` → `472:4248`)
|
|
28
|
+
- `figma.com/design/:fileKey/branch/:branchKey/…` — use `branchKey` as the
|
|
29
|
+
fileKey
|
|
30
|
+
|
|
31
|
+
Then pull the design context:
|
|
32
|
+
|
|
33
|
+
```
|
|
34
|
+
get_code_connect_map(fileKey, nodeId) # FIRST — Figma node → real component names
|
|
35
|
+
get_design_context(fileKey, nodeId) # structure, tokens, variants
|
|
36
|
+
get_screenshot(fileKey, nodeId) # visual reference to check yourself against
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Read `get_code_connect_map` **first**. Muka publishes Code Connect mappings for
|
|
40
|
+
its components, so this is what tells you a node is a Muka `Button` rather than a
|
|
41
|
+
rounded rectangle with a label. Treat its answer as authoritative over your own
|
|
42
|
+
reading of the layers.
|
|
43
|
+
|
|
44
|
+
Treat `get_design_context` output as a **reference, not final code**. It
|
|
45
|
+
describes the design in generic terms; your job is the translation.
|
|
46
|
+
|
|
47
|
+
## Step 2: Inventory what Muka already provides
|
|
48
|
+
|
|
49
|
+
Before writing any JSX, find out what exists. In order of reliability:
|
|
50
|
+
|
|
51
|
+
1. **Storybook MCP**, if Muka's Storybook is running — the component list and
|
|
52
|
+
live prop tables are the most accurate source there is.
|
|
53
|
+
2. **The published Storybook** at <https://muka.kornmann.com> — component APIs,
|
|
54
|
+
Playgrounds, and usage patterns.
|
|
55
|
+
3. **The installed types**:
|
|
56
|
+
```bash
|
|
57
|
+
grep 'export' node_modules/@revikornmann/muka-ui/dist/types/components/index.d.ts
|
|
58
|
+
```
|
|
59
|
+
4. **`npx muka-ui components -v`** — names and prop summaries from the package
|
|
60
|
+
manifest.
|
|
61
|
+
5. **`docs/muka-ui-guidelines.md`** in this repo, if `npx muka-ui init` has run.
|
|
62
|
+
|
|
63
|
+
Write out the mapping before you build, so the gaps are visible up front:
|
|
64
|
+
|
|
65
|
+
| Figma layer | Muka component | Props |
|
|
66
|
+
|---|---|---|
|
|
67
|
+
| "Primary CTA" | `Button` | `variant="primary" size="md"` |
|
|
68
|
+
| "Search field" | `Input` | `placeholder`, leading icon slot |
|
|
69
|
+
| "Nav bar" | `TopBar` | title, actions |
|
|
70
|
+
|
|
71
|
+
## Step 3: Compose the screen
|
|
72
|
+
|
|
73
|
+
Build from the outside in: page shell, then regions, then controls.
|
|
74
|
+
|
|
75
|
+
- **Use Muka components for anything Muka has.** Reach for a raw element only
|
|
76
|
+
when nothing fits.
|
|
77
|
+
- **Compose, don't fork.** Prefer slots and composition over copying a
|
|
78
|
+
component's source to tweak it. A forked component stops receiving upgrades
|
|
79
|
+
and brand changes.
|
|
80
|
+
- **Only Muka's CSS custom properties for styling.** For app-specific layout,
|
|
81
|
+
read T3 semantic properties:
|
|
82
|
+
```css
|
|
83
|
+
.checkout-summary {
|
|
84
|
+
background-color: var(--color-surface-level1);
|
|
85
|
+
color: var(--color-text-default-default);
|
|
86
|
+
padding: var(--spacing-4);
|
|
87
|
+
border-radius: var(--radius-md);
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
Never paste a hex, px type size, or radius out of Figma. Those values belong to
|
|
91
|
+
one brand in one theme; the token survives both.
|
|
92
|
+
- **Match the design's intent, not its pixels.** If Figma shows 15px of padding
|
|
93
|
+
and the nearest token is 16, use the token. Report differences larger than a
|
|
94
|
+
step rather than hardcoding around them.
|
|
95
|
+
- **Mobile first.** Muka is designed mobile-up with the desktop breakpoint at
|
|
96
|
+
`1024px`. Build the narrow layout first, then enhance.
|
|
97
|
+
|
|
98
|
+
## Step 4: Handle what Muka does not have
|
|
99
|
+
|
|
100
|
+
When a design needs something Muka does not ship, say so explicitly rather than
|
|
101
|
+
quietly inventing a lookalike — a bespoke component that mimics a Muka one is
|
|
102
|
+
the most expensive outcome, because it looks correct until the brand changes.
|
|
103
|
+
|
|
104
|
+
1. Re-check whether composing existing primitives covers it.
|
|
105
|
+
2. If not, build it in **this repo** (not in Muka) styled entirely with Muka's
|
|
106
|
+
token custom properties, so it tracks brand and theme.
|
|
107
|
+
3. Tell the user it is app-local and worth requesting upstream at
|
|
108
|
+
<https://github.com/revikornmann/muka/issues> if it is generic.
|
|
109
|
+
|
|
110
|
+
## Step 5: Verify
|
|
111
|
+
|
|
112
|
+
- The screen renders and type-checks.
|
|
113
|
+
- **No hardcoded colours, type sizes, or radii.** Grep your diff for `#`,
|
|
114
|
+
`rgb(`, and `px` and justify every remaining hit.
|
|
115
|
+
- Compare against `get_screenshot` for structure, hierarchy, and spacing rhythm.
|
|
116
|
+
- **Switch theme and confirm nothing breaks.** Load the dark stylesheet and
|
|
117
|
+
re-check: anything that does not react was hardcoded. This is the single most
|
|
118
|
+
effective check that the mapping was done properly.
|
|
119
|
+
- Keyboard reachability: every interactive element is tabbable with a visible
|
|
120
|
+
focus ring.
|
|
121
|
+
- If this repo has a custom brand, confirm the screen picks it up.
|
|
122
|
+
|
|
123
|
+
## Next
|
|
124
|
+
|
|
125
|
+
- `/add-brand` — if the design is in a brand this repo does not have yet.
|
|
126
|
+
- `/pull-from-figma` — if a designer changed brand colours in Figma and the code
|
|
127
|
+
needs to catch up.
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: pull-from-figma
|
|
3
|
+
description: Pull brand colour and font changes a designer made in Figma back into this repo's brand token files.
|
|
4
|
+
disable-model-invocation: true
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Pull brand changes from Figma
|
|
8
|
+
|
|
9
|
+
A designer retuned your brand's colours in Figma; bring those edits back into
|
|
10
|
+
`brand/light.json`, `brand/dark.json`, and `brand/fonts.json`.
|
|
11
|
+
|
|
12
|
+
**Direction:** Figma → Code. **Scope:** only your brand's `alias/*` tokens.
|
|
13
|
+
Nothing is created or deleted — existing `$value` fields are updated in place.
|
|
14
|
+
|
|
15
|
+
## Prerequisites
|
|
16
|
+
|
|
17
|
+
1. This repo has a custom brand with modes pushed to Figma — run `/add-brand`
|
|
18
|
+
then `/push-to-figma` first.
|
|
19
|
+
2. **Figma Console MCP** is configured and the Desktop Bridge plugin is running.
|
|
20
|
+
One-time setup:
|
|
21
|
+
`node_modules/@revikornmann/muka-ui/docs/consumers/figma-console-mcp.md`
|
|
22
|
+
(also online at
|
|
23
|
+
<https://github.com/revikornmann/muka/blob/main/docs/consumers/figma-console-mcp.md>).
|
|
24
|
+
|
|
25
|
+
## Why only the alias layer
|
|
26
|
+
|
|
27
|
+
Your repo owns exactly one layer of the token system. Semantics and component
|
|
28
|
+
tokens come from the installed package and are overwritten on the next upgrade,
|
|
29
|
+
so pulling them in would produce changes that silently disappear. If a designer
|
|
30
|
+
changed `color/surface/level1` or a `button/*` variable, that is a **library**
|
|
31
|
+
change: it belongs in a pull request against
|
|
32
|
+
<https://github.com/revikornmann/muka>, and you should say so rather than writing
|
|
33
|
+
it into `brand/`.
|
|
34
|
+
|
|
35
|
+
## Step 1: Confirm the bridge is live
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
figma_get_status { probe: true }
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Step 2: Find your brand's modes
|
|
42
|
+
|
|
43
|
+
Look collections and modes up by name — never hardcode IDs:
|
|
44
|
+
|
|
45
|
+
```javascript
|
|
46
|
+
const collections = await figma.variables.getLocalVariableCollectionsAsync();
|
|
47
|
+
const theme = collections.find((c) => c.name === 'Theme');
|
|
48
|
+
const light = theme.modes.find((m) => m.name === 'Acme Light').modeId;
|
|
49
|
+
const dark = theme.modes.find((m) => m.name === 'Acme Dark').modeId;
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Step 3: Read the alias variables
|
|
53
|
+
|
|
54
|
+
Read every variable whose name starts with `alias/`, taking the value for your
|
|
55
|
+
two modes only. Ignore all other modes — they are other brands.
|
|
56
|
+
|
|
57
|
+
## Step 4: Resolve each value back to a token reference
|
|
58
|
+
|
|
59
|
+
- **Variable alias** (the normal case, pointing into Primitives): resolve the
|
|
60
|
+
target variable's name and convert slashes to dots.
|
|
61
|
+
`color/violet/9` → `{color.violet.9}`
|
|
62
|
+
- **Concrete string** (font family or weight): keep the string, converting
|
|
63
|
+
Figma's style names back to CSS numerics — `SemiBold` → `600`, `Bold` → `700`,
|
|
64
|
+
`Medium` → `500`, `Regular` → `400`.
|
|
65
|
+
- **Raw colour value**: this is a problem, not a value to pull. It means the
|
|
66
|
+
variable was detached from the ramp. Report it and re-push that token as an
|
|
67
|
+
alias instead of writing a hex into the token files, which would opt it out of
|
|
68
|
+
the system permanently.
|
|
69
|
+
|
|
70
|
+
## Step 5: Map to files
|
|
71
|
+
|
|
72
|
+
| Variable prefix | Target file |
|
|
73
|
+
|---|---|
|
|
74
|
+
| `alias/color/*` read at your **light** mode | `brand/light.json` |
|
|
75
|
+
| `alias/color/*` read at your **dark** mode | `brand/dark.json` |
|
|
76
|
+
| `alias/font/*` | `brand/fonts.json` |
|
|
77
|
+
|
|
78
|
+
Figma slash-paths map to token dot-paths directly:
|
|
79
|
+
`alias/color/accent/default` → `alias.color.accent.default`.
|
|
80
|
+
|
|
81
|
+
## Step 6: Apply the diff
|
|
82
|
+
|
|
83
|
+
For each token that already exists in the target file:
|
|
84
|
+
|
|
85
|
+
1. Compare the current `$value` with the resolved Figma value.
|
|
86
|
+
2. **Show the user the full diff before writing anything.**
|
|
87
|
+
3. Update only `$value`. Never touch `$type`, and preserve the `$schema` entry
|
|
88
|
+
and key order so the diff stays reviewable.
|
|
89
|
+
|
|
90
|
+
Safety rules:
|
|
91
|
+
|
|
92
|
+
- Only tokens already present in the files are updated.
|
|
93
|
+
- No tokens are created or deleted. A variable in Figma with no counterpart in
|
|
94
|
+
the files is reported, not added — it usually means the designer added
|
|
95
|
+
something that needs a code-side decision first.
|
|
96
|
+
- A token missing from Figma is left alone, not blanked.
|
|
97
|
+
|
|
98
|
+
## Step 7: Rebuild and check
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
npm run build:tokens
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Then verify:
|
|
105
|
+
|
|
106
|
+
- No `undefined` in `styles/tokens-<brand>-*.css` — a failed reference resolution.
|
|
107
|
+
- Both light and dark still read correctly; a designer tuning light mode in
|
|
108
|
+
isolation is the usual way dark-mode contrast regresses.
|
|
109
|
+
- Muka components pick up the change in the app.
|
|
110
|
+
- The dark values reference `Dark` ramps (`{color.violetDark.9}`). If a dark
|
|
111
|
+
token came back pointing at a light ramp, the designer edited the wrong mode.
|
|
112
|
+
|
|
113
|
+
Commit `brand/**` with a message naming what the designer changed.
|
|
114
|
+
|
|
115
|
+
## Troubleshooting
|
|
116
|
+
|
|
117
|
+
| Symptom | Cause |
|
|
118
|
+
|---|---|
|
|
119
|
+
| Values come back as raw colours | The variable was detached from the ramp — re-push it as an alias |
|
|
120
|
+
| Everything appears unchanged | Reading the wrong modes; confirm the mode names match your brand |
|
|
121
|
+
| Dark values reference light ramps | The wrong Figma mode was edited |
|
|
122
|
+
| Semibold and bold pull the same weight | They were pushed as numerics and collapsed in Figma |
|
|
123
|
+
| `figma-console` tools absent | Session predates `.mcp.json`; approve via `/mcp` and restart |
|