@aurora-ds/theme 2.0.1 → 3.0.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,95 +1,203 @@
1
- # Aurora Theme
1
+ # 🎨 Aurora DS Theme
2
2
 
3
- A performant, type-safe, and **fully customizable** CSS-in-JS theme management library for React applications.
3
+ > **A flexible, type-safe theming system for React applications**
4
4
 
5
- ## Features
5
+ [![npm version](https://img.shields.io/npm/v/@aurora-ds/theme.svg)](https://www.npmjs.com/package/@aurora-ds/theme)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
7
+ [![TypeScript](https://img.shields.io/badge/TypeScript-5.0+-blue.svg)](https://www.typescriptlang.org/)
6
8
 
7
- - 🎨 **Modular Theming** - Customize colors, spacing, or any token independently
8
- - 🎯 **Color Scales** - 20 color scales with 12 shades each (25-950)
9
- - ⚡ **Optimized Performance** - LRU caching, static style deduplication
10
- - 🖥️ **SSR Support** - Server-side rendering compatible
11
- - 📦 **Lightweight** - No runtime dependencies besides React
12
- - 🔒 **Type-safe** - Full TypeScript support with generics
13
- - 🎨 **Ready to Use** - Default palette with semantic color tokens
9
+ Aurora DS Theme is a modern theming library that provides **automatic type inference**, **flexible customization**, and **zero boilerplate** for your design system.
14
10
 
15
- ## Installation
11
+ ---
12
+
13
+ ## ✨ Key Features
14
+
15
+ - 🎯 **Simple API**
16
+ - 🔮 **Automatic type inference**: TypeScript knows your exact theme structure
17
+ - 🎨 **Optional defaults**: Start instantly with `defaultPalette` (37 semantic colors)
18
+ - 🔧 **Ultra-flexible**: Customize any token independently
19
+ - 📦 **Lightweight**
20
+ - ⚡ **Zero-runtime overhead**: Pure JavaScript, no runtime theme merging
21
+ - 🎭 **CSS-in-JS**: Runtime style generation with SSR support
22
+
23
+ ---
24
+
25
+ ## 📦 Installation
16
26
 
17
27
  ```bash
18
28
  npm install @aurora-ds/theme
19
29
  ```
20
30
 
21
- ## Quick Start
31
+ ```bash
32
+ yarn add @aurora-ds/theme
33
+ ```
34
+
35
+ ```bash
36
+ pnpm add @aurora-ds/theme
37
+ ```
38
+
39
+ ---
40
+
41
+ ## 🚀 Quick Start
42
+
43
+ ### 1. Create your theme (3 options)
44
+
45
+ #### Option A: Use defaults (fastest)
46
+ ```typescript
47
+ import { createTheme } from '@aurora-ds/theme'
48
+
49
+ const theme = createTheme()
50
+ // ✅ Ready to use! Includes 37 semantic colors
51
+ ```
52
+
53
+ #### Option B: Customize or expand the default palette
54
+ ```typescript
55
+ import { createTheme, defaultPalette } from '@aurora-ds/theme'
56
+
57
+ const theme = createTheme({
58
+ colors: {
59
+ ...defaultPalette,
60
+ primary: '#007bff', // Your brand color
61
+ primaryHover: '#0056b3',
62
+ }
63
+ })
64
+ ```
65
+
66
+ #### Option C: Define your own colors
67
+ ```typescript
68
+ import { createTheme } from '@aurora-ds/theme'
69
+
70
+ const theme = createTheme({
71
+ colors: {
72
+ primary: '#007bff',
73
+ background: '#ffffff',
74
+ text: '#212529',
75
+ }
76
+ })
77
+ ```
78
+
79
+ ### 2. Provide the theme to your app
22
80
 
23
81
  ```tsx
24
- import { defaultTheme, ThemeProvider, createStyles } from '@aurora-ds/theme'
82
+ import { ThemeProvider } from '@aurora-ds/theme'
83
+ import { theme } from './theme'
84
+
85
+ function App() {
86
+ return (
87
+ <ThemeProvider theme={theme}>
88
+ <YourApp />
89
+ </ThemeProvider>
90
+ )
91
+ }
92
+ ```
93
+
94
+ ### 3. Use the theme in components
25
95
 
26
- // 1. Wrap your app
27
- <ThemeProvider theme={defaultTheme}>
28
- <App />
29
- </ThemeProvider>
96
+ ```tsx
97
+ import { useTheme, createStyles } from '@aurora-ds/theme'
30
98
 
31
- // 2. Create styles
32
- const STYLES = createStyles((theme) => ({
33
- container: {
99
+ // With createStyles
100
+ const useStyles = createStyles((theme) => ({
101
+ button: {
102
+ backgroundColor: theme.colors.primary,
34
103
  padding: theme.spacing.md,
35
- backgroundColor: theme.colors.surface,
36
- borderRadius: theme.radius.lg,
37
- },
104
+ borderRadius: theme.radius.md,
105
+ }
38
106
  }))
39
107
 
40
- // 3. Use in components
41
- function MyComponent() {
42
- return <div className={STYLES.container}>Hello!</div>
108
+ function Button() {
109
+ const styles = useStyles()
110
+ return <button className={styles.button}>Click me</button>
111
+ }
112
+
113
+ // With useTheme hook
114
+ function Card() {
115
+ const theme = useTheme()
116
+
117
+ return (
118
+ <div style={{
119
+ backgroundColor: theme.colors.background,
120
+ padding: theme.spacing.lg,
121
+ borderRadius: theme.radius.lg,
122
+ }}>
123
+ Card content
124
+ </div>
125
+ )
43
126
  }
44
127
  ```
45
128
 
46
129
  ---
47
130
 
48
- ## Color Scales
131
+ ## 📚 Core Concepts
132
+
133
+ ### Theme Structure
134
+
135
+ A theme consists of **design tokens** organized into categories:
136
+
137
+ ```typescript
138
+ {
139
+ colors: { ... }, // Color palette
140
+ spacing: { ... }, // Spacing scale
141
+ radius: { ... }, // Border radius scale
142
+ shadows: { ... }, // Box shadow scale
143
+ fontSize: { ... }, // Font size scale
144
+ fontWeight: { ... }, // Font weight scale
145
+ lineHeight: { ... }, // Line height scale
146
+ zIndex: { ... }, // Z-index scale
147
+ transition: { ... }, // Transition presets
148
+ opacity: { ... }, // Opacity scale
149
+ breakpoints: { ... }, // Responsive breakpoints
150
+ }
151
+ ```
49
152
 
50
- Aurora provides **20 color scales** with **12 shades each** (25, 50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950).
153
+ **All tokens are optional** - if you don't specify a value, sensible defaults are used.
51
154
 
52
- ### Available Scales
155
+ ### Type Inference (Automatic!)
53
156
 
54
- **Neutrals**
55
- - `gray` - Pure neutral, universal default
56
- - `slate` - Cool/blue undertone, tech & corporate
57
- - `stone` - Warm undertone, lifestyle & natural
157
+ TypeScript **automatically infers** your theme structure:
58
158
 
59
- **Colors**
60
- - `red` `orange` `amber` `yellow` `lime` `green`
61
- - `emerald` `teal` `cyan` `sky` `blue` `indigo`
62
- - `violet` `purple` `fuchsia` `pink` `rose`
159
+ ```typescript
160
+ const theme = createTheme({
161
+ colors: {
162
+ brand: '#007bff',
163
+ danger: '#dc3545'
164
+ }
165
+ })
166
+ ```
63
167
 
64
- ### Usage
168
+ ## 🎨 Working with Colors
65
169
 
66
- ```tsx
67
- import { colors } from '@aurora-ds/theme'
68
-
69
- // Access colors via the colors object
70
- colors.indigo[500] // '#6366f1'
71
- colors.emerald[400] // '#34d399'
72
- colors.gray[900] // '#18181b'
73
-
74
- // Special values (also via colors)
75
- colors.white // '#ffffff'
76
- colors.black // '#000000'
77
- colors.transparent // 'transparent'
78
- colors.current // 'currentColor'
170
+ ### Default Palette
171
+
172
+ Aurora DS provides `defaultPalette` with **37 semantic color tokens**:
173
+
174
+ ```typescript
175
+ import { defaultPalette } from '@aurora-ds/theme'
176
+
177
+ // Colors included:
178
+ // - Surface: background, surface, surfaceHover, surfaceActive
179
+ // - Text: text, textSecondary, textTertiary
180
+ // - Primary: primary, primaryHover, primaryActive, primarySubtle, primaryDisabled, onPrimary
181
+ // - Secondary: secondary, secondaryHover, secondaryActive, secondarySubtle, secondaryDisabled, onSecondary
182
+ // - Semantic: success, warning, error, info (+ subtle variants)
183
+ // - Links: link, linkHover, linkActive, linkDisabled
184
+ // - Borders: border
185
+ // - Disabled: disabled, disabledText
79
186
  ```
80
187
 
81
- ### Build Custom Theme Colors
188
+ ### Color Scales
82
189
 
83
- ```tsx
84
- import { colors, defaultTheme, createTheme } from '@aurora-ds/theme'
190
+ Aurora DS includes **color scales** with 11 shades (50-950) for each color:
191
+
192
+ ```typescript
193
+ import { createTheme, colors } from '@aurora-ds/theme'
85
194
 
86
- const myTheme = createTheme(defaultTheme, {
195
+ const theme = createTheme({
87
196
  colors: {
88
- primary: colors.purple[500],
89
- primaryHover: colors.purple[600],
90
- primaryActive: colors.purple[700],
91
- primarySubtle: colors.purple[50],
92
- // ... other colors
197
+ primary: colors.blue[600],
198
+ primaryHover: colors.blue[700],
199
+ background: colors.slate[50],
200
+ text: colors.slate[900],
93
201
  }
94
202
  })
95
203
  ```
@@ -98,46 +206,23 @@ const myTheme = createTheme(defaultTheme, {
98
206
 
99
207
  All color scales with their hex values (25-950 shades):
100
208
 
101
- #### Neutrals
102
-
103
209
  | Scale | 25 | 50 | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | 950 |
104
210
  |-------|----|----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|
105
211
  | **gray** | ![](https://img.shields.io/badge/%20-fcfcfc?style=flat-square) | ![](https://img.shields.io/badge/%20-fafafa?style=flat-square) | ![](https://img.shields.io/badge/%20-f4f4f5?style=flat-square) | ![](https://img.shields.io/badge/%20-e4e4e7?style=flat-square) | ![](https://img.shields.io/badge/%20-d4d4d8?style=flat-square) | ![](https://img.shields.io/badge/%20-a1a1aa?style=flat-square) | ![](https://img.shields.io/badge/%20-71717a?style=flat-square) | ![](https://img.shields.io/badge/%20-52525b?style=flat-square) | ![](https://img.shields.io/badge/%20-3f3f46?style=flat-square) | ![](https://img.shields.io/badge/%20-27272a?style=flat-square) | ![](https://img.shields.io/badge/%20-18181b?style=flat-square) | ![](https://img.shields.io/badge/%20-09090b?style=flat-square) |
106
212
  | **slate** | ![](https://img.shields.io/badge/%20-fcfcfd?style=flat-square) | ![](https://img.shields.io/badge/%20-f8fafc?style=flat-square) | ![](https://img.shields.io/badge/%20-f1f5f9?style=flat-square) | ![](https://img.shields.io/badge/%20-e2e8f0?style=flat-square) | ![](https://img.shields.io/badge/%20-cbd5e1?style=flat-square) | ![](https://img.shields.io/badge/%20-94a3b8?style=flat-square) | ![](https://img.shields.io/badge/%20-64748b?style=flat-square) | ![](https://img.shields.io/badge/%20-475569?style=flat-square) | ![](https://img.shields.io/badge/%20-334155?style=flat-square) | ![](https://img.shields.io/badge/%20-1e293b?style=flat-square) | ![](https://img.shields.io/badge/%20-0f172a?style=flat-square) | ![](https://img.shields.io/badge/%20-020617?style=flat-square) |
107
213
  | **stone** | ![](https://img.shields.io/badge/%20-fcfcfb?style=flat-square) | ![](https://img.shields.io/badge/%20-fafaf9?style=flat-square) | ![](https://img.shields.io/badge/%20-f5f5f4?style=flat-square) | ![](https://img.shields.io/badge/%20-e7e5e4?style=flat-square) | ![](https://img.shields.io/badge/%20-d6d3d1?style=flat-square) | ![](https://img.shields.io/badge/%20-a8a29e?style=flat-square) | ![](https://img.shields.io/badge/%20-78716c?style=flat-square) | ![](https://img.shields.io/badge/%20-57534e?style=flat-square) | ![](https://img.shields.io/badge/%20-44403c?style=flat-square) | ![](https://img.shields.io/badge/%20-292524?style=flat-square) | ![](https://img.shields.io/badge/%20-1c1917?style=flat-square) | ![](https://img.shields.io/badge/%20-0c0a09?style=flat-square) |
108
-
109
- #### Warm Colors
110
-
111
- | Scale | 25 | 50 | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | 950 |
112
- |-------|----|----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|
113
214
  | **red** | ![](https://img.shields.io/badge/%20-fffbfb?style=flat-square) | ![](https://img.shields.io/badge/%20-fef2f2?style=flat-square) | ![](https://img.shields.io/badge/%20-fee2e2?style=flat-square) | ![](https://img.shields.io/badge/%20-fecaca?style=flat-square) | ![](https://img.shields.io/badge/%20-fca5a5?style=flat-square) | ![](https://img.shields.io/badge/%20-f87171?style=flat-square) | ![](https://img.shields.io/badge/%20-ef4444?style=flat-square) | ![](https://img.shields.io/badge/%20-dc2626?style=flat-square) | ![](https://img.shields.io/badge/%20-b91c1c?style=flat-square) | ![](https://img.shields.io/badge/%20-991b1b?style=flat-square) | ![](https://img.shields.io/badge/%20-7f1d1d?style=flat-square) | ![](https://img.shields.io/badge/%20-450a0a?style=flat-square) |
114
215
  | **orange** | ![](https://img.shields.io/badge/%20-fffcfa?style=flat-square) | ![](https://img.shields.io/badge/%20-fff7ed?style=flat-square) | ![](https://img.shields.io/badge/%20-ffedd5?style=flat-square) | ![](https://img.shields.io/badge/%20-fed7aa?style=flat-square) | ![](https://img.shields.io/badge/%20-fdba74?style=flat-square) | ![](https://img.shields.io/badge/%20-fb923c?style=flat-square) | ![](https://img.shields.io/badge/%20-f97316?style=flat-square) | ![](https://img.shields.io/badge/%20-ea580c?style=flat-square) | ![](https://img.shields.io/badge/%20-c2410c?style=flat-square) | ![](https://img.shields.io/badge/%20-9a3412?style=flat-square) | ![](https://img.shields.io/badge/%20-7c2d12?style=flat-square) | ![](https://img.shields.io/badge/%20-431407?style=flat-square) |
115
216
  | **amber** | ![](https://img.shields.io/badge/%20-fffdfb?style=flat-square) | ![](https://img.shields.io/badge/%20-fffbeb?style=flat-square) | ![](https://img.shields.io/badge/%20-fef3c7?style=flat-square) | ![](https://img.shields.io/badge/%20-fde68a?style=flat-square) | ![](https://img.shields.io/badge/%20-fcd34d?style=flat-square) | ![](https://img.shields.io/badge/%20-fbbf24?style=flat-square) | ![](https://img.shields.io/badge/%20-f59e0b?style=flat-square) | ![](https://img.shields.io/badge/%20-d97706?style=flat-square) | ![](https://img.shields.io/badge/%20-b45309?style=flat-square) | ![](https://img.shields.io/badge/%20-92400e?style=flat-square) | ![](https://img.shields.io/badge/%20-78350f?style=flat-square) | ![](https://img.shields.io/badge/%20-451a03?style=flat-square) |
116
217
  | **yellow** | ![](https://img.shields.io/badge/%20-fefef9?style=flat-square) | ![](https://img.shields.io/badge/%20-fefce8?style=flat-square) | ![](https://img.shields.io/badge/%20-fef9c3?style=flat-square) | ![](https://img.shields.io/badge/%20-fef08a?style=flat-square) | ![](https://img.shields.io/badge/%20-fde047?style=flat-square) | ![](https://img.shields.io/badge/%20-facc15?style=flat-square) | ![](https://img.shields.io/badge/%20-eab308?style=flat-square) | ![](https://img.shields.io/badge/%20-ca8a04?style=flat-square) | ![](https://img.shields.io/badge/%20-a16207?style=flat-square) | ![](https://img.shields.io/badge/%20-854d0e?style=flat-square) | ![](https://img.shields.io/badge/%20-713f12?style=flat-square) | ![](https://img.shields.io/badge/%20-422006?style=flat-square) |
117
-
118
- #### Green Colors
119
-
120
- | Scale | 25 | 50 | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | 950 |
121
- |-------|----|----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|
122
218
  | **lime** | ![](https://img.shields.io/badge/%20-fbfef8?style=flat-square) | ![](https://img.shields.io/badge/%20-f7fee7?style=flat-square) | ![](https://img.shields.io/badge/%20-ecfccb?style=flat-square) | ![](https://img.shields.io/badge/%20-d9f99d?style=flat-square) | ![](https://img.shields.io/badge/%20-bef264?style=flat-square) | ![](https://img.shields.io/badge/%20-a3e635?style=flat-square) | ![](https://img.shields.io/badge/%20-84cc16?style=flat-square) | ![](https://img.shields.io/badge/%20-65a30d?style=flat-square) | ![](https://img.shields.io/badge/%20-4d7c0f?style=flat-square) | ![](https://img.shields.io/badge/%20-3f6212?style=flat-square) | ![](https://img.shields.io/badge/%20-365314?style=flat-square) | ![](https://img.shields.io/badge/%20-1a2e05?style=flat-square) |
123
219
  | **green** | ![](https://img.shields.io/badge/%20-f6fef9?style=flat-square) | ![](https://img.shields.io/badge/%20-f0fdf4?style=flat-square) | ![](https://img.shields.io/badge/%20-dcfce7?style=flat-square) | ![](https://img.shields.io/badge/%20-bbf7d0?style=flat-square) | ![](https://img.shields.io/badge/%20-86efac?style=flat-square) | ![](https://img.shields.io/badge/%20-4ade80?style=flat-square) | ![](https://img.shields.io/badge/%20-22c55e?style=flat-square) | ![](https://img.shields.io/badge/%20-16a34a?style=flat-square) | ![](https://img.shields.io/badge/%20-15803d?style=flat-square) | ![](https://img.shields.io/badge/%20-166534?style=flat-square) | ![](https://img.shields.io/badge/%20-14532d?style=flat-square) | ![](https://img.shields.io/badge/%20-052e16?style=flat-square) |
124
220
  | **emerald** | ![](https://img.shields.io/badge/%20-f5fefc?style=flat-square) | ![](https://img.shields.io/badge/%20-ecfdf5?style=flat-square) | ![](https://img.shields.io/badge/%20-d1fae5?style=flat-square) | ![](https://img.shields.io/badge/%20-a7f3d0?style=flat-square) | ![](https://img.shields.io/badge/%20-6ee7b7?style=flat-square) | ![](https://img.shields.io/badge/%20-34d399?style=flat-square) | ![](https://img.shields.io/badge/%20-10b981?style=flat-square) | ![](https://img.shields.io/badge/%20-059669?style=flat-square) | ![](https://img.shields.io/badge/%20-047857?style=flat-square) | ![](https://img.shields.io/badge/%20-065f46?style=flat-square) | ![](https://img.shields.io/badge/%20-064e3b?style=flat-square) | ![](https://img.shields.io/badge/%20-022c22?style=flat-square) |
125
221
  | **teal** | ![](https://img.shields.io/badge/%20-f4fefe?style=flat-square) | ![](https://img.shields.io/badge/%20-f0fdfa?style=flat-square) | ![](https://img.shields.io/badge/%20-ccfbf1?style=flat-square) | ![](https://img.shields.io/badge/%20-99f6e4?style=flat-square) | ![](https://img.shields.io/badge/%20-5eead4?style=flat-square) | ![](https://img.shields.io/badge/%20-2dd4bf?style=flat-square) | ![](https://img.shields.io/badge/%20-14b8a6?style=flat-square) | ![](https://img.shields.io/badge/%20-0d9488?style=flat-square) | ![](https://img.shields.io/badge/%20-0f766e?style=flat-square) | ![](https://img.shields.io/badge/%20-115e59?style=flat-square) | ![](https://img.shields.io/badge/%20-134e4a?style=flat-square) | ![](https://img.shields.io/badge/%20-042f2e?style=flat-square) |
126
-
127
- #### Blue Colors
128
-
129
- | Scale | 25 | 50 | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | 950 |
130
- |-------|----|----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|
131
222
  | **cyan** | ![](https://img.shields.io/badge/%20-f3fefe?style=flat-square) | ![](https://img.shields.io/badge/%20-ecfeff?style=flat-square) | ![](https://img.shields.io/badge/%20-cffafe?style=flat-square) | ![](https://img.shields.io/badge/%20-a5f3fc?style=flat-square) | ![](https://img.shields.io/badge/%20-67e8f9?style=flat-square) | ![](https://img.shields.io/badge/%20-22d3ee?style=flat-square) | ![](https://img.shields.io/badge/%20-06b6d4?style=flat-square) | ![](https://img.shields.io/badge/%20-0891b2?style=flat-square) | ![](https://img.shields.io/badge/%20-0e7490?style=flat-square) | ![](https://img.shields.io/badge/%20-155e75?style=flat-square) | ![](https://img.shields.io/badge/%20-164e63?style=flat-square) | ![](https://img.shields.io/badge/%20-083344?style=flat-square) |
132
- | **sky** | ![](https://img.shields.io/badge/%20-f5faff?style=flat-square) | ![](https://img.shields.io/badge/%20-f0f9ff?style=flat-square) | ![](https://img.shields.io/badge/%20-e0f2fe?style=flat-square) | ![](https://img.shields.io/badge/%20-bae6fd?style=flat-square) | ![](https://img.shields.io/badge/%20-7dd3fc?style=flat-square) | ![](https://img.shields.io/badge/%20-38bdf8?style=flat-square) | ![](https://img.shields.io/badge/%20-0ea5e9?style=flat-square) | ![](https://img.shields.io/badge/%20-0284c7?style=flat-square) | ![](https://img.shields.io/badge/%20-0369a1?style=flat-square) | ![](https://img.shields.io/badge/%20-075985?style=flat-square) | ![](https://img.shields.io/badge/%20-0c4a6e?style=flat-square) | ![](https://img.shields.io/badge/%20-082f49?style=flat-square) |
133
223
  | **blue** | ![](https://img.shields.io/badge/%20-f5f8ff?style=flat-square) | ![](https://img.shields.io/badge/%20-eff6ff?style=flat-square) | ![](https://img.shields.io/badge/%20-dbeafe?style=flat-square) | ![](https://img.shields.io/badge/%20-bfdbfe?style=flat-square) | ![](https://img.shields.io/badge/%20-93c5fd?style=flat-square) | ![](https://img.shields.io/badge/%20-60a5fa?style=flat-square) | ![](https://img.shields.io/badge/%20-3b82f6?style=flat-square) | ![](https://img.shields.io/badge/%20-2563eb?style=flat-square) | ![](https://img.shields.io/badge/%20-1d4ed8?style=flat-square) | ![](https://img.shields.io/badge/%20-1e40af?style=flat-square) | ![](https://img.shields.io/badge/%20-1e3a8a?style=flat-square) | ![](https://img.shields.io/badge/%20-172554?style=flat-square) |
134
224
  | **indigo** | ![](https://img.shields.io/badge/%20-f5f7ff?style=flat-square) | ![](https://img.shields.io/badge/%20-eef2ff?style=flat-square) | ![](https://img.shields.io/badge/%20-e0e7ff?style=flat-square) | ![](https://img.shields.io/badge/%20-c7d2fe?style=flat-square) | ![](https://img.shields.io/badge/%20-a5b4fc?style=flat-square) | ![](https://img.shields.io/badge/%20-818cf8?style=flat-square) | ![](https://img.shields.io/badge/%20-6366f1?style=flat-square) | ![](https://img.shields.io/badge/%20-4f46e5?style=flat-square) | ![](https://img.shields.io/badge/%20-4338ca?style=flat-square) | ![](https://img.shields.io/badge/%20-3730a3?style=flat-square) | ![](https://img.shields.io/badge/%20-312e81?style=flat-square) | ![](https://img.shields.io/badge/%20-1e1b4b?style=flat-square) |
135
225
  | **violet** | ![](https://img.shields.io/badge/%20-f8f5ff?style=flat-square) | ![](https://img.shields.io/badge/%20-f5f3ff?style=flat-square) | ![](https://img.shields.io/badge/%20-ede9fe?style=flat-square) | ![](https://img.shields.io/badge/%20-ddd6fe?style=flat-square) | ![](https://img.shields.io/badge/%20-c4b5fd?style=flat-square) | ![](https://img.shields.io/badge/%20-a78bfa?style=flat-square) | ![](https://img.shields.io/badge/%20-8b5cf6?style=flat-square) | ![](https://img.shields.io/badge/%20-7c3aed?style=flat-square) | ![](https://img.shields.io/badge/%20-6d28d9?style=flat-square) | ![](https://img.shields.io/badge/%20-5b21b6?style=flat-square) | ![](https://img.shields.io/badge/%20-4c1d95?style=flat-square) | ![](https://img.shields.io/badge/%20-2e1065?style=flat-square) |
136
-
137
- #### Purple & Pink Colors
138
-
139
- | Scale | 25 | 50 | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | 950 |
140
- |-------|----|----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|
141
226
  | **purple** | ![](https://img.shields.io/badge/%20-faf5ff?style=flat-square) | ![](https://img.shields.io/badge/%20-faf5ff?style=flat-square) | ![](https://img.shields.io/badge/%20-f3e8ff?style=flat-square) | ![](https://img.shields.io/badge/%20-e9d5ff?style=flat-square) | ![](https://img.shields.io/badge/%20-d8b4fe?style=flat-square) | ![](https://img.shields.io/badge/%20-c084fc?style=flat-square) | ![](https://img.shields.io/badge/%20-a855f7?style=flat-square) | ![](https://img.shields.io/badge/%20-9333ea?style=flat-square) | ![](https://img.shields.io/badge/%20-7e22ce?style=flat-square) | ![](https://img.shields.io/badge/%20-6b21a8?style=flat-square) | ![](https://img.shields.io/badge/%20-581c87?style=flat-square) | ![](https://img.shields.io/badge/%20-3b0764?style=flat-square) |
142
227
  | **fuchsia** | ![](https://img.shields.io/badge/%20-fef5ff?style=flat-square) | ![](https://img.shields.io/badge/%20-fdf4ff?style=flat-square) | ![](https://img.shields.io/badge/%20-fae8ff?style=flat-square) | ![](https://img.shields.io/badge/%20-f5d0fe?style=flat-square) | ![](https://img.shields.io/badge/%20-f0abfc?style=flat-square) | ![](https://img.shields.io/badge/%20-e879f9?style=flat-square) | ![](https://img.shields.io/badge/%20-d946ef?style=flat-square) | ![](https://img.shields.io/badge/%20-c026d3?style=flat-square) | ![](https://img.shields.io/badge/%20-a21caf?style=flat-square) | ![](https://img.shields.io/badge/%20-86198f?style=flat-square) | ![](https://img.shields.io/badge/%20-701a75?style=flat-square) | ![](https://img.shields.io/badge/%20-4a044e?style=flat-square) |
143
228
  | **pink** | ![](https://img.shields.io/badge/%20-fef5f9?style=flat-square) | ![](https://img.shields.io/badge/%20-fdf2f8?style=flat-square) | ![](https://img.shields.io/badge/%20-fce7f3?style=flat-square) | ![](https://img.shields.io/badge/%20-fbcfe8?style=flat-square) | ![](https://img.shields.io/badge/%20-f9a8d4?style=flat-square) | ![](https://img.shields.io/badge/%20-f472b6?style=flat-square) | ![](https://img.shields.io/badge/%20-ec4899?style=flat-square) | ![](https://img.shields.io/badge/%20-db2777?style=flat-square) | ![](https://img.shields.io/badge/%20-be185d?style=flat-square) | ![](https://img.shields.io/badge/%20-9d174d?style=flat-square) | ![](https://img.shields.io/badge/%20-831843?style=flat-square) | ![](https://img.shields.io/badge/%20-500724?style=flat-square) |
@@ -145,575 +230,450 @@ All color scales with their hex values (25-950 shades):
145
230
 
146
231
  ---
147
232
 
148
-
149
- ## Modular Customization
150
-
151
- Customize only what you need - colors, spacing, or any individual token.
152
-
153
- ### Available Presets
154
-
155
- ```tsx
156
- import {
157
- // Complete theme
158
- defaultTheme,
159
-
160
- // Individual presets
161
- defaultPalette,
162
- defaultSpacing,
163
- defaultRadius,
164
- defaultShadows,
165
- defaultFontSize,
166
- defaultFontWeight,
167
- defaultLineHeight,
168
- defaultZIndex,
169
- defaultTransition,
170
- defaultOpacity,
171
- defaultBreakpoints,
172
- } from '@aurora-ds/theme'
233
+ ```typescript
234
+ // Example: Using multiple shades
235
+ const theme = createTheme({
236
+ colors: {
237
+ // Blues for primary actions
238
+ primary: colors.blue[600],
239
+ primaryHover: colors.blue[700],
240
+ primaryActive: colors.blue[800],
241
+ primarySubtle: colors.blue[50],
242
+
243
+ // Grays for surfaces
244
+ background: colors.slate[50],
245
+ surface: colors.slate[100],
246
+ border: colors.slate[200],
247
+ text: colors.slate[900],
248
+
249
+ // Semantic colors
250
+ success: colors.green[600],
251
+ warning: colors.amber[500],
252
+ error: colors.red[600],
253
+ info: colors.blue[500],
254
+ }
255
+ })
173
256
  ```
174
257
 
175
- ### Customize Only Colors
258
+ ---
176
259
 
177
- ```tsx
178
- import { defaultTheme, defaultPalette, createTheme } from '@aurora-ds/theme'
260
+ ## Multiple Themes (e.g., Light & Dark)
179
261
 
180
- const myTheme = createTheme(defaultTheme, {
181
- colors: {
182
- ...defaultPalette,
183
- primary: '#your-brand-color',
184
- primaryHover: '#your-brand-hover',
185
- },
186
- })
187
- ```
262
+ Use the `satisfies` pattern to ensure consistent structure:
188
263
 
189
- ### Customize Only Spacing
264
+ ```typescript
265
+ import { createTheme, colors } from '@aurora-ds/theme'
190
266
 
191
- ```tsx
192
- import { defaultTheme, defaultSpacing, createTheme } from '@aurora-ds/theme'
267
+ // Define your color structure
268
+ type AppColors = {
269
+ primary: string
270
+ background: string
271
+ surface: string
272
+ text: string
273
+ }
193
274
 
194
- const myTheme = createTheme(defaultTheme, {
195
- spacing: {
196
- ...defaultSpacing,
197
- md: '1.25rem', // Override medium
198
- lg: '2rem', // Override large
199
- },
275
+ // Light theme
276
+ const lightTheme = createTheme({
277
+ colors: {
278
+ primary: colors.blue[600],
279
+ background: colors.white,
280
+ surface: colors.slate[50],
281
+ text: colors.slate[900],
282
+ } satisfies AppColors
200
283
  })
201
- ```
202
-
203
- ### Mix and Match
204
284
 
205
- ```tsx
206
- import {
207
- defaultSpacing,
208
- defaultRadius,
209
- defaultShadows,
210
- colors,
211
- createTheme,
212
- defaultTheme,
213
- } from '@aurora-ds/theme'
214
-
215
- const myTheme = createTheme(defaultTheme, {
285
+ // Dark theme - TypeScript ensures same structure
286
+ const darkTheme = createTheme({
216
287
  colors: {
217
- ...defaultTheme.colors,
218
- primary: colors.emerald[600], // Use emerald as primary
219
- primaryHover: colors.emerald[700],
220
- primaryActive: colors.emerald[800],
221
- },
222
- spacing: defaultSpacing, // Keep default spacing
223
- radius: {
224
- ...defaultRadius,
225
- md: '8px', // More rounded
226
- },
288
+ primary: colors.blue[500],
289
+ background: colors.slate[950],
290
+ surface: colors.slate[900],
291
+ text: colors.slate[50],
292
+ } satisfies AppColors
227
293
  })
294
+
295
+ // Use in app
296
+ function App() {
297
+ const [isDark, setIsDark] = useState(false)
298
+ const theme = isDark ? darkTheme : lightTheme
299
+
300
+ return <ThemeProvider theme={theme}>...</ThemeProvider>
301
+ }
228
302
  ```
229
303
 
230
304
  ---
231
305
 
232
- ## Custom Themes (Complete Token Replacement)
233
-
234
- Need a completely different color token structure? Aurora supports **full customization** where you can define your own semantic tokens without inheriting `BaseColors`.
235
-
236
- ### Option 1: Replace Mode
306
+ ## 💡 Typing Your Theme with `typeof`
237
307
 
238
- Use `{ mode: 'replace' }` to completely replace a token category instead of deep-merging:
308
+ Aurora DS uses **type inference** for maximum type safety. Always use `typeof` to extract your theme type.
239
309
 
240
- ```tsx
241
- import { createTheme, defaultTheme } from '@aurora-ds/theme'
310
+ ### The Standard Pattern
242
311
 
243
- // Replace the entire colors object (no merge with defaults)
244
- const myTheme = createTheme(defaultTheme, {
312
+ ```typescript
313
+ // 1. Create your theme
314
+ const appTheme = createTheme({
245
315
  colors: {
246
- brand: '#007bff',
247
- brandHover: '#0056b3',
248
- surface: '#ffffff',
249
- text: '#212529',
316
+ brand: colors.blue[600],
317
+ accent: colors.emerald[500],
318
+ surface: colors.white,
319
+ text: colors.slate[900],
250
320
  },
251
- }, { mode: 'replace' })
252
-
253
- // Result: theme.colors = { brand, brandHover, surface, text }
254
- // Note: theme.colors.primary no longer exists!
255
- ```
256
-
257
- ### Option 2: Custom Theme Function
321
+ spacing: {
322
+ tight: '4px',
323
+ normal: '16px',
324
+ relaxed: '32px',
325
+ }
326
+ })
258
327
 
259
- For full type safety with your own color tokens, use `createCustomTheme`:
328
+ // 2. Extract the type with typeof
329
+ export type AppTheme = typeof appTheme
260
330
 
261
- ```tsx
262
- import { createCustomTheme } from '@aurora-ds/theme'
263
- import type { CustomTheme } from '@aurora-ds/theme'
264
-
265
- // 1. Define your own color token structure
266
- type MyBrandColors = {
267
- brand: string
268
- brandHover: string
269
- brandActive: string
270
- surface: string
271
- surfaceElevated: string
272
- textPrimary: string
273
- textSecondary: string
274
- border: string
331
+ // 3. Use it in your components
332
+ type ButtonProps = {
333
+ color: keyof AppTheme['colors'] // 'brand' | 'accent' | 'surface' | 'text'
334
+ gap: keyof AppTheme['spacing'] // 'tight' | 'normal' | 'relaxed'
275
335
  }
276
336
 
277
- // 2. Create your theme with full type safety
278
- const myTheme = createCustomTheme<MyBrandColors>({
279
- colors: {
280
- brand: '#007bff',
281
- brandHover: '#0056b3',
282
- brandActive: '#004085',
283
- surface: '#ffffff',
284
- surfaceElevated: '#f8f9fa',
285
- textPrimary: '#212529',
286
- textSecondary: '#6c757d',
287
- border: '#dee2e6',
288
- },
289
- // Other tokens use defaults, or provide your own:
290
- // spacing: { ... },
291
- // radius: { ... },
292
- })
293
-
294
- // 3. TypeScript knows your exact token structure!
295
- myTheme.colors.brand // ✅ OK - string
296
- myTheme.colors.primary // ❌ Error - property doesn't exist
297
-
298
- // 4. Type your theme for components
299
- type MyTheme = typeof myTheme
300
- // or: type MyTheme = CustomTheme<MyBrandColors>
337
+ function Button({ color, gap }: ButtonProps) {
338
+ const theme = useTheme()
339
+ return <button style={{
340
+ backgroundColor: theme.colors[color],
341
+ padding: theme.spacing[gap],
342
+ }} />
343
+ }
301
344
  ```
302
345
 
303
- ### Use Custom Theme in Components
346
+ ### Why `typeof` is the only way
304
347
 
305
- ```tsx
306
- import { ThemeProvider, createTypedStyles, useTheme } from '@aurora-ds/theme'
348
+ **Type inference gives you:**
349
+ - **Exact types**: TypeScript knows your exact tokens
350
+ - ✅ **No casts needed**: Everything works automatically
351
+ - ✅ **Better autocomplete**: IDE shows only YOUR tokens
352
+ - ✅ **Compile-time safety**: Can't access tokens that don't exist
307
353
 
308
- // ✨ Create a pre-typed createStyles function ONCE
309
- export const createStyles = createTypedStyles<MyTheme>()
354
+ ```typescript
355
+ const myTheme = createTheme({
356
+ colors: { brand: '#FF0000', accent: '#00FF00' }
357
+ })
310
358
 
311
- // Now use it everywhere WITHOUT specifying the type!
312
- const STYLES = createStyles((theme) => ({
313
- button: {
314
- backgroundColor: theme.colors.brand, // ✅ TypeScript knows!
315
- color: theme.colors.textPrimary, // ✅ Works
316
- // backgroundColor: theme.colors.primary, // ❌ Would error
317
- },
318
- }))
359
+ type MyTheme = typeof myTheme
319
360
 
320
- // Access in components
321
- function MyComponent() {
322
- const theme = useTheme<MyTheme>()
323
- return <div style={{ color: theme.colors.textSecondary }}>Hello</div>
361
+ // TypeScript knows EXACTLY what you have
362
+ type ColorKeys = keyof MyTheme['colors'] // 'brand' | 'accent'
363
+
364
+ const props: { color: ColorKeys } = {
365
+ color: 'brand' // ✅ OK
324
366
  }
325
367
 
326
- // Wrap your app
327
- <ThemeProvider theme={myTheme}>
328
- <App />
329
- </ThemeProvider>
368
+ const invalid: { color: ColorKeys } = {
369
+ color: 'primary' // ❌ Error: 'primary' doesn't exist!
370
+ }
330
371
  ```
331
372
 
332
- ### Project Setup (Recommended)
373
+ ### Best Practice: Export from a single file
333
374
 
334
- Create a `theme.ts` file in your project to centralize your custom theme:
335
-
336
- ```tsx
337
- // src/theme.ts
338
- import {
339
- createCustomTheme,
340
- createTypedStyles,
341
- ThemeProvider as BaseThemeProvider,
342
- useTheme as baseUseTheme,
343
- } from '@aurora-ds/theme'
344
- import type { CustomTheme } from '@aurora-ds/theme'
345
-
346
- // 1. Define your color tokens
347
- type MyColors = {
348
- brand: string
349
- brandHover: string
350
- brandActive: string
351
- surface: string
352
- surfaceElevated: string
353
- textPrimary: string
354
- textSecondary: string
355
- border: string
356
- }
375
+ ```typescript
376
+ // src/theme.ts - Single source of truth
377
+ import { createTheme, colors } from '@aurora-ds/theme'
357
378
 
358
- // 2. Create your theme
359
- export const theme = createCustomTheme<MyColors>({
379
+ export const appTheme = createTheme({
360
380
  colors: {
361
- brand: '#007bff',
362
- brandHover: '#0056b3',
363
- brandActive: '#004085',
364
- surface: '#ffffff',
365
- surfaceElevated: '#f8f9fa',
366
- textPrimary: '#212529',
367
- textSecondary: '#6c757d',
368
- border: '#dee2e6',
369
- },
381
+ brand: colors.blue[600],
382
+ accent: colors.emerald[500],
383
+ surface: colors.white,
384
+ text: colors.slate[900],
385
+ }
370
386
  })
371
387
 
372
- // 3. Export typed utilities (use these throughout your app!)
373
- export type MyTheme = typeof theme
374
- export const createStyles = createTypedStyles<MyTheme>()
375
- export const useTheme = () => baseUseTheme<MyTheme>()
376
- export const ThemeProvider = BaseThemeProvider
377
- ```
378
-
379
- Then use in your components:
388
+ export type AppTheme = typeof appTheme
380
389
 
381
- ```tsx
382
- // src/components/Button.tsx
383
- import { createStyles } from '../theme'
384
-
385
- // No need to specify <MyTheme> - it's already typed!
386
- const STYLES = createStyles((theme) => ({
387
- root: {
388
- backgroundColor: theme.colors.brand,
389
- color: theme.colors.textPrimary,
390
- padding: theme.spacing.md,
391
- borderRadius: theme.radius.md,
392
- ':hover': {
393
- backgroundColor: theme.colors.brandHover,
394
- },
395
- },
396
- }))
390
+ // src/components/Button.tsx - Import and use
391
+ import type { AppTheme } from '../theme'
397
392
 
398
- export const Button = ({ children }) => (
399
- <button className={STYLES.root}>{children}</button>
400
- )
393
+ type ButtonProps = {
394
+ color: keyof AppTheme['colors'] // ✅ Type-safe!
395
+ }
401
396
  ```
402
397
 
403
- ### When to Use Each Approach
404
-
405
- | Approach | Use Case |
406
- |----------|----------|
407
- | `createTheme()` (default merge) | Extend default tokens, keep compatibility |
408
- | `createTheme()` with `{ mode: 'replace' }` | Quick replacement without type safety |
409
- | `createCustomTheme<T>()` | Full type safety with custom token structure |
410
- | `createTypedStyles<T>()` | Pre-type your `createStyles` for DX (recommended with custom themes) |
411
-
412
- ---
398
+ ### Alternative: Type-First Approach
413
399
 
414
- ## Theme Structure
400
+ You can define the type first, then create themes matching it:
415
401
 
416
- ### Colors
417
-
418
- | Token | Description |
419
- |-------|-------------|
420
- | `primary`, `primaryHover`, `primaryActive`, `primarySubtle`, `primaryDisabled`, `onPrimary` | Primary brand color |
421
- | `secondary`, `secondaryHover`, `secondaryActive`, `secondarySubtle`, `secondaryDisabled`, `onSecondary` | Secondary actions |
422
- | `background`, `surface`, `surfaceHover`, `surfaceActive` | Surfaces |
423
- | `text`, `textSecondary`, `textTertiary` | Text hierarchy |
424
- | `border` | Borders |
425
- | `success`, `successSubtle` | Success state |
426
- | `warning`, `warningSubtle` | Warning state |
427
- | `error`, `errorHover`, `errorSubtle`, `onError` | Error state |
428
- | `info`, `infoSubtle` | Info state |
429
- | `link`, `linkHover`, `linkActive`, `linkDisabled` | Links |
430
- | `disabled`, `disabledText` | Disabled states |
431
-
432
- ### Spacing
433
-
434
- ```tsx
435
- spacing: {
436
- none: '0',
437
- '2xs': '0.125rem', // 2px
438
- xs: '0.25rem', // 4px
439
- sm: '0.5rem', // 8px
440
- md: '1rem', // 16px
441
- lg: '1.5rem', // 24px
442
- xl: '2rem', // 32px
443
- '2xl': '3rem', // 48px
444
- '3xl': '4rem', // 64px
445
- '4xl': '6rem', // 96px
446
- '5xl': '8rem', // 128px
402
+ ```typescript
403
+ // 1. Define type structure
404
+ type AppTheme = {
405
+ colors: { brand: string; accent: string }
406
+ spacing: { tight: string; normal: string }
447
407
  }
448
- ```
449
408
 
450
- ### Opacity
409
+ // 2. Create theme (cast needed)
410
+ const theme: AppTheme = createTheme({
411
+ colors: { brand: '#000', accent: '#fff' },
412
+ spacing: { tight: '4px', normal: '16px' }
413
+ }) as unknown as AppTheme
451
414
 
452
- ```tsx
453
- opacity: {
454
- none: 0, // Fully transparent
455
- lowest: 0.05, // Very subtle
456
- low: 0.1, // Subtle
457
- medium: 0.25, // Noticeable
458
- high: 0.5, // Semi-transparent
459
- higher: 0.75, // Mostly opaque
460
- full: 1, // Fully opaque
461
- }
415
+ // 3. Use AppTheme directly
416
+ type Props = { color: keyof AppTheme['colors'] }
462
417
  ```
463
418
 
464
- ### Other Tokens
465
-
466
- | Token | Values |
467
- |-------|--------|
468
- | `radius` | `none`, `xs`, `sm`, `md`, `lg`, `xl`, `2xl`, `full` |
469
- | `shadows` | `none`, `xs`, `sm`, `md`, `lg`, `xl`, `2xl`, `inner`, `focus` |
470
- | `fontSize` | `2xs`, `xs`, `sm`, `md`, `lg`, `xl`, `2xl`, `3xl`, `4xl`, `5xl` |
471
- | `fontWeight` | `light`, `regular`, `medium`, `semibold`, `bold` |
472
- | `lineHeight` | `none`, `tight`, `normal`, `relaxed`, `loose` |
473
- | `zIndex` | `behind`, `base`, `dropdown`, `sticky`, `overlay`, `modal`, `popover`, `tooltip`, `toast` |
474
- | `transition` | `fast`, `normal`, `slow` |
475
- | `opacity` | `none`, `lowest`, `low`, `medium`, `high`, `higher`, `full` |
476
- | `breakpoints` | `xs`, `sm`, `md`, `lg`, `xl`, `2xl` |
419
+ See [examples/type-first-approach.md](./examples/type-first-approach.md) for details.
477
420
 
478
421
  ---
479
422
 
480
- ## Extending Types
423
+ ### ⚠️ Important: Theme Structure Consistency
481
424
 
482
- Add custom tokens with full TypeScript support:
425
+ **When using multiple themes in your app, ALL themes MUST have the same token structure.**
483
426
 
484
- ```tsx
485
- import type { BaseColors, ExtendTheme } from '@aurora-ds/theme'
427
+ This applies to **ALL tokens**: `colors`, `spacing`, `radius`, `shadows`, `fontSize`, `fontWeight`, etc.
486
428
 
487
- // Extend colors
488
- type MyColors = BaseColors & {
489
- brand: string
490
- brandHover: string
491
- }
429
+ #### Bad Practice - Inconsistent structures
492
430
 
493
- // Create extended theme type
494
- type MyTheme = ExtendTheme<{
495
- colors: MyColors
496
- }>
431
+ ```typescript
432
+ // Theme 1: Has 'primary', 'secondary', 'background' colors
433
+ const theme1 = createTheme({
434
+ colors: {
435
+ primary: '#007bff',
436
+ secondary: '#6c757d',
437
+ background: '#ffffff',
438
+ }
439
+ })
497
440
 
498
- // Use with type safety
499
- const STYLES = createStyles<MyTheme>((theme) => ({
500
- button: {
501
- backgroundColor: theme.colors.brand, // TypeScript knows this!
441
+ // Theme 2: Has 'brand', 'surface', 'text' - DIFFERENT TOKENS!
442
+ const theme2 = createTheme({
443
+ colors: {
444
+ brand: '#28a745', // Different token name
445
+ surface: '#f8f9fa', // ❌ Different token name
446
+ text: '#212529', // ❌ Different token name
502
447
  },
503
- }))
448
+ spacing: {
449
+ tight: '4px', // ❌ Different token names
450
+ normal: '8px', // ❌ Different from theme1
451
+ }
452
+ })
504
453
 
505
- // Access in components
506
- const theme = useTheme<MyTheme>()
454
+ // Problem: createStyles won't work with both themes
455
+ const useStyles = createStyles((theme) => ({
456
+ button: {
457
+ backgroundColor: theme.colors.primary, // Works with theme1, BREAKS with theme2
458
+ padding: theme.spacing.sm, // BREAKS if theme2 doesn't have 'sm'
459
+ }
460
+ }))
507
461
  ```
508
462
 
509
- ---
510
-
511
- ## Dynamic Styles
463
+ #### ✅ Good Practice
512
464
 
513
- ```tsx
514
- const STYLES = createStyles((theme) => ({
515
- button: (variant: 'primary' | 'secondary', size: 'sm' | 'md' | 'lg') => ({
516
- backgroundColor: theme.colors[variant],
517
- padding: theme.spacing[size],
518
- borderRadius: theme.radius.md,
519
- transition: theme.transition.fast,
520
- }),
521
- }))
465
+ **Define a common type and use `satisfies`** (Recommended)
522
466
 
523
- // Usage
524
- <button className={STYLES.button('primary', 'md')}>Click me</button>
525
- ```
467
+ ```typescript
468
+ // 1. Define your app's complete theme structure
469
+ type AppTheme = {
470
+ colors: {
471
+ primary: string
472
+ background: string
473
+ text: string
474
+ border: string
475
+ }
476
+ spacing: {
477
+ sm: string
478
+ md: string
479
+ lg: string
480
+ }
481
+ }
482
+ }
526
483
 
527
- ---
484
+ // 2. All themes satisfy this structure
485
+ const lightTheme = createTheme({
486
+ colors: {
487
+ primary: '#007bff',
488
+ background: '#ffffff',
489
+ text: '#000000',
490
+ border: '#dee2e6',
491
+ },
492
+ spacing: {
493
+ sm: '8px',
494
+ md: '16px',
495
+ lg: '24px',
496
+ }
497
+ } satisfies AppTheme) // ✅ TypeScript enforces structure
528
498
 
529
- ## SSR Support
499
+ const darkTheme = createTheme({
500
+ colors: {
501
+ primary: '#4dabf7',
502
+ background: '#1a1a1a',
503
+ text: '#ffffff',
504
+ border: '#495057',
505
+ },
506
+ spacing: {
507
+ sm: '8px',
508
+ md: '16px',
509
+ lg: '24px',
510
+ }
511
+ } satisfies AppTheme) // ✅ TypeScript enforces structure
530
512
 
531
- ```tsx
532
- import { getSSRStyles, clearSSRRules } from '@aurora-ds/theme'
533
-
534
- // Server-side
535
- const html = renderToString(<App />)
536
- const styles = getSSRStyles()
537
-
538
- const fullHtml = `
539
- <!DOCTYPE html>
540
- <html>
541
- <head>
542
- <style id="aurora-styles">${styles}</style>
543
- </head>
544
- <body>${html}</body>
545
- </html>
546
- `
547
-
548
- clearSSRRules() // Reset for next request
513
+ // TypeScript will error if you:
514
+ // - Forget a required token (in colors OR spacing)
515
+ // - Add an extra token
516
+ // - Use a different token name
549
517
  ```
550
518
 
551
- ---
552
519
 
553
- ## API Reference
554
-
555
- ### Types
556
-
557
- | Type | Description |
558
- |------|-------------|
559
- | `Theme` | Complete theme structure |
560
- | `BaseColors` | Color token type |
561
- | `BaseSpacing` | Spacing token type |
562
- | `BaseOpacity` | Opacity token type |
563
- | `BaseBreakpoints` | Breakpoints token type |
564
- | `ColorScale` | Color scale type (25-950) |
565
- | `ColorName` | Union of color scale names |
566
- | `ExtendTheme<T>` | Helper to extend theme |
567
- | `DeepPartial<T>` | For partial overrides |
568
- | `CustomTheme<TColors, ...>` | Generic type for fully custom themes |
569
- | `CustomThemeBase<TColors>` | Base type for custom color themes |
570
- | `CreateThemeOptions` | Options for `createTheme()` (`{ mode: 'merge' \| 'replace' }`) |
571
-
572
- ### Components & Hooks
573
-
574
- | Export | Description |
575
- |--------|-------------|
576
- | `ThemeProvider` | Theme context provider |
577
- | `useTheme<T>()` | Access current theme |
578
-
579
- ### Theme Creation
580
-
581
- | Export | Description |
582
- |--------|-------------|
583
- | `createTheme(base, overrides, options?)` | Create theme by merging/replacing base with overrides |
584
- | `createCustomTheme<TColors>(config)` | Create theme with fully custom color tokens |
585
- | `mergeThemes(base, ...overrides)` | Merge multiple theme overrides |
586
- | `createThemeVariant(overrides)` | Create a reusable theme variant factory |
587
-
588
- ### Styling
589
-
590
- | Export | Description |
591
- |--------|-------------|
592
- | `createStyles<T>()` | Create themed styles |
593
- | `createTypedStyles<T>()` | Create a pre-typed `createStyles` function for custom themes |
594
- | `keyframes()` | CSS keyframe animations |
595
- | `fontFace()` | @font-face rules |
596
- | `cssVariables()` | CSS custom properties |
520
+ ### Best Practices Summary
521
+
522
+ 1. ✅ **Define a type** for your app's colors and use `satisfies`
523
+ 2. ✅ **Or you can use `defaultPalette`** as a base for consistency
524
+ 3. **Same tokens across all themes** - only values change
525
+ 4. ❌ **Don't create themes with different token sets**
526
+ 5. **Don't mix token naming schemes**
597
527
 
598
528
  ---
599
529
 
600
- ## Migration Guide (v1 → v2)
530
+ ## 🔧 Customizing Tokens
601
531
 
602
- Aurora v2 is a **major simplification** focused on flexibility and reduced bundle size. This guide helps you upgrade from v1.x to v2.0.
532
+ ### Customize any token independently
603
533
 
604
- > 📖 **Full migration guide with all details:** [CHANGELOG.md - Migration Guide](./CHANGELOG.md#migration-guide-v1-to-v2)
534
+ You can customize **any token** without affecting others:
605
535
 
606
- ### 🚨 Breaking Changes Summary
536
+ ```typescript
537
+ // Just spacing (uses defaultPalette for colors)
538
+ const theme = createTheme({
539
+ spacing: {
540
+ xs: '0.25rem',
541
+ sm: '0.5rem',
542
+ md: '1rem',
543
+ lg: '2rem',
544
+ }
545
+ })
607
546
 
608
- #### 1. Removed Pre-built Theme Palettes (~40% smaller bundle)
547
+ // Just radius
548
+ const theme = createTheme({
549
+ radius: {
550
+ none: '0',
551
+ sm: '4px',
552
+ md: '8px',
553
+ full: '9999px',
554
+ }
555
+ })
609
556
 
610
- ```tsx
611
- // v1 - Pre-built palettes (removed)
612
- import { indigoPalette, bluePalette, defaultDarkTheme } from '@aurora-ds/theme'
613
-
614
- // v2 - Build your own with full control
615
- import { colors, createTheme, defaultTheme } from '@aurora-ds/theme'
616
-
617
- const myTheme = createTheme(defaultTheme, {
618
- colors: {
619
- primary: colors.indigo[600],
620
- primaryHover: colors.indigo[700],
621
- // ... full control over all tokens
622
- }
557
+ // Multiple tokens
558
+ const theme = createTheme({
559
+ colors: { primary: '#007bff', background: '#fff' },
560
+ spacing: { sm: '0.5rem', md: '1rem' },
561
+ radius: { sm: '4px', md: '8px' },
623
562
  })
624
563
  ```
625
564
 
626
- #### 2. Color Scales Import Restriction
565
+ ### Available tokens
566
+
567
+ | Token | Default | Description |
568
+ |-------|---------|-------------|
569
+ | `colors` | `defaultPalette` | Color palette (37 semantic colors) |
570
+ | `spacing` | `defaultSpacing` | Spacing scale (11 sizes) |
571
+ | `radius` | `defaultRadius` | Border radius scale (8 sizes) |
572
+ | `shadows` | `defaultShadows` | Box shadow scale (9 shadows) |
573
+ | `fontSize` | `defaultFontSize` | Font size scale (10 sizes) |
574
+ | `fontWeight` | `defaultFontWeight` | Font weight scale (5 weights) |
575
+ | `lineHeight` | `defaultLineHeight` | Line height scale (5 values) |
576
+ | `zIndex` | `defaultZIndex` | Z-index scale (9 layers) |
577
+ | `transition` | `defaultTransition` | Transition presets (3 presets) |
578
+ | `opacity` | `defaultOpacity` | Opacity scale (7 values) |
579
+ | `breakpoints` | `defaultBreakpoints` | Responsive breakpoints (6 breakpoints) |
580
+
581
+ ---
582
+
583
+ ## 🎭 Styling Components
584
+
585
+ ### Using `createStyles`
627
586
 
628
587
  ```tsx
629
- // v1 - Direct imports (removed for better tree-shaking)
630
- import { indigo, blue } from '@aurora-ds/theme'
588
+ import { createStyles } from '@aurora-ds/theme'
631
589
 
632
- // v2 - Import via colors object only
633
- import { colors } from '@aurora-ds/theme'
634
- colors.indigo[500]
635
- colors.blue[600]
590
+ const useStyles = createStyles((theme) => ({
591
+ card: {
592
+ backgroundColor: theme.colors.surface,
593
+ padding: theme.spacing.lg,
594
+ borderRadius: theme.radius.lg,
595
+ boxShadow: theme.shadows.md,
596
+
597
+ ':hover': {
598
+ backgroundColor: theme.colors.surfaceHover,
599
+ }
600
+ }
601
+ }))
602
+
603
+ function Card() {
604
+ const styles = useStyles()
605
+ return <div className={styles.card}>Content</div>
606
+ }
636
607
  ```
637
608
 
638
- #### 3. Removed WCAG Contrast Utilities
609
+ ### Pseudo-classes and Media Queries
639
610
 
640
611
  ```tsx
641
- // v1 - Contrast utilities (removed)
642
- import { getContrastRatio, meetsWCAG } from '@aurora-ds/theme'
643
-
644
- // ✅ v2 - Use dedicated accessibility tools
645
- // - polished / color2k (libraries)
646
- // - axe DevTools (browser extension)
647
- // - Lighthouse (Chrome DevTools)
612
+ const useStyles = createStyles((theme) => ({
613
+ button: {
614
+ padding: theme.spacing.md,
615
+
616
+ ':hover': {
617
+ backgroundColor: theme.colors.primaryHover,
618
+ },
619
+
620
+ '@media (min-width: 768px)': {
621
+ padding: theme.spacing.lg,
622
+ }
623
+ }
624
+ }))
648
625
  ```
649
626
 
650
- #### 4. Simplified Color Tokens (83 → 33 tokens, 60% reduction)
627
+ ---
628
+
629
+ ## 📘 API Reference
651
630
 
652
- **Removed color tokens:**
653
- - ❌ Accent colors (5 tokens): `accent`, `accentHover`, `accentActive`, `onAccent`, `accentSubtle`
654
- - ❌ Tertiary colors (6 tokens): `tertiary`, `tertiaryHover`, `tertiaryActive`, `onTertiary`, `tertiarySubtle`, `tertiaryDisabled`
655
- - ❌ Extra surface (2): `elevated`, `overlay`
656
- - ❌ Extra text (1): `textInverse`
657
- - ❌ Extra borders (3): `borderHover`, `borderFocus`, `borderSubtle`
658
- - ❌ Extra semantic (6): `onSuccess`, `successHover`, `onWarning`, `warningHover`, `onInfo`, `infoHover`
659
- - ❌ Extra interactive (3): `linkVisited`, `linkDisabled`, `focus`
631
+ ### `createTheme(config?)`
660
632
 
661
- **Migration:**
633
+ Creates a theme. All parameters optional.
662
634
 
663
- ```tsx
664
- // ❌ v1
665
- theme.colors.accent
666
- theme.colors.tertiary
667
- theme.colors.elevated
668
-
669
- // ✅ v2 - Use existing tokens or extend theme
670
- theme.colors.primary // Use existing
671
- theme.colors.secondary // Use existing
672
- theme.colors.surface // Use existing
673
-
674
- // OR extend if needed:
675
- const myTheme = createTheme(defaultTheme, {
676
- colors: {
677
- ...defaultTheme.colors,
678
- accent: colors.cyan[500],
679
- tertiary: colors.violet[500],
680
- elevated: colors.slate[100],
681
- }
635
+ ```typescript
636
+ createTheme({
637
+ colors?: Record<string, string>
638
+ spacing?: Record<string, string>
639
+ radius?: Record<string, string>
640
+ // ... other tokens
682
641
  })
683
642
  ```
684
643
 
685
- ### Quick Migration Steps
644
+ ### `<ThemeProvider theme={theme}>`
686
645
 
687
- 1. **Replace color scale imports**
688
- ```tsx
689
- // Before: import { indigo } from '@aurora-ds/theme'
690
- // After: import { colors } from '@aurora-ds/theme'
691
- // colors.indigo[500]
692
- ```
646
+ Provides theme to component tree.
693
647
 
694
- 2. **Replace palette imports** - Build your own theme (see [CHANGELOG](./CHANGELOG.md#3-pre-built-palettes-removed))
648
+ ### `useTheme()`
695
649
 
696
- 3. **Replace removed color tokens** - Use existing tokens or extend theme (see [CHANGELOG](./CHANGELOG.md#1-removed-color-tokens))
650
+ Hook to access current theme.
697
651
 
698
- 4. **Replace contrast utilities** - Use external tools
652
+ ### `createStyles(stylesOrCreator)`
699
653
 
700
- 5. **Test thoroughly**
701
- ```bash
702
- npm run typecheck # Catch type errors
703
- npm run build # Ensure no import errors
704
- npm test # Run tests
705
- ```
654
+ Creates component styles with theme access.
706
655
 
707
- ### Benefits of v2
656
+ ### `keyframes(definition)`
708
657
 
709
- - 📦 **~40% smaller bundle** - Only include what you use
710
- - 🎯 **More flexible** - Full control over color tokens
711
- - ⚡ **Better tree-shaking** - Optimized exports
712
- - 🧩 **Simpler** - Fewer built-in tokens = less decision fatigue
658
+ Creates CSS keyframes animation.
713
659
 
714
- ## License
660
+ ### `fontFace(definition)`
661
+
662
+ Registers custom font face.
663
+
664
+ ---
665
+
666
+ ## 📄 License
715
667
 
716
668
  MIT
717
669
 
670
+ ---
671
+
672
+ ## 🔗 Links
718
673
 
674
+ - [Migration Guide (V1/V2 → V3)](documentation/MIGRATION-GUIDE.md) - Complete migration guide
675
+ - [Changelog](documentation/CHANGELOG.md) - Version history
676
+ - [GitHub Repository](https://github.com/LilianMrzt/Aurora)
677
+ - [NPM Package](https://www.npmjs.com/package/@aurora-ds/theme)
719
678
 
679
+ ---