material-theme-builder 2.1.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 +249 -0
- package/dist/cli.js +828 -0
- package/dist/index.d.ts +191 -0
- package/dist/index.js +888 -0
- package/dist/tailwind.css +181 -0
- package/package.json +105 -0
- package/src/tailwind.css +181 -0
package/README.md
ADDED
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
[](https://www.npmjs.com/package/material-theme-builder)
|
|
2
|
+
[](https://www.chromatic.com/library?appId=695eb517cb602e59b4cc045c&branch=main)
|
|
3
|
+
[](https://main--695eb517cb602e59b4cc045c.chromatic.com)
|
|
4
|
+
|
|
5
|
+
[Material Design colors](https://m3.material.io/styles/color/system/overview)
|
|
6
|
+
for React.
|
|
7
|
+
|
|
8
|
+
It injects `--md-sys-color-*` and `--md-ref-palette-*` CSS variables into the page (prefix is [configurable](#programmatic-api)).
|
|
9
|
+
|
|
10
|
+
https://github.com/user-attachments/assets/5b67c961-d7a4-4b64-9356-4ada26bc9be4
|
|
11
|
+
|
|
12
|
+
m3 references:
|
|
13
|
+
|
|
14
|
+
| builder | roles |
|
|
15
|
+
| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
16
|
+
| [<img width="2836" height="2266" alt="CleanShot 2026-01-14 at 08 58 40@2x" src="https://github.com/user-attachments/assets/e4b47c00-716f-4b08-b393-de306d5ce302" />](https://material-foundation.github.io/material-theme-builder/) | [<img width="2836" height="2266" alt="CleanShot 2026-01-14 at 09 01 23@2x" src="https://github.com/user-attachments/assets/826e502d-e173-43c4-807a-53d0ba075a88" />](https://m3.material.io/styles/color/roles) |
|
|
17
|
+
|
|
18
|
+
Support for:
|
|
19
|
+
|
|
20
|
+
Base (like in the Builder):
|
|
21
|
+
|
|
22
|
+
- [x] light/dark mode
|
|
23
|
+
- [x] source color
|
|
24
|
+
- [x] scheme
|
|
25
|
+
- [x] contrast
|
|
26
|
+
- [x] core-colors overrides: primary, secondary, tertiary, error, neutral,
|
|
27
|
+
neutralVariant
|
|
28
|
+
- [x] custom-colors (aka. "Extended colors")
|
|
29
|
+
- [x] Harmonization (aka. `blend`) -- with effective color: `source` or
|
|
30
|
+
`primary` if defined
|
|
31
|
+
- [x] Shades (aka. "tonals")
|
|
32
|
+
- [ ] colorMatch
|
|
33
|
+
|
|
34
|
+
Extra:
|
|
35
|
+
|
|
36
|
+
- [x] `contrastAllColors`: contrast also applies to custom-colors and shades
|
|
37
|
+
(not only the core-colors)
|
|
38
|
+
- [x] `adaptiveShades`: shades adapt to the light/dark mode (instead of being
|
|
39
|
+
fixed)
|
|
40
|
+
|
|
41
|
+
# Usage
|
|
42
|
+
|
|
43
|
+
```tsx
|
|
44
|
+
import { Mcu } from "material-theme-builder";
|
|
45
|
+
|
|
46
|
+
<Mcu
|
|
47
|
+
source="#0e1216"
|
|
48
|
+
scheme="vibrant"
|
|
49
|
+
contrast={0.5}
|
|
50
|
+
customColors={[
|
|
51
|
+
{ name: "myCustomColor1", hex: "#6C8A0C", blend: true },
|
|
52
|
+
{ name: "myCustomColor2", hex: "#E126C6", blend: true },
|
|
53
|
+
{ name: "myCustomColor3", hex: "#E126C6", blend: false },
|
|
54
|
+
]}
|
|
55
|
+
>
|
|
56
|
+
<p style={{
|
|
57
|
+
backgroundColor: "var(--md-sys-color-surface)",
|
|
58
|
+
color: "var(--md-sys-color-on-surface)",
|
|
59
|
+
}}>
|
|
60
|
+
Hello, MCU <span style={{
|
|
61
|
+
backgroundColor: "var(--md-sys-color-my-custom-color-1)",
|
|
62
|
+
color: "var(--md-sys-color-on-my-custom-color-1)",
|
|
63
|
+
}}>colors<span>!
|
|
64
|
+
</p>
|
|
65
|
+
</Mcu>
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
> [!TIP]
|
|
69
|
+
>
|
|
70
|
+
> Typically wrapping `{children}` in a
|
|
71
|
+
> [layout](https://nextjs.org/docs/app/getting-started/layouts-and-pages#creating-a-layout).
|
|
72
|
+
|
|
73
|
+
> [!NOTE]
|
|
74
|
+
>
|
|
75
|
+
> CSS varnames are always kebab-cased, e.g. `myCustomColor1` →
|
|
76
|
+
> `--md-sys-color-my-custom-color-1` / `--md-ref-palette-my-custom-color-1-<tone>`
|
|
77
|
+
|
|
78
|
+
## `useMcu`
|
|
79
|
+
|
|
80
|
+
A hook is also provided:
|
|
81
|
+
|
|
82
|
+
```tsx
|
|
83
|
+
import { useMcu } from "material-theme-builder";
|
|
84
|
+
|
|
85
|
+
const { initials, setMcuConfig, getMcuColor } = useMcu();
|
|
86
|
+
|
|
87
|
+
return (
|
|
88
|
+
<button onClick={() => setMcuConfig({ ...initials, source: "#FF5722" })}>
|
|
89
|
+
Change to {getMcuColor("primary", "light")}
|
|
90
|
+
</button>
|
|
91
|
+
);
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Tailwind
|
|
95
|
+
|
|
96
|
+
Compatible through [theme variables](https://tailwindcss.com/docs/theme):
|
|
97
|
+
|
|
98
|
+
https://github.com/abernier/material-theme-builder/blob/688c789e322ed3858b51389b33eb7ea342bba81e/src/tailwind.css#L3-L186
|
|
99
|
+
|
|
100
|
+
Or simply:
|
|
101
|
+
|
|
102
|
+
```css
|
|
103
|
+
@import "material-theme-builder/tailwind.css";
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
> [!IMPORTANT]
|
|
107
|
+
>
|
|
108
|
+
> Do not forget to manually add your custom colors, as in:
|
|
109
|
+
> https://github.com/abernier/material-theme-builder/blob/688c789e322ed3858b51389b33eb7ea342bba81e/src/tailwind.css#L126-L185
|
|
110
|
+
|
|
111
|
+
## shadcn
|
|
112
|
+
|
|
113
|
+
Pre-requisites:
|
|
114
|
+
|
|
115
|
+
- You should use
|
|
116
|
+
[`tailwind.cssVariables`](https://ui.shadcn.com/docs/theming#css-variables)
|
|
117
|
+
|
|
118
|
+
Simply override/remap
|
|
119
|
+
[shadcn's CSS variables](https://ui.shadcn.com/docs/theming#list-of-variables):
|
|
120
|
+
|
|
121
|
+
```css
|
|
122
|
+
:root {
|
|
123
|
+
/* ... */
|
|
124
|
+
}
|
|
125
|
+
.dark {
|
|
126
|
+
/* ... */
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
:root,
|
|
130
|
+
.dark {
|
|
131
|
+
--background: var(--md-sys-color-surface);
|
|
132
|
+
--foreground: var(--md-sys-color-on-surface);
|
|
133
|
+
--card: var(--md-sys-color-surface-container-low);
|
|
134
|
+
--card-foreground: var(--md-sys-color-on-surface);
|
|
135
|
+
--popover: var(--md-sys-color-surface-container-high);
|
|
136
|
+
--popover-foreground: var(--md-sys-color-on-surface);
|
|
137
|
+
--primary: var(--md-sys-color-primary);
|
|
138
|
+
--primary-foreground: var(--md-sys-color-on-primary);
|
|
139
|
+
--secondary: var(--md-sys-color-secondary-container);
|
|
140
|
+
--secondary-foreground: var(--md-sys-color-on-secondary-container);
|
|
141
|
+
--muted: var(--md-sys-color-surface-container-highest);
|
|
142
|
+
--muted-foreground: var(--md-sys-color-on-surface-variant);
|
|
143
|
+
--accent: var(--md-sys-color-secondary-container);
|
|
144
|
+
--accent-foreground: var(--md-sys-color-on-secondary-container);
|
|
145
|
+
--destructive: var(--md-sys-color-error);
|
|
146
|
+
--border: var(--md-sys-color-outline-variant);
|
|
147
|
+
--input: var(--md-sys-color-outline);
|
|
148
|
+
--ring: var(--md-sys-color-primary);
|
|
149
|
+
--chart-1: var(--md-sys-color-primary-fixed);
|
|
150
|
+
--chart-2: var(--md-sys-color-secondary-fixed);
|
|
151
|
+
--chart-3: var(--md-sys-color-tertiary-fixed);
|
|
152
|
+
--chart-4: var(--md-sys-color-primary-fixed-dim);
|
|
153
|
+
--chart-5: var(--md-sys-color-secondary-fixed-dim);
|
|
154
|
+
--sidebar: var(--md-sys-color-surface-container-low);
|
|
155
|
+
--sidebar-foreground: var(--md-sys-color-on-surface);
|
|
156
|
+
--sidebar-primary: var(--md-sys-color-primary);
|
|
157
|
+
--sidebar-primary-foreground: var(--md-sys-color-on-primary);
|
|
158
|
+
--sidebar-accent: var(--md-sys-color-secondary-container);
|
|
159
|
+
--sidebar-accent-foreground: var(--md-sys-color-on-secondary-container);
|
|
160
|
+
--sidebar-border: var(--md-sys-color-outline-variant);
|
|
161
|
+
--sidebar-ring: var(--md-sys-color-primary);
|
|
162
|
+
}
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
<details>
|
|
166
|
+
<summary>mapping details</summary>
|
|
167
|
+
see:
|
|
168
|
+
|
|
169
|
+
- https://chatgpt.com/share/6899f20a-422c-8011-a072-62fb649589a0
|
|
170
|
+
- https://gemini.google.com/share/51e072b6f1d2
|
|
171
|
+
</details>
|
|
172
|
+
|
|
173
|
+
> [!IMPORTANT]
|
|
174
|
+
>
|
|
175
|
+
> Make sure `:root, .dark { ... }` comes AFTER `.root { ... } .dark { ... }` to
|
|
176
|
+
> take precedence.
|
|
177
|
+
|
|
178
|
+
## Programmatic API
|
|
179
|
+
|
|
180
|
+
```ts
|
|
181
|
+
import { builder } from "material-theme-builder";
|
|
182
|
+
|
|
183
|
+
const theme = builder("#6750A4", {
|
|
184
|
+
scheme: "vibrant",
|
|
185
|
+
contrast: 0.5,
|
|
186
|
+
primary: "#FF0000",
|
|
187
|
+
secondary: "#00FF00",
|
|
188
|
+
customColors: [
|
|
189
|
+
{ name: "brand", hex: "#FF5733", blend: true },
|
|
190
|
+
{ name: "success", hex: "#28A745", blend: false },
|
|
191
|
+
],
|
|
192
|
+
contrastAllColors: true,
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
theme.toJson();
|
|
196
|
+
theme.toCss();
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
## CLI
|
|
200
|
+
|
|
201
|
+
```sh
|
|
202
|
+
$ npx material-theme-builder builder "#6750A4"
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
will generate a `material-theme` folder with: `Light.tokens.json` and `Dark.tokens.json` [design-tokens](https://www.designtokens.org/tr/2025.10/) files, you can (both) import into Figma.
|
|
206
|
+
|
|
207
|
+
See `npx material-theme-builder builder --help` for all available options.
|
|
208
|
+
|
|
209
|
+
# Dev
|
|
210
|
+
|
|
211
|
+
## INSTALL
|
|
212
|
+
|
|
213
|
+
Pre-requisites:
|
|
214
|
+
|
|
215
|
+
- Install [nvm](https://github.com/nvm-sh/nvm), then:
|
|
216
|
+
```sh
|
|
217
|
+
$ nvm install
|
|
218
|
+
$ nvm use
|
|
219
|
+
$ node -v # make sure your version satisfies package.json#engines.node
|
|
220
|
+
```
|
|
221
|
+
nb: if you want this node version to be your default nvm's one:
|
|
222
|
+
`nvm alias default node`
|
|
223
|
+
- Install pnpm, with:
|
|
224
|
+
```sh
|
|
225
|
+
$ corepack enable
|
|
226
|
+
$ corepack prepare --activate # it reads "packageManager"
|
|
227
|
+
$ pnpm -v # make sure your version satisfies package.json#engines.pnpm
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
```sh
|
|
231
|
+
$ pnpm i
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
## Validation
|
|
235
|
+
|
|
236
|
+
```sh
|
|
237
|
+
$ pnpm run lgtm
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
## CONTRIBUTING
|
|
241
|
+
|
|
242
|
+
When submitting a pull request, please include a changeset to document your
|
|
243
|
+
changes:
|
|
244
|
+
|
|
245
|
+
```bash
|
|
246
|
+
pnpm exec changeset
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
This helps us maintain the changelog and version the package appropriately.
|