maz-ui 5.0.0 → 5.1.0-beta.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.
Files changed (186) hide show
  1. package/dist/assets/{MazDropzone.DJ8au25t.css → MazDropzone.BW2grpTi.css} +1 -1
  2. package/dist/chunks/{MazDrawer.DANxKYxJ.js → MazDrawer.CC8zomfx.js} +2 -2
  3. package/dist/chunks/{MazDropzone.POH3pmfi.js → MazDropzone.Dez5j0WP.js} +2 -2
  4. package/dist/components/MazDrawer.js +1 -1
  5. package/dist/components/MazDropzone.js +1 -1
  6. package/dist/components/MazDropzone.vue.d.ts +2 -2
  7. package/dist/components/MazInputPrice.vue.d.ts +1 -1
  8. package/dist/components/index.js +2 -2
  9. package/docs/README.md +207 -0
  10. package/docs/agents/agents-md.md +52 -0
  11. package/docs/agents/claude-rule.md +52 -0
  12. package/docs/components/maz-accordion.md +76 -0
  13. package/docs/components/maz-alert.md +241 -0
  14. package/docs/components/maz-animated-counter.md +87 -0
  15. package/docs/components/maz-animated-element.md +46 -0
  16. package/docs/components/maz-animated-text.md +53 -0
  17. package/docs/components/maz-avatar.md +193 -0
  18. package/docs/components/maz-backdrop.md +178 -0
  19. package/docs/components/maz-badge.md +167 -0
  20. package/docs/components/maz-bottom-sheet.md +257 -0
  21. package/docs/components/maz-btn-group.md +316 -0
  22. package/docs/components/maz-btn.md +423 -0
  23. package/docs/components/maz-card-spotlight.md +84 -0
  24. package/docs/components/maz-card.md +321 -0
  25. package/docs/components/maz-carousel.md +153 -0
  26. package/docs/components/maz-chart.md +206 -0
  27. package/docs/components/maz-checkbox.md +138 -0
  28. package/docs/components/maz-checklist.md +251 -0
  29. package/docs/components/maz-circular-progress-bar.md +109 -0
  30. package/docs/components/maz-code-highlight.md +155 -0
  31. package/docs/components/maz-container.md +241 -0
  32. package/docs/components/maz-date-picker.md +791 -0
  33. package/docs/components/maz-dialog-confirm.md +215 -0
  34. package/docs/components/maz-dialog.md +143 -0
  35. package/docs/components/maz-drawer.md +106 -0
  36. package/docs/components/maz-dropdown.md +419 -0
  37. package/docs/components/maz-dropzone.md +387 -0
  38. package/docs/components/maz-expand-animation.md +82 -0
  39. package/docs/components/maz-fullscreen-loader.md +58 -0
  40. package/docs/components/maz-gallery.md +79 -0
  41. package/docs/components/maz-icon.md +203 -0
  42. package/docs/components/maz-input-code.md +73 -0
  43. package/docs/components/maz-input-number.md +79 -0
  44. package/docs/components/maz-input-phone-number.md +536 -0
  45. package/docs/components/maz-input-price.md +68 -0
  46. package/docs/components/maz-input-tags.md +112 -0
  47. package/docs/components/maz-input.md +334 -0
  48. package/docs/components/maz-lazy-img.md +113 -0
  49. package/docs/components/maz-link.md +146 -0
  50. package/docs/components/maz-loading-bar.md +38 -0
  51. package/docs/components/maz-markdown-editor.md +320 -0
  52. package/docs/components/maz-pagination.md +82 -0
  53. package/docs/components/maz-popover.md +794 -0
  54. package/docs/components/maz-pull-to-refresh.md +222 -0
  55. package/docs/components/maz-radio-buttons.md +313 -0
  56. package/docs/components/maz-radio.md +119 -0
  57. package/docs/components/maz-read-more.md +209 -0
  58. package/docs/components/maz-reading-progress-bar.md +96 -0
  59. package/docs/components/maz-select-country.md +513 -0
  60. package/docs/components/maz-select.md +318 -0
  61. package/docs/components/maz-sidebar-content.md +25 -0
  62. package/docs/components/maz-sidebar-footer.md +25 -0
  63. package/docs/components/maz-sidebar-group.md +27 -0
  64. package/docs/components/maz-sidebar-header.md +25 -0
  65. package/docs/components/maz-sidebar-menu-button.md +41 -0
  66. package/docs/components/maz-sidebar-menu-item.md +25 -0
  67. package/docs/components/maz-sidebar-menu-sub.md +32 -0
  68. package/docs/components/maz-sidebar-menu.md +25 -0
  69. package/docs/components/maz-sidebar-separator.md +21 -0
  70. package/docs/components/maz-sidebar-trigger.md +25 -0
  71. package/docs/components/maz-sidebar.md +507 -0
  72. package/docs/components/maz-skeleton.md +226 -0
  73. package/docs/components/maz-slider.md +165 -0
  74. package/docs/components/maz-spinner.md +84 -0
  75. package/docs/components/maz-stepper.md +301 -0
  76. package/docs/components/maz-switch.md +86 -0
  77. package/docs/components/maz-table-cell.md +27 -0
  78. package/docs/components/maz-table-row.md +28 -0
  79. package/docs/components/maz-table-title.md +27 -0
  80. package/docs/components/maz-table-virtualizer.md +31 -0
  81. package/docs/components/maz-table.md +426 -0
  82. package/docs/components/maz-tabs-bar.md +43 -0
  83. package/docs/components/maz-tabs-content-item.md +27 -0
  84. package/docs/components/maz-tabs-content.md +27 -0
  85. package/docs/components/maz-tabs.md +308 -0
  86. package/docs/components/maz-textarea.md +255 -0
  87. package/docs/components/maz-ticker.md +427 -0
  88. package/docs/components/maz-timeline.md +304 -0
  89. package/docs/components/maz-ui-provider.md +26 -0
  90. package/docs/components/maz-window-mockup.md +182 -0
  91. package/docs/composables/use-aos.md +41 -0
  92. package/docs/composables/use-breakpoints.md +42 -0
  93. package/docs/composables/use-dialog.md +58 -0
  94. package/docs/composables/use-display-names.md +130 -0
  95. package/docs/composables/use-drag.md +185 -0
  96. package/docs/composables/use-form-validator.md +1123 -0
  97. package/docs/composables/use-idle-timeout.md +172 -0
  98. package/docs/composables/use-pull-to-refresh.md +86 -0
  99. package/docs/composables/use-reading-time.md +132 -0
  100. package/docs/composables/use-string-matching.md +41 -0
  101. package/docs/composables/use-swipe.md +171 -0
  102. package/docs/composables/use-timer.md +104 -0
  103. package/docs/composables/use-toast.md +50 -0
  104. package/docs/composables/use-user-visibility.md +127 -0
  105. package/docs/composables/use-wait.md +50 -0
  106. package/docs/composables/use-window-size.md +25 -0
  107. package/docs/directives/click-outside.md +182 -0
  108. package/docs/directives/fullscreen-img.md +83 -0
  109. package/docs/directives/lazy-img.md +182 -0
  110. package/docs/directives/tooltip.md +298 -0
  111. package/docs/directives/zoom-img.md +100 -0
  112. package/docs/ecosystem/eslint-config.md +289 -0
  113. package/docs/ecosystem/icons/icon-set.md +25 -0
  114. package/docs/ecosystem/icons/index.md +584 -0
  115. package/docs/ecosystem/mcp.md +165 -0
  116. package/docs/ecosystem/node/exec-promise.md +93 -0
  117. package/docs/ecosystem/node/index.md +53 -0
  118. package/docs/ecosystem/node/logger.md +152 -0
  119. package/docs/ecosystem/node/print-banner.md +101 -0
  120. package/docs/ecosystem/node/setup-agents.md +102 -0
  121. package/docs/ecosystem/nuxt.md +551 -0
  122. package/docs/ecosystem/stylelint-config.md +310 -0
  123. package/docs/ecosystem/themes.md +966 -0
  124. package/docs/ecosystem/translations.md +1173 -0
  125. package/docs/ecosystem/utils/camel-case.md +37 -0
  126. package/docs/ecosystem/utils/capitalize.md +37 -0
  127. package/docs/ecosystem/utils/check-availability.md +85 -0
  128. package/docs/ecosystem/utils/cookie.md +86 -0
  129. package/docs/ecosystem/utils/country-code-to-unicode-flag.md +128 -0
  130. package/docs/ecosystem/utils/currency.md +53 -0
  131. package/docs/ecosystem/utils/date.md +53 -0
  132. package/docs/ecosystem/utils/debounce-callback.md +44 -0
  133. package/docs/ecosystem/utils/debounce-id.md +75 -0
  134. package/docs/ecosystem/utils/debounce.md +71 -0
  135. package/docs/ecosystem/utils/fetch-locale-ip.md +39 -0
  136. package/docs/ecosystem/utils/format-json.md +39 -0
  137. package/docs/ecosystem/utils/format-phone-number.md +43 -0
  138. package/docs/ecosystem/utils/get-browser-locale.md +35 -0
  139. package/docs/ecosystem/utils/get-country-flag-url.md +67 -0
  140. package/docs/ecosystem/utils/get-error-message.md +45 -0
  141. package/docs/ecosystem/utils/idle-timeout.md +96 -0
  142. package/docs/ecosystem/utils/index.md +57 -0
  143. package/docs/ecosystem/utils/is-client.md +38 -0
  144. package/docs/ecosystem/utils/is-equal.md +44 -0
  145. package/docs/ecosystem/utils/is-ios.md +43 -0
  146. package/docs/ecosystem/utils/is-server.md +37 -0
  147. package/docs/ecosystem/utils/is-standalone-mode.md +49 -0
  148. package/docs/ecosystem/utils/kebab-case.md +42 -0
  149. package/docs/ecosystem/utils/normalize-string.md +83 -0
  150. package/docs/ecosystem/utils/number.md +51 -0
  151. package/docs/ecosystem/utils/pascal-case.md +41 -0
  152. package/docs/ecosystem/utils/prevent-ios-input-zoom.md +72 -0
  153. package/docs/ecosystem/utils/script-loader.md +85 -0
  154. package/docs/ecosystem/utils/sleep.md +65 -0
  155. package/docs/ecosystem/utils/snake-case.md +42 -0
  156. package/docs/ecosystem/utils/swipe-handler.md +97 -0
  157. package/docs/ecosystem/utils/textarea-autogrow.md +47 -0
  158. package/docs/ecosystem/utils/throttle-id.md +54 -0
  159. package/docs/ecosystem/utils/throttle.md +63 -0
  160. package/docs/ecosystem/utils/truthy-filter.md +37 -0
  161. package/docs/ecosystem/utils/types/deep-key-of.md +54 -0
  162. package/docs/ecosystem/utils/types/deep-partial.md +48 -0
  163. package/docs/ecosystem/utils/types/deep-required.md +45 -0
  164. package/docs/ecosystem/utils/types/flatten-object-keys.md +50 -0
  165. package/docs/ecosystem/utils/types/generic-instance-type.md +48 -0
  166. package/docs/ecosystem/utils/types/infer-maybe-ref.md +41 -0
  167. package/docs/ecosystem/utils/upper-first.md +38 -0
  168. package/docs/ecosystem/utils/user-visibility.md +75 -0
  169. package/docs/guide/ai-agents.md +237 -0
  170. package/docs/guide/browser-support.md +88 -0
  171. package/docs/guide/getting-started.md +191 -0
  172. package/docs/guide/global-defaults.md +103 -0
  173. package/docs/guide/maz-ui-provider.md +231 -0
  174. package/docs/guide/migration-v5.md +871 -0
  175. package/docs/guide/resolvers.md +650 -0
  176. package/docs/guide/tailwind.md +483 -0
  177. package/docs/guide/vue.md +286 -0
  178. package/docs/manifest.json +1 -0
  179. package/docs/plugins/aos.md +312 -0
  180. package/docs/plugins/dialog.md +269 -0
  181. package/docs/plugins/toast.md +221 -0
  182. package/docs/plugins/wait.md +78 -0
  183. package/docs/reference/icons.md +46 -0
  184. package/docs/reference/tailwind-tokens.md +191 -0
  185. package/docs/rules.md +57 -0
  186. package/package.json +31 -4
@@ -0,0 +1,966 @@
1
+ ---
2
+ title: "Theming"
3
+ description: "Modern and performant theme system for Maz-UI built on native CSS features (light-dark(), color-scheme, color-mix(in oklch)) for v5."
4
+ package: "@maz-ui/themes"
5
+ url: "https://maz-ui.com/ecosystem/themes"
6
+ ---
7
+
8
+ # Theming
9
+
10
+ > Modern and performant theme system for Maz-UI built on native CSS features (light-dark(), color-scheme, color-mix(in oklch)) for v5.
11
+
12
+ - Package: `@maz-ui/themes`
13
+ - Import: `import { definePreset, useTheme } from '@maz-ui/themes'` or `import { mazUi } from '@maz-ui/themes/presets/mazUi'`
14
+ - Web: https://maz-ui.com/ecosystem/themes
15
+
16
+ Modern and performant theme system for Maz-UI built on native CSS features (`light-dark()`, `color-scheme`, `color-mix(in oklch)`) for v5.
17
+
18
+ ## Features
19
+
20
+ - **Native `light-dark()` + `color-scheme`** - Modern CSS theming with zero JS overhead for the light/dark switch
21
+ - **Native widget theming** - `color-scheme` makes scrollbars, native `<select>`, date pickers and autofill follow the active mode automatically
22
+ - **Animated theme switch** - Optional full-page View Transitions via `setColorMode(..., { animate: true })`
23
+ - **Anti-FART** - `<meta name="color-scheme">` injected at boot to prevent any Flash of inAccurate coloR Theme (no setup needed)
24
+ - **Automatic color scales** - `--maz-X-50` through `--maz-X-950` derived via OKLCh relative color syntax - perceptually uniform and chroma-preserving
25
+ - **Performance Strategies** - Runtime injection or build-time generation according to your needs
26
+ - **Strict TypeScript** - Complete types for perfect DX
27
+ - **Zero FOUC** - Pass the preset object up front; the full CSS is injected synchronously on first paint
28
+ - **Flexible Presets** - Ready-to-use and customizable configurations
29
+
30
+ ## Theme Editor
31
+
32
+ Create your own theme with the Theme Editor.
33
+
34
+ ## Quick Usage
35
+
36
+ ### 1. Plugin Configuration with `MazUi` plugin
37
+
38
+ To avoid FOUC (Flash of Unstyled Content), **you should provide the theme preset**.
39
+
40
+ ```typescript
41
+ // main.ts
42
+ import { MazUi } from 'maz-ui/plugins/maz-ui'
43
+ import { mazUi } from '@maz-ui/themes/presets/mazUi'
44
+ import { createApp } from 'vue'
45
+
46
+ const app = createApp(App)
47
+
48
+ app.use(MazUi, {
49
+ theme: {
50
+ preset: mazUi, // pristine | ocean | obsidian | nova
51
+ strategy: 'runtime', // 'runtime' | 'buildtime'
52
+ darkModeStrategy: 'class', // 'class' | 'media' (only if mode is `both`)
53
+ mode: 'both', // 'light' | 'dark' | 'both' (supported color modes)
54
+ colorMode: 'auto', // 'auto' | 'light' | 'dark' (initial color mode, only if mode is 'both')
55
+ // Class added to <html> when dark mode is forced (default: 'dark')
56
+ darkClass: 'dark',
57
+ // Class added to <html> when light mode is forced (default: 'light')
58
+ lightClass: 'light',
59
+ persistPreset: true, // remember the active preset name across reloads
60
+ }
61
+ })
62
+ ```
63
+
64
+ **Tip: Alternative: MazUiProvider**
65
+
66
+ You can also initialize the theme via the [`MazUiProvider`](../guide/maz-ui-provider.md) component for lazy-loaded pages or subtree-scoped themes.
67
+
68
+ ### 2. Setup your CSS to support theme foundation and dark mode
69
+
70
+ ```css
71
+ html {
72
+ font-size: var(--maz-base-font-size);
73
+ font-family: var(--maz-font-family);
74
+ background-color: var(--maz-surface);
75
+ color: var(--maz-foreground);
76
+ }
77
+ ```
78
+
79
+ ### 3. Using in your components
80
+
81
+ ```vue
82
+ <script setup>
83
+ import { useTheme } from '@maz-ui/themes'
84
+
85
+ const { toggleDarkMode, isDark, updateTheme } = useTheme()
86
+ </script>
87
+
88
+ <template>
89
+ <div class="bg-surface text-foreground">
90
+ <button
91
+ class="rounded-md bg-primary text-primary-foreground"
92
+ @click="toggleDarkMode"
93
+ >
94
+ {{ isDark ? '☀️' : '🌙' }} Toggle theme
95
+ </button>
96
+ </div>
97
+ </template>
98
+ ```
99
+
100
+ ## Configuration
101
+
102
+ - `preset`: The theme preset to use
103
+ - `overrides` (optional): Override specific parts of the theme
104
+ - `strategy` (optional, default `'runtime'`): The rendering strategy to use - `'runtime' | 'buildtime'`
105
+ - `darkModeStrategy` (optional, default `'class'`): The dark mode strategy - `'class' | 'media'`, only if you use mode `both`
106
+ - `mode` (optional, default `'both'`): The supported color modes - `'light' | 'dark' | 'both'`
107
+ - `colorMode` (optional, default `'auto'`): The initial color mode - `'light' | 'dark' | 'auto'` (only if mode is `'both'`)
108
+ - `darkClass` (optional, default `'dark'`): Class added to `<html>` when `colorMode === 'dark'`
109
+ - `lightClass` (optional, default `'light'`): Class added to `<html>` when `colorMode === 'light'` - mirror of `darkClass`
110
+ - `persistPreset` (optional, default `true`): Persist the active preset name in the `maz-preset` cookie so it is restored on reload.
111
+
112
+ ### Preset persistence
113
+
114
+ When `persistPreset` is enabled (default), `@maz-ui/themes` stores the resolved preset name in a `maz-preset` cookie (1-year TTL, `SameSite=Lax`) - exactly like `maz-color-mode` for the dark/light state. The cookie is:
115
+
116
+ - **Read at boot** and used to resolve the active preset - even when `options.preset` is provided. `options.preset` (string name **or** preset object) is treated as the *default* the app boots with, while the cookie carries the user's last explicit choice. The cookie wins.
117
+ - **Written** after every successful preset resolution and after every `useTheme().updateTheme()` call (idempotent - no write if the value already matches).
118
+ - **Auto-cleared** when the saved name no longer resolves (e.g. typo, preset removed in a downgrade) - the runtime falls back to `options.preset` (or default) and clears the cookie silently.
119
+
120
+ Custom preset names are stored exactly like bundled ones: `@maz-ui/themes` does not maintain a whitelist. Switch the option off to disable any cookie read/write:
121
+
122
+ ```typescript
123
+ app.use(MazUi, {
124
+ theme: {
125
+ preset: mazUi,
126
+ persistPreset: false, // never write or read the maz-preset cookie
127
+ },
128
+ })
129
+ ```
130
+
131
+ Useful when:
132
+ - You want zero theme-related cookies (privacy / regulatory).
133
+ - The active preset is fully driven by the consumer app and no end-user switching is exposed.
134
+
135
+ ## Color modes and class toggling
136
+
137
+ `darkClass` and `lightClass` interact with `darkModeStrategy` to control how `<html>` is decorated when the user picks an explicit mode.
138
+
139
+ ### `darkModeStrategy: 'class'` (default)
140
+
141
+ - `setColorMode('dark')` adds `darkClass` (default `.dark`) to `<html>` → `color-scheme: only dark`.
142
+ - `setColorMode('light')` adds `lightClass` (default `.light`) to `<html>` → `color-scheme: only light`.
143
+ - `setColorMode('auto')` removes both classes → `color-scheme: light dark` lets the browser follow the system `prefers-color-scheme`.
144
+
145
+ Forcing both classes on the root ensures native widgets (scrollbars, native `<select>`, date pickers, autofill backgrounds, …) match the explicit user choice rather than the OS preference.
146
+
147
+ ### `darkModeStrategy: 'media'`
148
+
149
+ - No class is ever added to `<html>`.
150
+ - The browser always follows `prefers-color-scheme` via `color-scheme: light dark`.
151
+ - `setColorMode()` still updates the persisted cookie but does **not** force a visual override.
152
+
153
+ ## Animated theme switch
154
+
155
+ For a full-page animated swap (rather than per-variable color tweens), pass `{ animate: true }` to `setColorMode` or `toggleDarkMode`:
156
+
157
+ ```vue
158
+ <script setup>
159
+ import { useTheme } from '@maz-ui/themes'
160
+
161
+ const { toggleDarkMode, setColorMode } = useTheme()
162
+
163
+ async function onToggle() {
164
+ await toggleDarkMode({ animate: true })
165
+ }
166
+
167
+ async function forceDark() {
168
+ await setColorMode('dark', { animate: true })
169
+ }
170
+ </script>
171
+ ```
172
+
173
+ - Wraps the switch in `document.startViewTransition()` so the browser captures a snapshot of the page before/after and crossfades between them.
174
+ - The View Transition glue is **lazy-imported** - when `animate` is not used, it stays out of the boot bundle.
175
+ - **Graceful degradation:** in browsers that don't support the API, the change is applied immediately with no animation (no error thrown).
176
+
177
+ ## Interactive Demo
178
+
179
+ **Real-time theme control**
180
+
181
+ ```vue
182
+ <script setup>
183
+ import { useTheme } from '@maz-ui/themes'
184
+
185
+ const { presetName, updateTheme, colorMode, setColorMode } = useTheme()
186
+ </script>
187
+
188
+ <template>
189
+ <div class="demo-theme-controls">
190
+ <div class="space-y-4">
191
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
192
+ <MazBtn color="primary">Primary Button</MazBtn>
193
+ <MazBtn color="secondary">Secondary Button</MazBtn>
194
+ <MazBtn color="success">Success Button</MazBtn>
195
+ <MazBtn color="warning">Warning Button</MazBtn>
196
+ </div>
197
+ <div class="theme-controls space-y-4">
198
+ <div class="flex items-center gap-4">
199
+ <label class="text-sm font-medium">Mode:</label>
200
+ <MazBtn
201
+ size="sm"
202
+ :color="colorMode === 'light' ? 'primary' : 'secondary'"
203
+ @click="setColorMode('light')"
204
+ >
205
+ ☀️ Light
206
+ </MazBtn>
207
+ <MazBtn
208
+ size="sm"
209
+ :color="colorMode === 'dark' ? 'primary' : 'secondary'"
210
+ @click="setColorMode('dark')"
211
+ >
212
+ 🌙 Dark
213
+ </MazBtn>
214
+ <MazBtn
215
+ size="sm"
216
+ :color="colorMode === 'auto' ? 'primary' : 'secondary'"
217
+ @click="setColorMode('auto')"
218
+ >
219
+ 🔄 Auto
220
+ </MazBtn>
221
+ </div>
222
+ <div class="space-y-2">
223
+ <label class="text-sm font-medium">Preset:</label>
224
+ <div class="flex gap-2">
225
+ <MazBtn
226
+ size="sm"
227
+ :color="presetName === 'maz-ui' ? 'primary' : 'secondary'"
228
+ @click="updateTheme('mazUi')"
229
+ >
230
+ Maz-UI
231
+ </MazBtn>
232
+ <MazBtn
233
+ size="sm"
234
+ :color="presetName === 'ocean' ? 'primary' : 'secondary'"
235
+ @click="updateTheme('ocean')"
236
+ >
237
+ Ocean
238
+ </MazBtn>
239
+ <MazBtn
240
+ size="sm"
241
+ :color="presetName === 'pristine' ? 'primary' : 'secondary'"
242
+ @click="updateTheme('pristine')"
243
+ >
244
+ Pristine
245
+ </MazBtn>
246
+ <MazBtn
247
+ size="sm"
248
+ :color="presetName === 'obsidian' ? 'primary' : 'secondary'"
249
+ @click="updateTheme('obsidian')"
250
+ >
251
+ Obsidian
252
+ </MazBtn>
253
+ </div>
254
+ </div>
255
+ </div>
256
+ </div>
257
+ </div>
258
+ </template>
259
+ ```
260
+
261
+ ## Available Presets
262
+
263
+ ### Maz-UI (Default)
264
+
265
+ The default theme inspired by Maz-UI identity with vibrant and modern colors.
266
+
267
+ ```typescript
268
+ import { mazUi } from '@maz-ui/themes/presets'
269
+ ```
270
+
271
+ ### Pristine
272
+
273
+ A minimalist and elegant theme inspired by Apple design with pure black and white aesthetics.
274
+
275
+ ```typescript
276
+ import { pristine } from '@maz-ui/themes/presets'
277
+ ```
278
+
279
+ ### Ocean
280
+
281
+ A vibrant ocean-inspired theme with deep blues, aquatic greens, and coral accents. Features rounded borders and Poppins font for a fresh, modern look.
282
+
283
+ ```typescript
284
+ import { ocean } from '@maz-ui/themes/presets'
285
+ ```
286
+
287
+ ### Obsidian
288
+
289
+ A dark and elegant theme with a focus on readability and minimalism.
290
+
291
+ ```typescript
292
+ import { obsidian } from '@maz-ui/themes/presets'
293
+ ```
294
+
295
+ ### Nova
296
+
297
+ A modern startup / AI / creative preset - electric violet primary, hot coral secondary, cyan accent. Tight 0.5rem `md` radius, Geist + Inter font stack, snappy ease-out spring. Built for product / AI surfaces (think Linear, Vercel, OpenAI energy) where the UI itself should feel alive.
298
+
299
+ ```typescript
300
+ import { nova } from '@maz-ui/themes/presets'
301
+ ```
302
+
303
+ ## Rendering Strategies
304
+
305
+ ### ⚡ Runtime (Recommended)
306
+
307
+ CSS is generated and injected synchronously on first paint. Pass the preset object directly (`preset: mazUi`) so the full stylesheet is rendered before the first frame - no FOUC.
308
+
309
+ ```typescript
310
+ import { mazUi } from '@maz-ui/themes/presets'
311
+
312
+ app.use(MazUi, {
313
+ theme: {
314
+ preset: mazUi,
315
+ strategy: 'runtime'
316
+ }
317
+ })
318
+ ```
319
+
320
+ ### 🏗️ Buildtime
321
+
322
+ CSS generated at build-time and included in the bundle.
323
+ You have to build your CSS files before running your app.
324
+
325
+ See Build-time for more details.
326
+
327
+ ```typescript
328
+ import { mazUi } from '@maz-ui/themes/presets'
329
+
330
+ app.use(MazUi, {
331
+ theme: {
332
+ preset: mazUi,
333
+ strategy: 'buildtime'
334
+ }
335
+ })
336
+ ```
337
+
338
+ ## Creating Custom Themes
339
+
340
+ ### Basic Theme
341
+
342
+ **Create your own theme**
343
+
344
+ ```typescript
345
+ import { definePreset, MazUiTheme, type ThemePresetOverrides, ocean } from '@maz-ui/themes'
346
+
347
+ const customTheme = await definePreset({
348
+ base: 'ocean',
349
+ overrides: {
350
+ name: 'custom-purple',
351
+ foundation: {
352
+ 'font-family': 'Inter, sans-serif'
353
+ },
354
+ scales: {
355
+ rounded: { md: '1rem' }
356
+ },
357
+ colors: {
358
+ light: {
359
+ primary: 'oklch(0.62 0.24 305)',
360
+ secondary: 'oklch(0.94 0.04 320)',
361
+ accent: 'oklch(0.7 0.22 290)'
362
+ },
363
+ dark: {
364
+ primary: 'oklch(0.72 0.22 305)',
365
+ secondary: 'oklch(0.28 0.06 320)',
366
+ accent: 'oklch(0.78 0.2 290)'
367
+ }
368
+ }
369
+ },
370
+ })
371
+ /**
372
+ * or with preset object
373
+ * The function is synchronous when using a preset object
374
+ */
375
+ const customTheme = definePreset({
376
+ base: ocean,
377
+ overrides,
378
+ })
379
+
380
+ // Usage
381
+
382
+ // with plugin
383
+ app.use(MazUiTheme, {
384
+ preset: customTheme,
385
+ })
386
+
387
+ // or with composable
388
+ const { updateTheme } = useTheme()
389
+ updateTheme(customTheme)
390
+ ```
391
+
392
+ ### Advanced Theme with Overrides
393
+
394
+ ```typescript
395
+ import { definePreset } from '@maz-ui/themes'
396
+
397
+ const brandTheme = await definePreset({
398
+ base: 'maz-ui',
399
+ overrides: {
400
+ name: 'brand',
401
+ foundation: {
402
+ 'border-width': '2px',
403
+ 'font-family': 'Inter, sans-serif'
404
+ },
405
+ scales: {
406
+ rounded: { md: '0.75rem' }
407
+ },
408
+ colors: {
409
+ light: {
410
+ primary: 'oklch(0.6 0.18 254)',
411
+ secondary: 'oklch(0.96 0.01 254)',
412
+ surface: 'oklch(0.99 0.005 254)',
413
+ accent: 'oklch(0.7 0.22 305)'
414
+ },
415
+ dark: {
416
+ primary: 'oklch(0.7 0.18 254)',
417
+ secondary: 'oklch(0.22 0.03 254)',
418
+ surface: 'oklch(0.18 0.02 254)',
419
+ accent: 'oklch(0.78 0.2 305)'
420
+ }
421
+ }
422
+ }
423
+ })
424
+ ```
425
+
426
+ ### Customizing scales
427
+
428
+ Each `ThemeScales` entry maps to a Tailwind utility - override the keys you care about and the rest stays untouched:
429
+
430
+ ```typescript
431
+ const denseTheme = definePreset({
432
+ base: 'maz-ui',
433
+ overrides: {
434
+ name: 'dense',
435
+ foundation: {
436
+ // Tighter spacing - every p-N / gap-N / m-N rescales
437
+ space: '0.2rem',
438
+ },
439
+ scales: {
440
+ // Sharper corners on the whole radius scale
441
+ rounded: {
442
+ 'xs': '0.0625rem',
443
+ 'sm': '0.125rem',
444
+ 'md': '0.375rem',
445
+ 'lg': '0.5rem',
446
+ 'xl': '0.75rem',
447
+ '2xl': '1rem',
448
+ '3xl': '1.5rem',
449
+ },
450
+ // Custom elevated-surface shadow
451
+ shadow: {
452
+ elevation: '0 8px 24px rgba(0, 0, 0, 0.15)',
453
+ },
454
+ },
455
+ },
456
+ })
457
+ ```
458
+
459
+ Foundation gets new optional keys for fonts and disabled-state behaviour:
460
+
461
+ ```typescript
462
+ const codeTheme = definePreset({
463
+ base: 'maz-ui',
464
+ overrides: {
465
+ foundation: {
466
+ 'font-mono-stack': '"JetBrains Mono", ui-monospace, SFMono-Regular, monospace',
467
+ 'font-display-stack': '"Cal Sans", Manrope, sans-serif',
468
+ 'disabled-opacity': '0.4',
469
+ 'disabled-cursor': 'wait',
470
+ },
471
+ },
472
+ })
473
+ ```
474
+
475
+ ### Per-component overrides
476
+
477
+ `components` is a small, validated set of per-component knobs. Every entry is per-mode where appropriate so light and dark can drift independently:
478
+
479
+ ```typescript
480
+ const surfaceTheme = definePreset({
481
+ base: 'maz-ui',
482
+ overrides: {
483
+ name: 'cool-surfaces',
484
+ components: {
485
+ btn: {
486
+ // Bias every button text heavier
487
+ 'font-weight': '600',
488
+ },
489
+ container: {
490
+ // Cards / dialogs / popovers / drawers - light = page surface, dark = a tier above
491
+ bg: { light: 'var(--maz-surface)', dark: 'var(--maz-surface-300)' },
492
+ },
493
+ input: {
494
+ // All form-control surfaces
495
+ bg: { light: 'var(--maz-surface-100)', dark: 'var(--maz-surface-400)' },
496
+ },
497
+ },
498
+ },
499
+ })
500
+ ```
501
+
502
+ Components consume these via `bg-container` / `bg-input` Tailwind utilities, so a single override propagates everywhere - no per-component class hunt.
503
+
504
+ ### Dialog sizing
505
+
506
+ `components.dialog` controls the width of [`MazDialog`](../components/maz-dialog.md) on tablet and up. The two keys are emitted as `--maz-dialog-max-width` / `--maz-dialog-min-width` and consumed by the component through `var(--maz-dialog-max-width, 38rem)` / `var(--maz-dialog-min-width, 32rem)`:
507
+
508
+ ```typescript
509
+ const wideDialogTheme = definePreset({
510
+ base: 'maz-ui',
511
+ overrides: {
512
+ name: 'wide-dialogs',
513
+ components: {
514
+ dialog: {
515
+ 'max-width': '48rem',
516
+ 'min-width': '36rem',
517
+ },
518
+ },
519
+ },
520
+ })
521
+ ```
522
+
523
+ Both values are in `rem`, so they scale with the preset's `base-font-size`. Bundled presets anchored on `14px` use `38rem` / `32rem`; `ocean` (`16px`) ships scaled rem values (`33.25rem` / `28rem`) to keep the same rendered pixel width. The `max-width` / `min-width` props on `MazDialog` still override the preset per instance.
524
+
525
+ ## useTheme Composable API
526
+
527
+ ```typescript
528
+ const {
529
+ // Reactive state
530
+ preset, // ComputedRef<ThemePreset>
531
+ presetName, // ComputedRef<string>
532
+ colorMode, // Ref<'light' | 'dark' | 'auto'> - also accepts assignment (computed setter)
533
+ isDark, // ComputedRef<boolean>
534
+ strategy, // ComputedRef<'runtime' | 'buildtime'>
535
+ mode, // ComputedRef<'light' | 'dark' | 'both'>
536
+ darkModeStrategy, // ComputedRef<'class' | 'media'>
537
+
538
+ // Actions
539
+ updateTheme, // (preset: ThemePreset | ThemePresetName | ThemePresetOverrides) => Promise<void>
540
+ setColorMode, // (mode: 'light' | 'dark' | 'auto', options?: { animate?: boolean }) => Promise<void>
541
+ toggleDarkMode, // (options?: { animate?: boolean }) => Promise<void>
542
+ } = useTheme()
543
+
544
+ // Set the color mode imperatively
545
+ await setColorMode('dark')
546
+
547
+ // Or assign to `colorMode` - it's a computed with a setter
548
+ colorMode.value = 'dark'
549
+
550
+ // Animated full-page switch via View Transitions
551
+ await toggleDarkMode({ animate: true })
552
+ ```
553
+
554
+ `setColorMode` and `toggleDarkMode` are **async** (`Promise<void>`). The promise resolves once the change - and the optional View Transition - has been applied. Callers can ignore the return value when no transition is needed.
555
+
556
+ ### Advanced Usage Examples
557
+
558
+ ```vue
559
+ <script setup>
560
+ import { useTheme } from '@maz-ui/themes'
561
+ import { computed } from 'vue'
562
+
563
+ const { presetName, isDark, updateTheme, setColorMode } = useTheme()
564
+
565
+ // Computed for interface
566
+ const themeIcon = computed(() => isDark.value ? '☀️' : '🌙')
567
+
568
+ // Function to apply a temporary custom theme
569
+ function previewColor(color: string) {
570
+ updateTheme({
571
+ colors: {
572
+ light: { primary: color },
573
+ dark: { primary: color }
574
+ }
575
+ })
576
+ }
577
+
578
+ // Auto mode with system detection
579
+ function enableAutoMode() {
580
+ setColorMode('auto')
581
+ }
582
+ </script>
583
+ ```
584
+
585
+ ## Build-time Strategy: Complete Guide
586
+
587
+ The build-time strategy allows you to generate your theme CSS files at compile time, offering the best performance in production.
588
+
589
+ ### Step-by-step configuration
590
+
591
+ #### 1. Generate CSS
592
+
593
+ ```typescript [Vue]
594
+ import { mkdirSync, writeFileSync } from 'node:fs'
595
+ import { join } from 'node:path'
596
+ import {
597
+ // Build all css in one file
598
+ buildThemeCSS,
599
+ // Build multiple themes with one file each
600
+ generateThemeBundle,
601
+ // Build separate css files
602
+ buildSeparateThemeFiles,
603
+ definePreset,
604
+ mazUi,
605
+ } from '@maz-ui/themes'
606
+
607
+ import App from './App.vue'
608
+
609
+ const _dirname = dirname(fileURLToPath(import.meta.url))
610
+
611
+ // Custom theme
612
+ const customPreset = definePreset({
613
+ base: mazUi,
614
+ overrides: {
615
+ name: 'custom',
616
+ colors: {
617
+ light: { primary: 'oklch(0.6 0.18 254)' },
618
+ dark: { primary: 'oklch(0.7 0.18 254)' },
619
+ },
620
+ },
621
+ })
622
+
623
+ /**
624
+ * Generate complete CSS
625
+ */
626
+ const fullCSS = buildThemeCSS({
627
+ preset: customPreset,
628
+ mode: 'both',
629
+ })
630
+
631
+ writeFileSync(join(_dirname, 'public/custom.css'), fullCSS)
632
+
633
+ /**
634
+ * Or generate per-mode CSS files
635
+ */
636
+ const { full, lightOnly, darkOnly } = buildSeparateThemeFiles(customPreset, {
637
+ darkSelector: 'class',
638
+ })
639
+
640
+ writeFileSync(join(_dirname, 'public/custom-full.css'), full)
641
+
642
+ /**
643
+ * Or generate bundle for multiple themes in one file each
644
+ */
645
+ const themeBundle = generateThemeBundle([customPreset, mazUi], {
646
+ mode: 'both',
647
+ })
648
+
649
+ Object.entries(themeBundle).forEach(([name, css]) => {
650
+ writeFileSync(join(_dirname, `public/${name}.css`), css)
651
+ })
652
+
653
+ const app = createApp(App)
654
+
655
+ app.use(MazUiTheme, {
656
+ preset: customPreset,
657
+ strategy: 'buildtime', // Important!
658
+ darkModeStrategy: 'class',
659
+ })
660
+
661
+ app.mount('#app')
662
+ ```
663
+
664
+ ```typescript [Vitepress]
665
+ import {
666
+ buildThemeCSS,
667
+ generateThemeBundle,
668
+ buildSeparateThemeFiles,
669
+ createThemeStylesheet,
670
+ definePreset,
671
+ mazUi,
672
+ CSS_ID,
673
+ } from '@maz-ui/themes'
674
+
675
+ // Custom theme
676
+ const customPreset = definePreset({
677
+ base: mazUi,
678
+ overrides: {
679
+ name: 'custom',
680
+ colors: {
681
+ light: { primary: 'oklch(0.6 0.18 254)' },
682
+ dark: { primary: 'oklch(0.7 0.18 254)' },
683
+ },
684
+ },
685
+ })
686
+
687
+ // Generate complete CSS
688
+ const fullCSS = buildThemeCSS({
689
+ preset: customPreset,
690
+ mode: 'both',
691
+ })
692
+
693
+ // Or generate per-mode CSS files
694
+ const { full, lightOnly, darkOnly } = buildSeparateThemeFiles(customPreset, {
695
+ darkSelector: 'class',
696
+ })
697
+
698
+ // Or generate bundle for multiple themes
699
+ const themeBundle = generateThemeBundle([customPreset, mazUi], {
700
+ mode: 'both',
701
+ })
702
+
703
+ export default defineConfig<DefaultTheme.Config>({
704
+ head: [
705
+ ['style', { id: CSS_ID, type: 'text/css' }, full],
706
+ ] satisfies HeadConfig[],
707
+ })
708
+ ```
709
+
710
+ ```typescript [Nuxt]
711
+ /*
712
+ * You dont need to do anything,
713
+ * The module will handle it for you.
714
+ *
715
+ * Just provide a preset to the module
716
+ */
717
+
718
+ const customPreset = definePreset({
719
+ base: mazUi,
720
+ overrides: {
721
+ name: 'custom',
722
+ colors: {
723
+ light: { primary: 'oklch(0.6 0.18 254)' },
724
+ dark: { primary: 'oklch(0.7 0.18 254)' },
725
+ },
726
+ },
727
+ })
728
+
729
+ export default defineConfig({
730
+ modules: ['@maz-ui/nuxt'],
731
+ mazUi: {
732
+ theme: {
733
+ preset: customPreset,
734
+ mode: 'both',
735
+ colorMode: 'auto',
736
+ },
737
+ },
738
+ })
739
+ ```
740
+
741
+ #### 2. Include in your HTML (Only for Vue users)
742
+
743
+ ```html
744
+ <link rel="stylesheet" href="/themes/custom-full.css">
745
+ ```
746
+
747
+ ### Utility functions
748
+
749
+ #### `buildThemeCSS(options)`
750
+
751
+ Generates complete CSS for a theme.
752
+
753
+ ```typescript
754
+ const css = buildThemeCSS({
755
+ preset: customPreset,
756
+ mode: 'both', // 'light' | 'dark' | 'both'
757
+ darkSelector: 'class', // 'class' | 'media'
758
+ })
759
+ ```
760
+
761
+ #### `generateThemeBundle(presets, options)`
762
+
763
+ Generates a bundle containing multiple themes.
764
+
765
+ ```typescript
766
+ const bundle = generateThemeBundle([theme1, theme2], {
767
+ mode: 'both',
768
+ darkSelector: 'class',
769
+ })
770
+ // Result: { 'theme1': 'css...', 'theme2': 'css...' }
771
+ ```
772
+
773
+ #### `buildSeparateThemeFiles(preset, options)`
774
+
775
+ Generates separate files for different use cases.
776
+
777
+ ```typescript
778
+ const files = buildSeparateThemeFiles(preset)
779
+ // Result: { full, lightOnly, darkOnly }
780
+ ```
781
+
782
+ #### `createThemeStylesheet(css, options)`
783
+
784
+ Creates a `
785
+ @reference "../../.vitepress/theme/main.css";
786
+ ` tag with the provided CSS.
787
+
788
+ ```typescript
789
+ const styleTag = createThemeStylesheet(css, {
790
+ id: 'my-theme',
791
+ media: 'screen', // optional
792
+ })
793
+ ```
794
+
795
+ ### Build-time strategy advantages
796
+
797
+ - **Optimal performance** - No client-side CSS generation
798
+ - **Efficient caching** - CSS files cached by CDN
799
+ - **Reduced bundle** - Generation utilities excluded from client
800
+ - **Full compatibility** - Works even with JavaScript disabled
801
+
802
+ ### Recommended use cases
803
+
804
+ - Production applications with static themes
805
+ - Sites with critical performance requirements
806
+ - Projects with multiple predefined themes
807
+ - Applications requiring fine control over CSS loading
808
+
809
+ ## Token Reference
810
+
811
+ Every preset emits the same set of CSS variables on `:root`. With `mode: 'both'`, each base color is a single `light-dark(L, D)` declaration that the browser resolves to the active scheme. Use these names directly in your own CSS - `var(--maz-primary)`, `calc(var(--maz-space) * 4)`, etc.
812
+
813
+ ### Foundation
814
+
815
+ Single-value design tokens. Set via `foundation.<key>` on the preset.
816
+
817
+ | Preset key | CSS variable | Default | Notes |
818
+ | --- | --- | --- | --- |
819
+ | `base-font-size` | `--maz-base-font-size` | `14px` | Anchors `rem` for the whole app. Apply on `html { font-size: var(--maz-base-font-size) }`. |
820
+ | `border-width` | `--maz-border-width` | `1px` | Default border for components and the global `*::before/::after` reset. |
821
+ | `space` | `--maz-space` | `0.25rem` | Base step for every Tailwind spacing utility (`p-1`, `gap-2`, …). |
822
+ | `font-family` | `--maz-font-family` | preset-specific | Sans / body font stack. Bridged to Tailwind `--font-sans`. |
823
+ | `font-mono-stack` | `--maz-font-mono-stack` | `ui-monospace, …` | Monospace stack - `MazInputCode`, `<code>`, `<kbd>`. Bridged to `--font-mono`. |
824
+ | `font-display-stack` | `--maz-font-display-stack` | same as `font-family` | Display / heading stack. Bridged to `--font-display`. |
825
+ | `motion-fast` | `--maz-motion-fast` | `100ms` | Bridged to Tailwind `--duration-fast`. |
826
+ | `motion-normal` | `--maz-motion-normal` | `200ms` | Default transition duration (`--default-transition-duration`). |
827
+ | `motion-slow` | `--maz-motion-slow` | `300ms` | Bridged to `--duration-slow`. |
828
+ | `easing-out` | `--maz-easing-out` | `cubic-bezier(0.4, 0, 0.2, 1)` | Default easing (`--ease-out`, also `--default-transition-timing-function`). |
829
+ | `easing-in` | `--maz-easing-in` | `cubic-bezier(0.4, 0, 1, 1)` | Bridged to `--ease-in`. |
830
+ | `easing-in-out` | `--maz-easing-in-out` | `cubic-bezier(0.4, 0, 0.2, 1)` | Bridged to `--ease-in-out`. |
831
+ | `disabled-opacity` | `--maz-disabled-opacity` | `0.5` | Applied to disabled buttons / inputs. |
832
+ | `disabled-cursor` | `--maz-disabled-cursor` | `not-allowed` | Cursor for disabled interactive elements. |
833
+
834
+ > **Why `font-mono-stack` / `font-display-stack` / `motion-*`?** Under Tailwind v4 `prefix(maz)`, the bridge LHS gets prefixed (`--font-mono` → `--maz-font-mono`), so a same-named source token would self-cycle. The `-stack` and `motion-` suffixes break the collision.
835
+
836
+ ### Colors
837
+
838
+ Defined per mode under `colors.light` / `colors.dark`. Each base color also gets an automatic 50-950 scale.
839
+
840
+ | Preset key | CSS variable (base) | Auto scale | Notes |
841
+ | --- | --- | --- | --- |
842
+ | `surface` | `--maz-surface` | `--maz-surface-50..900` | Page / container background. |
843
+ | `foreground` | `--maz-foreground` | `--maz-foreground-50..900` | Default text color. |
844
+ | `primary` | `--maz-primary` | `--maz-primary-50..900` | Brand color. |
845
+ | `primary-foreground` | `--maz-primary-foreground` | - | Text on `bg-primary`. |
846
+ | `secondary` | `--maz-secondary` | `--maz-secondary-50..900` | |
847
+ | `secondary-foreground` | `--maz-secondary-foreground` | - | |
848
+ | `accent` | `--maz-accent` | `--maz-accent-50..900` | |
849
+ | `accent-foreground` | `--maz-accent-foreground` | - | |
850
+ | `info` | `--maz-info` | `--maz-info-50..900` | Status - informational. |
851
+ | `info-foreground` | `--maz-info-foreground` | - | |
852
+ | `success` | `--maz-success` | `--maz-success-50..900` | Status - success. |
853
+ | `success-foreground` | `--maz-success-foreground` | - | |
854
+ | `warning` | `--maz-warning` | `--maz-warning-50..900` | Status - warning. |
855
+ | `warning-foreground` | `--maz-warning-foreground` | - | |
856
+ | `destructive` | `--maz-destructive` | `--maz-destructive-50..900` | Status - error / danger. |
857
+ | `destructive-foreground` | `--maz-destructive-foreground` | - | |
858
+ | `contrast` | `--maz-contrast` | `--maz-contrast-50..900` | High-contrast accent (light = near-black, dark = near-white). |
859
+ | `contrast-foreground` | `--maz-contrast-foreground` | - | |
860
+ | `divider` | `--maz-divider` | `--maz-divider-50..900` | Default border / separator color. |
861
+ | `muted` | `--maz-muted` | `--maz-muted-50..900` | Muted / secondary text. |
862
+ | `overlay` | `--maz-overlay` | `--maz-overlay-50..900` | Backdrop / dialog scrim. |
863
+ | `shadow` | `--maz-shadow` | `--maz-shadow-50..900` | Tint used by Tailwind `shadow-*` utilities (via `--color-elevation`). |
864
+
865
+ ### Scales
866
+
867
+ Multi-step scales under `scales.<key>`.
868
+
869
+ | Preset key | CSS variables | Tailwind utility |
870
+ | --- | --- | --- |
871
+ | `rounded.xs..3xl` | `--maz-rounded-xs..3xl` | `rounded-{key}` (bridged to `--radius-{key}`) |
872
+ | `shadow.{sm, md, lg, xl, elevation}` | `--maz-shadow-style-{key}` | `shadow-{key}` (bridged to `--shadow-{key}`) |
873
+
874
+ > Same naming-collision avoidance as foundation: `rounded.*` (instead of `radius.*`) and `shadow-style-*` (instead of plain `shadow-*`) keep the bridge cycle-free under `prefix(maz)`.
875
+
876
+ ### Components
877
+
878
+ Per-component knobs under `components.<key>`. All optional - omit to fall back to the surface tokens.
879
+
880
+ | Preset key | CSS variable | Notes |
881
+ | --- | --- | --- |
882
+ | `btn.font-weight` | `--maz-btn-font-weight` | Font-weight on `.m-btn`. Defaults to `'500'`. |
883
+ | `container.bg.light` / `.dark` | `--maz-container-bg` (per mode) | Background of `Card`, `Container`, `Dialog`, `Popover`, `Drawer`, … Defaults to `var(--maz-surface)`. Bridged to `--color-container`. |
884
+ | `input.bg.light` / `.dark` | `--maz-input-bg` (per mode) | Background of `Input`, `Textarea`, `Select`, `Checkbox`, … Defaults to `var(--maz-surface)` light, `var(--maz-surface-400)` dark. Bridged to `--color-input`. |
885
+ | `dialog.max-width` | `--maz-dialog-max-width` | Max-width of `MazDialog` on tablet and up. Defaults to `38rem` (`33.25rem` on `ocean`). Overridable via the `max-width` prop. |
886
+ | `dialog.min-width` | `--maz-dialog-min-width` | Min-width of `MazDialog` on tablet and up. Defaults to `32rem` (`28rem` on `ocean`). Overridable via the `min-width` prop. |
887
+
888
+ ### Sample output
889
+
890
+ Each base color is emitted as a `light-dark()` value; scales `--maz-X-50` through `--maz-X-950` are derived via OKLCh relative color syntax so they automatically follow base color overrides at runtime, preserving chroma at every step.
891
+
892
+ ```css
893
+ :root {
894
+ color-scheme: light dark;
895
+
896
+ /* Base colors - one declaration each, resolved by the browser */
897
+ --maz-primary: light-dark(oklch(0.65 0.19 254), oklch(0.72 0.18 254));
898
+ --maz-primary-foreground: light-dark(oklch(1 0 0), oklch(0.16 0.01 254));
899
+ --maz-surface: light-dark(oklch(1 0 0), oklch(0.18 0.01 254));
900
+ --maz-foreground: light-dark(oklch(0.26 0.01 254), oklch(0.96 0.005 254));
901
+
902
+ /* Auto-generated 50-950 scale - derived via relative color syntax */
903
+ --maz-primary-500: var(--maz-primary);
904
+ --maz-primary-600: oklch(from var(--maz-primary) clamp(0, calc(l - 0.07), 1) c h);
905
+ /* ... */
906
+
907
+ /* Foundation */
908
+ --maz-base-font-size: 14px;
909
+ --maz-border-width: 1px;
910
+ --maz-space: 0.25rem;
911
+ --maz-font-family: Manrope, sans-serif, …;
912
+ --maz-motion-normal: 200ms;
913
+
914
+ /* Scales */
915
+ --maz-rounded-md: 0.7rem;
916
+ --maz-shadow-style-md: 0 4px 6px -1px rgb(0 0 0 / 0.1), …;
917
+ }
918
+
919
+ /* With darkModeStrategy: 'class' - explicit user choice overrides the system */
920
+ .dark { color-scheme: only dark; }
921
+ .light { color-scheme: only light; }
922
+ ```
923
+
924
+ For deeper detail on the generated CSS contract, see the [`@maz-ui/themes` README](https://github.com/LouisMazel/maz-ui/tree/master/packages/themes#generated-css-variables).
925
+
926
+ ## Usage with Nuxt
927
+
928
+ For Nuxt users, check the [dedicated Nuxt documentation](./nuxt.md) which covers installation and framework-specific configuration.
929
+
930
+ ## Migration from Legacy System
931
+
932
+ If you're using the legacy theme system with CLI:
933
+
934
+ ```typescript [Before (CLI)]
935
+ // maz-ui.config.ts
936
+ export default defineConfig({
937
+ theme: {
938
+ colors: {
939
+ primary: 'hsl(210, 100%, 56%)',
940
+ secondary: 'hsl(164, 76%, 46%)'
941
+ }
942
+ }
943
+ })
944
+ ```
945
+
946
+ ```typescript [After (@maz-ui/themes)]
947
+ // main.ts
948
+ import { definePreset, mazUi } from '@maz-ui/themes'
949
+ import { MazUiTheme } from '@maz-ui/themes/plugin'
950
+
951
+ const myTheme = definePreset({
952
+ base: mazUi,
953
+ overrides: {
954
+ colors: {
955
+ light: {
956
+ primary: 'oklch(0.65 0.19 254)',
957
+ secondary: 'oklch(0.72 0.16 168)'
958
+ }
959
+ }
960
+ }
961
+ })
962
+
963
+ app.use(MazUiTheme, { preset: myTheme })
964
+ ```
965
+
966
+ The new system offers much more flexibility and performance!