@revikornmann/muka-ui 0.18.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/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/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/ArrowReturnIcon.js +11 -0
- package/dist/cjs/components/Icon/custom/ArrowReturnIcon.js.map +1 -0
- package/dist/cjs/components/Icon/iconRegistry.js +5 -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 +123 -37
- package/dist/cjs/components/Menu/Menu.js +283 -25
- package/dist/cjs/components/Menu/Menu.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/index.js +5 -3
- package/dist/cjs/components/index.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/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/ArrowReturnIcon.js +7 -0
- package/dist/esm/components/Icon/custom/ArrowReturnIcon.js.map +1 -0
- package/dist/esm/components/Icon/iconRegistry.js +5 -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 +123 -37
- package/dist/esm/components/Menu/Menu.js +284 -26
- package/dist/esm/components/Menu/Menu.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/index.js +1 -0
- package/dist/esm/components/index.js.map +1 -1
- package/dist/styles/components/Combobox.css +116 -132
- package/dist/styles/components/DropdownSelect.css +225 -0
- package/dist/styles/components/Input.css +45 -8
- package/dist/styles/components/Menu.css +123 -37
- package/dist/styles/components/ProgressTracker.css +273 -22
- package/dist/styles/components/Scrollbar.css +7 -6
- package/dist/styles/components/Typography.css +89 -0
- package/dist/styles/index.css +1285 -605
- package/dist/styles/muka-dark.css +1285 -605
- package/dist/styles/muka-light.css +1285 -605
- 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 +1330 -650
- package/dist/styles/wireframe-light.css +1330 -650
- 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/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 +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 +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
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
# Project Guidelines for AI Development
|
|
2
|
+
|
|
3
|
+
> Generated by `muka-ui init` on {{DATE}}
|
|
4
|
+
|
|
5
|
+
This is the vendor-neutral brief every coding agent reads. `CLAUDE.md` points
|
|
6
|
+
here rather than repeating it, so there is one copy to keep current.
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## UI Component Constraint
|
|
11
|
+
|
|
12
|
+
**This project uses Muka UI as its sole component library. All UI must be built with components from muka-ui.**
|
|
13
|
+
|
|
14
|
+
### Rules
|
|
15
|
+
|
|
16
|
+
1. **Only use components available in Muka UI**
|
|
17
|
+
- Check availability at {{STORYBOOK_URL}}
|
|
18
|
+
- Import from `'{{PACKAGE_NAME}}'`
|
|
19
|
+
|
|
20
|
+
2. **No alternative styling solutions for UI components**
|
|
21
|
+
- No Tailwind utilities for component styling
|
|
22
|
+
- No CSS modules for UI elements
|
|
23
|
+
- No styled-components or Emotion
|
|
24
|
+
- No inline styles except for layout (using Muka tokens)
|
|
25
|
+
|
|
26
|
+
3. **When a component doesn't exist**
|
|
27
|
+
- Do NOT create a local component as a workaround
|
|
28
|
+
- Note the missing component as a blocker
|
|
29
|
+
- The component must be built in muka-ui first
|
|
30
|
+
- Once available in Storybook, it can be used here
|
|
31
|
+
|
|
32
|
+
### Imports
|
|
33
|
+
|
|
34
|
+
```tsx
|
|
35
|
+
// Import components
|
|
36
|
+
import { Button, Card, Input, Chip } from '{{PACKAGE_NAME}}';
|
|
37
|
+
|
|
38
|
+
// Import styles (choose one theme) — these bundles include the brand's fonts
|
|
39
|
+
import '{{PACKAGE_NAME}}/styles'; // Default muka-light + muka fonts
|
|
40
|
+
import '{{PACKAGE_NAME}}/styles/muka-dark.css'; // muka-dark + muka fonts
|
|
41
|
+
import '{{PACKAGE_NAME}}/styles/wireframe-light.css'; // wireframe (system fonts)
|
|
42
|
+
|
|
43
|
+
// For a brand loaded via its raw token file (e.g. bouwplan/grip/fscl), also import fonts:
|
|
44
|
+
import '{{PACKAGE_NAME}}/styles/tokens-bouwplan-light.css';
|
|
45
|
+
import '{{PACKAGE_NAME}}/styles/fonts-bouwplan.css';
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Fonts come from Muka — never load them yourself
|
|
49
|
+
|
|
50
|
+
- Muka self-hosts every brand's fonts as `@font-face` (offline-ready, no CDN). The
|
|
51
|
+
default `/styles` bundle and the `/styles/muka-*.css` + `/styles/wireframe-*.css`
|
|
52
|
+
bundles already include them; only a brand loaded via a raw `tokens-<brand>-<mode>.css`
|
|
53
|
+
file needs a separate `{{PACKAGE_NAME}}/styles/fonts-<brand>.css` import.
|
|
54
|
+
- Do NOT load these fonts via `next/font` or a Google Fonts `<link>`.
|
|
55
|
+
- Do NOT override the `--*-fontFamily` / `--alias-font-*-family` tokens — their
|
|
56
|
+
values are the exact `@font-face` family names.
|
|
57
|
+
|
|
58
|
+
### Acceptable Styling Patterns
|
|
59
|
+
|
|
60
|
+
```tsx
|
|
61
|
+
// ✅ GOOD: Use Muka UI components
|
|
62
|
+
import { Button, Card } from '{{PACKAGE_NAME}}';
|
|
63
|
+
|
|
64
|
+
// ✅ GOOD: Use Muka UI tokens for layout
|
|
65
|
+
<div style={{
|
|
66
|
+
display: 'flex',
|
|
67
|
+
gap: 'var(--spacing-4)',
|
|
68
|
+
padding: 'var(--spacing-6)'
|
|
69
|
+
}}>
|
|
70
|
+
|
|
71
|
+
// ✅ GOOD: Use semantic color tokens
|
|
72
|
+
<span style={{ color: 'var(--color-text-subtle-default)' }}>
|
|
73
|
+
|
|
74
|
+
// ❌ BAD: Tailwind classes
|
|
75
|
+
<div className="flex gap-4 p-6">
|
|
76
|
+
|
|
77
|
+
// ❌ BAD: CSS modules
|
|
78
|
+
import styles from './Component.module.css';
|
|
79
|
+
|
|
80
|
+
// ❌ BAD: Arbitrary values
|
|
81
|
+
<div style={{ color: '#6366f1', padding: '24px' }}>
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## Available Components
|
|
87
|
+
|
|
88
|
+
{{COMPONENT_LIST}}
|
|
89
|
+
|
|
90
|
+
For the full component API and examples, visit: {{STORYBOOK_URL}}
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
## Theme and brand selection
|
|
95
|
+
|
|
96
|
+
Muka's token stylesheets are `:root`-scoped. There are **no `[data-brand]` or
|
|
97
|
+
`[data-theme]` selectors**, so the active theme is whichever stylesheet loaded
|
|
98
|
+
last. Do not add those attributes expecting them to switch anything — to toggle
|
|
99
|
+
at runtime, swap a `<link href>` to a different `tokens-<brand>-<mode>.css`.
|
|
100
|
+
|
|
101
|
+
If this repo has a `brand/` directory, it owns a **custom brand** that overrides
|
|
102
|
+
Muka's brand layer. In that case:
|
|
103
|
+
|
|
104
|
+
- Edit colours and fonts only in `brand/light.json`, `brand/dark.json`, and
|
|
105
|
+
`brand/fonts.json`, using `{color.*}` primitive references rather than hex.
|
|
106
|
+
- Run `npm run build:tokens` after any change, and after every Muka upgrade.
|
|
107
|
+
- Never edit semantic or component tokens — they come from `node_modules` and are
|
|
108
|
+
replaced on upgrade.
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
## Muka skills
|
|
113
|
+
|
|
114
|
+
`npx muka-ui install-skill --list` shows the skills the installed version ships.
|
|
115
|
+
`/add-brand` creates or revises this repo's brand; `/figma-to-code` turns a Figma
|
|
116
|
+
link into a screen built from Muka components.
|
|
117
|
+
|
|
118
|
+
Skills install to `.claude/skills/`, which is the directory Claude Code and
|
|
119
|
+
Cursor both read. An agent that does not read that path can still follow the
|
|
120
|
+
skills, since each is a plain markdown file — point it at
|
|
121
|
+
`.claude/skills/<name>/SKILL.md`.
|
|
122
|
+
|
|
123
|
+
## Human Docs
|
|
124
|
+
<!-- SYNC: Update paths when Storybook docs change -->
|
|
125
|
+
- Storybook: {{STORYBOOK_URL}}
|
|
126
|
+
- Local guidelines: `docs/muka-ui-guidelines.md`
|
|
127
|
+
- Consumer docs: `node_modules/{{PACKAGE_NAME}}/docs/consumers/README.md`
|
|
128
|
+
- Package: {{PACKAGE_NAME}} v{{VERSION}}
|
package/cli/templates/CLAUDE.md
CHANGED
|
@@ -1,95 +1,15 @@
|
|
|
1
|
-
#
|
|
1
|
+
# CLAUDE.md
|
|
2
2
|
|
|
3
3
|
> Generated by `muka-ui init` on {{DATE}}
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
The guidelines for this project live in [`AGENTS.md`](AGENTS.md) — the
|
|
6
|
+
vendor-neutral file every coding agent reads. Read it before writing UI code.
|
|
6
7
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
### Rules
|
|
12
|
-
|
|
13
|
-
1. **Only use components available in Muka UI**
|
|
14
|
-
- Check availability at {{STORYBOOK_URL}}
|
|
15
|
-
- Import from `'{{PACKAGE_NAME}}'`
|
|
16
|
-
|
|
17
|
-
2. **No alternative styling solutions for UI components**
|
|
18
|
-
- No Tailwind utilities for component styling
|
|
19
|
-
- No CSS modules for UI elements
|
|
20
|
-
- No styled-components or Emotion
|
|
21
|
-
- No inline styles except for layout (using Muka tokens)
|
|
22
|
-
|
|
23
|
-
3. **When a component doesn't exist**
|
|
24
|
-
- Do NOT create a local component as a workaround
|
|
25
|
-
- Note the missing component as a blocker
|
|
26
|
-
- The component must be built in muka-ui first
|
|
27
|
-
- Once available in Storybook, it can be used here
|
|
28
|
-
|
|
29
|
-
### Imports
|
|
30
|
-
|
|
31
|
-
```tsx
|
|
32
|
-
// Import components
|
|
33
|
-
import { Button, Card, Input, Chip } from '{{PACKAGE_NAME}}';
|
|
34
|
-
|
|
35
|
-
// Import styles (choose one theme) — these bundles include the brand's fonts
|
|
36
|
-
import '{{PACKAGE_NAME}}/styles'; // Default muka-light + muka fonts
|
|
37
|
-
import '{{PACKAGE_NAME}}/styles/muka-dark.css'; // muka-dark + muka fonts
|
|
38
|
-
import '{{PACKAGE_NAME}}/styles/wireframe-light.css'; // wireframe (system fonts)
|
|
39
|
-
|
|
40
|
-
// For a brand loaded via its raw token file (e.g. bouwplan/grip/fscl), also import fonts:
|
|
41
|
-
import '{{PACKAGE_NAME}}/styles/tokens-bouwplan-light.css';
|
|
42
|
-
import '{{PACKAGE_NAME}}/styles/fonts-bouwplan.css';
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
### Fonts come from Muka — never load them yourself
|
|
46
|
-
|
|
47
|
-
- Muka self-hosts every brand's fonts as `@font-face` (offline-ready, no CDN). The
|
|
48
|
-
default `/styles` bundle and the `/styles/muka-*.css` + `/styles/wireframe-*.css`
|
|
49
|
-
bundles already include them; only a brand loaded via a raw `tokens-<brand>-<mode>.css`
|
|
50
|
-
file needs a separate `{{PACKAGE_NAME}}/styles/fonts-<brand>.css` import.
|
|
51
|
-
- Do NOT load these fonts via `next/font` or a Google Fonts `<link>`.
|
|
52
|
-
- Do NOT override the `--*-fontFamily` / `--alias-font-*-family` tokens — their
|
|
53
|
-
values are the exact `@font-face` family names.
|
|
54
|
-
|
|
55
|
-
### Acceptable Styling Patterns
|
|
56
|
-
|
|
57
|
-
```tsx
|
|
58
|
-
// ✅ GOOD: Use Muka UI components
|
|
59
|
-
import { Button, Card } from '{{PACKAGE_NAME}}';
|
|
60
|
-
|
|
61
|
-
// ✅ GOOD: Use Muka UI tokens for layout
|
|
62
|
-
<div style={{
|
|
63
|
-
display: 'flex',
|
|
64
|
-
gap: 'var(--spacing-4)',
|
|
65
|
-
padding: 'var(--spacing-6)'
|
|
66
|
-
}}>
|
|
67
|
-
|
|
68
|
-
// ✅ GOOD: Use semantic color tokens
|
|
69
|
-
<span style={{ color: 'var(--color-text-subtle-default)' }}>
|
|
70
|
-
|
|
71
|
-
// ❌ BAD: Tailwind classes
|
|
72
|
-
<div className="flex gap-4 p-6">
|
|
73
|
-
|
|
74
|
-
// ❌ BAD: CSS modules
|
|
75
|
-
import styles from './Component.module.css';
|
|
76
|
-
|
|
77
|
-
// ❌ BAD: Arbitrary values
|
|
78
|
-
<div style={{ color: '#6366f1', padding: '24px' }}>
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
---
|
|
82
|
-
|
|
83
|
-
## Available Components
|
|
84
|
-
|
|
85
|
-
{{COMPONENT_LIST}}
|
|
86
|
-
|
|
87
|
-
For the full component API and examples, visit: {{STORYBOOK_URL}}
|
|
88
|
-
|
|
89
|
-
---
|
|
8
|
+
It covers: Muka UI as the sole component library, the styling patterns that are
|
|
9
|
+
and are not allowed, how fonts and theme selection work, and the Muka skills
|
|
10
|
+
available in this repo.
|
|
90
11
|
|
|
91
12
|
## Human Docs
|
|
92
|
-
|
|
13
|
+
- Guidelines: `AGENTS.md`
|
|
93
14
|
- Storybook: {{STORYBOOK_URL}}
|
|
94
|
-
-
|
|
95
|
-
- Package: {{PACKAGE_NAME}} v{{VERSION}}
|
|
15
|
+
- Consumer docs: `node_modules/{{PACKAGE_NAME}}/docs/consumers/README.md`
|
|
@@ -71,17 +71,25 @@ import '{{PACKAGE_NAME}}/styles/fonts-bouwplan.css';
|
|
|
71
71
|
|
|
72
72
|
### Theme Switching
|
|
73
73
|
|
|
74
|
-
|
|
74
|
+
Every Muka stylesheet declares its variables on `:root`. There are **no
|
|
75
|
+
`[data-brand]` or `[data-theme]` selectors**, so the active theme is simply
|
|
76
|
+
whichever stylesheet loaded last — importing two of them means one always wins.
|
|
77
|
+
Setting `data-theme` does nothing.
|
|
75
78
|
|
|
76
|
-
|
|
77
|
-
// In your root layout
|
|
78
|
-
import '{{PACKAGE_NAME}}/styles/muka-light.css';
|
|
79
|
-
import '{{PACKAGE_NAME}}/styles/muka-dark.css';
|
|
79
|
+
For a runtime light/dark toggle, swap a `<link>` rather than importing both:
|
|
80
80
|
|
|
81
|
-
|
|
82
|
-
<
|
|
81
|
+
```html
|
|
82
|
+
<link id="muka-theme" rel="stylesheet" href="/styles/tokens-muka-light.css" />
|
|
83
83
|
```
|
|
84
84
|
|
|
85
|
+
```ts
|
|
86
|
+
document.getElementById('muka-theme').href =
|
|
87
|
+
`/styles/tokens-${brand}-${mode}.css`;
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Copy the token CSS you need into this project's static/public directory so those
|
|
91
|
+
hrefs resolve. If the app only ever needs one theme, a plain import is simpler.
|
|
92
|
+
|
|
85
93
|
---
|
|
86
94
|
|
|
87
95
|
## Available Components
|
|
@@ -120,7 +128,8 @@ var(--spacing-12) /* 3rem */
|
|
|
120
128
|
/* Text */
|
|
121
129
|
var(--color-text-default-default)
|
|
122
130
|
var(--color-text-subtle-default)
|
|
123
|
-
var(--color-text-
|
|
131
|
+
var(--color-text-muted-default)
|
|
132
|
+
var(--color-text-default-inverse) /* on an inverted surface */
|
|
124
133
|
|
|
125
134
|
/* Backgrounds */
|
|
126
135
|
var(--color-surface-level1)
|
|
@@ -143,9 +152,16 @@ var(--color-action-pressed)
|
|
|
143
152
|
```css
|
|
144
153
|
var(--alias-font-brand-family)
|
|
145
154
|
var(--alias-font-brand-weight-semibold)
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
155
|
+
|
|
156
|
+
/* Text styles are composite: --text-<role>-<size>-<weight>-<property>.
|
|
157
|
+
The weight is part of the name, so there is no --text-label-md-fontSize.
|
|
158
|
+
Weights: regular | semibold | bold
|
|
159
|
+
label sizes: xs sm md lg xl 2xl
|
|
160
|
+
body sizes: xs sm base lg xl 2xl (body uses "base", not "md") */
|
|
161
|
+
var(--text-label-md-regular-fontSize)
|
|
162
|
+
var(--text-label-md-semibold-lineHeight)
|
|
163
|
+
var(--text-body-base-regular-fontSize)
|
|
164
|
+
var(--text-body-base-regular-lineHeight)
|
|
149
165
|
```
|
|
150
166
|
|
|
151
167
|
---
|
|
@@ -159,16 +175,36 @@ If you need a component that doesn't exist in Muka UI:
|
|
|
159
175
|
2. **Don't create a local workaround** — this defeats the purpose of using a design system
|
|
160
176
|
|
|
161
177
|
3. **Request the component** by:
|
|
162
|
-
- Opening an issue
|
|
163
|
-
- Or building it yourself in muka
|
|
178
|
+
- Opening an issue at https://github.com/revikornmann/muka/issues
|
|
179
|
+
- Or building it yourself in muka and submitting a PR
|
|
164
180
|
|
|
165
181
|
4. **Wait for availability** — once the component is in Storybook, you can use it
|
|
166
182
|
|
|
167
183
|
---
|
|
168
184
|
|
|
185
|
+
## Muka skills available in this repo
|
|
186
|
+
|
|
187
|
+
Installed with `npx muka-ui install-skill` (run `--list` to see what the
|
|
188
|
+
installed version ships):
|
|
189
|
+
|
|
190
|
+
| Skill | Use it to |
|
|
191
|
+
|---|---|
|
|
192
|
+
| `/setup-muka` | Install and wire up Muka, including the auto-update workflow |
|
|
193
|
+
| `/add-brand` | Give this repo its own brand, overriding Muka's brand layer |
|
|
194
|
+
| `/figma-to-code` | Turn a Figma link into a screen composed from Muka components |
|
|
195
|
+
| `/push-to-figma` | Publish this repo's brand to Figma as variables |
|
|
196
|
+
| `/pull-from-figma` | Bring a designer's Figma brand edits back into the token files |
|
|
197
|
+
|
|
198
|
+
The two Figma sync skills need [Figma Console
|
|
199
|
+
MCP](https://github.com/southleft/figma-console-mcp); see
|
|
200
|
+
`node_modules/{{PACKAGE_NAME}}/docs/consumers/figma-console-mcp.md`.
|
|
201
|
+
|
|
202
|
+
---
|
|
203
|
+
|
|
169
204
|
## Human Docs
|
|
170
205
|
<!-- SYNC: Update paths when Storybook docs change -->
|
|
171
206
|
|
|
172
207
|
- **Storybook:** {{STORYBOOK_URL}}
|
|
173
|
-
- **GitHub:** https://github.com/
|
|
208
|
+
- **GitHub:** https://github.com/revikornmann/muka
|
|
209
|
+
- **Consumer docs:** `node_modules/{{PACKAGE_NAME}}/docs/consumers/README.md`
|
|
174
210
|
- **Package:** {{PACKAGE_NAME}} v{{VERSION}}
|
|
@@ -1,186 +1,170 @@
|
|
|
1
|
-
/* Combobox
|
|
1
|
+
/* Combobox — Figma Input Combobox (free-input chips + suggestion Menu) */
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
.muka-combobox {
|
|
4
|
+
display: inline-flex;
|
|
5
|
+
flex-direction: column;
|
|
6
|
+
gap: var(--spacing-2);
|
|
7
|
+
min-width: 200px;
|
|
8
|
+
}
|
|
4
9
|
|
|
5
|
-
|
|
6
|
-
* The clear control is a sibling of the trigger, not a child (a <button> may
|
|
7
|
-
* not contain interactive content), so it is overlaid on the trigger's trailing
|
|
8
|
-
* padding. The trigger reserves that space with padding-right below.
|
|
9
|
-
*/
|
|
10
|
-
.muka-combobox__trigger-group {
|
|
11
|
-
position: relative;
|
|
12
|
-
display: block;
|
|
10
|
+
.muka-combobox--full-width {
|
|
13
11
|
width: 100%;
|
|
14
12
|
}
|
|
15
13
|
|
|
16
|
-
|
|
14
|
+
.muka-combobox__label {
|
|
15
|
+
color: var(--color-text-default-default);
|
|
16
|
+
cursor: pointer;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.muka-combobox__label--sm {
|
|
20
|
+
font-family: var(--text-label-sm-semibold-fontFamily);
|
|
21
|
+
font-weight: var(--text-label-sm-semibold-fontWeight);
|
|
22
|
+
font-size: var(--text-label-sm-semibold-fontSize);
|
|
23
|
+
line-height: var(--text-label-sm-semibold-lineHeight);
|
|
24
|
+
}
|
|
17
25
|
|
|
18
|
-
.muka-
|
|
19
|
-
|
|
26
|
+
.muka-combobox__label--md {
|
|
27
|
+
font-family: var(--text-label-md-semibold-fontFamily);
|
|
28
|
+
font-weight: var(--text-label-md-semibold-fontWeight);
|
|
29
|
+
font-size: var(--text-label-md-semibold-fontSize);
|
|
30
|
+
line-height: var(--text-label-md-semibold-lineHeight);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.muka-combobox__label--lg {
|
|
34
|
+
font-family: var(--text-label-lg-semibold-fontFamily);
|
|
35
|
+
font-weight: var(--text-label-lg-semibold-fontWeight);
|
|
36
|
+
font-size: var(--text-label-lg-semibold-fontSize);
|
|
37
|
+
line-height: var(--text-label-lg-semibold-lineHeight);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.muka-combobox__field {
|
|
41
|
+
display: flex;
|
|
20
42
|
align-items: center;
|
|
21
|
-
gap: var(--spacing-2);
|
|
22
43
|
width: 100%;
|
|
23
|
-
|
|
44
|
+
position: relative;
|
|
45
|
+
isolation: isolate;
|
|
46
|
+
box-sizing: border-box;
|
|
24
47
|
background-color: var(--input-field-color-default-background);
|
|
25
48
|
border: var(--border-width-regular) solid var(--input-field-color-default-border);
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
cursor:
|
|
29
|
-
|
|
30
|
-
font-weight: var(--text-body-md-regular-fontWeight);
|
|
31
|
-
font-size: var(--text-body-md-regular-fontSize);
|
|
32
|
-
line-height: var(--text-body-md-regular-lineHeight);
|
|
33
|
-
-webkit-tap-highlight-color: transparent;
|
|
34
|
-
transition: border-color 0.12s ease;
|
|
35
|
-
|
|
36
|
-
/* Room for the chevron overlaid on the trailing edge. */
|
|
37
|
-
--muka-combobox-trailing-space: calc(
|
|
38
|
-
var(--input-field-padding-x) + var(--icon-size-sm) + var(--spacing-2)
|
|
39
|
-
);
|
|
49
|
+
border-radius: var(--input-field-radius-lg);
|
|
50
|
+
padding: var(--spacing-2);
|
|
51
|
+
cursor: text;
|
|
52
|
+
transition: border-color 0.12s ease, background-color 0.12s ease;
|
|
40
53
|
}
|
|
41
54
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
);
|
|
55
|
+
.muka-combobox__field::after {
|
|
56
|
+
content: '';
|
|
57
|
+
position: absolute;
|
|
58
|
+
inset: 0;
|
|
59
|
+
border-radius: inherit;
|
|
60
|
+
box-shadow: inset 0 1px 2px 0 rgba(26, 26, 26, 0.08);
|
|
61
|
+
pointer-events: none;
|
|
48
62
|
}
|
|
49
63
|
|
|
50
|
-
.muka-
|
|
64
|
+
.muka-combobox__field--sm {
|
|
51
65
|
min-height: var(--input-field-height-sm);
|
|
52
66
|
border-radius: var(--input-field-radius-sm);
|
|
53
67
|
}
|
|
54
68
|
|
|
55
|
-
.muka-
|
|
69
|
+
.muka-combobox__field--md {
|
|
56
70
|
min-height: var(--input-field-height-default);
|
|
57
71
|
border-radius: var(--input-field-radius-md);
|
|
58
72
|
}
|
|
59
73
|
|
|
60
|
-
.muka-
|
|
74
|
+
.muka-combobox__field--lg {
|
|
61
75
|
min-height: var(--input-field-height-lg);
|
|
62
76
|
border-radius: var(--input-field-radius-lg);
|
|
63
77
|
}
|
|
64
78
|
|
|
65
|
-
.muka-
|
|
66
|
-
border-
|
|
79
|
+
.muka-combobox__field--focused:not(.muka-combobox__field--disabled) {
|
|
80
|
+
border-width: var(--border-width-bold);
|
|
81
|
+
border-color: var(--input-field-color-focus-border);
|
|
82
|
+
background-color: var(--input-field-color-focus-background);
|
|
83
|
+
padding: calc(var(--spacing-2) - 1px);
|
|
67
84
|
}
|
|
68
85
|
|
|
69
|
-
.muka-
|
|
70
|
-
|
|
71
|
-
border-color: var(--input-field-color-focus-border, var(--color-action-default));
|
|
86
|
+
.muka-combobox__field--error:not(.muka-combobox__field--disabled) {
|
|
87
|
+
border-color: var(--color-state-error-border, var(--color-state-error-foreground));
|
|
72
88
|
}
|
|
73
89
|
|
|
74
|
-
.muka-
|
|
75
|
-
.muka-combobox:disabled {
|
|
90
|
+
.muka-combobox__field--disabled {
|
|
76
91
|
opacity: 0.5;
|
|
77
92
|
cursor: not-allowed;
|
|
78
93
|
}
|
|
79
94
|
|
|
80
|
-
.muka-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
.muka-combobox__leading {
|
|
85
|
-
display: inline-flex;
|
|
86
|
-
align-items: center;
|
|
87
|
-
justify-content: center;
|
|
88
|
-
flex-shrink: 0;
|
|
89
|
-
color: var(--color-text-subtle-default);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
.muka-combobox__label {
|
|
93
|
-
flex: 1 1 auto;
|
|
94
|
-
min-width: 0;
|
|
95
|
-
white-space: nowrap;
|
|
96
|
-
overflow: hidden;
|
|
97
|
-
text-overflow: ellipsis;
|
|
95
|
+
.muka-combobox__field--multiline {
|
|
96
|
+
align-items: flex-start;
|
|
97
|
+
min-height: 7rem;
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
.muka-combobox__actions {
|
|
103
|
-
position: absolute;
|
|
104
|
-
top: 0;
|
|
105
|
-
right: var(--input-field-padding-x);
|
|
106
|
-
height: 100%;
|
|
100
|
+
.muka-combobox__chips {
|
|
107
101
|
display: flex;
|
|
108
|
-
|
|
102
|
+
flex: 1 1 auto;
|
|
103
|
+
flex-wrap: wrap;
|
|
109
104
|
gap: var(--spacing-2);
|
|
110
|
-
/*
|
|
111
|
-
* The strip sits on top of the trigger, so it must not swallow taps meant to
|
|
112
|
-
* open the picker. Only the clear button takes pointer events back.
|
|
113
|
-
*/
|
|
114
|
-
pointer-events: none;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
.muka-combobox__clear,
|
|
118
|
-
.muka-combobox__chevron {
|
|
119
|
-
display: inline-flex;
|
|
120
105
|
align-items: center;
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
106
|
+
min-width: 0;
|
|
107
|
+
width: 100%;
|
|
108
|
+
position: relative;
|
|
109
|
+
z-index: 1;
|
|
124
110
|
}
|
|
125
111
|
|
|
126
|
-
.muka-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
112
|
+
.muka-combobox__input {
|
|
113
|
+
flex: 1 1 5rem;
|
|
114
|
+
min-width: 5rem;
|
|
115
|
+
min-height: 2rem;
|
|
116
|
+
margin: 0;
|
|
117
|
+
padding: 0 var(--spacing-1);
|
|
130
118
|
border: none;
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
.muka-combobox__clear:focus-visible {
|
|
142
|
-
outline: 2px solid var(--color-border-focus);
|
|
143
|
-
outline-offset: 2px;
|
|
144
|
-
color: var(--color-text-default-default);
|
|
119
|
+
outline: none;
|
|
120
|
+
background: transparent;
|
|
121
|
+
color: var(--input-field-color-default-foreground);
|
|
122
|
+
caret-color: var(--input-field-color-default-foreground);
|
|
123
|
+
font-family: var(--text-label-md-regular-fontFamily);
|
|
124
|
+
font-size: var(--text-label-md-regular-fontSize);
|
|
125
|
+
font-weight: var(--text-label-md-regular-fontWeight);
|
|
126
|
+
line-height: var(--text-label-md-regular-lineHeight);
|
|
145
127
|
}
|
|
146
128
|
|
|
147
|
-
.muka-
|
|
148
|
-
|
|
149
|
-
opacity: 0.5;
|
|
129
|
+
.muka-combobox__input::placeholder {
|
|
130
|
+
color: var(--color-text-subtle-default);
|
|
150
131
|
}
|
|
151
132
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
min-height: 0;
|
|
160
|
-
max-height: 80vh;
|
|
133
|
+
.muka-combobox__helper {
|
|
134
|
+
margin: 0;
|
|
135
|
+
color: var(--color-text-subtle-default);
|
|
136
|
+
font-family: var(--text-label-sm-regular-fontFamily);
|
|
137
|
+
font-size: var(--text-label-sm-regular-fontSize);
|
|
138
|
+
font-weight: var(--text-label-sm-regular-fontWeight);
|
|
139
|
+
line-height: var(--text-label-sm-regular-lineHeight);
|
|
161
140
|
}
|
|
162
141
|
|
|
163
|
-
.muka-
|
|
142
|
+
.muka-combobox__error {
|
|
164
143
|
margin: 0;
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
font-
|
|
168
|
-
font-weight: var(--text-
|
|
169
|
-
|
|
170
|
-
line-height: var(--text-heading-sm-lineHeight);
|
|
144
|
+
color: var(--color-state-error-foreground);
|
|
145
|
+
font-family: var(--text-label-sm-regular-fontFamily);
|
|
146
|
+
font-size: var(--text-label-sm-regular-fontSize);
|
|
147
|
+
font-weight: var(--text-label-sm-regular-fontWeight);
|
|
148
|
+
line-height: var(--text-label-sm-regular-lineHeight);
|
|
171
149
|
}
|
|
172
150
|
|
|
173
|
-
.muka-
|
|
174
|
-
position:
|
|
175
|
-
|
|
176
|
-
z-index:
|
|
177
|
-
|
|
178
|
-
|
|
151
|
+
.muka-combobox__menu-anchor {
|
|
152
|
+
position: absolute;
|
|
153
|
+
inset: 0;
|
|
154
|
+
z-index: 0;
|
|
155
|
+
width: 100%;
|
|
156
|
+
height: 100%;
|
|
157
|
+
margin: 0;
|
|
158
|
+
padding: 0;
|
|
159
|
+
border: none;
|
|
160
|
+
background: transparent;
|
|
161
|
+
pointer-events: none;
|
|
162
|
+
opacity: 0;
|
|
179
163
|
}
|
|
180
164
|
|
|
181
|
-
.muka-
|
|
182
|
-
|
|
183
|
-
min-
|
|
184
|
-
|
|
185
|
-
-
|
|
165
|
+
.muka-combobox__menu {
|
|
166
|
+
/* Prefer Menu token min-width (280px); may exceed the field when left-aligned. */
|
|
167
|
+
min-width: var(--menu-content-min-width);
|
|
168
|
+
width: max-content;
|
|
169
|
+
max-width: min(100vw - 2rem, 24rem);
|
|
186
170
|
}
|