@atomazing-org/design-system 1.1.1 → 1.2.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 CHANGED
@@ -1,345 +1,257 @@
1
- @atomazing-org/design-system
2
-
3
- Modern MUI + Emotion design system with a ready theme factory, extended typography, global styles, component overrides, animations, and handy utilities.
4
-
5
- Contents
6
- - Introduction
7
- - Installation
8
- - Quick Start
9
- - Provider Props
10
- - Dynamic Themes (array)
11
- - Theme Switching (UI)
12
- - Dark Mode Control
13
- - Extended Palette (4 variants)
14
- - Palette Overrides
15
- - Using Palette In SX
16
- - Typography Variants
17
- - Global Styles
18
- - Animations
19
- - Components
20
- - Utilities
21
- - SSR Notes
22
- - Peer Dependencies
23
-
24
- Introduction
25
- The package streamlines consistent theming across apps: dark/light mode, typography variants, global styles, and component defaults. Built on MUI v7 + Emotion.
26
-
27
- Installation
28
- ```bash
29
- npm install @atomazing-org/design-system
30
- npm install @mui/material @mui/icons-material @emotion/react @emotion/styled @emotion/css
31
- ```
32
-
33
- Quick Start
34
- ```tsx
35
- import { ThemeProviderWrapper } from '@atomazing-org/design-system';
36
-
37
- export function App() {
38
- return (
39
- <ThemeProviderWrapper>
40
- {/* your app */}
41
- </ThemeProviderWrapper>
42
- );
43
- }
44
- ```
45
-
46
- If `themes` is not provided, the provider falls back to a single "Default" theme using the current palette brand color.
47
-
48
- Provider Props
49
- - `themes?: ThemesProp` (single theme may omit `name`, multiple themes require `name`)
50
- - `fontFamily?: string`
51
- - `colorPaletteOverride?: Partial<ColorPaletteType>`
52
- `ThemeOptions` is the MUI theme options type from `@mui/material/styles`.
53
-
54
- Theme Names
55
- Single theme can omit `name` (defaults to `"Default"`). Multiple themes require a non-empty `name` for each theme.
56
-
57
- Before (single theme required a name):
58
- ```tsx
59
- <ThemeProviderWrapper
60
- themes={[
61
- {
62
- name: 'Blue',
63
- palette: { primary: { main: '#3B82F6' } },
64
- },
65
- ]}
66
- />
67
- ```
68
-
69
- After (single theme name omitted):
70
- ```tsx
71
- <ThemeProviderWrapper
72
- themes={[
73
- {
74
- palette: { primary: { main: '#3B82F6' } },
75
- },
76
- ]}
77
- />
78
- ```
79
-
80
- Multiple themes (name required):
81
- ```tsx
82
- <ThemeProviderWrapper
83
- themes={[
84
- {
85
- name: 'BrandA',
86
- palette: { primary: { main: '#00A3FF' } },
87
- },
88
- {
89
- name: 'BrandB',
90
- palette: { primary: { main: '#10B981' } },
91
- },
92
- ]}
93
- />
94
- ```
95
-
96
- Dynamic Themes (array)
97
- Provide a fully dynamic list of `ThemeOptions` overrides. Names are required when supplying multiple themes. Provider-controlled `palette.mode` always wins.
98
-
99
- Minimal example (primary color only):
100
- ```tsx
101
- <ThemeProviderWrapper
102
- themes={[
103
- {
104
- name: 'Blue',
105
- palette: {
106
- primary: { main: '#3B82F6' },
107
- },
108
- },
109
- ]}
110
- >
111
- {/* ... */}
112
- </ThemeProviderWrapper>
113
- ```
114
-
115
- Advanced example (palette + components overrides):
116
- ```tsx
117
- <ThemeProviderWrapper
118
- themes={[
119
- {
120
- name: 'BrandA',
121
- palette: {
122
- primary: { main: '#00A3FF' },
123
- background: { default: '#F7FAFF', paper: '#FFFFFF' },
124
- },
125
- components: {
126
- MuiButton: {
127
- styleOverrides: {
128
- root: { textTransform: 'none' },
129
- },
130
- },
131
- },
132
- },
133
- ]}
134
- >
135
- {/* ... */}
136
- </ThemeProviderWrapper>
137
- ```
138
-
139
- Migration Notes (breaking)
140
- - Legacy `themes` shape (`primaryColor`, `secondaryColor`, `background`) removed.
141
- - `themeOverrides` prop removed.
142
- - Use `themes: ThemesProp` for customization (single theme may omit `name`, multiple themes require `name`).
143
-
144
- Theme Switching (UI)
145
- Use the theme context to read and change the active theme.
146
-
147
- ```tsx
148
- import { useThemeSettings } from '@atomazing-org/design-system';
149
- import { ToggleButton, ToggleButtonGroup } from '@mui/material';
150
-
151
- export function ThemeToggle() {
152
- const { theme, setTheme } = useThemeSettings();
153
- const options = ['Blue', 'Green', 'Gray'];
154
-
155
- return (
156
- <ToggleButtonGroup
157
- size="small"
158
- exclusive
159
- color="brand"
160
- value={theme}
161
- onChange={(_, v) => v && setTheme(v)}
162
- >
163
- {options.map((o) => (
164
- <ToggleButton key={o} value={o}>{o}</ToggleButton>
165
- ))}
166
- </ToggleButtonGroup>
167
- );
168
- }
169
- ```
170
-
171
- Dark Mode Control
172
- Use `useThemeSettings()` to read and set dark mode. Modes: `light | dark | system | auto`.
173
-
174
- ```tsx
175
- import { useThemeSettings, darkModeOptions } from '@atomazing-org/design-system';
176
- import { RadioGroup, FormControlLabel, Radio } from '@mui/material';
177
-
178
- export function DarkModeSelector() {
179
- const { darkMode, setDarkMode } = useThemeSettings();
180
- const options = darkModeOptions; // label + icon
181
-
182
- return (
183
- <RadioGroup
184
- row
185
- value={darkMode}
186
- onChange={(e) => setDarkMode(e.target.value as any)}
187
- >
188
- {options.map((o) => (
189
- <FormControlLabel key={o.value} value={o.value} control={<Radio />} label={o.label} />
190
- ))}
191
- </RadioGroup>
192
- );
193
- }
194
- ```
195
-
196
- Extended Palette (4 variants)
197
- The design system adds four typed colors to the MUI palette, available on common components via the `color` prop:
198
-
199
- - brand: project brand color (uses the active theme `primary`).
200
- - neutral: neutral/gray scale color (from the design-system palette).
201
- - accent: supporting accent color (from palette `accent`).
202
- - muted: soft/desaturated color (based on neutral by default).
203
-
204
- Supported components: `Button`, `Chip`, `Badge`, `Alert`.
205
-
206
- ```tsx
207
- import { Button, Chip, Alert } from '@mui/material';
208
-
209
- <Button color="brand" variant="contained">Brand</Button>
210
- <Button color="neutral" variant="outlined">Neutral</Button>
211
- <Chip color="accent" label="Accent" />
212
- <Alert color="muted" variant="filled">Muted Alert</Alert>
213
- ```
214
-
215
- Palette Overrides
216
- Override base palette tokens for the whole app.
217
-
218
- ```tsx
219
- <ThemeProviderWrapper
220
- colorPaletteOverride={{
221
- brand: '#4F46E5',
222
- accent: '#F59E0B',
223
- muted: '#94A3B8',
224
- neutral: '#64748B',
225
- success: '#16A34A',
226
- warning: '#D97706',
227
- error: '#DC2626',
228
- info: '#0284C7',
229
- }}
230
- >
231
- {/* ... */}
232
- </ThemeProviderWrapper>
233
- ```
234
-
235
- Using Palette In SX
236
- ```tsx
237
- import { Box } from '@mui/material';
238
-
239
- <Box sx={{ bgcolor: (t) => t.palette.accent.main, color: (t) => t.palette.getContrastText(t.palette.accent.main) }}>
240
- Accent surface
241
- </Box>
242
- ```
243
-
244
- Typography Variants
245
- Extra variants are available (mapping to `<p>`/headers). Examples:
246
-
247
- ```tsx
248
- import { Typography } from '@mui/material';
249
-
250
- <Typography variant="text_md_regular">Body text</Typography>
251
- <Typography variant="text_sm_bold">Strong caption</Typography>
252
- <Typography variant="header_lg_bold">Section Title</Typography>
253
- <Typography variant="header_md_semibold">Semibold Heading</Typography>
254
- ```
255
-
256
- Global Styles
257
- `ThemeProviderWrapper` injects global styles via Emotion. You can also set a custom font family:
258
-
259
- ```tsx
260
- <ThemeProviderWrapper fontFamily="Inter, system-ui, -apple-system, 'Segoe UI', Roboto, Arial, sans-serif">
261
- {/* ... */}
262
- </ThemeProviderWrapper>
263
- ```
264
-
265
- Animations
266
- Keyframes ready for use in Emotion/MUI `sx`:
267
-
268
- ```tsx
269
- import { keyframes } from '@emotion/react';
270
- import { fadeIn, slideIn, scale, pulseAnimation, progressPulse } from '@atomazing-org/design-system';
271
- import styled from '@emotion/styled';
272
-
273
- const Card = styled.div`
274
- animation: ${fadeIn} 300ms ease-in both;
275
- `;
276
-
277
- const Glowing = styled.div`
278
- animation: ${progressPulse('#9FA9EA')} 2s ease-in-out infinite;
279
- `;
280
- ```
281
-
282
- Components
283
- - ErrorBoundary
284
- ```tsx
285
- import { ErrorBoundary } from '@atomazing-org/design-system';
286
-
287
- <ErrorBoundary>
288
- <App />
289
- </ErrorBoundary>
290
- ```
291
-
292
- - Loading
293
- ```tsx
294
- import { Loading } from '@atomazing-org/design-system';
295
-
296
- <Loading />
297
- ```
298
-
299
- - PathName / DialogBtn
300
- ```tsx
301
- import { PathName, DialogBtn } from '@atomazing-org/design-system';
302
-
303
- <PathName>/settings/profile</PathName>
304
- <DialogBtn variant="contained" color="brand">OK</DialogBtn>
305
- ```
306
-
307
- Utilities
308
- ```tsx
309
- import {
310
- getFontColor, isFontLight, isHexColor,
311
- timeAgo, timeAgoFromStart,
312
- useResponsiveDisplay, useSystemTheme,
313
- displayGreeting, getDayIdentifier,
314
- systemInfo,
315
- } from '@atomazing-org/design-system';
316
-
317
- // Colors
318
- getFontColor('#ffffff'); // '#101727' | '#f0f0f0'
319
- isFontLight('#222');
320
- isHexColor('#abc');
321
-
322
- // Time
323
- timeAgo(new Date(Date.now() - 3600_000));
324
- timeAgoFromStart(new Date(Date.now() + 90_000));
325
-
326
- // Device
327
- const isMobile = useResponsiveDisplay(768);
328
- const sysTheme = useSystemTheme(); // 'light' | 'dark' | 'unknown'
329
-
330
- // Misc
331
- displayGreeting(); // Good morning / afternoon / evening
332
- getDayIdentifier(new Date()); // 'YYYY-MM-DD'
333
- console.log(systemInfo.os, systemInfo.browser);
334
- ```
335
-
336
- SSR Notes
337
- - The library guards `localStorage`/`navigator`. Use normally in SSR apps; hydration updates settings on client.
338
- - For Next.js, place the provider in a client boundary (e.g., `layout.tsx` with `"use client"`).
339
-
340
- Peer Dependencies
341
- - `@mui/material` ^7
342
- - `@mui/icons-material` ^7
343
- - `@emotion/react` ^11
344
- - `@emotion/styled` ^11
345
- - `@emotion/css` ^11 (optional)
1
+ # @atomazing-org/design-system
2
+
3
+ Modern MUI v7 + Emotion design system with strongly differentiated visual presets, scheme-based light/dark tokens, SSR-safe theming, and persistence.
4
+
5
+ ## Preview
6
+ ![Design system preview](https://raw.githubusercontent.com/atomazing/design-system/master/preview.gif)
7
+
8
+ ## Contents
9
+ - Preview
10
+ - Why this library
11
+ - Installation
12
+ - Quickstart
13
+ - Presets
14
+ - Dark mode
15
+ - Custom presets
16
+ - API reference
17
+ - Examples
18
+ - Troubleshooting
19
+ - Consumer alias guidance
20
+ - Contributing
21
+ - Release notes
22
+ - License
23
+
24
+ ## Why this library
25
+ - True light/dark presets via colorSchemes (not just palette.mode)
26
+ - Distinct preset identities (minimal, liquid glass, editorial, warm organic, retro terminal)
27
+ - Persisted theme and darkMode with safe defaults
28
+ - SSR-safe (no module-scope browser APIs)
29
+ - MUI v7 + Emotion ready, with typography variants and component overrides
30
+ - Guardrails: contrast checks on preset tokens
31
+ - Easy to extend with custom presets
32
+
33
+ ## Installation
34
+ ```bash
35
+ npm install @atomazing-org/design-system
36
+ npm install @mui/material @mui/icons-material @emotion/react @emotion/styled @emotion/css
37
+ ```
38
+
39
+ ## Quickstart
40
+ ```tsx
41
+ import React from "react";
42
+ import ReactDOM from "react-dom/client";
43
+ import { ThemeProviderWrapper } from "@atomazing-org/design-system";
44
+ import { defaultThemes } from "@atomazing-org/design-system/presets";
45
+
46
+ import App from "./App";
47
+
48
+ ReactDOM.createRoot(document.getElementById("root")!).render(
49
+ <ThemeProviderWrapper themes={defaultThemes}>
50
+ <App />
51
+ </ThemeProviderWrapper>
52
+ );
53
+ ```
54
+
55
+ ## Presets
56
+ Ship-ready presets live under the `/presets` subpath. `defaultThemes` contains all built-in presets.
57
+
58
+ ```ts
59
+ import { defaultThemes, modernMinimal } from "@atomazing-org/design-system/presets";
60
+ ```
61
+
62
+ Built-in presets:
63
+ - Warm Earth
64
+ - Editorial Classic
65
+ - Modern Minimal
66
+ - Neo Glass
67
+ - Retro Terminal
68
+ - Kids Cartoon
69
+
70
+ ## Dark mode
71
+ `darkMode` controls which scheme is active. Supported values:
72
+ - `light`
73
+ - `dark`
74
+ - `system`
75
+ - `auto` (alias of `system`)
76
+
77
+ `effectiveMode` is derived from `darkMode` + the OS preference. If the system preference is unknown, the library falls back to `light`.
78
+
79
+ ```tsx
80
+ import { useThemeSettings, darkModeOptions } from "@atomazing-org/design-system";
81
+ import { FormControlLabel, Radio, RadioGroup } from "@mui/material";
82
+
83
+ export function DarkModeSelector() {
84
+ const { darkMode, setDarkMode } = useThemeSettings();
85
+
86
+ return (
87
+ <RadioGroup
88
+ row
89
+ value={darkMode}
90
+ onChange={(event) => setDarkMode(event.target.value as typeof darkMode)}
91
+ >
92
+ {darkModeOptions.map((option) => (
93
+ <FormControlLabel
94
+ key={option.value}
95
+ control={<Radio />}
96
+ label={option.label}
97
+ value={option.value}
98
+ />
99
+ ))}
100
+ </RadioGroup>
101
+ );
102
+ }
103
+ ```
104
+
105
+ ## Custom presets
106
+ Define a `ThemePreset` with `colorSchemes.light` and `colorSchemes.dark`.
107
+
108
+ ```ts
109
+ import type { ThemePreset } from "@atomazing-org/design-system";
110
+
111
+ export const myPreset: ThemePreset = {
112
+ id: "my-brand",
113
+ label: "My Brand",
114
+ colorSchemes: {
115
+ light: {
116
+ palette: {
117
+ background: { default: "#ffffff", paper: "#ffffff" },
118
+ text: { primary: "#111111", secondary: "#444444" },
119
+ divider: "rgba(0,0,0,0.12)",
120
+ },
121
+ },
122
+ dark: {
123
+ palette: {
124
+ background: { default: "#0f1115", paper: "#151922" },
125
+ text: { primary: "#f1f3f5", secondary: "#c6cbd1" },
126
+ divider: "rgba(241,243,245,0.16)",
127
+ },
128
+ },
129
+ },
130
+ };
131
+ ```
132
+
133
+ Merge with built-ins:
134
+ ```ts
135
+ const themes = [...defaultThemes, myPreset];
136
+ ```
137
+
138
+ Duplicate preset ids are resolved by last-wins while preserving the first-occurrence order.
139
+
140
+ ## API reference
141
+
142
+ ### ThemeProviderWrapper
143
+ | Prop | Type | Default | Description |
144
+ | --- | --- | --- | --- |
145
+ | `themes` | `ThemesInput` | `Default` preset | `ThemePreset[]` list used for runtime preset selection. |
146
+ | `fontFamily` | `string` | `undefined` | Optional global font stack. |
147
+ | `children` | `ReactNode` | required | Application content. |
148
+
149
+ `ThemeProviderWrapper` no longer supports legacy theme tuple/object contracts (`Theme1`, `ThemeN`, `ThemesProp`) and expects `ThemePreset[]` only.
150
+
151
+ ### ThemePreset
152
+ | Field | Type | Description |
153
+ | --- | --- | --- |
154
+ | `id` | `string` | Stable preset identifier (used for selection + persistence). |
155
+ | `label` | `string` | Human-friendly preset name. |
156
+ | `colorSchemes.light` | `ThemeOptions` | Light scheme tokens. |
157
+ | `colorSchemes.dark` | `ThemeOptions` | Dark scheme tokens. |
158
+ | `description` | `string?` | Optional description. |
159
+ | `tags` | `string[]?` | Optional tags. |
160
+ | `version` | `string?` | Optional preset version. |
161
+
162
+ ### DarkModeSetting
163
+ | Value | Meaning |
164
+ | --- | --- |
165
+ | `light` | Force light scheme |
166
+ | `dark` | Force dark scheme |
167
+ | `system` | Follow OS preference |
168
+ | `auto` | Alias of `system` |
169
+
170
+ ### useThemeSettings
171
+ Returns:
172
+ - `theme`, `setTheme`
173
+ - `darkMode`, `setDarkMode`
174
+ - `themes`, `selectedTheme`, `defaultThemeName`
175
+
176
+ ### Presets exports
177
+ `@atomazing-org/design-system/presets` exports:
178
+ - `defaultThemes`
179
+ - `editorialClassic`, `modernMinimal`, `neoGlass`, `retroTerminal`, `warmEarth`
180
+
181
+ ## Examples
182
+ The repro app is the fastest way to validate presets and dark mode:
183
+
184
+ ```bash
185
+ pnpm -C examples/repro install
186
+ pnpm -C examples/repro dev
187
+ ```
188
+
189
+ Look for:
190
+ - Theme controls (preset + mode)
191
+ - Token Debug Panel (tokens + persistence)
192
+ - Smoke Gate checklist and overlay demos
193
+
194
+ ## Troubleshooting
195
+ - Dark mode does not change background:
196
+ - Ensure both `colorSchemes.light` and `colorSchemes.dark` set `palette.background.default` and `palette.background.paper`.
197
+ - Remove hardcoded `#fff`/`#000` from layouts that override theme tokens.
198
+ - Text is unreadable in dark mode:
199
+ - Verify `palette.text.primary`/`secondary` for dark schemes.
200
+ - Check divider and surface contrast in the repro app.
201
+ - Preset switching does not update:
202
+ - Ensure preset ids are unique and non-empty.
203
+ - Clear `localStorage` key `appSettings` if persisted values are invalid.
204
+ - SSR warnings:
205
+ - Ensure the provider is mounted inside a client boundary for SSR apps.
206
+
207
+ ## Consumer alias guidance
208
+ These aliases are for your application code (not library internals).
209
+
210
+ `tsconfig.json`:
211
+ ```json
212
+ {
213
+ "compilerOptions": {
214
+ "baseUrl": ".",
215
+ "paths": {
216
+ "@/*": ["src/*"],
217
+ "@components/*": ["src/components/*"],
218
+ "@features/*": ["src/features/*"]
219
+ }
220
+ }
221
+ }
222
+ ```
223
+
224
+ `vite.config.ts`:
225
+ ```ts
226
+ import { defineConfig } from "vite";
227
+ import react from "@vitejs/plugin-react";
228
+ import { resolve } from "path";
229
+
230
+ export default defineConfig({
231
+ plugins: [react()],
232
+ resolve: {
233
+ alias: {
234
+ "@": resolve(__dirname, "src"),
235
+ "@components": resolve(__dirname, "src/components"),
236
+ "@features": resolve(__dirname, "src/features"),
237
+ },
238
+ },
239
+ });
240
+ ```
241
+
242
+ ## Contributing
243
+ ```bash
244
+ pnpm lint
245
+ pnpm build
246
+ pnpm test
247
+ pnpm -C examples/repro dev
248
+ ```
249
+
250
+ ## Release notes
251
+ Current release highlights:
252
+ - Scheme-based presets with explicit light/dark schemes
253
+ - Improved dark mode and persistence alignment
254
+ - Stable `@atomazing-org/design-system/presets` subpath export
255
+
256
+ ## License
257
+ MIT