@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.
- 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.css +4 -4
- package/dist/cjs/components/BottomBar/BottomBar.css +0 -3
- package/dist/cjs/components/Breadcrumb/Breadcrumb.css +26 -2
- 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 +4 -4
- package/dist/cjs/components/DocumentViewer/DocumentViewer.css +2 -2
- 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/EmptyState/EmptyState.css +8 -8
- package/dist/cjs/components/FAB/FAB.css +1 -1
- package/dist/cjs/components/FileUpload/FileUpload.css +10 -10
- 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 +14 -1
- package/dist/cjs/components/Icon/iconRegistry.js.map +1 -1
- package/dist/cjs/components/Input/Input.css +47 -10
- package/dist/cjs/components/Input/Input.js +14 -3
- package/dist/cjs/components/Input/Input.js.map +1 -1
- package/dist/cjs/components/Label/Label.css +1 -1
- package/dist/cjs/components/LicensePlateInput/LicensePlateInput.css +1 -1
- package/dist/cjs/components/Menu/Menu.css +124 -38
- package/dist/cjs/components/Menu/Menu.js +283 -25
- package/dist/cjs/components/Menu/Menu.js.map +1 -1
- package/dist/cjs/components/Pagination/Pagination.css +15 -15
- package/dist/cjs/components/PhotoUploader/PhotoUploader.css +4 -4
- package/dist/cjs/components/ProgressAccordeon/ProgressAccordeon.css +10 -6
- package/dist/cjs/components/ProgressAccordeon/ProgressAccordeon.js +27 -16
- package/dist/cjs/components/ProgressAccordeon/ProgressAccordeon.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 +7 -6
- package/dist/cjs/components/SearchInput/SearchInput.css +4 -4
- package/dist/cjs/components/Select/Select.css +2 -2
- package/dist/cjs/components/SmsOtpField/SmsOtpField.css +2 -2
- package/dist/cjs/components/SpecList/SpecList.css +8 -8
- package/dist/cjs/components/Spinner/Spinner.css +1 -1
- package/dist/cjs/components/SwipeActions/SwipeActions.css +6 -6
- package/dist/cjs/components/Table/Table.css +3 -3
- package/dist/cjs/components/Table/TablePagination.css +1 -1
- package/dist/cjs/components/Tabs/Tabs.css +6 -6
- package/dist/cjs/components/Textarea/Textarea.css +2 -2
- package/dist/cjs/components/Waveform/Waveform.css +1 -1
- package/dist/cjs/components/index.js +5 -3
- package/dist/cjs/components/index.js.map +1 -1
- package/dist/esm/components/ActionSheet/ActionSheet.css +4 -4
- package/dist/esm/components/BottomBar/BottomBar.css +0 -3
- package/dist/esm/components/Breadcrumb/Breadcrumb.css +26 -2
- 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 +4 -4
- package/dist/esm/components/DocumentViewer/DocumentViewer.css +2 -2
- 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/EmptyState/EmptyState.css +8 -8
- package/dist/esm/components/FAB/FAB.css +1 -1
- package/dist/esm/components/FileUpload/FileUpload.css +10 -10
- 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 +14 -1
- package/dist/esm/components/Icon/iconRegistry.js.map +1 -1
- package/dist/esm/components/Input/Input.css +47 -10
- package/dist/esm/components/Input/Input.js +14 -3
- package/dist/esm/components/Input/Input.js.map +1 -1
- package/dist/esm/components/Label/Label.css +1 -1
- package/dist/esm/components/LicensePlateInput/LicensePlateInput.css +1 -1
- package/dist/esm/components/Menu/Menu.css +124 -38
- package/dist/esm/components/Menu/Menu.js +284 -26
- package/dist/esm/components/Menu/Menu.js.map +1 -1
- package/dist/esm/components/Pagination/Pagination.css +15 -15
- package/dist/esm/components/PhotoUploader/PhotoUploader.css +4 -4
- package/dist/esm/components/ProgressAccordeon/ProgressAccordeon.css +10 -6
- package/dist/esm/components/ProgressAccordeon/ProgressAccordeon.js +27 -16
- package/dist/esm/components/ProgressAccordeon/ProgressAccordeon.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 +7 -6
- package/dist/esm/components/SearchInput/SearchInput.css +4 -4
- package/dist/esm/components/Select/Select.css +2 -2
- package/dist/esm/components/SmsOtpField/SmsOtpField.css +2 -2
- package/dist/esm/components/SpecList/SpecList.css +8 -8
- package/dist/esm/components/Spinner/Spinner.css +1 -1
- package/dist/esm/components/SwipeActions/SwipeActions.css +6 -6
- package/dist/esm/components/Table/Table.css +3 -3
- package/dist/esm/components/Table/TablePagination.css +1 -1
- package/dist/esm/components/Tabs/Tabs.css +6 -6
- package/dist/esm/components/Textarea/Textarea.css +2 -2
- package/dist/esm/components/Waveform/Waveform.css +1 -1
- package/dist/esm/components/index.js +1 -0
- package/dist/esm/components/index.js.map +1 -1
- package/dist/styles/components/ActionSheet.css +4 -4
- package/dist/styles/components/BottomBar.css +0 -3
- package/dist/styles/components/Breadcrumb.css +26 -2
- package/dist/styles/components/Combobox.css +116 -132
- package/dist/styles/components/ContextSelect.css +4 -4
- package/dist/styles/components/DocumentViewer.css +2 -2
- package/dist/styles/components/DropdownSelect.css +225 -0
- package/dist/styles/components/EmptyState.css +8 -8
- package/dist/styles/components/FAB.css +1 -1
- package/dist/styles/components/FileUpload.css +10 -10
- package/dist/styles/components/Input.css +47 -10
- package/dist/styles/components/Label.css +1 -1
- package/dist/styles/components/LicensePlateInput.css +1 -1
- package/dist/styles/components/Menu.css +124 -38
- package/dist/styles/components/Pagination.css +15 -15
- package/dist/styles/components/PhotoUploader.css +4 -4
- package/dist/styles/components/ProgressAccordeon.css +10 -6
- package/dist/styles/components/ProgressTracker.css +273 -22
- package/dist/styles/components/Scrollbar.css +7 -6
- package/dist/styles/components/SearchInput.css +4 -4
- package/dist/styles/components/Select.css +2 -2
- package/dist/styles/components/SmsOtpField.css +2 -2
- package/dist/styles/components/SpecList.css +8 -8
- package/dist/styles/components/Spinner.css +1 -1
- package/dist/styles/components/SwipeActions.css +6 -6
- package/dist/styles/components/Table.css +3 -3
- package/dist/styles/components/Tabs.css +6 -6
- package/dist/styles/components/Textarea.css +2 -2
- package/dist/styles/components/Typography.css +89 -0
- package/dist/styles/components/Waveform.css +1 -1
- package/dist/styles/index.css +1167 -462
- package/dist/styles/muka-dark.css +1167 -462
- package/dist/styles/muka-light.css +1167 -462
- package/dist/styles/tokens-bouwplan-dark.css +5 -4
- package/dist/styles/tokens-bouwplan-light.css +5 -4
- package/dist/styles/tokens-fscl-dark.css +25 -24
- package/dist/styles/tokens-fscl-light.css +25 -24
- package/dist/styles/tokens-grip-dark.css +4 -3
- package/dist/styles/tokens-grip-light.css +4 -3
- package/dist/styles/tokens-muka-dark.css +4 -3
- package/dist/styles/tokens-muka-light.css +4 -3
- package/dist/styles/tokens-wireframe-dark.css +49 -48
- package/dist/styles/tokens-wireframe-light.css +49 -48
- package/dist/styles/wireframe-dark.css +1212 -507
- package/dist/styles/wireframe-light.css +1212 -507
- 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/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/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 +42 -2
- package/dist/types/components/Menu/Menu.d.ts.map +1 -1
- package/dist/types/components/ProgressAccordeon/ProgressAccordeon.d.ts +17 -12
- package/dist/types/components/ProgressAccordeon/ProgressAccordeon.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/index.d.ts +1 -0
- 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 +5 -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 +39 -17
- 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 +8 -3
|
@@ -9,6 +9,9 @@ version.
|
|
|
9
9
|
Muka UI is a **public npm package** — installing it needs no `.npmrc`, registry
|
|
10
10
|
configuration, or auth token.
|
|
11
11
|
|
|
12
|
+
For the wider picture — brands, Figma, the skills — start at
|
|
13
|
+
[`README.md`](README.md).
|
|
14
|
+
|
|
12
15
|
## 1. Install
|
|
13
16
|
|
|
14
17
|
```bash
|
|
@@ -22,29 +25,80 @@ import '@revikornmann/muka-ui/styles'; // default muka-light — muka fonts incl
|
|
|
22
25
|
import { Button } from '@revikornmann/muka-ui';
|
|
23
26
|
```
|
|
24
27
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
## 2. Pick a brand and theme
|
|
29
|
+
|
|
30
|
+
Muka ships five brands — `muka`, `wireframe`, `grip`, `fscl`, `bouwplan` — each in
|
|
31
|
+
light and dark, for **ten themes**. How you load one depends on the brand.
|
|
32
|
+
|
|
33
|
+
**Pre-bundled (muka and wireframe).** `/styles` is `muka-light`; three
|
|
34
|
+
alternatives are drop-in replacements for it. Each is self-contained: base
|
|
35
|
+
styles, tokens, every component's CSS, and that brand's self-hosted fonts.
|
|
36
|
+
|
|
37
|
+
```ts
|
|
38
|
+
import '@revikornmann/muka-ui/styles'; // muka-light
|
|
39
|
+
import '@revikornmann/muka-ui/styles/muka-dark.css';
|
|
40
|
+
import '@revikornmann/muka-ui/styles/wireframe-light.css';
|
|
41
|
+
import '@revikornmann/muka-ui/styles/wireframe-dark.css';
|
|
42
|
+
```
|
|
30
43
|
|
|
31
|
-
|
|
32
|
-
|
|
44
|
+
**Composed (grip, fscl, bouwplan).** No pre-bundled file, so combine three
|
|
45
|
+
imports — base styles, the brand's raw token CSS, and the brand's fonts. The raw
|
|
46
|
+
token CSS carries no `@font-face`, which is why the fonts import is separate:
|
|
33
47
|
|
|
34
48
|
```ts
|
|
49
|
+
import '@revikornmann/muka-ui/styles/base.css';
|
|
35
50
|
import '@revikornmann/muka-ui/styles/tokens-bouwplan-light.css';
|
|
36
51
|
import '@revikornmann/muka-ui/styles/fonts-bouwplan.css';
|
|
37
52
|
```
|
|
38
53
|
|
|
54
|
+
None of the five fitting? Build your own brand — see [`brand.md`](brand.md).
|
|
55
|
+
|
|
56
|
+
### How theme selection actually works
|
|
57
|
+
|
|
58
|
+
Every token stylesheet declares its variables on `:root`. There are **no
|
|
59
|
+
`[data-brand]` or `[data-theme]` selectors in Muka's CSS**, so you select a theme
|
|
60
|
+
by **choosing which stylesheet loads**, and importing two means the last one
|
|
61
|
+
wins. Setting `data-brand` / `data-theme` attributes has no effect.
|
|
62
|
+
|
|
63
|
+
For a runtime light/dark toggle, swap a `<link>` instead of importing both:
|
|
64
|
+
|
|
65
|
+
```html
|
|
66
|
+
<link id="muka-theme" rel="stylesheet" href="/styles/tokens-muka-light.css" />
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
```ts
|
|
70
|
+
document.getElementById('muka-theme').href =
|
|
71
|
+
`/styles/tokens-${brand}-${mode}.css`;
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Copy the token CSS you need into your static/public directory (or let your
|
|
75
|
+
bundler emit it at a stable URL) so those hrefs resolve. Muka's own Storybook
|
|
76
|
+
switches between all ten themes exactly this way — see
|
|
77
|
+
`.storybook/ThemeDecorator.ts` in the repo.
|
|
78
|
+
|
|
79
|
+
### `data-layout`: the one attribute that does do something
|
|
80
|
+
|
|
81
|
+
Brand and theme are not attributes, but **layout density is**. Section padding
|
|
82
|
+
and container gaps respond to viewport width through `@media` blocks, and
|
|
83
|
+
`data-layout` forces one of those steps regardless of viewport:
|
|
84
|
+
|
|
39
85
|
```html
|
|
40
|
-
<
|
|
86
|
+
<div data-layout="desktop">…</div>
|
|
41
87
|
```
|
|
42
88
|
|
|
89
|
+
Accepted values are `tablet`, `desktop`, and `widescreen`; omit the attribute to
|
|
90
|
+
let the media queries decide. Use it when a region should keep desktop spacing
|
|
91
|
+
inside a narrow container (or the reverse) — it only overrides
|
|
92
|
+
`--section-padding-*` and `--container-gap-*`, never colours or type.
|
|
93
|
+
|
|
94
|
+
If your app only ever needs one theme, a plain import is simpler and this does
|
|
95
|
+
not apply.
|
|
96
|
+
|
|
43
97
|
### Fonts come from Muka — do not load them yourself
|
|
44
98
|
|
|
45
99
|
Muka self-hosts every brand's fonts and ships them as `@font-face` in
|
|
46
|
-
`styles/fonts-<brand>.css
|
|
47
|
-
CDN
|
|
100
|
+
`styles/fonts-<brand>.css`, backed by bundled WOFF2, so they work offline with no
|
|
101
|
+
CDN. Importing that one file is all the wiring you need:
|
|
48
102
|
|
|
49
103
|
- **Do not** load these fonts via `next/font`, a Google Fonts `<link>`, or any
|
|
50
104
|
other loader — you'd ship the bytes twice and risk a name mismatch.
|
|
@@ -52,7 +106,7 @@ CDN). Importing that one file is all the wiring you need:
|
|
|
52
106
|
font-family names in Muka's tokens are the exact `@font-face` family names, so
|
|
53
107
|
overriding them only breaks the resolution.
|
|
54
108
|
|
|
55
|
-
##
|
|
109
|
+
## 3. Add the auto-update workflow
|
|
56
110
|
|
|
57
111
|
Copy the shipped template into your repo so it stays current with Muka releases:
|
|
58
112
|
|
|
@@ -77,7 +131,10 @@ The workflow auto-detects your package manager from the lockfile
|
|
|
77
131
|
> rejecting a just-published version). Match the value to the pnpm/yarn version
|
|
78
132
|
> you use locally (e.g. `lockfileVersion: 9.0` → pnpm 9).
|
|
79
133
|
|
|
80
|
-
|
|
134
|
+
Muka is under active development, so a bump can change component behaviour or
|
|
135
|
+
appearance. Keep CI checks on the update PR rather than trusting it blindly.
|
|
136
|
+
|
|
137
|
+
## 4. Register as a consumer
|
|
81
138
|
|
|
82
139
|
Add `owner/repo` to Muka's [`.github/consumers.txt`](../../.github/consumers.txt)
|
|
83
140
|
so the release pipeline dispatches updates here. The `/setup-muka` skill opens
|
|
@@ -85,3 +142,32 @@ this PR automatically; merge it to enable automatic updates.
|
|
|
85
142
|
|
|
86
143
|
The Muka `CONSUMER_DISPATCH_TOKEN` PAT must have **write** access to this repo
|
|
87
144
|
for the `repository_dispatch` to succeed.
|
|
145
|
+
|
|
146
|
+
## 5. Give your agents the house rules
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
npx muka-ui init
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
Writes `AGENTS.md`, `CLAUDE.md`, and `docs/muka-ui-guidelines.md` into your repo
|
|
153
|
+
(prompting before overwriting any of them), so agents working here compose Muka
|
|
154
|
+
components and use token custom properties instead of inventing markup and
|
|
155
|
+
hardcoding values. It also warns about styling libraries that conflict with Muka.
|
|
156
|
+
|
|
157
|
+
`AGENTS.md` holds the rules, because that filename is the vendor-neutral
|
|
158
|
+
convention most agents read. `CLAUDE.md` is a few lines pointing at it, so Claude
|
|
159
|
+
Code finds them too without a second copy that can drift.
|
|
160
|
+
|
|
161
|
+
## Verify
|
|
162
|
+
|
|
163
|
+
- `npm ls @revikornmann/muka-ui` shows a semver version resolved from npmjs.
|
|
164
|
+
- The app builds and Muka components render with brand tokens.
|
|
165
|
+
- A component's computed `background-color` resolves to a real colour rather than
|
|
166
|
+
falling back — that is the check that the token CSS actually loaded.
|
|
167
|
+
- `.github/workflows/update-muka.yml` exists and is valid YAML.
|
|
168
|
+
|
|
169
|
+
## Next
|
|
170
|
+
|
|
171
|
+
- [`brand.md`](brand.md) — build your own brand
|
|
172
|
+
- [`skills.md`](skills.md) — every shipped agent skill
|
|
173
|
+
- <https://muka.kornmann.com> — component APIs, Playgrounds, token docs
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# Agent skills shipped with Muka UI
|
|
2
|
+
|
|
3
|
+
`@revikornmann/muka-ui` ships agent skills inside the package. They turn the
|
|
4
|
+
multi-step jobs around a design system — installing it, branding it, translating
|
|
5
|
+
a design into code, syncing tokens with Figma — into one command each.
|
|
6
|
+
|
|
7
|
+
## Installing them
|
|
8
|
+
|
|
9
|
+
Agents discover skills under `.claude/skills/`, never inside `node_modules/`, so
|
|
10
|
+
the package ships them and the CLI copies them in:
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
npx muka-ui install-skill # install all of them
|
|
14
|
+
npx muka-ui install-skill --list # see what's available first
|
|
15
|
+
npx muka-ui install-skill add-brand figma-to-code # install specific ones
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Restart your agent afterwards so it picks up the new slash commands. Re-run the
|
|
19
|
+
same command after a Muka upgrade to refresh them; it skips anything already
|
|
20
|
+
identical and prompts before overwriting local edits.
|
|
21
|
+
|
|
22
|
+
## Which agents can use them
|
|
23
|
+
|
|
24
|
+
The directory name is Claude's, but the contents are not: a skill is a plain
|
|
25
|
+
markdown file with YAML frontmatter, and `.claude/skills/` is scanned by **Claude
|
|
26
|
+
Code and Cursor** alike. For an agent that reads neither, the skills still work
|
|
27
|
+
as documentation — point it at `.claude/skills/<name>/SKILL.md` and it has the
|
|
28
|
+
same instructions, just without a slash command to trigger them.
|
|
29
|
+
|
|
30
|
+
Nothing else Muka ships is agent-specific. The tokens are CSS custom properties,
|
|
31
|
+
the components are React, and these consumer docs are prose — none of that cares
|
|
32
|
+
what is editing your repo. `npx muka-ui init` writes the house rules to
|
|
33
|
+
`AGENTS.md`, the vendor-neutral convention, and leaves a short `CLAUDE.md`
|
|
34
|
+
pointing at it.
|
|
35
|
+
|
|
36
|
+
## The skills
|
|
37
|
+
|
|
38
|
+
| Skill | What it does | Needs |
|
|
39
|
+
|---|---|---|
|
|
40
|
+
| `/setup-muka` | Installs the package, wires up styles and fonts, adds the release auto-update workflow, and registers your repo as a consumer. Start here. | — |
|
|
41
|
+
| `/add-brand` | Creates a custom brand in **your** repo that overrides Muka's brand layer, so every Muka component takes your colours and typography. Scaffolds the token files, explains the palette choices, and builds the CSS. | `/setup-muka` |
|
|
42
|
+
| `/figma-to-code` | Turns a Figma link into a working screen composed from Muka components and token custom properties — rather than a pixel-matched rebuild that ignores your brand. | A Figma MCP server |
|
|
43
|
+
| `/push-to-figma` | Publishes your brand's tokens into Figma as variables, so designers can design in your brand. Code → Figma. | `/add-brand` + Figma Console MCP |
|
|
44
|
+
| `/pull-from-figma` | Brings brand colour and font changes a designer made in Figma back into your token files. Figma → Code. | `/push-to-figma` + Figma Console MCP |
|
|
45
|
+
|
|
46
|
+
`/setup-muka` and `/add-brand` are the two most people need. The Figma pair
|
|
47
|
+
matters once designers and engineers are both editing the brand.
|
|
48
|
+
|
|
49
|
+
## The Figma Console MCP dependency
|
|
50
|
+
|
|
51
|
+
`/push-to-figma` and `/pull-from-figma` read and write Figma **variables**, which
|
|
52
|
+
the Figma REST API cannot do for local variables. They therefore drive
|
|
53
|
+
[**Figma Console MCP**](https://github.com/southleft/figma-console-mcp), an
|
|
54
|
+
open-source (MIT) MCP server by **[Southleft](https://southleft.com)** published
|
|
55
|
+
as [`figma-console-mcp`](https://www.npmjs.com/package/figma-console-mcp). It
|
|
56
|
+
relays commands to a Desktop Bridge plugin inside Figma Desktop.
|
|
57
|
+
|
|
58
|
+
It is a third-party project. Muka ships only the skills that drive it; report
|
|
59
|
+
server problems [upstream](https://github.com/southleft/figma-console-mcp/issues).
|
|
60
|
+
|
|
61
|
+
One-time setup — token, `.mcp.json`, Desktop Bridge plugin, verification — is in
|
|
62
|
+
[`figma-console-mcp.md`](figma-console-mcp.md). Without it, those two skills
|
|
63
|
+
cannot run; the other three are unaffected.
|
|
64
|
+
|
|
65
|
+
`/figma-to-code` is different: it reads designs through **Figma's own official
|
|
66
|
+
MCP server**, not Figma Console MCP, and needs no Desktop Bridge.
|
|
67
|
+
|
|
68
|
+
## Maintainer skills are not shipped
|
|
69
|
+
|
|
70
|
+
The Muka repo has its own skills for working **on** the design system —
|
|
71
|
+
`/component-rules`, `/token-system`, `/new-component`, `/release`, and a
|
|
72
|
+
repo-scoped `/add-brand` that adds a brand to Muka itself for every consumer.
|
|
73
|
+
Those live in
|
|
74
|
+
[`.claude/skills/`](https://github.com/revikornmann/muka/tree/main/.claude/skills)
|
|
75
|
+
and are deliberately excluded from the package, because they edit files that
|
|
76
|
+
exist only in the Muka repo.
|
|
77
|
+
|
|
78
|
+
If you are contributing to Muka rather than consuming it, clone the repo and use
|
|
79
|
+
those directly.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@revikornmann/muka-ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.20.0",
|
|
4
4
|
"description": "Muka Design System - Multi-brand design tokens and React components",
|
|
5
5
|
"main": "dist/cjs/components/index.js",
|
|
6
6
|
"module": "dist/esm/components/index.js",
|
|
@@ -62,6 +62,7 @@
|
|
|
62
62
|
"figma:connect:publish": "figma-code-connect --publish",
|
|
63
63
|
"typecheck": "tsc --project tsconfig.typecheck.json",
|
|
64
64
|
"check:docs": "node scripts/check-doc-sync.js",
|
|
65
|
+
"check:tokens-used": "node scripts/check-tokens-used.js",
|
|
65
66
|
"lint": "eslint .",
|
|
66
67
|
"lint:rsc": "eslint --config eslint.rsc.mjs \"components/**/*.{ts,tsx}\"",
|
|
67
68
|
"validate:tokens": "node scripts/validate-tokens.js",
|
|
@@ -69,8 +70,6 @@
|
|
|
69
70
|
"disable:automation": "node scripts/disable-automation.js",
|
|
70
71
|
"enable:automation": "node scripts/enable-automation.js",
|
|
71
72
|
"check:automation": "node scripts/check-automation-status.js",
|
|
72
|
-
"sync:skills": "node scripts/sync-shipped-skills.js",
|
|
73
|
-
"prepack": "node scripts/sync-shipped-skills.js",
|
|
74
73
|
"prepublishOnly": "npm run build",
|
|
75
74
|
"postinstall": "node scripts/postinstall-nudge.js",
|
|
76
75
|
"prepare": "husky || true"
|
|
@@ -108,15 +107,14 @@
|
|
|
108
107
|
"@fontsource-variable/ibm-plex-sans": "^5.2.8",
|
|
109
108
|
"@fontsource-variable/lora": "^5.2.8",
|
|
110
109
|
"@fontsource-variable/quicksand": "^5.2.10",
|
|
111
|
-
"@fontsource-variable/red-hat-display": "^5.
|
|
112
|
-
"@fontsource-variable/red-hat-text": "^5.
|
|
110
|
+
"@fontsource-variable/red-hat-display": "^5.3.0",
|
|
111
|
+
"@fontsource-variable/red-hat-text": "^5.3.0",
|
|
113
112
|
"@fontsource/yesteryear": "^5.2.8",
|
|
114
113
|
"@playwright/test": "^1.56.1",
|
|
115
114
|
"@storybook/addon-a11y": "^10.3.4",
|
|
116
115
|
"@storybook/addon-designs": "^11.1.3",
|
|
117
116
|
"@storybook/addon-docs": "^10.3.4",
|
|
118
117
|
"@storybook/addon-mcp": "^0.5.0",
|
|
119
|
-
"@storybook/addon-onboarding": "^10.3.4",
|
|
120
118
|
"@storybook/addon-vitest": "^10.3.4",
|
|
121
119
|
"@storybook/react-vite": "^10.3.4",
|
|
122
120
|
"@testing-library/dom": "^10.4.1",
|
|
@@ -139,6 +137,7 @@
|
|
|
139
137
|
"playwright": "^1.56.1",
|
|
140
138
|
"react": "^18.0.0",
|
|
141
139
|
"react-dom": "^18.0.0",
|
|
140
|
+
"remark-gfm": "^4.0.1",
|
|
142
141
|
"storybook": "^10.3.4",
|
|
143
142
|
"typescript": "^5.0.0",
|
|
144
143
|
"typescript-eslint": "^8.59.2",
|
|
@@ -18,9 +18,13 @@ if (!__dirname.includes(`${require('path').sep}node_modules${require('path').sep
|
|
|
18
18
|
console.log(`
|
|
19
19
|
🎨 Muka UI installed.
|
|
20
20
|
|
|
21
|
-
Finish setup in
|
|
22
|
-
1. npx muka-ui install-skill # makes
|
|
23
|
-
2. /setup-muka [brand] #
|
|
21
|
+
Finish setup in your agent:
|
|
22
|
+
1. npx muka-ui install-skill # makes the Muka skills available
|
|
23
|
+
2. /setup-muka [brand] # styles, fonts, auto-update workflow
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
Then, when you want your own brand:
|
|
26
|
+
/add-brand <name> # overrides Muka's brand layer in this repo
|
|
27
|
+
|
|
28
|
+
See every shipped skill: npx muka-ui install-skill --list
|
|
29
|
+
Docs: node_modules/@revikornmann/muka-ui/docs/consumers/README.md
|
|
26
30
|
`);
|
|
@@ -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 |
|