@viraui/react 2026.7.1 → 2026.9.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 (223) hide show
  1. package/dist/catalog.json +9 -3
  2. package/dist/components/button/button.css +1 -1
  3. package/dist/components/direction-provider/index.d.ts +2 -0
  4. package/dist/components/direction-provider/index.js +2 -0
  5. package/dist/components/index.d.ts +1 -0
  6. package/dist/components/menu/menu-popup.d.ts +2 -2
  7. package/dist/components/menu/menu.css +1 -1
  8. package/dist/components/progressive-blur/progressive-blur.css +1 -1
  9. package/dist/components/prose/prose.d.ts +4 -1
  10. package/dist/components/select/select-group.js +1 -1
  11. package/dist/components/select/select.css +1 -1
  12. package/dist/components/select/select.js +4 -1
  13. package/dist/components/spinner/spinner.d.ts +6 -1
  14. package/dist/components/spinner/variants/arc.css +1 -0
  15. package/dist/components/spinner/variants/arc.d.ts +2 -0
  16. package/dist/components/spinner/variants/arc.js +19 -0
  17. package/dist/components/spinner/variants/arc.module.js +8 -0
  18. package/dist/components/spinner/variants/atom.css +1 -0
  19. package/dist/components/spinner/variants/atom.d.ts +6 -0
  20. package/dist/components/spinner/variants/atom.js +40 -0
  21. package/dist/components/spinner/variants/atom.module.js +8 -0
  22. package/dist/components/spinner/variants/blocks.css +1 -0
  23. package/dist/components/spinner/variants/blocks.d.ts +2 -0
  24. package/dist/components/spinner/variants/blocks.js +25 -0
  25. package/dist/components/spinner/variants/blocks.module.js +8 -0
  26. package/dist/components/spinner/variants/bouncing-dots.css +1 -0
  27. package/dist/components/spinner/variants/bouncing-dots.d.ts +2 -0
  28. package/dist/components/spinner/variants/bouncing-dots.js +21 -0
  29. package/dist/components/spinner/variants/bouncing-dots.module.js +8 -0
  30. package/dist/components/spinner/variants/cascade.css +1 -0
  31. package/dist/components/spinner/variants/cascade.d.ts +2 -0
  32. package/dist/components/spinner/variants/cascade.js +34 -0
  33. package/dist/components/spinner/variants/cascade.module.js +8 -0
  34. package/dist/components/spinner/variants/circular-dots.css +1 -0
  35. package/dist/components/spinner/variants/circular-dots.d.ts +2 -0
  36. package/dist/components/spinner/variants/circular-dots.js +26 -0
  37. package/dist/components/spinner/variants/circular-dots.module.js +8 -0
  38. package/dist/components/spinner/variants/classic-v2.css +1 -0
  39. package/dist/components/spinner/variants/classic-v2.d.ts +2 -0
  40. package/dist/components/spinner/variants/classic-v2.js +24 -0
  41. package/dist/components/spinner/variants/classic-v2.module.js +8 -0
  42. package/dist/components/spinner/variants/classic.css +1 -0
  43. package/dist/components/spinner/variants/classic.d.ts +2 -0
  44. package/dist/components/spinner/variants/classic.js +22 -0
  45. package/dist/components/spinner/variants/classic.module.js +8 -0
  46. package/dist/components/spinner/variants/clock.css +1 -0
  47. package/dist/components/spinner/variants/clock.d.ts +2 -0
  48. package/dist/components/spinner/variants/clock.js +18 -0
  49. package/dist/components/spinner/variants/clock.module.js +8 -0
  50. package/dist/components/spinner/variants/comet.css +1 -0
  51. package/dist/components/spinner/variants/comet.d.ts +2 -0
  52. package/dist/components/spinner/variants/comet.js +33 -0
  53. package/dist/components/spinner/variants/comet.module.js +10 -0
  54. package/dist/components/spinner/variants/compass.css +1 -0
  55. package/dist/components/spinner/variants/compass.d.ts +2 -0
  56. package/dist/components/spinner/variants/compass.js +16 -0
  57. package/dist/components/spinner/variants/compass.module.js +8 -0
  58. package/dist/components/spinner/variants/dual.css +1 -0
  59. package/dist/components/spinner/variants/dual.d.ts +2 -0
  60. package/dist/components/spinner/variants/dual.js +25 -0
  61. package/dist/components/spinner/variants/dual.module.js +10 -0
  62. package/dist/components/spinner/variants/eclipse.css +1 -0
  63. package/dist/components/spinner/variants/eclipse.d.ts +6 -0
  64. package/dist/components/spinner/variants/eclipse.js +21 -0
  65. package/dist/components/spinner/variants/eclipse.module.js +9 -0
  66. package/dist/components/spinner/variants/flip.css +1 -0
  67. package/dist/components/spinner/variants/flip.d.ts +2 -0
  68. package/dist/components/spinner/variants/flip.js +17 -0
  69. package/dist/components/spinner/variants/flip.module.js +8 -0
  70. package/dist/components/spinner/variants/gather.css +1 -0
  71. package/dist/components/spinner/variants/gather.d.ts +2 -0
  72. package/dist/components/spinner/variants/gather.js +50 -0
  73. package/dist/components/spinner/variants/gather.module.js +11 -0
  74. package/dist/components/spinner/variants/index.d.ts +9 -1
  75. package/dist/components/spinner/variants/index.js +96 -10
  76. package/dist/components/spinner/variants/leap.css +1 -0
  77. package/dist/components/spinner/variants/leap.d.ts +6 -0
  78. package/dist/components/spinner/variants/leap.js +27 -0
  79. package/dist/components/spinner/variants/leap.module.js +8 -0
  80. package/dist/components/spinner/variants/linear-dots.css +1 -0
  81. package/dist/components/spinner/variants/linear-dots.d.ts +2 -0
  82. package/dist/components/spinner/variants/linear-dots.js +21 -0
  83. package/dist/components/spinner/variants/linear-dots.module.js +8 -0
  84. package/dist/components/spinner/variants/loading.css +1 -0
  85. package/dist/components/spinner/variants/loading.d.ts +2 -0
  86. package/dist/components/spinner/variants/loading.js +50 -0
  87. package/dist/components/spinner/variants/loading.module.js +8 -0
  88. package/dist/components/spinner/variants/morph.css +1 -0
  89. package/dist/components/spinner/variants/morph.d.ts +2 -0
  90. package/dist/components/spinner/variants/morph.js +17 -0
  91. package/dist/components/spinner/variants/morph.module.js +8 -0
  92. package/dist/components/spinner/variants/orbit.css +1 -0
  93. package/dist/components/spinner/variants/orbit.d.ts +2 -0
  94. package/dist/components/spinner/variants/orbit.js +24 -0
  95. package/dist/components/spinner/variants/orbit.module.js +8 -0
  96. package/dist/components/spinner/variants/pulse.css +1 -0
  97. package/dist/components/spinner/variants/pulse.d.ts +2 -0
  98. package/dist/components/spinner/variants/pulse.js +19 -0
  99. package/dist/components/spinner/variants/pulse.module.js +8 -0
  100. package/dist/components/spinner/variants/radar.css +1 -0
  101. package/dist/components/spinner/variants/radar.d.ts +2 -0
  102. package/dist/components/spinner/variants/radar.js +53 -0
  103. package/dist/components/spinner/variants/radar.module.js +8 -0
  104. package/dist/components/spinner/variants/ring.css +1 -0
  105. package/dist/components/spinner/variants/ring.d.ts +2 -0
  106. package/dist/components/spinner/variants/ring.js +24 -0
  107. package/dist/components/spinner/variants/ring.module.js +8 -0
  108. package/dist/components/spinner/variants/ripple.css +1 -0
  109. package/dist/components/spinner/variants/ripple.d.ts +2 -0
  110. package/dist/components/spinner/variants/ripple.js +23 -0
  111. package/dist/components/spinner/variants/ripple.module.js +8 -0
  112. package/dist/components/spinner/variants/slide.css +1 -0
  113. package/dist/components/spinner/variants/slide.d.ts +2 -0
  114. package/dist/components/spinner/variants/slide.js +24 -0
  115. package/dist/components/spinner/variants/slide.module.js +8 -0
  116. package/dist/components/spinner/variants/snake.css +1 -0
  117. package/dist/components/spinner/variants/snake.d.ts +2 -0
  118. package/dist/components/spinner/variants/snake.js +19 -0
  119. package/dist/components/spinner/variants/snake.module.js +11 -0
  120. package/dist/components/spinner/variants/swirl.css +1 -0
  121. package/dist/components/spinner/variants/swirl.d.ts +2 -0
  122. package/dist/components/spinner/variants/swirl.js +35 -0
  123. package/dist/components/spinner/variants/swirl.module.js +8 -0
  124. package/dist/components/spinner/variants/trace.css +1 -0
  125. package/dist/components/spinner/variants/trace.d.ts +2 -0
  126. package/dist/components/spinner/variants/trace.js +28 -0
  127. package/dist/components/spinner/variants/trace.module.js +8 -0
  128. package/dist/components/spinner/variants/wave.css +1 -0
  129. package/dist/components/spinner/variants/wave.d.ts +2 -0
  130. package/dist/components/spinner/variants/wave.js +25 -0
  131. package/dist/components/spinner/variants/wave.module.js +8 -0
  132. package/dist/components/stack/stack.css +1 -1
  133. package/dist/components/stack/stack.d.ts +15 -3
  134. package/dist/components/stack/stack.js +2 -1
  135. package/dist/components/surface/surface.css +1 -1
  136. package/dist/components/text/text.css +1 -1
  137. package/dist/components/text/text.d.ts +10 -2
  138. package/dist/components/title/title.d.ts +7 -0
  139. package/dist/index.js +2 -1
  140. package/dist/preflight.css +1 -1
  141. package/dist/specs/PROTOCOL.md +1 -1
  142. package/dist/specs/activity-hints.xml +4 -4
  143. package/dist/specs/components/accordion/props.xml +2 -2
  144. package/dist/specs/components/accordion/usage.xml +2 -0
  145. package/dist/specs/components/autocomplete/patterns.xml +4 -4
  146. package/dist/specs/components/autocomplete/props.xml +2 -2
  147. package/dist/specs/components/autocomplete/usage.xml +1 -1
  148. package/dist/specs/components/button/patterns.xml +2 -2
  149. package/dist/specs/components/button/props.xml +4 -4
  150. package/dist/specs/components/button/usage.xml +2 -1
  151. package/dist/specs/components/chip/patterns.xml +2 -2
  152. package/dist/specs/components/chip/props.xml +2 -2
  153. package/dist/specs/components/chip/usage.xml +2 -0
  154. package/dist/specs/components/direction-provider/a11y.xml +6 -0
  155. package/dist/specs/components/direction-provider/meta.xml +20 -0
  156. package/dist/specs/components/direction-provider/patterns.xml +27 -0
  157. package/dist/specs/components/direction-provider/props.xml +18 -0
  158. package/dist/specs/components/direction-provider/usage.xml +10 -0
  159. package/dist/specs/components/disclosure/patterns.xml +2 -2
  160. package/dist/specs/components/disclosure/props.xml +2 -2
  161. package/dist/specs/components/disclosure/usage.xml +2 -0
  162. package/dist/specs/components/glow/patterns.xml +1 -1
  163. package/dist/specs/components/grid/patterns.xml +3 -3
  164. package/dist/specs/components/icon-button/props.xml +4 -4
  165. package/dist/specs/components/icon-button/usage.xml +3 -1
  166. package/dist/specs/components/menu/patterns.xml +18 -18
  167. package/dist/specs/components/menu/props.xml +5 -5
  168. package/dist/specs/components/menu/usage.xml +3 -1
  169. package/dist/specs/components/meter/patterns.xml +1 -1
  170. package/dist/specs/components/progressive-blur/usage.xml +2 -0
  171. package/dist/specs/components/prose/meta.xml +1 -1
  172. package/dist/specs/components/prose/patterns.xml +34 -10
  173. package/dist/specs/components/prose/props.xml +3 -1
  174. package/dist/specs/components/prose/usage.xml +4 -1
  175. package/dist/specs/components/select/patterns.xml +2 -2
  176. package/dist/specs/components/select/props.xml +2 -2
  177. package/dist/specs/components/select/usage.xml +1 -0
  178. package/dist/specs/components/slider/patterns.xml +1 -1
  179. package/dist/specs/components/spinner/props.xml +1 -1
  180. package/dist/specs/components/spinner/usage.xml +1 -1
  181. package/dist/specs/components/stack/patterns.xml +102 -4
  182. package/dist/specs/components/stack/props.xml +9 -3
  183. package/dist/specs/components/stack/usage.xml +7 -3
  184. package/dist/specs/components/surface/patterns.xml +3 -3
  185. package/dist/specs/components/surface/usage.xml +1 -1
  186. package/dist/specs/components/tabs/patterns.xml +3 -3
  187. package/dist/specs/components/tabs/props.xml +1 -1
  188. package/dist/specs/components/tabs/usage.xml +2 -1
  189. package/dist/specs/components/text/meta.xml +2 -1
  190. package/dist/specs/components/text/patterns.xml +19 -16
  191. package/dist/specs/components/text/props.xml +8 -6
  192. package/dist/specs/components/text/usage.xml +9 -3
  193. package/dist/specs/components/textfield/patterns.xml +3 -3
  194. package/dist/specs/components/textfield/props.xml +2 -2
  195. package/dist/specs/components/textfield/usage.xml +2 -1
  196. package/dist/specs/components/title/meta.xml +2 -1
  197. package/dist/specs/components/title/patterns.xml +11 -10
  198. package/dist/specs/components/title/props.xml +5 -4
  199. package/dist/specs/components/title/usage.xml +8 -3
  200. package/dist/specs/components/toggle-button/patterns.xml +8 -8
  201. package/dist/specs/components/toggle-button/props.xml +3 -3
  202. package/dist/specs/components/toggle-button/usage.xml +2 -0
  203. package/dist/specs/components/toggle-group/patterns.xml +3 -3
  204. package/dist/specs/components/tooltip/patterns.xml +7 -7
  205. package/dist/specs/foundation/attributes.xml +24 -4
  206. package/dist/specs/foundation/bootstrap.xml +1 -1
  207. package/dist/specs/foundation/modules.xml +14 -5
  208. package/dist/specs/foundation/theme-topics.xml +3 -3
  209. package/dist/specs/foundation/toggles.xml +3 -3
  210. package/dist/specs/index.xml +14 -22
  211. package/dist/specs/patterns/compose-layout-first.xml +1 -1
  212. package/package.json +2 -2
  213. package/dist/components/spinner/variants/bars.d.ts +0 -2
  214. package/dist/components/spinner/variants/bars.js +0 -134
  215. package/dist/components/spinner/variants/dot-grid.css +0 -1
  216. package/dist/components/spinner/variants/dot-grid.d.ts +0 -2
  217. package/dist/components/spinner/variants/dot-grid.js +0 -57
  218. package/dist/components/spinner/variants/dot-grid.module.js +0 -16
  219. package/dist/components/spinner/variants/dots.d.ts +0 -2
  220. package/dist/components/spinner/variants/dots.js +0 -189
  221. package/dist/specs/patterns/equal-width-actions.xml +0 -22
  222. package/dist/specs/patterns/page-chrome.xml +0 -34
  223. package/dist/specs/patterns/stack-as-surface.xml +0 -37
@@ -18,7 +18,7 @@
18
18
  </Text>
19
19
  </Stack>
20
20
  </Stack>
21
- <ChevronExpandY aria-hidden size={16} />
21
+ <ChevronExpandY aria-hidden />
22
22
  </Stack>
23
23
  </Stack>
24
24
  }
@@ -36,15 +36,15 @@
36
36
  </Stack>
37
37
  </Stack>
38
38
  <Menu.Separator />
39
- <Menu.Item addon={<StarUpgrade aria-hidden size={16} />}>Upgrade to Pro</Menu.Item>
39
+ <Menu.Item addon={<StarUpgrade aria-hidden />}>Upgrade to Pro</Menu.Item>
40
40
  <Menu.Separator />
41
41
  <Menu.Group label="Settings">
42
- <Menu.Item addon={<BadgeCheck aria-hidden size={16} />}>Account</Menu.Item>
43
- <Menu.Item addon={<CreditCards aria-hidden size={16} />}>Billing</Menu.Item>
44
- <Menu.Item addon={<Bell aria-hidden size={16} />}>Notifications</Menu.Item>
42
+ <Menu.Item addon={<BadgeCheck aria-hidden />}>Account</Menu.Item>
43
+ <Menu.Item addon={<CreditCards aria-hidden />}>Billing</Menu.Item>
44
+ <Menu.Item addon={<Bell aria-hidden />}>Notifications</Menu.Item>
45
45
  </Menu.Group>
46
46
  <Menu.Separator />
47
- <Menu.Item addon={<ArrowDoorOut aria-hidden size={16} />} sentiment="destructive">
47
+ <Menu.Item addon={<ArrowDoorOut aria-hidden />} sentiment="destructive">
48
48
  Log out
49
49
  </Menu.Item>
50
50
  </Menu.Popup>
@@ -58,24 +58,24 @@
58
58
  <Menu>
59
59
  <Menu.Trigger
60
60
  render={
61
- <Button size="s" addon={<ChevronDown aria-hidden size={16} />} variant="secondary">
61
+ <Button size="s" addon={<ChevronDown aria-hidden />} variant="secondary">
62
62
  Actions
63
63
  </Button>
64
64
  }
65
65
  />
66
66
  <Menu.Popup align="end" side="bottom">
67
67
  <Menu.Group label="Edit">
68
- <Menu.Item addon={<Pencil aria-hidden size={16} />} note="⌘E">
68
+ <Menu.Item addon={<Pencil aria-hidden />} note="⌘E">
69
69
  Rename report
70
70
  </Menu.Item>
71
- <Menu.Item addon={<Duplicate aria-hidden size={16} />} note="⌘D">
71
+ <Menu.Item addon={<Duplicate aria-hidden />} note="⌘D">
72
72
  Duplicate
73
73
  </Menu.Item>
74
- <Menu.Item addon={<Archive aria-hidden size={16} />}>Archive</Menu.Item>
74
+ <Menu.Item addon={<Archive aria-hidden />}>Archive</Menu.Item>
75
75
  </Menu.Group>
76
76
  <Menu.Separator />
77
77
  <Menu.Group label="View">
78
- <Menu.CheckboxItem addon={<Eye aria-hidden size={16} />} checked>
78
+ <Menu.CheckboxItem addon={<Eye aria-hidden />} checked>
79
79
  Show totals row
80
80
  </Menu.CheckboxItem>
81
81
  <Menu.CheckboxItem>Compact table rows</Menu.CheckboxItem>
@@ -88,7 +88,7 @@
88
88
  </Menu.RadioGroup>
89
89
  <Menu.Separator />
90
90
  <Menu.Submenu>
91
- <Menu.SubmenuTrigger addon={<Link aria-hidden size={16} />}>Share</Menu.SubmenuTrigger>
91
+ <Menu.SubmenuTrigger addon={<Link aria-hidden />}>Share</Menu.SubmenuTrigger>
92
92
  <Menu.Popup side="inline-end">
93
93
  <Menu.LinkItem href="#">Copy link</Menu.LinkItem>
94
94
  <Menu.Item note="⌘⇧E">Export PDF</Menu.Item>
@@ -96,7 +96,7 @@
96
96
  </Menu.Popup>
97
97
  </Menu.Submenu>
98
98
  <Menu.Separator />
99
- <Menu.Item addon={<Trash aria-hidden size={16} />} sentiment="destructive">
99
+ <Menu.Item addon={<Trash aria-hidden />} sentiment="destructive">
100
100
  Delete report
101
101
  </Menu.Item>
102
102
  </Menu.Popup>
@@ -119,7 +119,7 @@
119
119
  render={
120
120
  <IconButton
121
121
  aria-label="More actions for Q2 payout report"
122
- icon={<DotsVertical size={16} />}
122
+ icon={<DotsVertical />}
123
123
  pill
124
124
  size="s"
125
125
  variant="flat"
@@ -127,11 +127,11 @@
127
127
  }
128
128
  />
129
129
  <Menu.Popup align="end" side="bottom">
130
- <Menu.Item addon={<Pencil aria-hidden size={16} />}>Rename</Menu.Item>
131
- <Menu.Item addon={<Duplicate aria-hidden size={16} />}>Duplicate</Menu.Item>
132
- <Menu.Item addon={<Archive aria-hidden size={16} />}>Archive</Menu.Item>
130
+ <Menu.Item addon={<Pencil aria-hidden />}>Rename</Menu.Item>
131
+ <Menu.Item addon={<Duplicate aria-hidden />}>Duplicate</Menu.Item>
132
+ <Menu.Item addon={<Archive aria-hidden />}>Archive</Menu.Item>
133
133
  <Menu.Separator />
134
- <Menu.Item addon={<Trash aria-hidden size={16} />} sentiment="destructive">
134
+ <Menu.Item addon={<Trash aria-hidden />} sentiment="destructive">
135
135
  Delete
136
136
  </Menu.Item>
137
137
  </Menu.Popup>
@@ -16,7 +16,7 @@
16
16
  <item>Rich non-menu panels with forms or free layout (use Popover / Dialog — do not wrap Menu in Popover)</item>
17
17
  </when_not_to_use>
18
18
  <prop name="CheckboxItem.addon" kind="react">
19
- <description>Decorative leading node rendered before the item label.</description>
19
+ <description>Decorative leading node rendered before the item label. Omit glyph `size` / width / height unless expressly overriding the icon-library default.</description>
20
20
  </prop>
21
21
  <prop name="CheckboxItem.note" kind="react">
22
22
  <description>End-aligned secondary text (e.g. keyboard shortcut) before the check indicator. Rendered muted `xs`.</description>
@@ -28,7 +28,7 @@
28
28
  <description>Accessible group label rendered with `Menu.GroupLabel`.</description>
29
29
  </prop>
30
30
  <prop name="Item.addon" kind="react">
31
- <description>Decorative leading node rendered before the item label.</description>
31
+ <description>Decorative leading node rendered before the item label. Omit glyph `size` / width / height unless expressly overriding the icon-library default.</description>
32
32
  </prop>
33
33
  <prop name="Item.note" kind="react">
34
34
  <description>End-aligned secondary text (e.g. keyboard shortcut). Rendered muted `xs`.</description>
@@ -37,7 +37,7 @@
37
37
  <description>Visual sentiment. `destructive` uses highlight-red wash + text.</description>
38
38
  </prop>
39
39
  <prop name="LinkItem.addon" kind="react">
40
- <description>Decorative leading node rendered before the item label.</description>
40
+ <description>Decorative leading node rendered before the item label. Omit glyph `size` / width / height unless expressly overriding the icon-library default.</description>
41
41
  </prop>
42
42
  <prop name="LinkItem.note" kind="react">
43
43
  <description>End-aligned secondary text (e.g. keyboard shortcut). Rendered muted `xs`.</description>
@@ -55,7 +55,7 @@
55
55
  <description>Optional accessible group label rendered with `Menu.GroupLabel`.</description>
56
56
  </prop>
57
57
  <prop name="RadioItem.addon" kind="react">
58
- <description>Decorative leading node rendered before the item label.</description>
58
+ <description>Decorative leading node rendered before the item label. Omit glyph `size` / width / height unless expressly overriding the icon-library default.</description>
59
59
  </prop>
60
60
  <prop name="RadioItem.note" kind="react">
61
61
  <description>End-aligned secondary text (e.g. keyboard shortcut) before the check indicator. Rendered muted `xs`.</description>
@@ -64,7 +64,7 @@
64
64
  <description>Visual sentiment. `destructive` uses highlight-red wash + text.</description>
65
65
  </prop>
66
66
  <prop name="SubmenuTrigger.addon" kind="react">
67
- <description>Decorative leading node rendered before the item label.</description>
67
+ <description>Decorative leading node rendered before the item label. Omit glyph `size` / width / height unless expressly overriding the icon-library default.</description>
68
68
  </prop>
69
69
  <prop name="SubmenuTrigger.sentiment" kind="react">
70
70
  <description>Visual sentiment. `destructive` uses highlight-red wash + text.</description>
@@ -6,10 +6,12 @@
6
6
  <do>Account / user chip: `Menu.Trigger` as Surface/Stack (Avatar + Text) opening `Menu.Popup` with static profile header plus Items</do>
7
7
  <do>Detached or multi-trigger menus via `Menu.createHandle`</do>
8
8
  <do>Custom portal host (iframe preview, shadow root, or app overlay root) via `container` on `Menu.Popup`</do>
9
+ <do>Omit `size` / width / height on Item / LinkItem / checkbox / radio / submenu `addon` icons — prefer icon-library default; set only to expressly override</do>
9
10
  <dont>Expecting `Menu.Arrow`, `Menu.Backdrop`, or public Portal/Positioner/Viewport exports</dont>
11
+ <dont>Passing `size={16}` on every menu `addon` icon by habit — omit unless expressly overriding the library default</dont>
10
12
  <dont>Closing checkbox/radio items on click by default when the menu should stay open for multi-toggle — pass `closeOnClick` only when a single pick should dismiss</dont>
11
13
  <dont>Using physical left/right CSS that breaks RTL submenu chevrons</dont>
12
- <dont>Expecting RTL item rows / left-opening submenus without Base UI `DirectionProvider direction=&quot;rtl&quot;` plus app `dir=&quot;rtl&quot;` on a portal ancestor (usually `&lt;html&gt;` / document root — a local wrapper alone does not reach body-mounted popups)</dont>
14
+ <dont>Expecting RTL item rows / left-opening submenus without `@viraui/react` `DirectionProvider direction=&quot;rtl&quot;` plus app `dir=&quot;rtl&quot;` on a portal ancestor (usually `&lt;html&gt;` / document root — a local wrapper alone does not reach body-mounted popups)</dont>
13
15
  <dont>Nesting Menu inside Popover for an account menu — Menu already owns portal, positioning, and listbox keyboard behavior</dont>
14
16
  <dont>Putting focusable controls (inputs, nested buttons) in `Menu.Popup` outside `Menu.Item` / `Menu.LinkItem` / checkbox / radio / submenu trigger parts — use Popover or Dialog for forms</dont>
15
17
  <dont>Using Menu for form-field single-select from a long list — use Select</dont>
@@ -25,7 +25,7 @@
25
25
  value={91}
26
26
  label={
27
27
  <Stack direction="row" columnGap="xs" vAlign="center">
28
- <Sun aria-hidden size={16} />
28
+ <Sun aria-hidden />
29
29
  <span>Backup health</span>
30
30
  </Stack>
31
31
  }
@@ -4,8 +4,10 @@
4
4
  <do>Edge scrim on glass / `data-vibrant` Surface heroes, sheets, or scroll regions where content should fade into blur</do>
5
5
  <do>Keep semantics and layout on Surface/Stack/Title/Text children underneath — ProgressiveBlur is decorative atmosphere only</do>
6
6
  <do>Use sparingly — stacked `backdrop-filter` is GPU/memory-heavy; prefer one focal overlay per view</do>
7
+ <do>Match a rounded Surface by setting `border-radius` on the ProgressiveBlur root — layers inherit it</do>
7
8
  <dont>Leaving the ProgressiveBlur root `position: static` so absolute layers escape the intended overlay box</dont>
8
9
  <dont>Driving layout size or scroll behavior from inside the overlay</dont>
9
10
  <dont>Scattering ProgressiveBlur across many cards or stacking full-viewport instances</dont>
10
11
  <dont>Using ProgressiveBlur as standalone loading or status feedback without a labeled parent region</dont>
12
+ <dont>Nesting under an ancestor that pairs overflow clipping with border-radius (e.g. Surface `overflow="hidden"` + `radius`) — Chromium drops masked backdrop-filter; leave Surface overflow alone and scroll on an inner node</dont>
11
13
  </usage>
@@ -1,6 +1,6 @@
1
1
  <?xml version="1.0" encoding="UTF-8"?>
2
2
  <meta id="prose" title="Prose" category="typography" shared_contract="prose">
3
- <summary>Grouping region that applies heading-aware em rhythm to direct document blocks.</summary>
3
+ <summary>Text-wall grouping region (articles, docs, privacy) with heading-aware em rhythm; reading column via parent Stack `maxWidth` sized for body Text `size`.</summary>
4
4
  <exports>
5
5
  <export name="Prose" />
6
6
  </exports>
@@ -2,17 +2,41 @@
2
2
  <patterns surface="prose">
3
3
  <example title="Article with Title and Text">
4
4
  <tsx><![CDATA[
5
- <Prose render={<article />}>
6
- <Title size="2" lineHeight="s" render={<h2 />}>
7
- Heading-aware document rhythm
8
- </Title>
9
- <Text render={<p />}>
10
- Direct heading and paragraph children pick up Prose gaps. Type stays on Title and Text.
11
- </Text>
12
- <Text render={<p />}>A second paragraph uses the block gap, not the heading-end gap.</Text>
13
- </Prose>
5
+ {/* Body defaults to size m → mid reading column (not the xl band); prefer ch */}
6
+ <Stack maxWidth="60ch" fullWidth>
7
+ <Prose render={<article />}>
8
+ <Title size="2" lineHeight="s" render={<h2 />}>
9
+ Heading-aware document rhythm
10
+ </Title>
11
+ <Text render={<p />} lineHeight="l">
12
+ Direct heading and paragraph children pick up Prose gaps. Type stays on Title and Text. Column width follows body
13
+ size — not the full viewport.
14
+ </Text>
15
+ <Text render={<p />}>A second paragraph uses the block gap, not the heading-end gap.</Text>
16
+ </Prose>
17
+ </Stack>
18
+ ]]></tsx>
19
+ <notes>Default `gap="l"`. Landmark via `render={<article />}`. Title in Prose uses `lineHeight="s"`. Stack `maxWidth` in `ch` tracks body Text size (~10–12 words/line). Prefer `ch` over rem. Do not wrap these blocks in Stack for rhythm.</notes>
20
+ </example>
21
+
22
+ <example title="Privacy / docs text wall">
23
+ <tsx><![CDATA[
24
+ {/* Dense body size s → narrower column than default m; prefer ch */}
25
+ <Stack maxWidth="48ch" fullWidth>
26
+ <Prose render={<article />} gap="l">
27
+ <Title size="2" lineHeight="s" render={<h2 />}>
28
+ Privacy policy
29
+ </Title>
30
+ <Text size="s" render={<p />} lineHeight="l">
31
+ Long legal paragraphs use Prose for block gaps. Leading stays on Text. Smaller body size → narrower Stack maxWidth.
32
+ </Text>
33
+ <Text size="s" render={<p />}>
34
+ Following paragraphs omit lineHeight when m is fine. Prefer render p for outline rhythm.
35
+ </Text>
36
+ </Prose>
37
+ </Stack>
14
38
  ]]></tsx>
15
- <notes>Default `gap="l"`. Landmark via `render={<article />}`. Title in Prose uses `lineHeight="s"`. Do not wrap these blocks in Stack for rhythm.</notes>
39
+ <notes>Text-wall path: Prose for rhythm + Stack measure sized for body `size` (here `s` → narrower than `m`). Not for short card blurbs — those stay Text/Title props (`maxWidth` / `balanced`).</notes>
16
40
  </example>
17
41
 
18
42
  <example title="Density and region align">
@@ -1,12 +1,14 @@
1
1
  <?xml version="1.0" encoding="UTF-8"?>
2
2
  <props surface="prose">
3
3
  <when_to_use>
4
- <item>Long-form copy whose direct children are headings and blocks that need heading-aware vertical rhythm</item>
4
+ <item>Text walls — articles, docs, privacy/terms, long editorial — whose direct children are headings and blocks that need heading-aware vertical rhythm</item>
5
5
  <item>Article, docs, or changelog regions where Stack `rowGap` would make heading→body and body→body the same</item>
6
6
  <item>Optional `gap` density (`s` / `m` / `l`) and region `align` (Title/Text that omit `align` inherit it)</item>
7
+ <item>Reading column via parent Stack `maxWidth` sized for the body Text `size` (smaller → narrower; not one fixed `65ch`–`75ch`); edge-to-edge wall of text is not OK</item>
7
8
  </when_to_use>
8
9
  <when_not_to_use>
9
10
  <item>UI chrome spacing (cards, toolbars, form rows) — use Stack `rowGap` / `columnGap`</item>
11
+ <item>Short card/hero blurbs “for leading” — use Text/Title `lineHeight` / `maxWidth` / `balanced`</item>
10
12
  <item>Restyling type, lists, links, or tables — stay on Title / Text / consumer CSS</item>
11
13
  <item>Markdown parse or sanitize — Prose only spaces matching direct children</item>
12
14
  </when_not_to_use>
@@ -1,12 +1,15 @@
1
1
  <?xml version="1.0" encoding="UTF-8"?>
2
2
  <usage surface="prose">
3
+ <do>Use for text walls — articles, docs, privacy/terms, long editorial — not every card blurb (those stay Text/Title + Stack)</do>
3
4
  <do>Put headings and blocks as **direct** children — Title/Text with `render={&lt;h* /&gt;}` / `render={&lt;p /&gt;}`, plus native `ul`/`ol`/`blockquote` when needed</do>
4
5
  <do>Pick `gap` `s` / `m` / `l` (default `l`) for density; `align` on Prose to set one `text-align` for the region (omit Title/Text `align` so they inherit)</do>
6
+ <do>Keep a reading column: wrap Prose in Stack `maxWidth` in **`ch`** sized for the **body Text `size`** (smaller type → narrower; `m` mid band; large body → wider — not one fixed band for every article); prefer `ch` over rem; edge-to-edge wall of text is not OK</do>
5
7
  <do>Use `render={&lt;article /&gt;}` (or another landmark) when the region is the document landmark; name it if the landmark needs a name</do>
6
- <do>Leave type on Title/Text; Title inside Prose uses `lineHeight=&quot;s&quot;`; override `--vui-prose-gap-*` on the Prose root only when the em triple must change</do>
8
+ <do>Leave type on Title/Text; Title inside Prose uses `lineHeight=&quot;s&quot;`; body leading via Text `lineHeight` per block (`m` / `l` / `s`); override `--vui-prose-gap-*` on the Prose root only when the em triple must change</do>
7
9
  <dont>Using Stack `rowGap` as article rhythm — one gap cannot split heading→body vs body→body</dont>
8
10
  <dont>Expecting default Title/Text `span` hosts to join rhythm — they are not heading/block tags</dont>
9
11
  <dont>Setting `as` — replace the root with `render` only</dont>
10
12
  <dont>Setting `align` on every Title/Text inside Prose when one Prose `align` covers the region</dont>
11
13
  <dont>Setting a widget `role` on Prose, or painting font/color/list/link chrome in Prose CSS</dont>
14
+ <dont>Wrapping a short UI blurb in Prose “for leading” — use Text/Title `lineHeight` / `maxWidth` / `balanced` instead</dont>
12
15
  </usage>
@@ -64,7 +64,7 @@
64
64
  defaultValue="round"
65
65
  items={cornerShapeItems}
66
66
  alignListWithTrigger={false}
67
- addon={<ChevronExpandY aria-hidden size="1rem" />}
67
+ addon={<ChevronExpandY aria-hidden />}
68
68
  >
69
69
  <Select.Option value="round">Round</Select.Option>
70
70
  <Select.Option value="squircle">Squircle</Select.Option>
@@ -109,7 +109,7 @@
109
109
  <Select.Option value="blue" addon={<Stack direction="row" columnGap="2xs">{/* swatches */}</Stack>}>
110
110
  Blue
111
111
  </Select.Option>
112
- <Select.Option value="custom" addon={<EyeDropper aria-hidden size={10} />}>
112
+ <Select.Option value="custom" addon={<EyeDropper aria-hidden />}>
113
113
  Custom
114
114
  </Select.Option>
115
115
  </Select>
@@ -15,7 +15,7 @@
15
15
  <item>Wrapping a lone Select in Fieldset when its own label is sufficient</item>
16
16
  </when_not_to_use>
17
17
  <prop name="addon" kind="react">
18
- <description>Trigger addon rendered inside `Select.Icon`. Pass any React node; use a named icon from `@viraui/icons/react` for content icons.</description>
18
+ <description>Trigger addon rendered inside `Select.Icon`. Pass any React node; use a named icon from `@viraui/icons/react` for content icons. Omit glyph `size` / width / height unless expressly overriding the icon-library default.</description>
19
19
  </prop>
20
20
  <prop name="alignListWithTrigger" kind="react">
21
21
  <description>When `true`, aligns the list popup width with the trigger via Base UI `alignItemWithTrigger`. Prefer `false` when options use a leading `addon`. On desktop, Base UI also scroll-locks the page while open when this is `true` (keeps the selected item aligned with the trigger) — independent of `modal`.</description>
@@ -39,7 +39,7 @@
39
39
  <description>When `true`, open select locks page scroll and blocks outside pointer interaction (Base UI modal). Default `false` skips the modal backdrop/outside pointer block, but page scroll can still lock when `alignListWithTrigger` is `true` (Base UI coupling).</description>
40
40
  </prop>
41
41
  <prop name="Option.addon" kind="react">
42
- <description>Decorative leading node rendered before the option label.</description>
42
+ <description>Decorative leading node rendered before the option label. Omit glyph `size` / width / height unless expressly overriding the icon-library default.</description>
43
43
  </prop>
44
44
  <prop name="Option.addonAlign" kind="react">
45
45
  <description>Vertical alignment of the addon relative to the option label row.</description>
@@ -11,6 +11,7 @@
11
11
  <dont>Leaving the trigger without `label` or `aria-label`</dont>
12
12
  <dont>Inventing `width: 100%` / `w-full` CSS on Select when a parent Stack `fullWidth` / `expandChildren` can own the fill</dont>
13
13
  <dont>Leaving `alignListWithTrigger` enabled when options have a leading addon — prefer `alignListWithTrigger={false}`</dont>
14
+ <dont>Passing `size={16}` / `size=&quot;1rem&quot;` on every trigger or Option `addon` icon by habit — omit unless expressly overriding the icon-library default</dont>
14
15
  <dont>Assuming `modal={false}` alone keeps page scroll — Base UI also scroll-locks while `alignListWithTrigger` is true on desktop</dont>
15
16
  <dont>Wrapping a lone Select in Fieldset when its own label is enough</dont>
16
17
  </usage>
@@ -24,7 +24,7 @@
24
24
  <Surface color={2} radius="l" hPadding="m" vPadding="m">
25
25
  <Stack columnGap="m" direction="row" vAlign="center" expandChildren>
26
26
  <Stack data-grow={false} minWidth="13ch" direction="row" columnGap="s" vAlign="center">
27
- <Sun size={16} />
27
+ <Sun />
28
28
  <Text weight="semibold" whiteSpace="nowrap">
29
29
  Brightness
30
30
  </Text>
@@ -16,7 +16,7 @@
16
16
  <description>Sets the rendered spinner size.</description>
17
17
  </prop>
18
18
  <prop name="variant" kind="react">
19
- <description>Visual animation style.</description>
19
+ <description>Visual animation style. Catalog: arc, atom, blocks, bouncing-dots, cascade, circular-dots, classic, classic-v2, clock, comet, compass, dual, eclipse, flip, gather, leap, linear-dots, loading, morph, orbit, pulse, radar, ring, ripple, slide, snake, swirl, trace, wave. Legacy aliases: bars→wave, dot-grid→blocks, dots→eclipse.</description>
20
20
  </prop>
21
21
  <prop name="size" kind="css">
22
22
  <description>Spinner glyph size on the root.</description>
@@ -3,7 +3,7 @@
3
3
  <do>Button / IconButton async chrome: set `loading` on the control — it owns the Spinner overlay, width lock, and `aria-busy`</do>
4
4
  <do>Standalone status: Stack row with Spinner `aria-hidden` + visible Text (or Autocomplete status) that names the work</do>
5
5
  <do>Chip in-progress affordance: small Spinner as Chip `addon` (`addonPosition=&quot;end&quot;`) — Chip label stays the accessible name</do>
6
- <do>Pair `variant=&quot;dot-grid&quot;` or `bars` / `dots` with muted Text / Shimmer in Surface footers when the parent region owns busy semantics</do>
6
+ <do>Pair any Spinner `variant` (catalog or legacy `bars` / `dot-grid` / `dots`) with muted Text / Shimmer in Surface footers when the parent region owns busy semantics</do>
7
7
  <dont>Nesting a manual Spinner inside Button / IconButton when `loading` already injects one</dont>
8
8
  <dont>Using Spinner alone as the only page-level loading announcement</dont>
9
9
  <dont>Omitting `aria-hidden` on decorative standalone Spinners — the component does not hide itself</dont>
@@ -1,6 +1,71 @@
1
1
  <?xml version="1.0" encoding="UTF-8"?>
2
2
  <patterns surface="stack">
3
3
  <!-- Sources: viraui-app/components — cleaned (no handlers, no app-only chrome, no CSS that reinvents Stack props). -->
4
+ <!-- Stack-owned recipes live HERE (local patterns unit). Core `specs/patterns/*` = true multi-surface screen recipes only. -->
5
+
6
+ <example title="Stack as Surface (one DOM node)">
7
+ <tsx><![CDATA[
8
+ {/* Preferred: layout + chrome share one root */}
9
+ <Stack
10
+ direction="row"
11
+ columnGap="s"
12
+ vAlign="center"
13
+ fullWidth
14
+ render={<Surface border="all" color={1} radius="m" hPadding="m" vPadding="s" />}
15
+ >
16
+ <Text size="sm" color="muted">
17
+ Status
18
+ </Text>
19
+ <Chip>Active</Chip>
20
+ </Stack>
21
+ ]]></tsx>
22
+ <notes>Gap/align/`fullWidth`/`expandChildren` on Stack; `border`/`color`/`radius`/padding on Surface in `render`. Nest Surface→Stack only when separate roots are required (Elevator, concentric Surfaces). Never invent border/radius CSS on Stack.</notes>
23
+ </example>
24
+
25
+ <example title="Equal-width action row">
26
+ <tsx><![CDATA[
27
+ {/* Full-bleed column CTAs */}
28
+ <Stack fullWidth rowGap="s">
29
+ <Button>Continue</Button>
30
+ <Button variant="secondary">Cancel</Button>
31
+ </Stack>
32
+
33
+ {/* Equal-width row actions — children grow on the main axis. Add fullWidth when this Stack must fill parent width */}
34
+ <Stack expandChildren direction="row" columnGap="s">
35
+ <Button>Continue</Button>
36
+ <Button variant="secondary">Cancel</Button>
37
+ </Stack>
38
+ ]]></tsx>
39
+ <notes>`fullWidth` sizes this Stack; `expandChildren` grows children on the main axis. Never invent `width: 100%` / `flex: 1` CSS on Button. Both-axes fill → examples below (not height CSS).</notes>
40
+ </example>
41
+
42
+ <example title="Page chrome (semantic hosts)">
43
+ <tsx><![CDATA[
44
+ <Stack rowGap="m" expandChildren>
45
+ <Stack
46
+ direction="row"
47
+ hAlign="space-between"
48
+ vAlign="center"
49
+ columnGap="m"
50
+ hPadding="m"
51
+ vPadding="m"
52
+ render={<header />}
53
+ >
54
+ <Title render={<h1 />}>Settings</Title>
55
+ <Button>Save</Button>
56
+ </Stack>
57
+ <Stack direction="row" columnGap="m" expandChildren render={<main />}>
58
+ <Stack rowGap="xs" hPadding="s" vPadding="s" render={<nav aria-label="Settings" />}>
59
+ {/* nav links */}
60
+ </Stack>
61
+ <Stack rowGap="l" expandChildren>
62
+ {/* content */}
63
+ </Stack>
64
+ </Stack>
65
+ </Stack>
66
+ ]]></tsx>
67
+ <notes>Semantic tags via `render` — Stack stays the layout engine. CSS may set `min-block-size` / scroll; never `display:flex`. Omit `render={&lt;div /&gt;}` (default host).</notes>
68
+ </example>
4
69
 
5
70
  <example title="App header (hub)">
6
71
  <tsx><![CDATA[
@@ -73,10 +138,10 @@
73
138
  {/* brand */}
74
139
  <Stack rowGap="xl" vAlign="center">
75
140
  <Stack vPadding={[0, 'l']} rowGap="xl">
76
- <Title size="1" render={<h1 />} maxWidth="32rem" lineHeight="s">
141
+ <Title size="1" render={<h1 />} maxWidth="36ch" lineHeight="s">
77
142
  Design systems that ship
78
143
  </Title>
79
- <Text size="2xl" tone="muted" maxWidth="32rem">
144
+ <Text size="2xl" tone="muted" maxWidth="68ch">
80
145
  Sign in to continue to the studio.
81
146
  </Text>
82
147
  </Stack>
@@ -216,7 +281,7 @@
216
281
  <Title align="center" size="5" render={<h3 />}>
217
282
  No Team Members
218
283
  </Title>
219
- <Text size="s" align="center" maxWidth="14rem" tone="muted">
284
+ <Text size="s" align="center" maxWidth="40ch" tone="muted">
220
285
  Invite your team to collaborate on this project.
221
286
  </Text>
222
287
  <Button>Invite Members</Button>
@@ -236,7 +301,7 @@
236
301
  <Title size="6" render={<h2 />}>
237
302
  Preferences
238
303
  </Title>
239
- <Text size="s" maxWidth="18rem" tone="muted">
304
+ <Text size="s" maxWidth="45ch" tone="muted">
240
305
  Manage your account settings and notifications.
241
306
  </Text>
242
307
  </Stack>
@@ -360,4 +425,37 @@
360
425
  ]]></tsx>
361
426
  <notes>From `editor/preview-grid/blocks/shipping-address`. `expandChildren` on row Stacks shares width across field pairs — do not invent per-field `flex`/`width` CSS.</notes>
362
427
  </example>
428
+
429
+ <example title="Row panels fill both axes">
430
+ <tsx><![CDATA[
431
+ {/* Parent must be sized (viewport shell, fullHeight ancestor, …). No height CSS on Stack/children. */}
432
+ <Stack direction="row" columnGap="s" expandChildren fullHeight vAlign="stretch">
433
+ <Stack rowGap="s" hPadding="m" vPadding="m">
434
+ {/* sidebar / panel A */}
435
+ </Stack>
436
+ <Stack rowGap="m" hPadding="m" vPadding="m" expandChildren>
437
+ {/* main / panel B */}
438
+ </Stack>
439
+ </Stack>
440
+ ]]></tsx>
441
+ <notes>Canonical horizontal both-axes fill (Stack-owned). Main = `expandChildren`; cross = `vAlign=&quot;stretch&quot;`; root block size = `fullHeight`. Never `style`/`className` height on Stack or children.</notes>
442
+ </example>
443
+
444
+ <example title="Column sections fill both axes">
445
+ <tsx><![CDATA[
446
+ {/* Parent must be sized. Children share height + fill width — props only. */}
447
+ <Stack rowGap="s" expandChildren fullWidth fullHeight hAlign="stretch">
448
+ <Stack direction="row" columnGap="m" vAlign="center" hPadding="m" vPadding="s">
449
+ {/* header strip */}
450
+ </Stack>
451
+ <Stack rowGap="m" hPadding="m" vPadding="m" expandChildren>
452
+ {/* grow body */}
453
+ </Stack>
454
+ <Stack direction="row" columnGap="s" hPadding="m" vPadding="s" data-grow="false">
455
+ {/* footer actions — opt out of main-axis grow */}
456
+ </Stack>
457
+ </Stack>
458
+ ]]></tsx>
459
+ <notes>Canonical vertical both-axes fill (Stack-owned). Main = `expandChildren`; cross = `hAlign=&quot;stretch&quot;`; root = `fullWidth` + `fullHeight`. Footer uses `data-grow=&quot;false&quot;` so only the body expands.</notes>
460
+ </example>
363
461
  </patterns>
@@ -6,13 +6,16 @@
6
6
  <item>Custom native root through render while keeping data-stack hooks</item>
7
7
  <item>Style descendants with `@container stack` queries when layout, gap, or typography should respond to the Stack&apos;s own inline-size instead of the viewport (set `enableContainer` on the Stack you&apos;re querying)</item>
8
8
  <item>Centered max-width shells: parent `hAlign=&quot;center&quot;` + child `fullWidth` + `maxWidth`</item>
9
+ <item>Readable type columns: `maxWidth` in **`ch`** around Text/Title/Prose for ~10–12 words/line — width **tracks body `size`** (smaller → narrower; prefer `ch` over rem; never one fixed band for every size)</item>
9
10
  <item>Full-bleed or equal-width action clusters (Buttons, etc.): `fullWidth` and/or `expandChildren` instead of per-child width CSS</item>
11
+ <item>Children fill both axes in a sized parent — see this surface `patterns.xml`: row = `direction=&quot;row&quot;` + `expandChildren` + `fullHeight` + `vAlign=&quot;stretch&quot;`; column = `expandChildren` + `fullWidth` + `fullHeight` + `hAlign=&quot;stretch&quot;` — never invent `height`/`width` / `block-size`/`inline-size: 100%` CSS</item>
10
12
  </when_to_use>
11
13
  <when_not_to_use>
12
14
  <item>Cases where a single component already owns required flex chrome</item>
13
15
  <item>Expecting direct children to grow on the main axis without setting `expandChildren`</item>
14
16
  <item>Expecting this stack to fill parent inline size under non-stretch alignment without `fullWidth` (or an explicit `inlineSize`)</item>
15
- <item>Inventing `width: 100%` / `inline-size: 100%` / `w-full` / size-fill className on content-sized children (Button, Chip, …) when this Stack can own fill via `fullWidth` / `expandChildren` — or on fixed-size children (IconButton) where width CSS is useless</item>
17
+ <item>Expecting this stack to fill parent block size without `fullHeight` (or an explicit `blockSize`)</item>
18
+ <item>Inventing `width`/`height` / `inline-size`/`block-size: 100%` / `w-full` / size-fill className on this Stack or content-sized children when `fullWidth` / `fullHeight` / `expandChildren` + stretch align cover it (see `patterns.xml`) — or on fixed-size children (IconButton) where size CSS is useless</item>
16
19
  <item>Using `enableContainer` inside complex masonry-like layouts when you don&apos;t need container queries (inline-size containment can change nested layout)</item>
17
20
  </when_not_to_use>
18
21
  <prop name="columnGap" kind="react">
@@ -25,10 +28,13 @@
25
28
  <description>Renders children across rows or columns using the chosen flex direction.</description>
26
29
  </prop>
27
30
  <prop name="expandChildren" kind="react">
28
- <description>Makes direct children grow along the flex main axis (`flex-grow`). Default `false`. Use for equal-width row actions (Buttons, etc.) instead of inventing `width`/`flex` CSS on each child. Orthogonal to `fullWidth` (children grow vs this root&apos;s inline size). A child opts out with its own `data-grow=&quot;false&quot;`; ancestor `data-grow` does not inherit into nested stacks.</description>
31
+ <description>Makes direct children grow along the flex main axis (`flex-grow`). Default `false`. Use for equal-width row actions (Buttons, etc.) instead of inventing `width`/`flex` CSS on each child. Cross-axis fill stays on `hAlign` / `vAlign=&quot;stretch&quot;` (which prop is cross depends on `direction`). Orthogonal to `fullWidth` / `fullHeight` (children grow vs this root&apos;s size). A child opts out with its own `data-grow=&quot;false&quot;`; ancestor `data-grow` does not inherit into nested stacks.</description>
32
+ </prop>
33
+ <prop name="fullHeight" kind="react">
34
+ <description>Sets `block-size: 100%` on the stack root so it fills the parent&apos;s block size. Default `false`. Prefer this over `style`/`className` `height` / `block-size: 100%` on this Stack. Pair with `expandChildren` and cross-axis `hAlign`/`vAlign=&quot;stretch&quot;` so children fill both axes without per-child size CSS. Orthogonal to `expandChildren` and `fullWidth`.</description>
29
35
  </prop>
30
36
  <prop name="fullWidth" kind="react">
31
- <description>Sets `inline-size: 100%` on the stack root so it fills the parent&apos;s inline size. Default `false`. Prefer this (plus cross-axis stretch) so content-sized children like Button span a panel — do not add `width: 100%` CSS on those children. Use with `maxWidth` under a parent `hAlign=&quot;center&quot;` for a fluid capped centered shell. Does not grow children — use `expandChildren` for that.</description>
37
+ <description>Sets `inline-size: 100%` on the stack root so it fills the parent&apos;s inline size. Default `false`. Prefer this (plus cross-axis stretch) so content-sized children like Button span a panel — do not add `width: 100%` CSS on those children. Use with `maxWidth` under a parent `hAlign=&quot;center&quot;` for a fluid capped centered shell. Pair with `fullHeight` when the root must fill both parent axes. Does not grow children — use `expandChildren` for that.</description>
32
38
  </prop>
33
39
  <prop name="hAlign" kind="react">
34
40
  <description>Aligns content on the horizontal axis from the consumer point of view.</description>
@@ -2,17 +2,21 @@
2
2
  <usage surface="stack">
3
3
  <do>Default structural box instead of a bare wrapper `div` — Stack owns flex + token gap/padding/align/`fullWidth`/`render`</do>
4
4
  <do>Login/signup (or similar auth swap): host Tabs + Textfield(s) + Button (+ optional Fieldset) inside a Stack or `Stack render={&lt;Surface … /&gt;}` shell — props only, 0 custom CSS</do>
5
- <do>Flex + Surface chrome on one node via `render={&lt;Surface … /&gt;}` — prefer over a CSS border class or an extra wrapper (see package pattern `stack-as-surface`)</do>
6
- <do>Equal-width action or field clusters (Button, Chip, Textfield): `fullWidth` and/or `expandChildren` on this Stack — never per-child width CSS</do>
5
+ <do>Flex + Surface chrome on one node via `render={&lt;Surface … /&gt;}` — prefer over a CSS border class or an extra wrapper (see this surface `patterns.xml` — Stack as Surface)</do>
6
+ <do>Equal-width action or field clusters (Button, Chip, Textfield): `fullWidth` and/or `expandChildren` on this Stack — never per-child width CSS (see `patterns.xml`)</do>
7
+ <do>Children fill **both** axes inside a sized parent — this surface `patterns.xml` (never invent size-fill CSS):
8
+ row → `direction=&quot;row&quot;` + `expandChildren` + `fullHeight` + `vAlign=&quot;stretch&quot;` (share width + fill height);
9
+ column → `expandChildren` + `fullWidth` + `fullHeight` + `hAlign=&quot;stretch&quot;` (share height + fill width)</do>
7
10
  <do>Settings rows: Stack `direction=&quot;row&quot;` + Text (label/description column) + Switch or Checkbox — nest in Surface for panel chrome</do>
8
11
  <do>Centered capped shells: parent `hAlign=&quot;center&quot;` + child Stack `fullWidth` + `maxWidth`</do>
12
+ <do>Readable type column: Stack `maxWidth` in **`ch`** around Text/Title/Prose sized for the dominant body `size` (~10–12 words/line; smaller → narrower) — prefer `ch` over rem; never one fixed ch for every size</do>
9
13
  <do>Semantic/native roots via `render` (`header`, `main`, `nav`, `section`, …) while keeping Stack as the layout engine</do>
10
14
  <do>Opt into `@container stack` with `enableContainer` when layout should follow this Stack&apos;s inline-size, not the viewport</do>
11
15
  <dont>Reaching for a plain wrapper `div` when Stack (optionally with `render` for a semantic tag) can own the box</dont>
12
16
  <dont>Passing `render={&lt;div /&gt;}` (or any host that matches Stack&apos;s default root) — omit `render`; use it only for a different host (`header`, `Surface`, …)</dont>
13
17
  <dont>Assuming Stack expands direct children by default — pass `expandChildren` when children should grow on the flex main axis</dont>
14
18
  <dont>Using `expandChildren` to fill parent width under `hAlign=&quot;center&quot;` — that is `fullWidth` on the child Stack (self `inline-size`), not child flex-grow</dont>
15
- <dont>Inventing `width: 100%` / `inline-size: 100%` / `w-full` / `.fullWidth` / size-fill `className` on content-sized children when this Stack can own the fill — or when children are intentionally fixed-size (e.g. IconButton)</dont>
19
+ <dont>Inventing `width`/`height` / `inline-size`/`block-size: 100%` / `w-full` / size-fill `className` on this Stack or content-sized children when `fullWidth` / `fullHeight` / `expandChildren` + stretch align can own the fill — or when children are intentionally fixed-size (e.g. IconButton)</dont>
16
20
  <dont>Inventing CSS `gap` / `padding` / `paddingBlock*` / `paddingInline*` / side paddings (`style` or className) when public spacing props cover it — one-sided inset uses `hPadding`/`vPadding` `[start, end]` tuples (e.g. `vPadding={[0, &apos;l&apos;]}`), not `paddingBlockEnd: &apos;1rem&apos;`</dont>
17
21
  <dont>Putting `data-grow=&quot;false&quot;` on an ancestor to control nested `expandChildren` — set it on the child that should not grow</dont>
18
22
  <dont>Combining `fullWidth` with `inline` — prefer block flex when the root must fill parent inline size</dont>
@@ -30,7 +30,7 @@
30
30
  <ToggleButton
31
31
  value="light"
32
32
  aria-label="Light"
33
- restingIcon={<Sun aria-hidden size="1rem" />}
33
+ restingIcon={<Sun aria-hidden />}
34
34
  variant="flat"
35
35
  size="s"
36
36
  pressedVariant="secondary"
@@ -38,7 +38,7 @@
38
38
  <ToggleButton
39
39
  value="dark"
40
40
  aria-label="Dark"
41
- restingIcon={<MoonStars aria-hidden size="1rem" />}
41
+ restingIcon={<MoonStars aria-hidden />}
42
42
  variant="flat"
43
43
  size="s"
44
44
  pressedVariant="secondary"
@@ -46,7 +46,7 @@
46
46
  <ToggleButton
47
47
  value="system"
48
48
  aria-label="System"
49
- restingIcon={<DarkLight aria-hidden size="1rem" />}
49
+ restingIcon={<DarkLight aria-hidden />}
50
50
  variant="flat"
51
51
  size="s"
52
52
  pressedVariant="secondary"
@@ -2,7 +2,7 @@
2
2
  <usage surface="surface">
3
3
  <do>Group content with base-level background and contrast border — nest Stack for child gaps (Surface has no gap prop)</do>
4
4
  <do>Login/signup shell: Surface (or `Stack render={&lt;Surface … /&gt;}`) hosts Tabs + Textfield(s) + Button (+ optional Fieldset) — chrome + layout via props, 0 custom CSS</do>
5
- <do>Accept Stack as host via their `render={&lt;Surface … /&gt;}` so border/fill/radius share one DOM node — prefer over inventing chrome CSS (see package pattern `stack-as-surface`)</do>
5
+ <do>Accept Stack as host via their `render={&lt;Surface … /&gt;}` so border/fill/radius share one DOM node — prefer over inventing chrome CSS (see Stack `patterns.xml` — Stack as Surface)</do>
6
6
  <do>Settings / preferences panels: Surface card + Stack body + Switch/Checkbox rows (optionally padded inner Surfaces) + Button footer strip</do>
7
7
  <do>Frosted glass panels with `data-vibrant` — omit `color` for page-level shell or pass `color` for a tinted fill</do>
8
8
  <do>Compose with Elevator for animated elevation — Surface has no `elevation` prop</do>