@atomazing-org/design-system 2.0.1 → 3.7.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. package/AGENTS.md +92 -0
  2. package/README.MD +263 -335
  3. package/dist/index.d.ts +11 -15
  4. package/dist/index.js +22 -22
  5. package/dist/presets/index.d.ts +15 -2
  6. package/dist/presets/index.js +315 -313
  7. package/dist/themePresets-CwgG5XEL.d.ts +65 -0
  8. package/dist/themePresets-CwgG5XEL.js +1 -0
  9. package/migrations/README.UPDATE.md +34 -20
  10. package/migrations/docs/migrations/design-system/README.md +48 -17
  11. package/migrations/docs/migrations/design-system/routes/adopt-existing/AEROCRM-EXAMPLE.md +197 -0
  12. package/migrations/docs/migrations/design-system/routes/adopt-existing/RUNBOOK.md +185 -25
  13. package/migrations/docs/migrations/design-system/routes/adopt-existing/migration.spec.json +84 -20
  14. package/migrations/docs/migrations/design-system/routes/greenfield/RUNBOOK.md +57 -25
  15. package/migrations/docs/migrations/design-system/routes/greenfield/migration.spec.json +37 -14
  16. package/migrations/docs/migrations/design-system/routes/mui4-to-latest/RUNBOOK.md +136 -77
  17. package/migrations/docs/migrations/design-system/routes/mui4-to-latest/migration.spec.json +104 -29
  18. package/migrations/docs/migrations/design-system/shared/WORKING-RULES.md +194 -0
  19. package/migrations/docs/migrations/design-system/shared/acceptance.md +76 -20
  20. package/migrations/docs/migrations/design-system/shared/common-regressions.md +218 -0
  21. package/migrations/docs/migrations/design-system/shared/gates.md +39 -3
  22. package/migrations/docs/migrations/design-system/shared/manual-qa-matrix.md +70 -0
  23. package/migrations/docs/migrations/design-system/shared/phase-exit-criteria.md +129 -0
  24. package/migrations/docs/migrations/design-system/shared/phases.md +377 -0
  25. package/migrations/skills/design-system-consumer-agent/SKILL.md +84 -0
  26. package/migrations/skills/design-system-migration-agent/SKILL.md +75 -9
  27. package/package.json +14 -4
  28. package/dist/typography-B-BeIk0v.d.ts +0 -120
package/README.MD CHANGED
@@ -1,232 +1,214 @@
1
1
  # @atomazing-org/design-system
2
2
 
3
- Modern MUI v7 + Emotion design system with strongly differentiated visual presets, scheme-based light/dark tokens, SSR-safe theming, and persistence.
3
+ Modern MUI v7 + Emotion design system built around visual presets, explicit
4
+ light and dark schemes, SSR-safe theming, and persisted runtime settings.
4
5
 
5
6
  ## Preview
6
- ![Design system preview](https://raw.githubusercontent.com/atomazing/design-system/master/preview.gif)
7
-
8
- ## Why use it
9
-
10
- - **True light/dark themes**: each preset ships **two curated schemes** (`light` + `dark`), so backgrounds, cards, and text actually change (not just `palette.mode`).
11
- - **Works out of the box**: includes ready-made presets you can use immediately.
12
- - **Easy to extend**: bring your own presets, or combine defaults + custom.
13
- - **Consistent UI**: global styles + MUI component overrides for predictable visuals.
14
- - **Safe persistence**: remembers selected theme + dark mode with SSR-safe guards.
15
-
16
- ---
17
7
 
8
+ ![Design system preview](./preview.gif)
9
+
10
+ ## At A Glance
11
+
12
+ - React 18 and 19 support
13
+ - MUI 7 + Emotion 11
14
+ - Preset-first theming via `ThemePreset`
15
+ - Runtime theme and dark-mode switching
16
+ - SSR-safe provider flow
17
+ - Curated root API plus `/presets` entrypoint
18
+
19
+ ## Contents
20
+
21
+ - [Why This Library](#why-this-library)
22
+ - [Installation](#installation)
23
+ - [Package Format](#package-format)
24
+ - [Quick Start](#quick-start)
25
+ - [Built-In Presets](#built-in-presets)
26
+ - [Dark Mode](#dark-mode)
27
+ - [Custom Presets](#custom-presets)
28
+ - [Persistence](#persistence)
29
+ - [SSR Notes](#ssr-notes)
30
+ - [API Reference](#api-reference)
31
+ - [Migration Docs](#migration-docs)
32
+ - [Examples](#examples)
33
+ - [Troubleshooting](#troubleshooting)
34
+ - [Contributing](#contributing)
35
+ - [Releases](#releases)
36
+ - [License](#license)
37
+
38
+ ## Why This Library
39
+
40
+ - Preset-first theming built on `ThemePreset`, not ad hoc per-app theme files
41
+ - True light and dark schemes via `colorSchemes`, not only `palette.mode`
42
+ - Strong visual differentiation between presets instead of subtle palette swaps
43
+ - Runtime theme selection and dark-mode switching with persisted settings
44
+ - SSR-safe provider flow with no browser APIs touched at module scope
45
+ - Curated public API for app integrations and consumer documentation
46
+ - Test coverage for contrast, baseline preset shape, and SSR behavior
18
47
 
19
48
  ## Installation
20
49
 
21
- Install the library:
50
+ ### npm
22
51
 
23
52
  ```bash
24
- npm install @atomazing-org/design-system
53
+ npm install @atomazing-org/design-system react react-dom @mui/material @emotion/react @emotion/styled
25
54
  ```
26
55
 
27
- Install required peer dependencies (React 18/19 + MUI v7 + Emotion core):
56
+ ### pnpm
28
57
 
29
58
  ```bash
30
- npm install react react-dom @mui/material @emotion/react @emotion/styled
59
+ pnpm add @atomazing-org/design-system react react-dom @mui/material @emotion/react @emotion/styled
31
60
  ```
32
61
 
33
- Optional peers:
62
+ Optional peer:
34
63
 
35
- - `@mui/icons-material` (only if your app imports MUI icons)
36
- - `@emotion/css` (only if your project uses Emotion `css` helpers)
64
+ - `@mui/icons-material`
37
65
 
38
- ```bash
39
- npm install @mui/icons-material @emotion/css
40
- ```
66
+ Expected ecosystem:
41
67
 
42
- ### Package format (v2)
68
+ - React `^18 || ^19`
69
+ - React DOM `^18 || ^19`
70
+ - MUI `^7`
71
+ - Emotion `^11`
43
72
 
44
- `@atomazing-org/design-system` v2 is **ESM-only**.
45
- Use ESM imports (`import ... from ...`). CommonJS `require()` is not supported.
73
+ ## Package Format
46
74
 
47
- ---
75
+ - ESM-only package
76
+ - Public entrypoints:
77
+ - `@atomazing-org/design-system`
78
+ - `@atomazing-org/design-system/presets`
48
79
 
49
- ## Quick start
80
+ The root entrypoint is intentionally curated. Preset registries and individual
81
+ presets live under the `/presets` subpath.
50
82
 
51
- Use built-in presets (recommended starting point):
83
+ ## Quick Start
52
84
 
53
85
  ```tsx
86
+ import ReactDOM from "react-dom/client";
54
87
  import { ThemeProviderWrapper } from "@atomazing-org/design-system";
55
88
  import { defaultThemes } from "@atomazing-org/design-system/presets";
56
89
 
57
- export function App() {
58
- return (
59
- <ThemeProviderWrapper themes={defaultThemes}>
60
- {/* your app */}
61
- </ThemeProviderWrapper>
62
- );
63
- }
64
- ```
65
-
66
- Notes:
67
- - `themes` can be **default presets**, **your presets**, or **both**.
68
- - Theme choice + dark mode are persisted (storage key: `appSettings`).
69
-
70
- ---
71
-
72
- ## Built-in presets
73
-
74
- Built-in presets are **ready-made theme packs shipped with the library**.
75
- You can use them as-is, or add your own presets alongside them.
76
-
77
- | Preset | Stable id | Best for |
78
- |---|---|---|
79
- | Warm Earth | `warm-earth` | Warm and friendly apps |
80
- | Editorial Classic | `editorial-classic` | Content-heavy UIs |
81
- | Modern Minimal | `modern-minimal` | Dashboards and tooling |
82
- | Neo Glass | `neo-glass` | Modern “glass” style UIs |
83
- | Retro Terminal | `retro-terminal` | Terminal-inspired branding |
84
-
85
- Import them from:
86
-
87
- ```ts
88
- import { defaultThemes } from "@atomazing-org/design-system/presets";
89
- ```
90
-
91
- ## Switching theme (UI)
92
-
93
- Build a simple theme switcher using the library’s theme settings hook.
94
-
95
- ```tsx
96
- import { ToggleButton, ToggleButtonGroup } from "@mui/material";
97
- import { useThemeSettings } from "@atomazing-org/design-system";
98
- import { defaultThemes } from "@atomazing-org/design-system/presets";
99
-
100
- export function ThemeSwitcher() {
101
- const { theme, setTheme } = useThemeSettings();
90
+ import App from "./App";
102
91
 
103
- return (
104
- <ToggleButtonGroup
105
- size="small"
106
- exclusive
107
- value={theme}
108
- onChange={(_, next) => next && setTheme(next)}
109
- >
110
- {defaultThemes.map((t) => (
111
- <ToggleButton key={t.id} value={t.id}>
112
- {t.label}
113
- </ToggleButton>
114
- ))}
115
- </ToggleButtonGroup>
116
- );
117
- }
92
+ ReactDOM.createRoot(document.getElementById("root")!).render(
93
+ <ThemeProviderWrapper themes={defaultThemes}>
94
+ <App />
95
+ </ThemeProviderWrapper>,
96
+ );
118
97
  ```
119
98
 
120
- ---
121
-
122
- ## Dark mode
99
+ Use `useThemeSettings()` when you need runtime access to:
123
100
 
124
- Dark mode switches the active **scheme** inside the current preset.
101
+ - the selected preset id
102
+ - the current dark-mode setting
103
+ - setters for both
125
104
 
126
- ### Supported values
127
-
128
- - `light` — always use the preset’s light scheme
129
- - `dark` — always use the preset’s dark scheme
130
- - `system` — follow OS/browser preference (`prefers-color-scheme`)
131
-
132
- ### Why `system` exists
133
-
134
- It’s the most common UX: the app automatically follows the user’s OS preference without custom code in every project.
135
-
136
- Example selector:
105
+ Example:
137
106
 
138
107
  ```tsx
139
- import { RadioGroup, FormControlLabel, Radio } from "@mui/material";
140
108
  import { useThemeSettings } from "@atomazing-org/design-system";
141
109
 
142
- export function DarkModeSelector() {
143
- const { darkMode, setDarkMode } = useThemeSettings();
110
+ export function ThemeDebug() {
111
+ const { theme, darkMode, setTheme, setDarkMode } = useThemeSettings();
144
112
 
145
113
  return (
146
- <RadioGroup row value={darkMode} onChange={(e) => setDarkMode(e.target.value as any)}>
147
- <FormControlLabel value="system" control={<Radio />} label="System" />
148
- <FormControlLabel value="light" control={<Radio />} label="Light" />
149
- <FormControlLabel value="dark" control={<Radio />} label="Dark" />
150
- </RadioGroup>
114
+ <>
115
+ <button onClick={() => setTheme("modern-minimal")}>Modern Minimal</button>
116
+ <button onClick={() => setDarkMode("dark")}>Dark</button>
117
+ <pre>{JSON.stringify({ theme, darkMode }, null, 2)}</pre>
118
+ </>
151
119
  );
152
120
  }
153
121
  ```
154
122
 
155
- ### Forcing mode (optional)
123
+ ## Built-In Presets
156
124
 
157
- If your app does not support dark mode, you can force the effective palette mode:
158
-
159
- ```tsx
160
- import { ThemeProviderWrapper } from "@atomazing-org/design-system";
161
- import { defaultThemes } from "@atomazing-org/design-system/presets";
125
+ Ship-ready preset packs live under `@atomazing-org/design-system/presets`.
162
126
 
163
- export function App() {
164
- return (
165
- <ThemeProviderWrapper themes={defaultThemes} darkMode="light">
166
- {/* your app */}
167
- </ThemeProviderWrapper>
168
- );
169
- }
127
+ ```ts
128
+ import {
129
+ allBuiltInThemes,
130
+ defaultThemes,
131
+ landingPageThemes,
132
+ modernMinimal,
133
+ } from "@atomazing-org/design-system/presets";
170
134
  ```
171
135
 
172
- Note: when `darkMode` is set, `darkMode` is locked and `setDarkMode` is ignored.
173
-
174
- ---
175
-
176
- ## Persistence (`appSettings`)
136
+ ### `defaultThemes`
177
137
 
178
- Theme selection is persisted in `localStorage` under the key `appSettings`.
138
+ Baseline application presets:
179
139
 
180
- v2 JSON shape:
181
-
182
- ```json
183
- { "themeId": "editorial-classic", "darkMode": "system" }
184
- ```
140
+ - `Editorial Classic`
141
+ - `Airport Ops`
142
+ - `Modern Minimal`
143
+ - `Neo Glass`
144
+ - `Retro Terminal`
145
+ - `Warm Earth`
185
146
 
186
- Notes:
187
- - v2 stores only `themeId` and `darkMode`.
188
- - v2 does not migrate legacy stored formats (`theme`, `version`, `auto`); invalid/legacy payloads reset to defaults.
147
+ ### `landingPageThemes`
189
148
 
190
- ---
149
+ Extended pack for landing pages, brand-heavy surfaces, and more expressive
150
+ visual directions. Representative families include:
191
151
 
192
- ## App migration routes (repo docs)
152
+ - `Flow Editorial`
153
+ - `Acid Editorial`
154
+ - `Bauhaus Ops`
155
+ - `Neon Bauhaus Grid`
156
+ - `Neon Bauhaus Ops`
157
+ - `Brutalist Sprint`
158
+ - `Brand Neon Motion`
159
+ - `Glass Reactor`
160
+ - `Holographic Ledger`
161
+ - `Kintsugi Protocol`
162
+ - `Solarpunk Enterprise`
193
163
 
194
- If you are migrating an app to v2, use the route runbooks under:
164
+ ### `allBuiltInThemes`
195
165
 
196
- - `migrations/docs/migrations/design-system/README.md`
197
- - `migrations/docs/migrations/design-system/routes/*`
166
+ Combined pack of `defaultThemes` and `landingPageThemes`.
198
167
 
199
- `examples/react-app` is the canonical Vite consumer smoke app for local v2 validation (`npm run smoke:react-app`).
200
- `examples/next-app-router` is the canonical Next.js App Router SSR reference consumer (`npm run smoke:next`).
168
+ ## Dark Mode
201
169
 
202
- ---
170
+ Supported dark-mode values:
203
171
 
204
- ## Custom themes
172
+ - `light`
173
+ - `dark`
174
+ - `system`
205
175
 
206
- Provide your own preset(s) to the provider. A preset is one identifiable theme with **two schemes**: `light` and `dark`.
176
+ `ThemeProviderWrapper` resolves the effective scheme from the selected dark-mode
177
+ value and the current system preference. The root export `darkModeOptions` is
178
+ available for building dark-mode UI controls.
207
179
 
208
- ### API reference — `ThemePreset`
180
+ ```tsx
181
+ import { darkModeOptions, useThemeSettings } from "@atomazing-org/design-system";
182
+ import { FormControlLabel, Radio, RadioGroup } from "@mui/material";
209
183
 
210
- | Field | Type | What it means |
211
- |---|---|---|
212
- | `id` | `string` | Stable identifier used for persistence and deduplication. Must be unique. |
213
- | `label` | `string` | Name shown in UI selectors. |
214
- | `colorSchemes.light` | `ThemeOptions` | MUI ThemeOptions for light mode. |
215
- | `colorSchemes.dark` | `ThemeOptions` | MUI ThemeOptions for dark mode. |
184
+ export function DarkModeSelector() {
185
+ const { darkMode, setDarkMode } = useThemeSettings();
216
186
 
217
- ### Minimum required tokens per scheme
187
+ return (
188
+ <RadioGroup
189
+ row
190
+ value={darkMode}
191
+ onChange={(event) => setDarkMode(event.target.value as typeof darkMode)}
192
+ >
193
+ {darkModeOptions.map((option) => (
194
+ <FormControlLabel
195
+ key={option.value}
196
+ control={<Radio />}
197
+ label={option.label}
198
+ value={option.value}
199
+ />
200
+ ))}
201
+ </RadioGroup>
202
+ );
203
+ }
204
+ ```
218
205
 
219
- Each scheme must define:
220
- - `palette.background.default` — page background
221
- - `palette.background.paper` — Card/Paper background
222
- - `palette.text.primary`
223
- - `palette.text.secondary`
224
- - `palette.divider`
206
+ ## Custom Presets
225
207
 
226
- Example:
208
+ Custom presets should follow the `ThemePreset` contract.
227
209
 
228
210
  ```ts
229
- import type { ThemePreset } from "@atomazing-org/design-system";
211
+ import type { ThemePreset } from "@atomazing-org/design-system/presets";
230
212
 
231
213
  export const myPreset: ThemePreset = {
232
214
  id: "my-brand",
@@ -236,241 +218,187 @@ export const myPreset: ThemePreset = {
236
218
  palette: {
237
219
  background: { default: "#ffffff", paper: "#ffffff" },
238
220
  text: { primary: "#111111", secondary: "#444444" },
239
- divider: "rgba(0,0,0,0.12)",
221
+ divider: "rgba(0, 0, 0, 0.12)",
240
222
  },
241
223
  },
242
224
  dark: {
243
225
  palette: {
244
226
  background: { default: "#0f1115", paper: "#151922" },
245
227
  text: { primary: "#f1f3f5", secondary: "#c6cbd1" },
246
- divider: "rgba(241,243,245,0.16)",
228
+ divider: "rgba(241, 243, 245, 0.16)",
247
229
  },
248
230
  },
249
231
  },
250
232
  };
251
233
  ```
252
234
 
253
- ### Using defaults + custom presets
235
+ Merge custom presets with the built-ins:
254
236
 
255
237
  ```ts
256
- import { defaultThemes } from "@atomazing-org/design-system/presets";
257
-
258
238
  const themes = [...defaultThemes, myPreset];
259
239
  ```
260
240
 
261
- Then pass `themes` into `ThemeProviderWrapper`.
241
+ Rules worth keeping in mind:
262
242
 
263
- ---
243
+ - preset ids must be unique and non-empty
244
+ - duplicate ids are deduped by id with last-wins token resolution
245
+ - first occurrence order is preserved for the visible preset list
264
246
 
265
- ## Typography variants
247
+ ## Persistence
266
248
 
267
- The library adds extra typography variants (beyond MUI defaults) so your text styles are consistent across the app.
249
+ Theme settings are stored in `localStorage` under `appSettings` by default.
268
250
 
269
- ```tsx
270
- import { Typography } from "@mui/material";
251
+ Current JSON shape:
271
252
 
272
- export function TypographyDemo() {
273
- return (
274
- <>
275
- <Typography variant="header_lg_bold">Page title</Typography>
276
- <Typography variant="text_md_regular">Body text</Typography>
277
- <Typography variant="text_sm_bold">Caption / label</Typography>
278
- </>
279
- );
280
- }
253
+ ```json
254
+ { "themeId": "editorial-classic", "darkMode": "system" }
281
255
  ```
282
256
 
283
- Notes:
284
- - Typography sizing is expected to be **rem-based** (scales with the user’s browser font size settings).
285
- - Variants are defined in the design system theme (no local “one-off” styles needed).
286
-
287
- ---
288
-
289
- ## Global styles
290
-
291
- `ThemeProviderWrapper` applies global styles (via Emotion) and MUI component defaults, so the app looks consistent immediately.
292
-
293
- Set a custom font stack:
257
+ If multiple applications share the same origin, override the storage key with
258
+ `settingsStorageKey` on `ThemeProviderWrapper`.
294
259
 
295
260
  ```tsx
296
- import { ThemeProviderWrapper } from "@atomazing-org/design-system";
297
-
298
- export function App() {
299
- return (
300
- <ThemeProviderWrapper fontFamily="Inter, system-ui, -apple-system, 'Segoe UI', Roboto, Arial, sans-serif">
301
- {/* your app */}
302
- </ThemeProviderWrapper>
303
- );
304
- }
261
+ <ThemeProviderWrapper
262
+ themes={defaultThemes}
263
+ settingsStorageKey="pampaLegacyThemeSettings"
264
+ >
265
+ <App />
266
+ </ThemeProviderWrapper>
305
267
  ```
306
268
 
307
- ---
308
-
309
- ## Animations
269
+ ## SSR Notes
310
270
 
311
- The library exports reusable keyframes so you can keep motion consistent.
271
+ - Keep `ThemeProviderWrapper` inside a client boundary for Next.js and other SSR
272
+ apps.
273
+ - Do not access `window`, `document`, or `localStorage` at module scope.
274
+ - When dark mode uses `system`, the effective mode resolves on the client after
275
+ hydration.
312
276
 
313
- ```tsx
314
- import styled from "@emotion/styled";
315
- import { fadeIn } from "@atomazing-org/design-system";
277
+ ## API Reference
316
278
 
317
- const Panel = styled.div`
318
- animation: ${fadeIn} 240ms ease-in both;
319
- `;
279
+ ### `ThemeProviderWrapper`
320
280
 
321
- export function AnimatedPanel() {
322
- return <Panel>Content</Panel>;
323
- }
324
- ```
281
+ | Prop | Type | Default | Description |
282
+ | --- | --- | --- | --- |
283
+ | `themes` | `ThemePreset[]` | `defaultThemes` | Preset list used by the provider. |
284
+ | `fontFamily` | `string` | `undefined` | Optional global font stack applied by `GlobalStyles`. |
285
+ | `darkMode` | `"light" \| "dark" \| "system"` | `undefined` | Optional hard override for dark mode. |
286
+ | `initialThemeId` | `string` | `undefined` | Fallback theme id when persisted settings are absent. |
287
+ | `initialDarkMode` | `"light" \| "dark" \| "system"` | `undefined` | Fallback dark mode when persisted settings are absent. |
288
+ | `settingsStorageKey` | `string` | `"appSettings"` | Optional localStorage key override. |
289
+ | `children` | `ReactNode` | required | Application content. |
325
290
 
326
- ---
291
+ If `darkMode` is passed as a prop, `setDarkMode()` becomes a no-op because the
292
+ provider is operating in controlled override mode.
327
293
 
328
- ## SSR notes
294
+ ### `useThemeSettings()`
329
295
 
330
- - The library is written to be **SSR-safe**: no `window`/`document`/`localStorage` access at module scope.
331
- - If you use **system** dark mode, the effective mode is derived from `prefers-color-scheme` on the client.
332
- - In Next.js, place the provider inside a client boundary (e.g., a component with `"use client"`), then wrap your app with `ThemeProviderWrapper`.
296
+ Returns:
333
297
 
334
- ## Consumer alias guidance (optional)
298
+ - `theme`
299
+ - `setTheme(themeId)`
300
+ - `darkMode`
301
+ - `setDarkMode(mode)`
302
+ - `themes`
303
+ - `selectedTheme`
304
+ - `defaultThemeName`
335
305
 
336
- Aliases are **optional**. They help you avoid long relative imports **inside your app**.
306
+ ### Root Exports
337
307
 
338
- ---
308
+ The curated root entrypoint exports:
339
309
 
340
- ## Local development (repo)
310
+ - `ThemeProviderWrapper`
311
+ - `useThemeSettings`
312
+ - `mergeThemes`
313
+ - `normalizeThemes`
314
+ - `resolveDefaultThemeName`
315
+ - `resolveThemeById`
316
+ - `GlobalStyles`
317
+ - `buildMuiTheme`
318
+ - `resolveEffectiveMode`
319
+ - `selectThemeOptions`
320
+ - `validateSchemeTokens`
321
+ - `darkModeOptions`
322
+ - `useSystemTheme`
323
+ - `readAppSettings`
324
+ - `writeAppSettings`
341
325
 
342
- From the repository root:
326
+ Preset registries and individual presets live under
327
+ `@atomazing-org/design-system/presets`.
343
328
 
344
- ```bash
345
- pnpm lint
346
- pnpm build
347
- pnpm test
348
- pnpm -C examples/react-app dev
349
- pnpm -C examples/next-app-router dev
350
- ```
329
+ ## Migration Docs
351
330
 
352
- ---
331
+ If you are migrating an existing app to this package, start with:
353
332
 
354
- ## Peer dependencies
355
-
356
- Make sure your app installs these (MUI v7 + Emotion):
357
-
358
- - `react`
359
- - `react-dom`
360
- - `@mui/material`
361
- - `@mui/icons-material` (optional, only if you use icons from MUI)
362
- - `@emotion/react`
363
- - `@emotion/styled`
364
- - `@emotion/css` (optional)
365
-
366
- ---
367
-
368
- ## Troubleshooting
369
-
370
- ### Dark mode switches, but background/cards do not change
371
- - Ensure your preset provides **both schemes**:
372
- - `colorSchemes.light.palette.background.default/paper`
373
- - `colorSchemes.dark.palette.background.default/paper`
374
- - Avoid hardcoded colors in overrides. Use `theme.palette.*` tokens.
375
-
376
- ### Text is hard to read in dark mode
377
- - Do not reuse light “ink” constants in dark mode.
378
- - Check:
379
- - `palette.text.primary` vs `palette.background.default`
380
- - `palette.text.secondary` vs `palette.background.paper`
333
+ - `migrations/README.UPDATE.md`
334
+ - `migrations/docs/migrations/design-system/README.md`
335
+ - `migrations/docs/migrations/design-system/shared/WORKING-RULES.md`
336
+ - `migrations/skills/design-system-consumer-agent/SKILL.md`
337
+ - `migrations/skills/design-system-migration-agent/SKILL.md`
381
338
 
382
- ### I want to add my own presets
383
- - Create a `ThemePreset` with `colorSchemes.light` and `colorSchemes.dark`.
384
- - Combine with defaults: `const themes = [...defaultThemes, myPreset];`
339
+ ## Examples
385
340
 
386
- ## Examples (`examples/react-app`, `examples/next-app-router`)
341
+ Run examples from the repository root after `pnpm install`.
387
342
 
388
- The repo includes runnable example apps that demonstrate:
389
- - preset switching
390
- - dark mode switching
391
- - background + card surfaces changing correctly
392
- - token/debug view (if enabled in the example)
393
- - Next.js App Router SSR integration with a client provider boundary
343
+ ### React App Smoke Consumer
394
344
 
395
- Run it from the repository root:
345
+ Fastest local validation path for presets and runtime theme switching:
396
346
 
397
347
  ```bash
398
- pnpm -C examples/react-app dev
399
- pnpm -C examples/next-app-router dev
348
+ pnpm --dir examples/react-app dev
400
349
  ```
401
350
 
402
- What to check in the UI:
403
- - switching to **dark** changes the **page background** and **Card/Paper** background
404
- - text stays readable on both backgrounds
405
- - inputs, buttons, menus, and dialogs remain usable
406
- - Next.js example keeps SSR stable while theme state finalizes on the client
351
+ ### Next.js App Router Reference
407
352
 
408
- ---
409
-
410
- ## API reference — `ThemeProviderWrapper`
411
-
412
- `ThemeProviderWrapper` wires MUI ThemeProvider, global styles, and persisted settings.
413
-
414
- | Prop | Type | Default | What it does |
415
- |---|---|---|---|
416
- | `themes` | `ThemePreset[]` (or built-in `defaultThemes`) | `defaultThemes` | List of presets available to the user. |
417
- | `fontFamily` | `string` | (theme default) | Optional global font stack for the whole app. |
418
- | `darkMode` | `DarkModeOptions` | - | Forces mode regardless of persisted settings and system preference. |
419
- | `children` | `ReactNode` | — | Your application tree. |
420
-
421
- Minimal usage:
422
-
423
- ```tsx
424
- import { ThemeProviderWrapper } from "@atomazing-org/design-system";
425
- import { defaultThemes } from "@atomazing-org/design-system/presets";
353
+ Starter reference for SSR-safe integration:
426
354
 
427
- export function App() {
428
- return (
429
- <ThemeProviderWrapper themes={defaultThemes}>
430
- {/* your app */}
431
- </ThemeProviderWrapper>
432
- );
433
- }
355
+ ```bash
356
+ pnpm --dir examples/next-app-router dev
434
357
  ```
435
358
 
436
- ---
437
-
438
- ## Public exports (recommended imports)
359
+ ## Troubleshooting
439
360
 
440
- Use only these stable entry points:
361
+ - Dark mode does not visibly change the app:
362
+ Ensure both `colorSchemes.light` and `colorSchemes.dark` define
363
+ `palette.background.default`, `palette.background.paper`, and readable text
364
+ colors.
365
+ - Preset switching appears stuck:
366
+ Check for duplicate or empty preset ids and clear the relevant
367
+ `localStorage` key if invalid persisted state exists.
368
+ - One app keeps overwriting another app's theme:
369
+ Use a custom `settingsStorageKey` instead of the shared default key.
370
+ - SSR build or hydration warnings appear:
371
+ Make sure the provider is mounted in a client boundary and that no browser API
372
+ access happens at module scope.
373
+
374
+ ## Contributing
441
375
 
442
- ### Core API
443
- ```ts
444
- import { ThemeProviderWrapper, useThemeSettings } from "@atomazing-org/design-system";
445
- ```
446
-
447
- ### Built-in presets
448
- ```ts
449
- import { defaultThemes } from "@atomazing-org/design-system/presets";
376
+ ```bash
377
+ pnpm lint
378
+ pnpm test
379
+ pnpm build
380
+ pnpm run smoke:esm
381
+ pnpm run smoke:react-app
382
+ pnpm run smoke:next
383
+ pnpm run check:migration-readiness
450
384
  ```
451
385
 
452
- Tip:
453
- - Avoid deep imports from internal folders. They may change during refactors.
386
+ ## Releases
454
387
 
455
- ---
388
+ This repo uses Changesets for package versioning and release automation.
456
389
 
457
- ## Migration notes (if upgrading)
390
+ Intended flow:
458
391
 
459
- If you previously passed a single theme object or a legacy “theme list”:
460
- 1) Move your theme into a preset shape with **two schemes**:
461
- - `colorSchemes.light`
462
- - `colorSchemes.dark`
463
- 2) Ensure each scheme defines the required tokens:
464
- - `background.default`, `background.paper`
465
- - `text.primary`, `text.secondary`
466
- - `divider`
467
- 3) Pass presets into the provider:
468
- - `themes={[...defaultThemes, myPreset]}` or only `[myPreset]`
392
+ - run `pnpm changeset`
393
+ - merge changes into `master`
394
+ - GitHub Actions opens or updates a release PR
395
+ - merge the release PR to publish to npm
469
396
 
470
- Goal:
471
- - dark mode changes **real palette tokens**, so backgrounds/cards/text update together.
397
+ See:
472
398
 
473
- ---
399
+ - `RELEASING.md` for the release checklist and example changeset
400
+ - `RELEASE-STATUS.md` if automation is temporarily blocked by GitHub
401
+ organization permissions
474
402
 
475
403
  ## License
476
404