@dashforge/tw 1.1.1 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (191) hide show
  1. package/CHANGELOG.md +113 -0
  2. package/README.md +45 -0
  3. package/dist/index.esm.js +3985 -476
  4. package/dist/src/components/Accordion/Accordion.d.ts.map +1 -1
  5. package/dist/src/components/Accordion/accordion.types.d.ts +7 -0
  6. package/dist/src/components/Accordion/accordion.types.d.ts.map +1 -1
  7. package/dist/src/components/Alert/Alert.d.ts +1 -1
  8. package/dist/src/components/Alert/Alert.d.ts.map +1 -1
  9. package/dist/src/components/Alert/alert.types.d.ts +17 -0
  10. package/dist/src/components/Alert/alert.types.d.ts.map +1 -1
  11. package/dist/src/components/AppShell/AppShell.d.ts.map +1 -1
  12. package/dist/src/components/AppShell/appShell.types.d.ts +7 -0
  13. package/dist/src/components/AppShell/appShell.types.d.ts.map +1 -1
  14. package/dist/src/components/Autocomplete/Autocomplete.d.ts.map +1 -1
  15. package/dist/src/components/Autocomplete/autocomplete.types.d.ts +47 -1
  16. package/dist/src/components/Autocomplete/autocomplete.types.d.ts.map +1 -1
  17. package/dist/src/components/Avatar/Avatar.d.ts.map +1 -1
  18. package/dist/src/components/Avatar/avatar.types.d.ts +17 -1
  19. package/dist/src/components/Avatar/avatar.types.d.ts.map +1 -1
  20. package/dist/src/components/Badge/Badge.d.ts.map +1 -1
  21. package/dist/src/components/Badge/badge.types.d.ts +27 -2
  22. package/dist/src/components/Badge/badge.types.d.ts.map +1 -1
  23. package/dist/src/components/Box/Box.d.ts.map +1 -1
  24. package/dist/src/components/Box/box.types.d.ts +64 -1
  25. package/dist/src/components/Box/box.types.d.ts.map +1 -1
  26. package/dist/src/components/Breadcrumbs/Breadcrumbs.d.ts.map +1 -1
  27. package/dist/src/components/Breadcrumbs/breadcrumbs.types.d.ts +26 -1
  28. package/dist/src/components/Breadcrumbs/breadcrumbs.types.d.ts.map +1 -1
  29. package/dist/src/components/Button/Button.d.ts.map +1 -1
  30. package/dist/src/components/Button/button.types.d.ts +53 -1
  31. package/dist/src/components/Button/button.types.d.ts.map +1 -1
  32. package/dist/src/components/Calendar/Calendar.d.ts.map +1 -1
  33. package/dist/src/components/Calendar/calendar.types.d.ts +16 -0
  34. package/dist/src/components/Calendar/calendar.types.d.ts.map +1 -1
  35. package/dist/src/components/Card/Card.d.ts.map +1 -1
  36. package/dist/src/components/Card/card.types.d.ts +17 -0
  37. package/dist/src/components/Card/card.types.d.ts.map +1 -1
  38. package/dist/src/components/Checkbox/Checkbox.d.ts.map +1 -1
  39. package/dist/src/components/Checkbox/checkbox.types.d.ts +19 -1
  40. package/dist/src/components/Checkbox/checkbox.types.d.ts.map +1 -1
  41. package/dist/src/components/Chip/Chip.d.ts.map +1 -1
  42. package/dist/src/components/Chip/chip.types.d.ts +40 -1
  43. package/dist/src/components/Chip/chip.types.d.ts.map +1 -1
  44. package/dist/src/components/ConfirmDialog/ConfirmDialog.d.ts.map +1 -1
  45. package/dist/src/components/ConfirmDialog/confirmDialog.types.d.ts +30 -2
  46. package/dist/src/components/ConfirmDialog/confirmDialog.types.d.ts.map +1 -1
  47. package/dist/src/components/Container/Container.d.ts.map +1 -1
  48. package/dist/src/components/Container/container.types.d.ts +29 -1
  49. package/dist/src/components/Container/container.types.d.ts.map +1 -1
  50. package/dist/src/components/DataGrid/DataGrid.d.ts +1 -1
  51. package/dist/src/components/DataGrid/DataGrid.d.ts.map +1 -1
  52. package/dist/src/components/DataGrid/dataGrid.types.d.ts +124 -10
  53. package/dist/src/components/DataGrid/dataGrid.types.d.ts.map +1 -1
  54. package/dist/src/components/DatePicker/DatePicker.d.ts +1 -1
  55. package/dist/src/components/DatePicker/DatePicker.d.ts.map +1 -1
  56. package/dist/src/components/DatePicker/datePicker.types.d.ts +18 -0
  57. package/dist/src/components/DatePicker/datePicker.types.d.ts.map +1 -1
  58. package/dist/src/components/DateRangePicker/DateRangePicker.d.ts +1 -1
  59. package/dist/src/components/DateRangePicker/DateRangePicker.d.ts.map +1 -1
  60. package/dist/src/components/DateRangePicker/dateRangePicker.types.d.ts +18 -0
  61. package/dist/src/components/DateRangePicker/dateRangePicker.types.d.ts.map +1 -1
  62. package/dist/src/components/DateTimePicker/DateTimePicker.d.ts +1 -1
  63. package/dist/src/components/DateTimePicker/DateTimePicker.d.ts.map +1 -1
  64. package/dist/src/components/DateTimePicker/dateTimePicker.types.d.ts +20 -0
  65. package/dist/src/components/DateTimePicker/dateTimePicker.types.d.ts.map +1 -1
  66. package/dist/src/components/Dialog/Dialog.d.ts.map +1 -1
  67. package/dist/src/components/Dialog/dialog.types.d.ts +25 -1
  68. package/dist/src/components/Dialog/dialog.types.d.ts.map +1 -1
  69. package/dist/src/components/Divider/Divider.d.ts.map +1 -1
  70. package/dist/src/components/Divider/divider.types.d.ts +37 -1
  71. package/dist/src/components/Divider/divider.types.d.ts.map +1 -1
  72. package/dist/src/components/Drawer/Drawer.d.ts +21 -0
  73. package/dist/src/components/Drawer/Drawer.d.ts.map +1 -0
  74. package/dist/src/components/Drawer/drawer.types.d.ts +311 -0
  75. package/dist/src/components/Drawer/drawer.types.d.ts.map +1 -0
  76. package/dist/src/components/Drawer/drawer.variants.d.ts +177 -0
  77. package/dist/src/components/Drawer/drawer.variants.d.ts.map +1 -0
  78. package/dist/src/components/Grid/Grid.d.ts.map +1 -1
  79. package/dist/src/components/Grid/grid.types.d.ts +16 -0
  80. package/dist/src/components/Grid/grid.types.d.ts.map +1 -1
  81. package/dist/src/components/IconButton/IconButton.d.ts.map +1 -1
  82. package/dist/src/components/IconButton/iconButton.types.d.ts +40 -1
  83. package/dist/src/components/IconButton/iconButton.types.d.ts.map +1 -1
  84. package/dist/src/components/LeftNav/LeftNav.d.ts.map +1 -1
  85. package/dist/src/components/LeftNav/leftNav.types.d.ts +26 -6
  86. package/dist/src/components/LeftNav/leftNav.types.d.ts.map +1 -1
  87. package/dist/src/components/Link/Link.d.ts +15 -0
  88. package/dist/src/components/Link/Link.d.ts.map +1 -0
  89. package/dist/src/components/Link/link.types.d.ts +169 -0
  90. package/dist/src/components/Link/link.types.d.ts.map +1 -0
  91. package/dist/src/components/Link/link.variants.d.ts +107 -0
  92. package/dist/src/components/Link/link.variants.d.ts.map +1 -0
  93. package/dist/src/components/Menu/Menu.d.ts +1 -1
  94. package/dist/src/components/Menu/Menu.d.ts.map +1 -1
  95. package/dist/src/components/Menu/menu.types.d.ts +20 -0
  96. package/dist/src/components/Menu/menu.types.d.ts.map +1 -1
  97. package/dist/src/components/NumberField/NumberField.d.ts.map +1 -1
  98. package/dist/src/components/NumberField/numberField.types.d.ts +47 -1
  99. package/dist/src/components/NumberField/numberField.types.d.ts.map +1 -1
  100. package/dist/src/components/OTPField/OTPField.d.ts.map +1 -1
  101. package/dist/src/components/OTPField/otpField.types.d.ts +35 -1
  102. package/dist/src/components/OTPField/otpField.types.d.ts.map +1 -1
  103. package/dist/src/components/Pagination/Pagination.d.ts.map +1 -1
  104. package/dist/src/components/Pagination/pagination.types.d.ts +26 -1
  105. package/dist/src/components/Pagination/pagination.types.d.ts.map +1 -1
  106. package/dist/src/components/Popover/Popover.d.ts.map +1 -1
  107. package/dist/src/components/Popover/popover.types.d.ts +29 -0
  108. package/dist/src/components/Popover/popover.types.d.ts.map +1 -1
  109. package/dist/src/components/Progress/Progress.d.ts +20 -0
  110. package/dist/src/components/Progress/Progress.d.ts.map +1 -0
  111. package/dist/src/components/Progress/progress.types.d.ts +200 -0
  112. package/dist/src/components/Progress/progress.types.d.ts.map +1 -0
  113. package/dist/src/components/Progress/progress.variants.d.ts +224 -0
  114. package/dist/src/components/Progress/progress.variants.d.ts.map +1 -0
  115. package/dist/src/components/RadioGroup/RadioGroup.d.ts.map +1 -1
  116. package/dist/src/components/RadioGroup/radioGroup.types.d.ts +25 -1
  117. package/dist/src/components/RadioGroup/radioGroup.types.d.ts.map +1 -1
  118. package/dist/src/components/Select/Select.d.ts +14 -0
  119. package/dist/src/components/Select/Select.d.ts.map +1 -0
  120. package/dist/src/components/Select/select.types.d.ts +272 -0
  121. package/dist/src/components/Select/select.types.d.ts.map +1 -0
  122. package/dist/src/components/Select/select.variants.d.ts +204 -0
  123. package/dist/src/components/Select/select.variants.d.ts.map +1 -0
  124. package/dist/src/components/Skeleton/Skeleton.d.ts.map +1 -1
  125. package/dist/src/components/Skeleton/skeleton.types.d.ts +25 -1
  126. package/dist/src/components/Skeleton/skeleton.types.d.ts.map +1 -1
  127. package/dist/src/components/Slider/Slider.d.ts +15 -0
  128. package/dist/src/components/Slider/Slider.d.ts.map +1 -0
  129. package/dist/src/components/Slider/slider.types.d.ts +268 -0
  130. package/dist/src/components/Slider/slider.types.d.ts.map +1 -0
  131. package/dist/src/components/Slider/slider.variants.d.ts +313 -0
  132. package/dist/src/components/Slider/slider.variants.d.ts.map +1 -0
  133. package/dist/src/components/Snackbar/Snackbar.d.ts.map +1 -1
  134. package/dist/src/components/Snackbar/snackbar.types.d.ts +29 -5
  135. package/dist/src/components/Snackbar/snackbar.types.d.ts.map +1 -1
  136. package/dist/src/components/Spinner/Spinner.d.ts.map +1 -1
  137. package/dist/src/components/Spinner/spinner.types.d.ts +22 -2
  138. package/dist/src/components/Spinner/spinner.types.d.ts.map +1 -1
  139. package/dist/src/components/Stack/Stack.d.ts.map +1 -1
  140. package/dist/src/components/Stack/stack.types.d.ts +53 -2
  141. package/dist/src/components/Stack/stack.types.d.ts.map +1 -1
  142. package/dist/src/components/Stack/stack.variants.d.ts +23 -0
  143. package/dist/src/components/Stack/stack.variants.d.ts.map +1 -1
  144. package/dist/src/components/Stepper/Step.d.ts +30 -0
  145. package/dist/src/components/Stepper/Step.d.ts.map +1 -0
  146. package/dist/src/components/Stepper/Stepper.d.ts +15 -0
  147. package/dist/src/components/Stepper/Stepper.d.ts.map +1 -0
  148. package/dist/src/components/Stepper/StepperContext.d.ts +8 -0
  149. package/dist/src/components/Stepper/StepperContext.d.ts.map +1 -0
  150. package/dist/src/components/Stepper/stepper.types.d.ts +358 -0
  151. package/dist/src/components/Stepper/stepper.types.d.ts.map +1 -0
  152. package/dist/src/components/Stepper/stepper.variants.d.ts +253 -0
  153. package/dist/src/components/Stepper/stepper.variants.d.ts.map +1 -0
  154. package/dist/src/components/Stepper/useStep.d.ts +53 -0
  155. package/dist/src/components/Stepper/useStep.d.ts.map +1 -0
  156. package/dist/src/components/Switch/Switch.d.ts.map +1 -1
  157. package/dist/src/components/Switch/switch.types.d.ts +44 -1
  158. package/dist/src/components/Switch/switch.types.d.ts.map +1 -1
  159. package/dist/src/components/Table/Table.d.ts +1 -1
  160. package/dist/src/components/Table/Table.d.ts.map +1 -1
  161. package/dist/src/components/Table/table.types.d.ts +103 -8
  162. package/dist/src/components/Table/table.types.d.ts.map +1 -1
  163. package/dist/src/components/Tabs/Tabs.d.ts.map +1 -1
  164. package/dist/src/components/Tabs/tabs.types.d.ts +26 -1
  165. package/dist/src/components/Tabs/tabs.types.d.ts.map +1 -1
  166. package/dist/src/components/TextField/TextField.d.ts.map +1 -1
  167. package/dist/src/components/TextField/textField.types.d.ts +30 -1
  168. package/dist/src/components/TextField/textField.types.d.ts.map +1 -1
  169. package/dist/src/components/Textarea/Textarea.d.ts.map +1 -1
  170. package/dist/src/components/Textarea/textarea.types.d.ts +51 -1
  171. package/dist/src/components/Textarea/textarea.types.d.ts.map +1 -1
  172. package/dist/src/components/TimePicker/TimePicker.d.ts +1 -1
  173. package/dist/src/components/TimePicker/TimePicker.d.ts.map +1 -1
  174. package/dist/src/components/TimePicker/timePicker.types.d.ts +18 -0
  175. package/dist/src/components/TimePicker/timePicker.types.d.ts.map +1 -1
  176. package/dist/src/components/Tooltip/Tooltip.d.ts.map +1 -1
  177. package/dist/src/components/Tooltip/tooltip.types.d.ts +30 -0
  178. package/dist/src/components/Tooltip/tooltip.types.d.ts.map +1 -1
  179. package/dist/src/components/TopBar/TopBar.d.ts.map +1 -1
  180. package/dist/src/components/TopBar/topBar.types.d.ts +25 -1
  181. package/dist/src/components/TopBar/topBar.types.d.ts.map +1 -1
  182. package/dist/src/components/Typography/Typography.d.ts.map +1 -1
  183. package/dist/src/components/Typography/typography.types.d.ts +47 -1
  184. package/dist/src/components/Typography/typography.types.d.ts.map +1 -1
  185. package/dist/src/components/Typography/typography.variants.d.ts +2 -2
  186. package/dist/src/components/Typography/typography.variants.d.ts.map +1 -1
  187. package/dist/src/hooks/useStandaloneFieldWarning.d.ts +38 -0
  188. package/dist/src/hooks/useStandaloneFieldWarning.d.ts.map +1 -0
  189. package/dist/src/index.d.ts +61 -41
  190. package/dist/src/index.d.ts.map +1 -1
  191. package/package.json +6 -5
package/CHANGELOG.md CHANGED
@@ -12,6 +12,119 @@ This project follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
12
12
  > duplicated intentionally — no shared "lowest common denominator" headless
13
13
  > layer.
14
14
 
15
+ ## [1.2.0] — 2026-07-24
16
+
17
+ Sprint 6 — closes the Option C rollout (`theme.components.<Name>.defaults`)
18
+ across the full catalog and adds 6 new primitives (Link, Select, Slider,
19
+ Progress, Stepper, Drawer). No breaking changes vs 1.1.1 — every
20
+ existing consumer works unchanged.
21
+
22
+ ### Added — new primitives
23
+
24
+ - **`<Link>`** — token-driven anchor primitive. Every visual axis
25
+ (`color` / `underline` / `weight` / `size`) is Option C configurable.
26
+ `startIcon` / `endIcon` accept any ReactNode; `external` toggles
27
+ `target="_blank"` + `rel="noopener noreferrer"`; `asChild` for router
28
+ integration via Radix Slot. 32 unit + precedence tests.
29
+ - **`<Select>`** — dedicated enum picker, narrower than Autocomplete
30
+ (no search, no async, no typeahead). Options shape
31
+ `{ value, label, disabled? }` mirrors AutocompleteOption. Two-arg
32
+ `onChange(value, option)`. Bridge + standalone controlled modes.
33
+ Multi-select shipped in v1. Generic `V extends string | number`.
34
+ 22 unit + 6 precedence tests. Unblocks Blueprint G-25.
35
+ - **`<Slider>`** — token-driven numeric picker. Single value or
36
+ `[min, max]` range via `range?: boolean` discriminated union.
37
+ Bridge commits on drag-end by default; opt into per-tick via
38
+ `commitOnChange`. Marks (explicit or auto). Value label tooltip with
39
+ formatter (`'auto' | 'always' | 'off'`). 6 color intents. Built on
40
+ `@radix-ui/react-slider`. 24 unit + 6 precedence tests.
41
+ - **`<Progress>`** — determinate progress indicator. Two visual flavors
42
+ on the same primitive: `variant='linear'` (bar) and `variant='circular'`
43
+ (SVG arc). Display-only (no bridge). `value` required (Spinner covers
44
+ indeterminate). 6 color intents, size + independent `thickness` axis,
45
+ custom `formatLabel`. 24 unit + 6 precedence tests.
46
+ - **`<Stepper>` + `<Step>` + `useStep()`** — declarative multi-step
47
+ wizard. Compound children with per-step config: `name`, `label`,
48
+ `helperText`, `icon`, `optional`, `fields` (RHF-triggered validation),
49
+ `isValid` (custom async, AND semantics with `fields`), `visibleWhen`
50
+ (reactive predicate for dynamic step composition), `access` (RBAC).
51
+ `useStep()` hook exposes navigation state + API. Horizontal + vertical
52
+ orientation, `labelPlacement 'end' | 'below'` (MUI `alternativeLabel`
53
+ parity), `initialStep` for name-based resume, `allowJumpTo: 'visited' | 'none'`.
54
+ Docs cover 4 error surfaces. 35 unit + precedence tests.
55
+ - **`<Drawer>`** — edge-anchored sliding panel. 4 positions
56
+ (`left`/`right`/`top`/`bottom`), 3 variants (`temporary` default,
57
+ `persistent`, `sticky`). `title: string | ReactNode`,
58
+ `closeButtonPosition: 'start' | 'end'` (bordered × styling),
59
+ `onCloseClick` side-effect hook, `onOpenAutoFocus` a11y customization
60
+ hook. Resize handle on the free edge with pointer drag + keyboard
61
+ step + localStorage persistence under `df.drawer.<resizeKey>`.
62
+ Curtain-like slide animation via inline `@keyframes` module-level
63
+ injection — `tailwindcss-animate` not required. `z-[1400]/[1410]`
64
+ stacks above MUI AppBar for MUI-coexistence. `visibleWhen` + `access`
65
+ catalog-uniform. 66 unit + precedence tests. Closes
66
+ [#108](https://github.com/kensaadi/dashforge/issues/108) (Blueprint
67
+ Builder V2 G-12 blocker).
68
+
69
+ ### Added — Option C coverage
70
+
71
+ - **`theme.components.<Name>.defaults`** wired across the full catalog
72
+ (46 components with visual axes; VisuallyHidden, AspectRatio,
73
+ Accordion, AppShell, Flex skipped with rationale — no theme-configurable
74
+ visual axes). Each consumer can now set application-wide defaults for
75
+ any component: `patchTheme({ components: { Button: { defaults: { size: 'lg' } } } })`.
76
+ - **`theme.components.<Name>.slotProps`** wired for compound components
77
+ where slot-level defaults have DS-identity value (Dialog, Popover,
78
+ Menu, DataGrid, Tabs, LeftNav, TopBar, Drawer, Stepper, Slider, Link,
79
+ Select).
80
+ - **47 `.precedence.test.tsx` files** shipped, verifying the 4-level
81
+ precedence chain (TV defaults → `theme.components.defaults` → instance
82
+ props → `sx`) across the whole catalog. Backward-compat guarantee:
83
+ every test's baseline confirms no-config behavior identical to 1.1.x.
84
+
85
+ ### Changed
86
+
87
+ - **`DashFormBridge` — new optional `trigger?: (name?: string | string[]) => Promise<boolean>`**
88
+ method on the bridge contract, implemented by `DashFormProvider`. Uses
89
+ `rhf.getFieldState()` internally to read fresh errors synchronously
90
+ after RHF trigger (bypasses React's render cycle where
91
+ `rhf.formState.errors` would be stale). Feature-gated / non-breaking —
92
+ consumers that don't call `bridge.trigger` are unaffected. Powers
93
+ `<Step fields={...}>` validation.
94
+ - **Stack `gap` type narrowed** from wide `string` to the 11-value
95
+ numeric union (Fix [#111](https://github.com/kensaadi/dashforge/issues/111)).
96
+ TypeScript now rejects `<Stack gap="md">`; a runtime dev-warn fires
97
+ when a non-numeric value slips through.
98
+ - **5 layout primitives (Box / Stack / Grid / Container / Flex)** —
99
+ runtime className sneak-in via `sx` no longer clobbers TV variant
100
+ classes; the merge chain is deterministic (Fix
101
+ [#112](https://github.com/kensaadi/dashforge/issues/112)).
102
+
103
+ ### Fixed
104
+
105
+ - **Standalone form widgets now dev-warn** when rendered outside a
106
+ `<DashFormProvider>` and without a controlled `value` / `onChange`
107
+ pair. Previously silent no-op that consumers couldn't diagnose
108
+ ([#113](https://github.com/kensaadi/dashforge/issues/113)).
109
+ - **`<DatePicker>` inside `<DashForm>`** now commits the value on
110
+ day-click when the field is bridge-registered
111
+ ([#114](https://github.com/kensaadi/dashforge/issues/114)).
112
+
113
+ ### Internal
114
+
115
+ - **`tw-theme` mode sync**: `patchTheme({ meta: { mode: 'dark' } })` now
116
+ correctly synchronizes the `data-dash-tw-theme` attribute + document
117
+ class (Fix [#110](https://github.com/kensaadi/dashforge/issues/110)).
118
+ - **JSDoc backfill**: every `*Props` interface now carries per-prop
119
+ JSDoc with `@default` tags. Powers `sync-props` MDX doc generation
120
+ in `dashforge-docs-lab`.
121
+
122
+ ### Migration
123
+
124
+ See [`docs/migration/1.2.0.md`](../../docs/migration/1.2.0.md) for the
125
+ full migration guide (all changes are additive — no code changes
126
+ required to upgrade).
127
+
15
128
  ## [1.1.1] — 2026-06-18
16
129
 
17
130
  > **Re-issued from the unpublished `1.1.0`** — `1.1.0` was published
package/README.md CHANGED
@@ -176,6 +176,51 @@ variant defaults regardless of stylesheet order.
176
176
 
177
177
  ---
178
178
 
179
+ ## Theme-level component defaults (Option C, since 1.2.0)
180
+
181
+ Instead of repeating `sx` / instance props on every component, pin
182
+ your DS identity once in the theme and every instance inherits it.
183
+
184
+ ```tsx
185
+ import { patchTheme } from '@dashforge/tw-theme';
186
+
187
+ patchTheme({
188
+ components: {
189
+ // Component-level defaults — apply to every <Button> in the app
190
+ Button: {
191
+ defaults: { variant: 'solid', color: 'primary', size: 'md' },
192
+ },
193
+ Drawer: {
194
+ defaults: { position: 'right', size: 'md', variant: 'temporary' },
195
+ },
196
+ // Slot-level defaults for compound components — override the visual
197
+ // chrome without touching consumer call sites
198
+ DataGrid: {
199
+ slotProps: {
200
+ header: { className: 'bg-neutral-100 font-semibold' },
201
+ cell: { className: 'py-3 text-sm' },
202
+ },
203
+ },
204
+ },
205
+ });
206
+ ```
207
+
208
+ **Precedence chain** (lowest → highest):
209
+
210
+ 1. Tailwind-variants `defaultVariants` — component-level baseline
211
+ 2. `theme.components.<Name>.defaults` — consumer-wide DS identity
212
+ 3. Instance props — `<Button size="lg">` beats theme default
213
+ 4. `sx` prop — merged last via `tailwind-merge`
214
+
215
+ Same 4-level chain applies to `slotProps` (theme slotProps → instance
216
+ slotProps). Backward-compat: consumers who don't set `theme.components`
217
+ get behavior identical to 1.1.x.
218
+
219
+ Full guide + per-component playgrounds:
220
+ [`/tw/docs/theme-system/component-defaults`](https://dashforge-docs-lab.pages.dev/tw/docs/theme-system/component-defaults).
221
+
222
+ ---
223
+
179
224
  ## Common consumer pitfalls
180
225
 
181
226
  The following are **not library bugs** — they're use-time issues that