@viraui/react 2026.5.0 → 2026.6.1

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 (169) hide show
  1. package/dist/catalog.json +5 -5
  2. package/dist/components/avatar/avatar.js +1 -1
  3. package/dist/components/stack/stack.d.ts +4 -1
  4. package/dist/components/tabs/tabs.css +1 -1
  5. package/dist/components/text/text.css +1 -1
  6. package/dist/components/text/text.d.ts +16 -5
  7. package/dist/components/text/text.js +2 -1
  8. package/dist/components/textfield/textfield.d.ts +1 -0
  9. package/dist/components/title/title.css +1 -1
  10. package/dist/components/title/title.d.ts +12 -2
  11. package/dist/components/title/title.js +2 -1
  12. package/dist/preflight.css +4 -1
  13. package/dist/specs/PROTOCOL.md +23 -19
  14. package/dist/specs/activity-hints.xml +18 -3
  15. package/dist/specs/components/accordion/patterns.xml +69 -5
  16. package/dist/specs/components/accordion/props.xml +4 -4
  17. package/dist/specs/components/accordion/usage.xml +8 -4
  18. package/dist/specs/components/annotate/patterns.xml +50 -3
  19. package/dist/specs/components/annotate/props.xml +22 -22
  20. package/dist/specs/components/annotate/usage.xml +7 -6
  21. package/dist/specs/components/autocomplete/patterns.xml +123 -7
  22. package/dist/specs/components/autocomplete/props.xml +14 -14
  23. package/dist/specs/components/autocomplete/usage.xml +11 -6
  24. package/dist/specs/components/avatar/patterns.xml +78 -3
  25. package/dist/specs/components/avatar/props.xml +8 -8
  26. package/dist/specs/components/avatar/usage.xml +9 -3
  27. package/dist/specs/components/avatar-group/patterns.xml +65 -3
  28. package/dist/specs/components/avatar-group/props.xml +8 -8
  29. package/dist/specs/components/avatar-group/usage.xml +10 -7
  30. package/dist/specs/components/badge/patterns.xml +57 -3
  31. package/dist/specs/components/badge/props.xml +8 -8
  32. package/dist/specs/components/badge/usage.xml +5 -3
  33. package/dist/specs/components/beam/meta.xml +1 -1
  34. package/dist/specs/components/beam/patterns.xml +68 -3
  35. package/dist/specs/components/beam/props.xml +22 -22
  36. package/dist/specs/components/beam/usage.xml +7 -7
  37. package/dist/specs/components/bleed/patterns.xml +54 -3
  38. package/dist/specs/components/bleed/props.xml +2 -2
  39. package/dist/specs/components/bleed/usage.xml +6 -3
  40. package/dist/specs/components/breakpoints/meta.xml +1 -1
  41. package/dist/specs/components/breakpoints/patterns.xml +1 -6
  42. package/dist/specs/components/breakpoints/props.xml +4 -2
  43. package/dist/specs/components/breakpoints/usage.xml +10 -2
  44. package/dist/specs/components/button/patterns.xml +124 -6
  45. package/dist/specs/components/button/props.xml +33 -32
  46. package/dist/specs/components/button/usage.xml +13 -13
  47. package/dist/specs/components/checkbox/patterns.xml +83 -3
  48. package/dist/specs/components/checkbox/props.xml +10 -10
  49. package/dist/specs/components/checkbox/usage.xml +11 -6
  50. package/dist/specs/components/chip/patterns.xml +74 -3
  51. package/dist/specs/components/chip/props.xml +14 -14
  52. package/dist/specs/components/chip/usage.xml +10 -6
  53. package/dist/specs/components/clamp-text/patterns.xml +1 -4
  54. package/dist/specs/components/clamp-text/props.xml +2 -2
  55. package/dist/specs/components/clamp-text/usage.xml +8 -5
  56. package/dist/specs/components/dialog/patterns.xml +136 -15
  57. package/dist/specs/components/dialog/props.xml +2 -2
  58. package/dist/specs/components/dialog/usage.xml +9 -7
  59. package/dist/specs/components/elevator/patterns.xml +54 -3
  60. package/dist/specs/components/elevator/usage.xml +8 -5
  61. package/dist/specs/components/fieldset/patterns.xml +97 -3
  62. package/dist/specs/components/fieldset/usage.xml +7 -5
  63. package/dist/specs/components/fit-text/patterns.xml +1 -4
  64. package/dist/specs/components/fit-text/props.xml +2 -2
  65. package/dist/specs/components/fit-text/usage.xml +8 -6
  66. package/dist/specs/components/glow/meta.xml +1 -1
  67. package/dist/specs/components/glow/patterns.xml +74 -3
  68. package/dist/specs/components/glow/props.xml +16 -16
  69. package/dist/specs/components/glow/usage.xml +8 -7
  70. package/dist/specs/components/grid/patterns.xml +88 -5
  71. package/dist/specs/components/grid/props.xml +23 -23
  72. package/dist/specs/components/grid/usage.xml +9 -5
  73. package/dist/specs/components/icon-button/patterns.xml +97 -6
  74. package/dist/specs/components/icon-button/props.xml +32 -32
  75. package/dist/specs/components/icon-button/usage.xml +11 -9
  76. package/dist/specs/components/linear-progress/patterns.xml +58 -3
  77. package/dist/specs/components/linear-progress/props.xml +6 -6
  78. package/dist/specs/components/linear-progress/usage.xml +9 -8
  79. package/dist/specs/components/masonry/patterns.xml +68 -5
  80. package/dist/specs/components/masonry/props.xml +2 -2
  81. package/dist/specs/components/masonry/usage.xml +9 -4
  82. package/dist/specs/components/menu/patterns.xml +179 -15
  83. package/dist/specs/components/menu/usage.xml +8 -7
  84. package/dist/specs/components/meter/patterns.xml +49 -3
  85. package/dist/specs/components/meter/props.xml +6 -6
  86. package/dist/specs/components/meter/usage.xml +10 -7
  87. package/dist/specs/components/popover/patterns.xml +118 -9
  88. package/dist/specs/components/popover/props.xml +2 -2
  89. package/dist/specs/components/popover/usage.xml +9 -8
  90. package/dist/specs/components/progressive-blur/meta.xml +1 -1
  91. package/dist/specs/components/progressive-blur/patterns.xml +1 -4
  92. package/dist/specs/components/progressive-blur/props.xml +2 -2
  93. package/dist/specs/components/progressive-blur/usage.xml +7 -6
  94. package/dist/specs/components/radio/patterns.xml +55 -5
  95. package/dist/specs/components/radio/props.xml +8 -8
  96. package/dist/specs/components/radio/usage.xml +9 -6
  97. package/dist/specs/components/select/patterns.xml +124 -8
  98. package/dist/specs/components/select/props.xml +18 -18
  99. package/dist/specs/components/select/usage.xml +11 -10
  100. package/dist/specs/components/separator/patterns.xml +121 -3
  101. package/dist/specs/components/separator/props.xml +4 -4
  102. package/dist/specs/components/separator/usage.xml +8 -5
  103. package/dist/specs/components/shimmer/patterns.xml +23 -3
  104. package/dist/specs/components/shimmer/props.xml +8 -8
  105. package/dist/specs/components/shimmer/usage.xml +7 -5
  106. package/dist/specs/components/skeleton/patterns.xml +172 -4
  107. package/dist/specs/components/skeleton/props.xml +14 -14
  108. package/dist/specs/components/skeleton/usage.xml +11 -7
  109. package/dist/specs/components/slider/patterns.xml +111 -3
  110. package/dist/specs/components/slider/props.xml +10 -10
  111. package/dist/specs/components/slider/usage.xml +11 -5
  112. package/dist/specs/components/spinner/patterns.xml +35 -3
  113. package/dist/specs/components/spinner/props.xml +2 -2
  114. package/dist/specs/components/spinner/usage.xml +8 -5
  115. package/dist/specs/components/stack/patterns.xml +359 -3
  116. package/dist/specs/components/stack/props.xml +24 -22
  117. package/dist/specs/components/stack/usage.xml +16 -10
  118. package/dist/specs/components/static-noise/meta.xml +1 -1
  119. package/dist/specs/components/static-noise/patterns.xml +20 -3
  120. package/dist/specs/components/static-noise/usage.xml +5 -5
  121. package/dist/specs/components/surface/patterns.xml +188 -3
  122. package/dist/specs/components/surface/props.xml +26 -26
  123. package/dist/specs/components/surface/usage.xml +15 -12
  124. package/dist/specs/components/switch/patterns.xml +73 -3
  125. package/dist/specs/components/switch/props.xml +12 -12
  126. package/dist/specs/components/switch/usage.xml +10 -5
  127. package/dist/specs/components/tabs/patterns.xml +111 -6
  128. package/dist/specs/components/tabs/props.xml +2 -2
  129. package/dist/specs/components/tabs/usage.xml +7 -3
  130. package/dist/specs/components/text/patterns.xml +97 -3
  131. package/dist/specs/components/text/props.xml +48 -43
  132. package/dist/specs/components/text/usage.xml +11 -4
  133. package/dist/specs/components/textarea/patterns.xml +49 -3
  134. package/dist/specs/components/textarea/props.xml +7 -6
  135. package/dist/specs/components/textarea/usage.xml +8 -5
  136. package/dist/specs/components/textfield/patterns.xml +163 -3
  137. package/dist/specs/components/textfield/props.xml +12 -11
  138. package/dist/specs/components/textfield/usage.xml +9 -3
  139. package/dist/specs/components/title/patterns.xml +74 -3
  140. package/dist/specs/components/title/props.xml +48 -43
  141. package/dist/specs/components/title/usage.xml +10 -7
  142. package/dist/specs/components/toast/patterns.xml +85 -8
  143. package/dist/specs/components/toast/usage.xml +8 -5
  144. package/dist/specs/components/toggle-button/patterns.xml +101 -3
  145. package/dist/specs/components/toggle-button/props.xml +16 -16
  146. package/dist/specs/components/toggle-button/usage.xml +9 -5
  147. package/dist/specs/components/toggle-group/patterns.xml +34 -5
  148. package/dist/specs/components/toggle-group/usage.xml +9 -5
  149. package/dist/specs/components/tooltip/patterns.xml +110 -6
  150. package/dist/specs/components/tooltip/props.xml +2 -2
  151. package/dist/specs/components/tooltip/usage.xml +8 -5
  152. package/dist/specs/components/typewriter/patterns.xml +18 -3
  153. package/dist/specs/components/typewriter/props.xml +2 -2
  154. package/dist/specs/components/typewriter/usage.xml +9 -8
  155. package/dist/specs/foundation/attributes.xml +67 -37
  156. package/dist/specs/foundation/bootstrap.xml +6 -6
  157. package/dist/specs/foundation/elevation.xml +51 -3
  158. package/dist/specs/foundation/modules.xml +117 -40
  159. package/dist/specs/foundation/theme-topics.xml +62 -27
  160. package/dist/specs/foundation/toggles.xml +2 -2
  161. package/dist/specs/index.xml +42 -6
  162. package/dist/specs/patterns/card-grid.xml +35 -0
  163. package/dist/specs/patterns/compose-layout-first.xml +32 -0
  164. package/dist/specs/patterns/equal-width-actions.xml +22 -0
  165. package/dist/specs/patterns/page-chrome.xml +34 -0
  166. package/dist/specs/patterns/settings-panel.xml +30 -0
  167. package/dist/specs/patterns/settings-row.xml +9 -7
  168. package/dist/specs/patterns/stack-as-surface.xml +37 -0
  169. package/package.json +2 -2
package/dist/catalog.json CHANGED
@@ -41,7 +41,7 @@
41
41
  {
42
42
  "id": "beam",
43
43
  "name": "Beam",
44
- "summary": "Decorative animated border, line, or pulse glow on a transparent Surface shell (radius only). Put the visual card as children. CSS-module geometry plus shared ~30fps pulse rAF for pulse variants. Memory/CPU cost — use sparingly.",
44
+ "summary": "Decorative animated border, line, or pulse glow on a transparent Surface shell (radius only). Put the visual card as children. CSS-module geometry plus shared ~30fps pulse rAF for pulse variants. Memory/CPU-heavy — use sparingly; prefer one focal instance per view.",
45
45
  "agentDocs": "./specs/components/beam/meta.xml"
46
46
  },
47
47
  {
@@ -53,7 +53,7 @@
53
53
  {
54
54
  "id": "breakpoints",
55
55
  "name": "BreakpointsProvider",
56
- "summary": "Client provider plus `useBreakpoints` for mobile-first viewport min-width matches. Defaults are hardcoded em thresholds, not theme tokens.",
56
+ "summary": "Client provider plus `useBreakpoints` for mobile-first viewport min-width matches. Defaults are hardcoded em thresholds, not theme tokens. Style-only CSS should reuse the same map lengths.",
57
57
  "agentDocs": "./specs/components/breakpoints/meta.xml"
58
58
  },
59
59
  {
@@ -107,7 +107,7 @@
107
107
  {
108
108
  "id": "glow",
109
109
  "name": "Glow",
110
- "summary": "Decorative pointer-driven border highlight on a transparent Surface shell (radius only). Put the visual card as children; a shared rAF tracker paints CSS variables without React re-renders. Memory-heavy — use sparingly (rarely).",
110
+ "summary": "Decorative pointer-driven border highlight on a transparent Surface shell (radius only). Put the visual card as children; a shared rAF tracker paints CSS variables without React re-renders. Memory/CPU-heavy — use sparingly; prefer one focal instance per view.",
111
111
  "agentDocs": "./specs/components/glow/meta.xml"
112
112
  },
113
113
  {
@@ -155,7 +155,7 @@
155
155
  {
156
156
  "id": "progressive-blur",
157
157
  "name": "ProgressiveBlur",
158
- "summary": "Decorative stacked backdrop-filter overlay that ramps blur from one edge toward the opposite edge.",
158
+ "summary": "Decorative stacked backdrop-filter overlay that ramps blur from one edge toward the opposite edge. GPU/memory-heavy — use sparingly; prefer one focal instance per view.",
159
159
  "agentDocs": "./specs/components/progressive-blur/meta.xml"
160
160
  },
161
161
  {
@@ -209,7 +209,7 @@
209
209
  {
210
210
  "id": "static-noise",
211
211
  "name": "StaticNoise",
212
- "summary": "Decorative SVG turbulence noise overlay for textured surfaces and hero sections. Memory-heavy — use sparingly (rarely).",
212
+ "summary": "Decorative SVG turbulence noise overlay for textured surfaces and hero sections. Memory-heavy — use sparingly; prefer one focal instance per view.",
213
213
  "agentDocs": "./specs/components/static-noise/meta.xml"
214
214
  },
215
215
  {
@@ -9,7 +9,7 @@ var fallbackTextSizeByAvatarSize = {
9
9
  xs: "xs",
10
10
  s: "xs",
11
11
  m: "s",
12
- l: "l"
12
+ l: "2xl"
13
13
  };
14
14
  var Avatar$1 = ({ alt = "", className, fallback, ref, size = "s", src, ...otherProps }) => {
15
15
  const hasImage = Boolean(src);
@@ -46,8 +46,9 @@ export type StackProps = React.ComponentPropsWithoutRef<'div'> & {
46
46
  /**
47
47
  * Makes direct children grow along the flex main axis (`flex-grow`).
48
48
  *
49
+ * Prefer for equal-width row actions instead of inventing width/flex CSS on each child.
49
50
  * Does not set the stack root's own inline size — use `fullWidth` when this stack must
50
- * fill its parent width (e.g. centered shell with `maxWidth`).
51
+ * fill its parent width (e.g. centered shell with `maxWidth`, or a full-bleed Button column).
51
52
  *
52
53
  * @default false
53
54
  */
@@ -55,6 +56,8 @@ export type StackProps = React.ComponentPropsWithoutRef<'div'> & {
55
56
  /**
56
57
  * Sets `inline-size: 100%` on the stack root so it fills the parent's inline size.
57
58
  *
59
+ * Prefer this (with cross-axis stretch) so content-sized children like Button span a panel —
60
+ * do not add `width: 100%` CSS on those children.
58
61
  * Use with `maxWidth` under a parent `hAlign="center"` for a fluid, capped, centered shell.
59
62
  * Orthogonal to `expandChildren` (self size vs children grow).
60
63
  *
@@ -1 +1 @@
1
- @layer viraui.preflight, viraui.components, viraui.overrides;@layer viraui.components{@property --vui-tabs-translate-amount{syntax:"<length>";inherits:true;initial-value:10px}.viraui__tabs-module__Tabs_AwbZZ{min-block-size:10rem}.viraui__tabs-module__Viewport_15X1I{display:grid;grid-template-columns:minmax(0,1fr);inline-size:100%}.viraui__tabs-module__Panel_vkCFI{grid-area:1/1;inline-size:100%;opacity:1;translate:0 0;transition:opacity var(--duration-fast) var(--easing-entrance),translate var(--duration-fast) var(--easing-entrance);&[data-ending-style]{pointer-events:none}&[data-ending-style],&[data-starting-style]{opacity:0}&[data-activation-direction=right][data-starting-style]{translate:var(--vui-tabs-translate-amount) 0}&[data-activation-direction=left][data-starting-style],&[data-activation-direction=right][data-ending-style]{translate:calc(var(--vui-tabs-translate-amount) * -1) 0}&[data-activation-direction=left][data-ending-style]{translate:var(--vui-tabs-translate-amount) 0}&[data-activation-direction=none][data-ending-style],&[data-activation-direction=none][data-starting-style]{translate:0 var(--vui-tabs-translate-amount)}&[hidden]{display:none}@media (prefers-reduced-motion:reduce){&[data-ending-style],&[data-starting-style]{opacity:1;translate:0 0}}}}@layer viraui.overrides{.viraui__tabs-module__List_XJorr{position:relative;max-inline-size:100%;overflow-x:auto;overflow-y:clip}.viraui__tabs-module__Track_Fet4f{display:inline-flex;min-inline-size:100%;box-sizing:border-box;padding-inline:var(--space-2xs)}.viraui__tabs-module__Indicator_UyNUn{position:absolute;pointer-events:none;inset-block-start:0;inset-inline-start:0;inline-size:var(--active-tab-width);block-size:round(nearest,var(--active-tab-height),2px);translate:var(--active-tab-left) calc(var(--active-tab-top) + (var(--active-tab-height) - round(nearest, var(--active-tab-height), 2px)) / 2);transition:translate var(--duration-fast) var(--easing-standard),inline-size var(--duration-fast) var(--easing-standard),block-size var(--duration-fast) var(--easing-standard)}.viraui__tabs-module__Item_XZ86Z{position:relative;flex-shrink:0;cursor:pointer;flex-basis:0;transition:none;will-change:auto;&[data-variant]:not(:disabled):active{translate:0 0}&:hover{background:#0000}&[data-disabled]{opacity:.5;background:#0000}&[data-active] .viraui__tabs-module__Label_5-8-Y{color:var(--global-foreground)}&:focus-visible{border-radius:var(--radius-s);outline-offset:-2px}}}
1
+ @layer viraui.preflight, viraui.components, viraui.overrides;@layer viraui.components{@property --vui-tabs-translate-amount{syntax:"<length>";inherits:true;initial-value:10px}.viraui__tabs-module__Tabs_AwbZZ{min-block-size:10rem}.viraui__tabs-module__Viewport_15X1I{display:grid;grid-template-columns:minmax(0,1fr);inline-size:100%}.viraui__tabs-module__Panel_vkCFI{grid-area:1/1;inline-size:100%;opacity:1;translate:0 0;transition:opacity var(--duration-fast) var(--easing-entrance),translate var(--duration-fast) var(--easing-entrance);&[data-ending-style]{pointer-events:none}&[data-ending-style],&[data-starting-style]{opacity:0}&[data-activation-direction=right][data-starting-style]{translate:var(--vui-tabs-translate-amount) 0}&[data-activation-direction=left][data-starting-style],&[data-activation-direction=right][data-ending-style]{translate:calc(var(--vui-tabs-translate-amount) * -1) 0}&[data-activation-direction=left][data-ending-style]{translate:var(--vui-tabs-translate-amount) 0}&[data-activation-direction=none][data-ending-style],&[data-activation-direction=none][data-starting-style]{translate:0 var(--vui-tabs-translate-amount)}&[hidden]{display:none}@media (prefers-reduced-motion:reduce){&[data-ending-style],&[data-starting-style]{opacity:1;translate:0 0}}}}@layer viraui.overrides{.viraui__tabs-module__List_XJorr{position:relative;max-inline-size:100%;overflow-x:auto;overflow-y:clip}.viraui__tabs-module__Track_Fet4f{display:inline-flex;min-inline-size:100%;box-sizing:border-box;padding-inline:var(--space-2xs)}.viraui__tabs-module__Indicator_UyNUn{position:absolute;pointer-events:none;inset-block-start:0;left:0;inline-size:var(--active-tab-width);block-size:round(nearest,var(--active-tab-height),2px);translate:var(--active-tab-left) calc(var(--active-tab-top) + (var(--active-tab-height) - round(nearest, var(--active-tab-height), 2px)) / 2);transition:translate var(--duration-fast) var(--easing-standard),inline-size var(--duration-fast) var(--easing-standard),block-size var(--duration-fast) var(--easing-standard)}.viraui__tabs-module__Item_XZ86Z{position:relative;flex-shrink:0;cursor:pointer;flex-basis:0;transition:none;will-change:auto;&[data-variant]:not(:disabled):active{translate:0 0}&:hover{background:#0000}&[data-disabled]{opacity:.5;background:#0000}&[data-active] .viraui__tabs-module__Label_5-8-Y{color:var(--global-foreground)}&:focus-visible{border-radius:var(--radius-s);outline-offset:-2px}}}
@@ -2,4 +2,4 @@
2
2
  var(--__text-size-min),
3
3
  calc(var(--__text-size-min) + (var(--__text-size-max) - var(--__text-size-min)) * var(--__text-fluid)),
4
4
  var(--__text-size-max)
5
- );--vui-text-font-family:var(--font-family-body);--vui-text-line-height:var(--font-leading-m);margin:0;max-inline-size:var(--vui-text-max-width);font-family:var(--vui-text-font-family);font-size:var(--vui-text-font-size);line-height:var(--vui-text-line-height);text-align:var(--vui-text-align);letter-spacing:var(--vui-text-letter-spacing);text-transform:var(--vui-text-text-transform);white-space:var(--vui-text-white-space);word-break:break-word;font-weight:var(--vui-text-font-weight);font-stretch:calc(var(--vui-text-font-width) * 1%);font-optical-sizing:auto;font-variation-settings:"wght" var(--vui-text-font-weight),"wdth" var(--vui-text-font-width),"opsz" var(--vui-text-font-opsz);text-box:var(--vui-text-trim) var(--vui-text-trim-type);&[data-text-balanced=true]{text-wrap:balance}&[data-text-selection=false]{-webkit-user-select:none;user-select:none}&[data-text-has-padding=true]{padding:var(--vui-text-padding-block-start) var(--vui-text-padding-inline-end) var(--vui-text-padding-block-end) var(--vui-text-padding-inline-start)}&[data-text-family=mono]{--vui-text-font-family:var(--font-family-mono)}&[data-text-size=xl]{--__text-size-min:var(--font-scale-body-l);--__text-size-max:var(--font-scale-body-xl)}&[data-text-size=l]{--__text-size-min:var(--font-scale-body-m);--__text-size-max:var(--font-scale-body-l)}&[data-text-size=s]{--__text-size-min:var(--font-scale-body-xs);--__text-size-max:var(--font-scale-body-s)}&[data-text-size=xs]{--vui-text-font-size:var(--font-scale-body-xs)}@container root style(--effect-fluid-typography: initial){--vui-text-font-size:var(--font-scale-body-m);&[data-text-size=xl]{--vui-text-font-size:var(--font-scale-body-xl)}&[data-text-size=l]{--vui-text-font-size:var(--font-scale-body-l)}&[data-text-size=m]{--vui-text-font-size:var(--font-scale-body-m)}&[data-text-size=s]{--vui-text-font-size:var(--font-scale-body-s)}&[data-text-size=xs]{--vui-text-font-size:var(--font-scale-body-xs)}}&[data-text-weight=light]{--vui-text-font-weight:200}&[data-text-weight=semibold]{--vui-text-font-weight:600}&[data-text-weight=bold]{--vui-text-font-weight:800}&[data-text-tone=primary]{color:var(--global-primary)}&[data-text-tone=muted]{color:var(--global-muted)}&[data-text-tone=interactive]{color:var(--global-interactive-text)}&[data-text-tone=positive]{color:var(--highlight-green)}&[data-text-tone=informative]{color:var(--highlight-blue)}&[data-text-tone=danger]{color:var(--highlight-red)}&[data-text-tone=warning]{color:var(--highlight-yellow)}&[data-text-has-literal-color=true]{color:var(--vui-text-literal-color)}&[data-text-line-height=none]{--vui-text-line-height:0}&[data-text-line-height=xs]{--vui-text-line-height:var(--font-leading-xs)}&[data-text-line-height=s]{--vui-text-line-height:var(--font-leading-s)}&[data-text-line-height=m]{--vui-text-line-height:var(--font-leading-m)}&[data-text-line-height=l]{--vui-text-line-height:var(--font-leading-l)}}}
5
+ );--vui-text-font-family:var(--font-family-body);--vui-text-line-height:var(--font-leading-m);margin:0;max-inline-size:var(--vui-text-max-width);font-family:var(--vui-text-font-family);font-size:var(--vui-text-font-size);line-height:var(--vui-text-line-height);text-align:var(--vui-text-align);letter-spacing:var(--vui-text-letter-spacing);text-transform:var(--vui-text-text-transform);white-space:var(--vui-text-white-space);word-break:break-word;font-weight:var(--vui-text-font-weight);font-stretch:calc(var(--vui-text-font-width) * 1%);font-optical-sizing:auto;font-variation-settings:"wght" var(--vui-text-font-weight),"wdth" var(--vui-text-font-width),"opsz" var(--vui-text-font-opsz);text-box:var(--vui-text-trim) var(--vui-text-trim-type);&[data-text-balanced=true]{text-wrap:balance}&[data-text-selection=false]{-webkit-user-select:none;user-select:none}&[data-text-has-padding=true]{padding:var(--vui-text-padding-block-start) var(--vui-text-padding-inline-end) var(--vui-text-padding-block-end) var(--vui-text-padding-inline-start)}&[data-text-family=mono]{--vui-text-font-family:var(--font-family-mono)}&[data-text-size="4xl"]{--__text-size-min:var(--font-scale-body-3xl);--__text-size-max:var(--font-scale-body-4xl)}&[data-text-size="3xl"]{--__text-size-min:var(--font-scale-body-2xl);--__text-size-max:var(--font-scale-body-3xl)}&[data-text-size="2xl"]{--__text-size-min:var(--font-scale-body-xl);--__text-size-max:var(--font-scale-body-2xl)}&[data-text-size=xl]{--__text-size-min:var(--font-scale-body-l);--__text-size-max:var(--font-scale-body-xl)}&[data-text-size=l]{--__text-size-min:var(--font-scale-body-m);--__text-size-max:var(--font-scale-body-l)}&[data-text-size=s]{--__text-size-max:var(--font-scale-body-s)}&[data-text-size=s],&[data-text-size=xs]{--__text-size-min:var(--font-scale-body-xs)}&[data-text-size=xs]{--__text-size-max:var(--font-scale-body-xs)}&[data-text-fluid=false]{--vui-text-font-size:var(--__text-size-max)}@container root style(--effect-fluid-typography: initial){--vui-text-font-size:var(--__text-size-max)}&[data-text-weight=light]{--vui-text-font-weight:200}&[data-text-weight=semibold]{--vui-text-font-weight:600}&[data-text-weight=bold]{--vui-text-font-weight:800}&[data-text-tone=primary]{color:var(--global-primary)}&[data-text-tone=muted]{color:var(--global-muted)}&[data-text-tone=interactive]{color:var(--global-interactive-text)}&[data-text-tone=positive]{color:var(--highlight-green)}&[data-text-tone=informative]{color:var(--highlight-blue)}&[data-text-tone=danger]{color:var(--highlight-red)}&[data-text-tone=warning]{color:var(--highlight-yellow)}&[data-text-has-literal-color=true]{color:var(--vui-text-literal-color)}&[data-text-line-height=none]{--vui-text-line-height:0}&[data-text-line-height=xs]{--vui-text-line-height:var(--font-leading-xs)}&[data-text-line-height=s]{--vui-text-line-height:var(--font-leading-s)}&[data-text-line-height=m]{--vui-text-line-height:var(--font-leading-m)}&[data-text-line-height=l]{--vui-text-line-height:var(--font-leading-l)}}}
@@ -25,11 +25,12 @@ export type TextProps = React.ComponentPropsWithoutRef<'span'> & {
25
25
  */
26
26
  ref?: React.Ref<HTMLElement>;
27
27
  /**
28
- * Selects a semantic body typography size from the active theme scale.
28
+ * Selects a semantic body typography size from the active theme scale
29
+ * (`4xl` | `3xl` | `2xl` | `xl` | `l` | `m` | `s` | `xs`).
29
30
  *
30
31
  * @default 'm'
31
32
  */
32
- size?: 'xl' | 'l' | 'm' | 's' | 'xs';
33
+ size?: '4xl' | '3xl' | '2xl' | 'xl' | 'l' | 'm' | 's' | 'xs';
33
34
  /**
34
35
  * Selects the semantic font family for body copy and inline code-like text.
35
36
  *
@@ -52,7 +53,7 @@ export type TextProps = React.ComponentPropsWithoutRef<'span'> & {
52
53
  */
53
54
  tone?: 'default' | 'primary' | 'muted' | 'interactive' | 'positive' | 'informative' | 'danger' | 'warning';
54
55
  /**
55
- * Applies a literal color escape hatch when semantic `tone` is not used.
56
+ * Applies a custom color as an escape hatch when semantic `tone` is not used.
56
57
  *
57
58
  * @default No literal color override.
58
59
  */
@@ -82,13 +83,15 @@ export type TextProps = React.ComponentPropsWithoutRef<'span'> & {
82
83
  */
83
84
  whiteSpace?: React.CSSProperties['whiteSpace'];
84
85
  /**
85
- * Sets letter spacing on the rendered copy.
86
+ * Sets letter-spacing on the rendered copy. Prefer this prop over CSS
87
+ * `letter-spacing` on the same Text root.
86
88
  *
87
89
  * @default No letter-spacing override.
88
90
  */
89
91
  tracking?: React.CSSProperties['letterSpacing'];
90
92
  /**
91
- * Applies a text-transform on the rendered copy.
93
+ * Applies `text-transform` on the rendered copy. Prefer this prop over CSS
94
+ * `text-transform` on the same Text root.
92
95
  *
93
96
  * @default No text-transform override.
94
97
  */
@@ -142,6 +145,14 @@ export type TextProps = React.ComponentPropsWithoutRef<'span'> & {
142
145
  * @default No optical size override.
143
146
  */
144
147
  opticalSize?: number;
148
+ /**
149
+ * Enables viewport fluid clamp sizing for this instance.
150
+ * Default locks at this size’s `--font-scale-body-*` token (UI chrome stays stable).
151
+ * Pass `true` for fluid page/body copy. Theme `--effect-fluid-typography: initial` still locks all Text globally.
152
+ *
153
+ * @default false
154
+ */
155
+ fluid?: boolean;
145
156
  };
146
157
  export declare const Text: React.FC<TextProps>;
147
158
  export {};
@@ -4,7 +4,7 @@ import { resolveAxisPadding } from "../../core/styles/resolve-axis-padding.js";
4
4
  import text_module_default from "./text.module.js";
5
5
  import { useRender } from "@base-ui/react/use-render";
6
6
  //#region src/components/text/text.tsx
7
- var Text = ({ align = "start", balanced = false, selection = true, className, color, family = "body", fontWidth, hPadding, lineHeight = "m", maxWidth, opticalSize, ref, render, size = "m", style, tone, tracking, transform, trim = "both", trimType = "cap alphabetic", vPadding, weight = "regular", whiteSpace = "normal", ...otherProps }) => {
7
+ var Text = ({ align = "start", balanced = false, selection = true, className, color, family = "body", fluid = false, fontWidth, hPadding, lineHeight = "m", maxWidth, opticalSize, ref, render, size = "m", style, tone, tracking, transform, trim = "both", trimType = "cap alphabetic", vPadding, weight = "regular", whiteSpace = "normal", ...otherProps }) => {
8
8
  const hasPadding = Boolean(hPadding || vPadding);
9
9
  const dynamicStyle = {
10
10
  "--vui-text-align": align,
@@ -35,6 +35,7 @@ var Text = ({ align = "start", balanced = false, selection = true, className, co
35
35
  "data-text-line-height": lineHeight,
36
36
  "data-text-balanced": balanced ? "true" : "false",
37
37
  "data-text-selection": selection ? "true" : "false",
38
+ "data-text-fluid": fluid ? "true" : "false",
38
39
  "data-text-has-padding": hasPadding ? "true" : "false",
39
40
  "data-text-has-literal-color": color ? "true" : "false",
40
41
  className: clsx(text_module_default.Text, className),
@@ -53,6 +53,7 @@ export type TextfieldProps = PrimitiveInput.Props & FieldRoot.Props & {
53
53
  fitContent?: BasicInputProps['fitContent'];
54
54
  /**
55
55
  * When `true`, root and control group take `inline-size: 100%`.
56
+ * Prefer this prop over CSS `width: 100%` / `w-full` on the Textfield root.
56
57
  *
57
58
  * @default false
58
59
  */
@@ -2,4 +2,4 @@
2
2
  var(--__title-size-min),
3
3
  calc(var(--__title-size-min) + (var(--__title-size-max) - var(--__title-size-min)) * var(--__title-fluid)),
4
4
  var(--__title-size-max)
5
- );--vui-title-font-family:var(--font-family-heading);--vui-title-line-height:var(--font-leading-m);--__title-letter-spacing:-0.03em;margin:0;max-inline-size:var(--vui-title-max-width);font-family:var(--vui-title-font-family);font-size:var(--vui-title-font-size);line-height:var(--vui-title-line-height);letter-spacing:var(--__title-letter-spacing);text-transform:var(--vui-title-text-transform);text-align:var(--vui-title-align);white-space:var(--vui-title-white-space);word-break:break-word;font-weight:var(--vui-title-font-weight);font-stretch:calc(var(--vui-title-font-width) * 1%);font-optical-sizing:auto;font-variation-settings:"wght" var(--vui-title-font-weight),"wdth" var(--vui-title-font-width),"opsz" var(--vui-title-font-opsz);text-box:var(--vui-title-trim) var(--vui-title-trim-type);display:inline-flex;&[data-title-has-tracking=true]{letter-spacing:var(--vui-title-letter-spacing)}&[data-title-balanced=true]{text-wrap:balance}&[data-title-selection=false]{-webkit-user-select:none;user-select:none}&[data-title-has-padding=true]{padding:var(--vui-title-padding-block-start) var(--vui-title-padding-inline-end) var(--vui-title-padding-block-end) var(--vui-title-padding-inline-start)}&[data-title-size=display]{--__title-size-min:var(--font-scale-h1);--__title-size-max:var(--font-scale-display)}&[data-title-size="2"]{--__title-size-min:var(--font-scale-h3);--__title-size-max:var(--font-scale-h2)}&[data-title-size="3"]{--__title-size-min:var(--font-scale-h4);--__title-size-max:var(--font-scale-h3)}&[data-title-size="4"]{--__title-size-min:var(--font-scale-h5);--__title-size-max:var(--font-scale-h4)}&[data-title-size="5"]{--__title-size-min:var(--font-scale-h6);--__title-size-max:var(--font-scale-h5);--__title-letter-spacing:-0.02em}&[data-title-size="6"]{--__title-size-min:var(--font-scale-body-m);--__title-size-max:var(--font-scale-h6);--__title-letter-spacing:-0.02em}@container root style(--effect-fluid-typography: initial){--vui-title-font-size:var(--font-scale-h1);&[data-title-size=display]{--vui-title-font-size:var(--font-scale-display)}&[data-title-size="1"]{--vui-title-font-size:var(--font-scale-h1)}&[data-title-size="2"]{--vui-title-font-size:var(--font-scale-h2)}&[data-title-size="3"]{--vui-title-font-size:var(--font-scale-h3)}&[data-title-size="4"]{--vui-title-font-size:var(--font-scale-h4)}&[data-title-size="5"]{--vui-title-font-size:var(--font-scale-h5)}&[data-title-size="6"]{--vui-title-font-size:var(--font-scale-h6)}}&[data-title-has-literal-color=true]{color:var(--vui-title-literal-color)}&[data-title-line-height=none]{--vui-title-line-height:0}&[data-title-line-height=xs]{--vui-title-line-height:var(--font-leading-xs)}&[data-title-line-height=s]{--vui-title-line-height:var(--font-leading-s)}&[data-title-line-height=m]{--vui-title-line-height:var(--font-leading-m)}&[data-title-line-height=l]{--vui-title-line-height:var(--font-leading-l)}}}
5
+ );--vui-title-font-family:var(--font-family-heading);--vui-title-line-height:var(--font-leading-m);--__title-letter-spacing:-0.03em;margin:0;max-inline-size:var(--vui-title-max-width);font-family:var(--vui-title-font-family);font-size:var(--vui-title-font-size);line-height:var(--vui-title-line-height);letter-spacing:var(--__title-letter-spacing);text-transform:var(--vui-title-text-transform);text-align:var(--vui-title-align);white-space:var(--vui-title-white-space);word-break:break-word;font-weight:var(--vui-title-font-weight);font-stretch:calc(var(--vui-title-font-width) * 1%);font-optical-sizing:auto;font-variation-settings:"wght" var(--vui-title-font-weight),"wdth" var(--vui-title-font-width),"opsz" var(--vui-title-font-opsz);text-box:var(--vui-title-trim) var(--vui-title-trim-type);display:inline-flex;&[data-title-has-tracking=true]{letter-spacing:var(--vui-title-letter-spacing)}&[data-title-balanced=true]{text-wrap:balance}&[data-title-selection=false]{-webkit-user-select:none;user-select:none}&[data-title-has-padding=true]{padding:var(--vui-title-padding-block-start) var(--vui-title-padding-inline-end) var(--vui-title-padding-block-end) var(--vui-title-padding-inline-start)}&[data-title-size=display]{--__title-size-min:var(--font-scale-h1);--__title-size-max:var(--font-scale-display)}&[data-title-size="2"]{--__title-size-min:var(--font-scale-h3);--__title-size-max:var(--font-scale-h2)}&[data-title-size="3"]{--__title-size-min:var(--font-scale-h4);--__title-size-max:var(--font-scale-h3)}&[data-title-size="4"]{--__title-size-min:var(--font-scale-h5);--__title-size-max:var(--font-scale-h4)}&[data-title-size="5"]{--__title-size-min:var(--font-scale-h6);--__title-size-max:var(--font-scale-h5);--__title-letter-spacing:-0.02em}&[data-title-size="6"]{--__title-size-min:var(--font-scale-body-m);--__title-size-max:var(--font-scale-h6);--__title-letter-spacing:-0.02em}&[data-title-fluid=false]{--vui-title-font-size:var(--__title-size-max)}@container root style(--effect-fluid-typography: initial){--vui-title-font-size:var(--__title-size-max)}&[data-title-has-literal-color=true]{color:var(--vui-title-literal-color)}&[data-title-line-height=none]{--vui-title-line-height:0}&[data-title-line-height=xs]{--vui-title-line-height:var(--font-leading-xs)}&[data-title-line-height=s]{--vui-title-line-height:var(--font-leading-s)}&[data-title-line-height=m]{--vui-title-line-height:var(--font-leading-m)}&[data-title-line-height=l]{--vui-title-line-height:var(--font-leading-l)}}}
@@ -72,7 +72,8 @@ export type TitleProps = React.ComponentPropsWithoutRef<'span'> & {
72
72
  */
73
73
  whiteSpace?: React.CSSProperties['whiteSpace'];
74
74
  /**
75
- * Sets letter spacing on the rendered copy.
75
+ * Sets letter-spacing on the rendered copy. Prefer this prop over CSS
76
+ * `letter-spacing` on the same Title root.
76
77
  *
77
78
  * Overrides size preset letter-spacing when set.
78
79
  *
@@ -80,7 +81,8 @@ export type TitleProps = React.ComponentPropsWithoutRef<'span'> & {
80
81
  */
81
82
  tracking?: React.CSSProperties['letterSpacing'];
82
83
  /**
83
- * Applies a text-transform on the rendered copy.
84
+ * Applies `text-transform` on the rendered copy. Prefer this prop over CSS
85
+ * `text-transform` on the same Title root.
84
86
  *
85
87
  * @default No text-transform override.
86
88
  */
@@ -134,6 +136,14 @@ export type TitleProps = React.ComponentPropsWithoutRef<'span'> & {
134
136
  * @default No optical size override.
135
137
  */
136
138
  opticalSize?: number;
139
+ /**
140
+ * Enables viewport fluid clamp sizing for this instance.
141
+ * Pass `false` to lock at this size’s `--font-scale-display` / `--font-scale-h*` token.
142
+ * Theme `--effect-fluid-typography: initial` still locks all Title globally.
143
+ *
144
+ * @default true
145
+ */
146
+ fluid?: boolean;
137
147
  };
138
148
  export declare const Title: React.FC<TitleProps>;
139
149
  export {};
@@ -4,7 +4,7 @@ import { resolveAxisPadding } from "../../core/styles/resolve-axis-padding.js";
4
4
  import title_module_default from "./title.module.js";
5
5
  import { useRender } from "@base-ui/react/use-render";
6
6
  //#region src/components/title/title.tsx
7
- var Title = ({ align = "start", balanced = false, selection = true, className, color, fontWidth, hPadding, size = "1", lineHeight = "m", maxWidth, opticalSize, ref, render, style, tracking, transform, trim = "both", trimType = "cap alphabetic", vPadding, weight, whiteSpace = "normal", ...otherProps }) => {
7
+ var Title = ({ align = "start", balanced = false, selection = true, className, color, fluid = true, fontWidth, hPadding, size = "1", lineHeight = "m", maxWidth, opticalSize, ref, render, style, tracking, transform, trim = "both", trimType = "cap alphabetic", vPadding, weight, whiteSpace = "normal", ...otherProps }) => {
8
8
  const hasPadding = Boolean(hPadding || vPadding);
9
9
  const hasTracking = tracking !== void 0;
10
10
  const dynamicStyle = {
@@ -33,6 +33,7 @@ var Title = ({ align = "start", balanced = false, selection = true, className, c
33
33
  "data-title-line-height": lineHeight,
34
34
  "data-title-balanced": balanced ? "true" : "false",
35
35
  "data-title-selection": selection ? "true" : "false",
36
+ "data-title-fluid": fluid ? "true" : "false",
36
37
  "data-title-has-padding": hasPadding ? "true" : "false",
37
38
  "data-title-has-literal-color": color ? "true" : "false",
38
39
  "data-title-has-tracking": hasTracking ? "true" : "false",
@@ -1 +1,4 @@
1
- @layer viraui.preflight, viraui.components, viraui.overrides;@layer viraui.preflight{@property --scrollbar-thumb{syntax:"<color>";initial-value:#0000;inherits:true}@property --scrollbar-track{syntax:"<color>";initial-value:#0000;inherits:true}@property --outline-offset{syntax:"<length>";initial-value:2px;inherits:true}@property --outline-color{syntax:"<color>";initial-value:currentcolor;inherits:true}@property --outline{syntax:"*";initial-value:2px solid currentcolor;inherits:true}@property --is-light-mode{syntax:"<color>";initial-value:#000;inherits:true}@property --vira-flex-grow{syntax:"<number>";initial-value:1;inherits:false}@property --vira-flex-shrink{syntax:"<number>";initial-value:1;inherits:false}@property --__corner-shape{syntax:"*";inherits:false}}@layer viraui.preflight{:root{--font-scale-body-xs:0.75rem;--font-scale-body-s:0.875rem;--font-scale-body-m:1rem;--font-scale-body-l:round(down, calc(1rem * pow(var(--font-body-typescale), 3)), 1px);--font-scale-body-xl:round(down, calc(1rem * pow(var(--font-body-typescale), 5)), 1px);--font-scale-h6:round(down, calc(1rem * pow(var(--font-heading-typescale), 1)), 1px);--font-scale-h5:round(down, calc(1rem * pow(var(--font-heading-typescale), 2)), 1px);--font-scale-h4:round(down, calc(1rem * pow(var(--font-heading-typescale), 3)), 1px);--font-scale-h3:round(down, calc(1rem * pow(var(--font-heading-typescale), 4)), 1px);--font-scale-h2:round(down, calc(1rem * pow(var(--font-heading-typescale), 5)), 1px);--font-scale-h1:round(down, calc(1rem * pow(var(--font-heading-typescale), 6)), 1px);--font-scale-display:round(down, calc(1rem * pow(var(--font-heading-typescale), 8)), 1px)}}@layer viraui.preflight{html{--scrollbar-thumb:oklab(from var(--global-contrast) l a b / 0.3);--scrollbar-track:#0000;--outline-offset:2px;--outline-color:var(--global-outline);--outline:2px solid var(--outline-color);--is-light-mode:contrast-color(var(--global-background));font-size:var(--font-root-size);box-sizing:border-box;line-height:1.5;background-color:var(--global-background);color:var(--global-foreground);container:root/normal;scroll-behavior:smooth;@media (prefers-reduced-motion:reduce){scroll-behavior:auto}}*,:after,:before{margin:0;box-sizing:inherit;scrollbar-width:thin;scrollbar-color:var(--scrollbar-thumb) var(--scrollbar-track);@container root not style(--effect-corner-shape: initial){corner-shape:var(--__corner-shape,var(--corner-shape))}@media (prefers-reduced-motion:reduce){animation:none!important;transition:none!important}}:focus-visible{outline:var(--outline);outline-offset:var(--outline-offset)}body{color:var(--global-foreground);margin:0;font-size:var(--font-scale-body-m);font-optical-sizing:auto;font-family:var(--font-family-body),system-ui,sans-serif;font-variation-settings:"wght" 400;font-variant-numeric:tabular-nums;@container root not style(--effect-holofoil: initial){&:after{content:"";position:fixed;inset:0;z-index:999;background-color:#99ffd8;pointer-events:none;mix-blend-mode:multiply;contain:strict;isolation:isolate;opacity:25%;background-image:radial-gradient(at 79% 56%,#70ade6 0,#0000 50%),radial-gradient(at 61% 80%,#ee909e 0,#0000 50%),radial-gradient(at 0 63%,#fdbc68 0,#0000 50%),radial-gradient(at 6% 50%,#e5cb8a 0,#0000 50%),radial-gradient(at 23% 10%,#e5db8f 0,#0000 50%),radial-gradient(at 36% 91%,#a0eea8 0,#0000 50%),radial-gradient(at 2% 80%,#e3a47d 0,#0000 50%);@container root style(--is-light-mode: white){mix-blend-mode:color;opacity:15%}}}}::selection{background-color:var(--global-primary);color:contrast-color(var(--global-primary));text-shadow:none}img{display:block;inline-size:100%;max-inline-size:100%}svg{display:inline-flex;vertical-align:middle;&:not([fill]){fill:currentcolor}}ol ul,ul ol{font-size:medium}table{border-spacing:0;inline-size:100%;border-collapse:collapse}table[data-layout-fixed]{table-layout:fixed}table thead{box-shadow:inset 0 -3px 0 var(--base-2)}table[data-table-separators] tr+tr{border-top:1px solid var(--base-2)}table th{white-space:nowrap;font-variation-settings:"wght" 800}table :is(td,th){border:none;text-align:left;font-size:medium;padding:calc(var(--space-xs) + var(--space-2xs)) var(--space-s)}button,fieldset{padding:0;margin:0;border:0}button{appearance:none;background:none;font-size:inherit;font-family:inherit;display:inline-flex;cursor:pointer;color:inherit}}@layer viraui.preflight{@container root not style(--effect-shadows: initial){[data-elevation]{--shadow-direction:1;--shadow-opacity-factor:0.16;--extra-shadow:0 0 0 1px #0000;--shadow-color:oklch(0% 0 0);transition-property:box-shadow;transition-duration:var(--elevation-transition-duration,.16s);transition-timing-function:var(--elevation-transition-easing,ease)}[data-elevation]:where([data-elevation-direction=bottom],[data-elevation-direction=right]){--shadow-direction:1}[data-elevation]:where([data-elevation-direction=top],[data-elevation-direction=left]){--shadow-direction:-1}[data-elevation-hover="0"]:hover,[data-elevation="0"]{--y1:0px;--x1:0px;box-shadow:calc(var(--x1) * var(--shadow-direction)) calc(var(--y1) * var(--shadow-direction)) 0 oklch(from var(--shadow-color) l c h/var(--shadow-opacity-factor)),0 0 0 color-mix(in oklch,var(--shadow-color),#0000 calc(94% - var(--shadow-opacity-factor))),0 0 0 oklch(from var(--shadow-color) l c h/var(--shadow-opacity-factor)),var(--extra-shadow)}[data-elevation-hover="1"]:hover,[data-elevation-hover="2"]:hover,[data-elevation-hover="3"]:hover,[data-elevation-hover="4"]:hover,[data-elevation="1"],[data-elevation="2"],[data-elevation="3"],[data-elevation="4"]{box-shadow:calc(var(--x1) * var(--shadow-direction)) calc(var(--y1) * var(--shadow-direction)) var(--shadow-blur-1) oklab(from var(--shadow-color) l a b/.1),calc(var(--x2) * var(--shadow-direction)) calc(var(--y2) * var(--shadow-direction)) var(--shadow-blur-2) oklab(from var(--shadow-color) l a b/.08),calc(var(--x3) * var(--shadow-direction)) calc(var(--y3) * var(--shadow-direction)) var(--shadow-blur-3) oklab(from var(--shadow-color) l a b/.06),calc(var(--x4) * var(--shadow-direction)) calc(var(--y4) * var(--shadow-direction)) var(--shadow-blur-4) oklab(from var(--shadow-color) l a b/.04),calc(var(--x5) * var(--shadow-direction)) calc(var(--y5) * var(--shadow-direction)) var(--shadow-blur-5) oklab(from var(--shadow-color) l a b/.02),var(--extra-shadow)}[data-elevation-hover="1"]:hover,[data-elevation="1"]{--y1:0px;--y2:1px;--y3:1px;--y4:3px;--y5:4px;--x1:0px;--x2:0px;--x3:0px;--x4:0px;--x5:0px;--shadow-blur-1:0px;--shadow-blur-2:1px;--shadow-blur-3:1px;--shadow-blur-4:3px;--shadow-blur-5:4px}[data-elevation-hover="1"]:where([data-elevation-direction=left],[data-elevation-direction=right]):hover,[data-elevation="1"]:where([data-elevation-direction=left],[data-elevation-direction=right]){--y1:0px;--y2:0px;--y3:0px;--y4:0px;--y5:0px;--x1:0px;--x2:1px;--x3:1px;--x4:3px;--x5:4px}[data-elevation-hover="2"]:hover,[data-elevation="2"]{--y1:0px;--y2:1px;--y3:3px;--y4:5px;--y5:8px;--x1:0px;--x2:0px;--x3:0px;--x4:0px;--x5:0px;--shadow-blur-1:0px;--shadow-blur-2:1px;--shadow-blur-3:3px;--shadow-blur-4:5px;--shadow-blur-5:8px}[data-elevation-hover="2"]:where([data-elevation-direction=left],[data-elevation-direction=right]):hover,[data-elevation="2"]:where([data-elevation-direction=left],[data-elevation-direction=right]){--y1:0px;--y2:0px;--y3:0px;--y4:0px;--y5:0px;--x1:0px;--x2:1px;--x3:3px;--x4:5px;--x5:8px}[data-elevation-hover="3"]:hover,[data-elevation="3"]{--y1:1px;--y2:3px;--y3:6px;--y4:10px;--y5:16px;--x1:0px;--x2:0px;--x3:0px;--x4:0px;--x5:0px;--shadow-blur-1:1px;--shadow-blur-2:3px;--shadow-blur-3:6px;--shadow-blur-4:10px;--shadow-blur-5:16px}[data-elevation-hover="3"]:where([data-elevation-direction=left],[data-elevation-direction=right]):hover,[data-elevation="3"]:where([data-elevation-direction=left],[data-elevation-direction=right]){--y1:0px;--y2:0px;--y3:0px;--y4:0px;--y5:0px;--x1:1px;--x2:3px;--x3:6px;--x4:10px;--x5:16px}[data-elevation-hover="4"]:hover,[data-elevation="4"]{--y1:1px;--y2:5px;--y3:12px;--y4:20px;--y5:32px;--x1:0px;--x2:0px;--x3:0px;--x4:0px;--x5:0px;--shadow-blur-1:1px;--shadow-blur-2:5px;--shadow-blur-3:12px;--shadow-blur-4:20px;--shadow-blur-5:32px}[data-elevation-hover="4"]:where([data-elevation-direction=left],[data-elevation-direction=right]):hover,[data-elevation="4"]:where([data-elevation-direction=left],[data-elevation-direction=right]){--y1:0px;--y2:0px;--y3:0px;--y4:0px;--y5:0px;--x1:1px;--x2:5px;--x3:12px;--x4:20px;--x5:32px}}}@layer viraui.preflight{[data-grow=true]{--vira-flex-grow:1;flex-grow:1}[data-grow=false]{--vira-flex-grow:0;flex-grow:0}[data-shrink=true]{--vira-flex-shrink:1;flex-shrink:1}[data-shrink=false]{--vira-flex-shrink:0;flex-shrink:0}}@layer viraui.preflight{:where(p){line-height:1.5;min-block-size:.01vh;font-size:var(--font-scale-body-m)}small{font-size:.7em}b,strong{font-variation-settings:"wght" 700}:where(a:any-link):not([data-no-link-style]){text-decoration:none;color:var(--global-interactive-text);word-break:break-word;&:not([class]){background:linear-gradient(currentcolor,currentcolor) no-repeat 0 100%;background-size:0 1px;transition:background-size var(--duration-fast) var(--easing-entrance);&:focus,&:hover{background-size:100% 1px}}}del{padding:0 .4em;margin:0 .2em;background-color:oklab(from var(--highlight-red) l a b/12%);color:var(--highlight-red);box-shadow:0 0 0 1px oklab(from var(--highlight-red) l a b/50%);border-radius:var(--radius-s)}ins{background-color:oklab(from var(--highlight-green) l a b/15%);color:var(--highlight-green);box-shadow:0 0 0 1px oklab(from var(--highlight-green) l a b/50%)}ins,mark{padding:0 .4em;margin:0 .2em;text-decoration:none;border-radius:var(--radius-s)}mark{background-color:oklab(from var(--highlight-yellow) l a b/15%);color:var(--highlight-yellow);box-shadow:0 0 0 1px oklab(from var(--highlight-yellow) l a b/50%)}address{font-style:normal;line-height:inherit}dt{font-variation-settings:"wght" 600}dd{margin:0;padding:0}ul{font-size:medium;padding-left:1rem;& li::marker{font-size:inherit;text-align:right;font-variation-settings:"wght" 400;min-inline-size:var(--space-xl);color:oklab(from currentColor l a b/80%)}}ol{font-size:medium;& li::marker{font-size:inherit;font-variation-settings:"wght" 400;min-inline-size:var(--space-xl);font-variant-numeric:tabular-nums;white-space:nowrap;color:oklab(from currentColor l a b/80%)}}kbd{padding:.2em .4em;border-radius:var(--radius-s);font-variation-settings:"wght" 600;box-shadow:var(--global-contrast);background:var(--global-contrast)}abbr{text-decoration:underline dashed var(--global-primary)}label,legend{font-size:inherit}code{font-size:1em;font-family:var(--font-family-mono);&:not(:where(pre &)){background-color:var(--global-contrast);border-radius:var(--radius-s);box-shadow:var(--global-contrast);padding:.2em .4em}}pre code{box-shadow:none}s{text-decoration:line-through;color:var(--global-disabled-foreground);text-decoration-color:oklab(from var(--global-foreground) l a b/50%)}:root{color-scheme:light dark}[data-mode=dark]{--is-light-mode:#fff;color:var(--global-foreground);color-scheme:dark}[data-mode=light]{--is-light-mode:#000;color:var(--global-foreground);color-scheme:light}}@layer viraui.preflight{[data-mode=inverted]{color:var(--global-foreground);@container root style(--is-light-mode: black){color-scheme:dark}@container root style(--is-light-mode: white){color-scheme:light}}}@layer viraui.preflight{@container root not style(--effect-vibrancy: initial){[data-vibrant]{backdrop-filter:brightness(var(--vibrancy-brightness)) blur(calc(var(--vibrancy-blur) * 1px)) saturate(150%);@container root style(--is-light-mode: black){backdrop-filter:brightness(100%) blur(calc(var(--vibrancy-blur) * 1px)) saturate(150%)}}}}
1
+ @layer viraui.preflight, viraui.components, viraui.overrides;@layer viraui.preflight{@property --scrollbar-thumb{syntax:"<color>";initial-value:#0000;inherits:true}@property --scrollbar-track{syntax:"<color>";initial-value:#0000;inherits:true}@property --outline-offset{syntax:"<length>";initial-value:2px;inherits:true}@property --outline-color{syntax:"<color>";initial-value:currentcolor;inherits:true}@property --outline{syntax:"*";initial-value:2px solid currentcolor;inherits:true}@property --is-light-mode{syntax:"<color>";initial-value:#000;inherits:true}@property --vira-flex-grow{syntax:"<number>";initial-value:1;inherits:false}@property --vira-flex-shrink{syntax:"<number>";initial-value:1;inherits:false}@property --__corner-shape{syntax:"*";inherits:false}}@layer viraui.preflight{:root{--font-scale-body-m:1rem;--font-scale-body-s:min(1rem, max(0.875rem, round(down, calc(1rem / pow(var(--font-body-typescale), 1)), 1px)));--font-scale-body-xs:min(
2
+ var(--font-scale-body-s),
3
+ max(0.75rem, round(down, calc(1rem / pow(var(--font-body-typescale), 2)), 1px))
4
+ );--font-scale-body-l:round(down, calc(1rem * pow(var(--font-body-typescale), 1)), 1px);--font-scale-body-xl:round(down, calc(1rem * pow(var(--font-body-typescale), 2)), 1px);--font-scale-body-2xl:round(down, calc(1rem * pow(var(--font-body-typescale), 3)), 1px);--font-scale-body-3xl:round(down, calc(1rem * pow(var(--font-body-typescale), 4)), 1px);--font-scale-body-4xl:round(down, calc(1rem * pow(var(--font-body-typescale), 5)), 1px);--font-scale-h6:round(down, calc(1rem * pow(var(--font-heading-typescale), 1)), 1px);--font-scale-h5:round(down, calc(1rem * pow(var(--font-heading-typescale), 2)), 1px);--font-scale-h4:round(down, calc(1rem * pow(var(--font-heading-typescale), 3)), 1px);--font-scale-h3:round(down, calc(1rem * pow(var(--font-heading-typescale), 4)), 1px);--font-scale-h2:round(down, calc(1rem * pow(var(--font-heading-typescale), 5)), 1px);--font-scale-h1:round(down, calc(1rem * pow(var(--font-heading-typescale), 6)), 1px);--font-scale-display:round(down, calc(1rem * pow(var(--font-heading-typescale), 8)), 1px)}}@layer viraui.preflight{html{--scrollbar-thumb:oklab(from var(--global-contrast) l a b / 0.3);--scrollbar-track:#0000;--outline-offset:2px;--outline-color:var(--global-outline);--outline:2px solid var(--outline-color);--is-light-mode:contrast-color(var(--global-background));font-size:var(--font-root-size);box-sizing:border-box;line-height:1.5;background-color:var(--global-background);color:var(--global-foreground);container:root/normal;scroll-behavior:smooth;@media (prefers-reduced-motion:reduce){scroll-behavior:auto}}*,:after,:before{margin:0;box-sizing:inherit;scrollbar-width:thin;scrollbar-color:var(--scrollbar-thumb) var(--scrollbar-track);@container root not style(--effect-corner-shape: initial){corner-shape:var(--__corner-shape,var(--corner-shape))}@media (prefers-reduced-motion:reduce){animation:none!important;transition:none!important}}:focus-visible{outline:var(--outline);outline-offset:var(--outline-offset)}body{color:var(--global-foreground);margin:0;font-size:var(--font-scale-body-m);font-optical-sizing:auto;font-family:var(--font-family-body),system-ui,sans-serif;font-variation-settings:"wght" 400;font-variant-numeric:tabular-nums;@container root not style(--effect-holofoil: initial){&:after{content:"";position:fixed;inset:0;z-index:999;background-color:#99ffd8;pointer-events:none;mix-blend-mode:multiply;contain:strict;isolation:isolate;opacity:25%;background-image:radial-gradient(at 79% 56%,#70ade6 0,#0000 50%),radial-gradient(at 61% 80%,#ee909e 0,#0000 50%),radial-gradient(at 0 63%,#fdbc68 0,#0000 50%),radial-gradient(at 6% 50%,#e5cb8a 0,#0000 50%),radial-gradient(at 23% 10%,#e5db8f 0,#0000 50%),radial-gradient(at 36% 91%,#a0eea8 0,#0000 50%),radial-gradient(at 2% 80%,#e3a47d 0,#0000 50%);@container root style(--is-light-mode: white){mix-blend-mode:color;opacity:15%}}}}::selection{background-color:var(--global-primary);color:contrast-color(var(--global-primary));text-shadow:none}img{display:block;inline-size:100%;max-inline-size:100%}svg{display:inline-flex;vertical-align:middle;&:not([fill]){fill:currentcolor}}ol ul,ul ol{font-size:medium}table{border-spacing:0;inline-size:100%;border-collapse:collapse}table[data-layout-fixed]{table-layout:fixed}table thead{box-shadow:inset 0 -3px 0 var(--base-2)}table[data-table-separators] tr+tr{border-top:1px solid var(--base-2)}table th{white-space:nowrap;font-variation-settings:"wght" 800}table :is(td,th){border:none;text-align:left;font-size:medium;padding:calc(var(--space-xs) + var(--space-2xs)) var(--space-s)}button,fieldset{padding:0;margin:0;border:0}button{appearance:none;background:none;font-size:inherit;font-family:inherit;display:inline-flex;cursor:pointer;color:inherit}}@layer viraui.preflight{@container root not style(--effect-shadows: initial){[data-elevation]{--shadow-direction:1;--shadow-opacity-factor:0.16;--extra-shadow:0 0 0 1px #0000;--shadow-color:oklch(0% 0 0);transition-property:box-shadow;transition-duration:var(--elevation-transition-duration,.16s);transition-timing-function:var(--elevation-transition-easing,ease)}[data-elevation]:where([data-elevation-direction=bottom],[data-elevation-direction=right]){--shadow-direction:1}[data-elevation]:where([data-elevation-direction=top],[data-elevation-direction=left]){--shadow-direction:-1}[data-elevation-hover="0"]:hover,[data-elevation="0"]{--y1:0px;--x1:0px;box-shadow:calc(var(--x1) * var(--shadow-direction)) calc(var(--y1) * var(--shadow-direction)) 0 oklch(from var(--shadow-color) l c h/var(--shadow-opacity-factor)),0 0 0 color-mix(in oklch,var(--shadow-color),#0000 calc(94% - var(--shadow-opacity-factor))),0 0 0 oklch(from var(--shadow-color) l c h/var(--shadow-opacity-factor)),var(--extra-shadow)}[data-elevation-hover="1"]:hover,[data-elevation-hover="2"]:hover,[data-elevation-hover="3"]:hover,[data-elevation-hover="4"]:hover,[data-elevation="1"],[data-elevation="2"],[data-elevation="3"],[data-elevation="4"]{box-shadow:calc(var(--x1) * var(--shadow-direction)) calc(var(--y1) * var(--shadow-direction)) var(--shadow-blur-1) oklab(from var(--shadow-color) l a b/.1),calc(var(--x2) * var(--shadow-direction)) calc(var(--y2) * var(--shadow-direction)) var(--shadow-blur-2) oklab(from var(--shadow-color) l a b/.08),calc(var(--x3) * var(--shadow-direction)) calc(var(--y3) * var(--shadow-direction)) var(--shadow-blur-3) oklab(from var(--shadow-color) l a b/.06),calc(var(--x4) * var(--shadow-direction)) calc(var(--y4) * var(--shadow-direction)) var(--shadow-blur-4) oklab(from var(--shadow-color) l a b/.04),calc(var(--x5) * var(--shadow-direction)) calc(var(--y5) * var(--shadow-direction)) var(--shadow-blur-5) oklab(from var(--shadow-color) l a b/.02),var(--extra-shadow)}[data-elevation-hover="1"]:hover,[data-elevation="1"]{--y1:0px;--y2:1px;--y3:1px;--y4:3px;--y5:4px;--x1:0px;--x2:0px;--x3:0px;--x4:0px;--x5:0px;--shadow-blur-1:0px;--shadow-blur-2:1px;--shadow-blur-3:1px;--shadow-blur-4:3px;--shadow-blur-5:4px}[data-elevation-hover="1"]:where([data-elevation-direction=left],[data-elevation-direction=right]):hover,[data-elevation="1"]:where([data-elevation-direction=left],[data-elevation-direction=right]){--y1:0px;--y2:0px;--y3:0px;--y4:0px;--y5:0px;--x1:0px;--x2:1px;--x3:1px;--x4:3px;--x5:4px}[data-elevation-hover="2"]:hover,[data-elevation="2"]{--y1:0px;--y2:1px;--y3:3px;--y4:5px;--y5:8px;--x1:0px;--x2:0px;--x3:0px;--x4:0px;--x5:0px;--shadow-blur-1:0px;--shadow-blur-2:1px;--shadow-blur-3:3px;--shadow-blur-4:5px;--shadow-blur-5:8px}[data-elevation-hover="2"]:where([data-elevation-direction=left],[data-elevation-direction=right]):hover,[data-elevation="2"]:where([data-elevation-direction=left],[data-elevation-direction=right]){--y1:0px;--y2:0px;--y3:0px;--y4:0px;--y5:0px;--x1:0px;--x2:1px;--x3:3px;--x4:5px;--x5:8px}[data-elevation-hover="3"]:hover,[data-elevation="3"]{--y1:1px;--y2:3px;--y3:6px;--y4:10px;--y5:16px;--x1:0px;--x2:0px;--x3:0px;--x4:0px;--x5:0px;--shadow-blur-1:1px;--shadow-blur-2:3px;--shadow-blur-3:6px;--shadow-blur-4:10px;--shadow-blur-5:16px}[data-elevation-hover="3"]:where([data-elevation-direction=left],[data-elevation-direction=right]):hover,[data-elevation="3"]:where([data-elevation-direction=left],[data-elevation-direction=right]){--y1:0px;--y2:0px;--y3:0px;--y4:0px;--y5:0px;--x1:1px;--x2:3px;--x3:6px;--x4:10px;--x5:16px}[data-elevation-hover="4"]:hover,[data-elevation="4"]{--y1:1px;--y2:5px;--y3:12px;--y4:20px;--y5:32px;--x1:0px;--x2:0px;--x3:0px;--x4:0px;--x5:0px;--shadow-blur-1:1px;--shadow-blur-2:5px;--shadow-blur-3:12px;--shadow-blur-4:20px;--shadow-blur-5:32px}[data-elevation-hover="4"]:where([data-elevation-direction=left],[data-elevation-direction=right]):hover,[data-elevation="4"]:where([data-elevation-direction=left],[data-elevation-direction=right]){--y1:0px;--y2:0px;--y3:0px;--y4:0px;--y5:0px;--x1:1px;--x2:5px;--x3:12px;--x4:20px;--x5:32px}}}@layer viraui.preflight{[data-grow=true]{--vira-flex-grow:1;flex-grow:1}[data-grow=false]{--vira-flex-grow:0;flex-grow:0}[data-shrink=true]{--vira-flex-shrink:1;flex-shrink:1}[data-shrink=false]{--vira-flex-shrink:0;flex-shrink:0}}@layer viraui.preflight{:where(p){line-height:1.5;min-block-size:.01vh;font-size:var(--font-scale-body-m)}small{font-size:.7em}b,strong{font-variation-settings:"wght" 700}:where(a:any-link):not([data-no-link-style]){text-decoration:none;color:var(--global-interactive-text);word-break:break-word;&:not([class]){background:linear-gradient(currentcolor,currentcolor) no-repeat 0 100%;background-size:0 1px;transition:background-size var(--duration-fast) var(--easing-entrance);&:focus,&:hover{background-size:100% 1px}}}del{padding:0 .4em;margin:0 .2em;background-color:oklab(from var(--highlight-red) l a b/12%);color:var(--highlight-red);box-shadow:0 0 0 1px oklab(from var(--highlight-red) l a b/50%);border-radius:var(--radius-s)}ins{background-color:oklab(from var(--highlight-green) l a b/15%);color:var(--highlight-green);box-shadow:0 0 0 1px oklab(from var(--highlight-green) l a b/50%)}ins,mark{padding:0 .4em;margin:0 .2em;text-decoration:none;border-radius:var(--radius-s)}mark{background-color:oklab(from var(--highlight-yellow) l a b/15%);color:var(--highlight-yellow);box-shadow:0 0 0 1px oklab(from var(--highlight-yellow) l a b/50%)}address{font-style:normal;line-height:inherit}dt{font-variation-settings:"wght" 600}dd{margin:0;padding:0}ul{font-size:medium;padding-left:1rem;& li::marker{font-size:inherit;text-align:right;font-variation-settings:"wght" 400;min-inline-size:var(--space-xl);color:oklab(from currentColor l a b/80%)}}ol{font-size:medium;& li::marker{font-size:inherit;font-variation-settings:"wght" 400;min-inline-size:var(--space-xl);font-variant-numeric:tabular-nums;white-space:nowrap;color:oklab(from currentColor l a b/80%)}}kbd{padding:.2em .4em;border-radius:var(--radius-s);font-variation-settings:"wght" 600;box-shadow:var(--global-contrast);background:var(--global-contrast)}abbr{text-decoration:underline dashed var(--global-primary)}label,legend{font-size:inherit}code{font-size:1em;font-family:var(--font-family-mono);&:not(:where(pre &)){background-color:var(--global-contrast);border-radius:var(--radius-s);box-shadow:var(--global-contrast);padding:.2em .4em}}pre code{box-shadow:none}s{text-decoration:line-through;color:var(--global-disabled-foreground);text-decoration-color:oklab(from var(--global-foreground) l a b/50%)}:root{color-scheme:light dark}[data-mode=dark]{--is-light-mode:#fff;color:var(--global-foreground);color-scheme:dark}[data-mode=light]{--is-light-mode:#000;color:var(--global-foreground);color-scheme:light}}@layer viraui.preflight{[data-mode=inverted]{color:var(--global-foreground);@container root style(--is-light-mode: black){color-scheme:dark}@container root style(--is-light-mode: white){color-scheme:light}}}@layer viraui.preflight{@container root not style(--effect-vibrancy: initial){[data-vibrant]{backdrop-filter:brightness(var(--vibrancy-brightness)) blur(calc(var(--vibrancy-blur) * 1px)) saturate(150%);@container root style(--is-light-mode: black){backdrop-filter:brightness(100%) blur(calc(var(--vibrancy-blur) * 1px)) saturate(150%)}}}}
@@ -1,29 +1,21 @@
1
1
  # ViraUI package specs protocol
2
2
 
3
3
  **Package:** `@viraui/react` agent documentation
4
- **Authority after cutover:** navigation index + scoped XML units only. `*.guide.json` is **not** agent API authority.
4
+ **Authority:** navigation index + scoped XML units only. `*.guide.json` is **not** agent API authority.
5
5
 
6
- ## Index-first (mandatory)
6
+ ## Resolve from the installed package (mandatory)
7
7
 
8
- 1. Open `index.xml` before any component or foundation unit.
9
- 2. Use `activity-hints.xml` for activity → load sequences (`choose-component`, `implement`, `foundation-attrs`).
10
- 3. Open only the unit files named for that activity (and the chosen surface).
11
- 4. Do **not** parse the full tree of XML unit files. Failure to route is an index or content defect—not a reason to tree-walk.
8
+ Consumer agents **MUST** read specs from the **installed** `@viraui/react` version — Node package resolution / `node_modules` — co-versioned with the code in use.
12
9
 
13
- ## Authority order
10
+ Do **not** search the consumer app tree, monorepo checkouts, or skills corpora for `index.xml` / unit files. Do **not** open ViraUI source under another clone unless that clone **is** the package under edit.
14
11
 
15
- 1. **Package specs units** for the installed version (`meta`, `props`, `usage`, `a11y`, `patterns`, foundation) — intent, Vira-added props, anti-patterns, public CSS hooks.
16
- 2. Installed package **types / source** — verify accepted props, inherited pass-through, and defaults **after** reading units. Never use types as first discovery.
17
- 3. Examples / stories — examples only; never API authority.
18
- 4. Skills prose — routers and playbooks only; never a second encyclopedia of component API facts.
19
-
20
- ## Co-versioned resolution
21
-
22
- Resolve docs from the **installed** `@viraui/react` package (Node resolution / `node_modules`), not from a newer skills corpus or another checkout. The `version` attribute on `index.xml` must match the installed package version.
12
+ Package exports: `@viraui/react/specs/*`.
23
13
 
24
14
  ### Filesystem recipe (Read tool)
25
15
 
26
- Prefer package subpaths; on disk under the install they map to:
16
+ Bare names below (`index.xml`, `activity-hints.xml`, `foundation/…`, `components/<id>/…`) are **paths under the published specs root**, not repo-root paths.
17
+
18
+ On disk under a typical install:
27
19
 
28
20
  - `node_modules/@viraui/react/dist/specs/PROTOCOL.md`
29
21
  - `node_modules/@viraui/react/dist/specs/index.xml`
@@ -31,7 +23,21 @@ Prefer package subpaths; on disk under the install they map to:
31
23
  - `node_modules/@viraui/react/dist/specs/components/<id>/*.xml`
32
24
  - `node_modules/@viraui/react/dist/specs/foundation/*.xml`
33
25
 
34
- Package exports: `@viraui/react/specs/*`.
26
+ Prefer opening via package export / that `dist/specs/` tree. The `version` attribute on `index.xml` must match the installed package version.
27
+
28
+ ## Index-first (mandatory)
29
+
30
+ 1. Open `index.xml` (specs root) before any component or foundation unit.
31
+ 2. Use `activity-hints.xml` for activity → load sequences (`choose-component`, `implement`, `compose-layout`, `foundation-attrs`, `bootstrap`).
32
+ 3. Open only the unit files named for that activity (and the chosen surface), using `href` values from the index (still under the same specs root).
33
+ 4. Do **not** parse the full tree of XML unit files. Failure to route is an index or content defect—not a reason to tree-walk or `rg` the package.
34
+
35
+ ## Authority order
36
+
37
+ 1. **Package specs units** for the installed version (`meta`, `props`, `usage`, `a11y`, `patterns`, foundation) — intent, Vira-added props, anti-patterns, public CSS hooks.
38
+ 2. Installed package **types / source** — verify accepted props, inherited pass-through, and defaults **after** reading units. Never use types as first discovery.
39
+ 3. Examples / stories — examples only; never API authority.
40
+ 4. Skills prose — routers and playbooks only; never a second encyclopedia of component API facts.
35
41
 
36
42
  ## Forbidden discovery
37
43
 
@@ -41,8 +47,6 @@ Do **not** `ls` / `rg` / `grep` `dist/components/**` or `*.d.ts` to discover Vir
41
47
 
42
48
  `catalog.json` is a small tooling index of public components. Narrative discovery uses the specs index + units—not skill encyclopedias or legacy surface JSON.
43
49
 
44
- **Core / preflight units** are hand-authored under `packages/react/src/core/specs/` and published as `specs/foundation/*` (bootstrap, attributes, toggles, theme-topics, elevation, modules).
45
-
46
50
  ## Defects
47
51
 
48
52
  Missing index entry, broken `href`, or empty high-traffic units → fix the package docs. Do not invent props or load every `props.xml`.
@@ -23,10 +23,10 @@
23
23
  <description>Mode, vibrancy, elevation, grow/shrink hooks.</description>
24
24
  <load>
25
25
  <step open="index.xml" />
26
- <step open="foundation/attributes.xml" />
27
- <step open="foundation/elevation.xml" when="elevation on React or raw DOM" />
26
+ <step open="foundation/attributes.xml" when="always" />
27
+ <step open="foundation/elevation.xml" when="elevation/shadows on React or raw DOM" />
28
28
  <step open="foundation/toggles.xml" when="effects involved" />
29
- <step open="foundation/modules.xml" when="debugging which preflight CSS module owns a hook" />
29
+ <step open="foundation/modules.xml" when="which preflight capability owns a behavior or CSS var" />
30
30
  </load>
31
31
  <forbid>Inventing data-* attributes not listed in foundation units</forbid>
32
32
  </activity>
@@ -39,4 +39,19 @@
39
39
  </load>
40
40
  <forbid>Guessing import paths or inventing provider trees</forbid>
41
41
  </activity>
42
+ <activity id="compose-layout">
43
+ <description>Page/section flex, grid, panels — prefer layout primitives and composition over custom CSS.</description>
44
+ <load>
45
+ <step open="index.xml" note="category=pattern + stack/surface/grid/masonry/bleed" />
46
+ <step open="patterns/compose-layout-first.xml" />
47
+ <step open="patterns/stack-as-surface.xml" when="border/fill/radius on a flex cluster" />
48
+ <step open="patterns/page-chrome.xml" when="page shell / semantic tags" />
49
+ <step open="patterns/equal-width-actions.xml" when="full-bleed or equal action rows" />
50
+ <step open="patterns/card-grid.xml" when="CSS grid tracks / card walls" />
51
+ <step open="patterns/settings-panel.xml" when="settings / form panels" />
52
+ <step unit="usage" note="confirm stack/surface/grid (etc.) do/dont after pattern" />
53
+ <step unit="props" note="verify spacing / render / fullWidth names" />
54
+ </load>
55
+ <forbid>Inventing display:flex / display:grid / CSS gap/padding/border chrome when Stack, Grid, Masonry, Bleed, or Surface cover it</forbid>
56
+ </activity>
42
57
  </activity_hints>
@@ -1,9 +1,73 @@
1
1
  <?xml version="1.0" encoding="UTF-8"?>
2
2
  <patterns surface="accordion">
3
- <example title="Accordion structure">
4
- <tsx><![CDATA[<Accordion>
5
- <Accordion.Item trigger="…">…</Accordion.Item>
6
- </Accordion>]]></tsx>
7
- <notes>Public assembly hint from legacy guide; not API authority.</notes>
3
+ <!-- Sources: viraui-app/components — cleaned (no handlers, no i18n, no scroll-box style). Public parts: Accordion + Accordion.Item only. -->
4
+
5
+ <example title="Help FAQ (multiple open)">
6
+ <tsx><![CDATA[
7
+ <Surface overflow="hidden" color={1} border="all" radius="l">
8
+ <Stack rowGap="l">
9
+ <Stack rowGap="l" hPadding="m" vPadding="m">
10
+ <Stack rowGap="xs">
11
+ <Title size="6" render={<h2 />}>
12
+ Payout Help
13
+ </Title>
14
+ <Text size="s" tone="muted">
15
+ Royalty deposits and tax reporting
16
+ </Text>
17
+ </Stack>
18
+
19
+ <Accordion defaultValue={['tax-docs']} multiple>
20
+ <Accordion.Item color={2} border="all" trigger="When do payouts arrive?" value="arrival-timing">
21
+ <Text tone="muted">
22
+ Payouts trigger when your balance crosses the minimum threshold. ACH transfers land in 2–3 business days;
23
+ instant payouts post within minutes for eligible accounts.
24
+ </Text>
25
+ </Accordion.Item>
26
+ <Accordion.Item color={2} border="all" trigger="What fees apply?" value="fees">
27
+ <Text tone="muted">
28
+ Standard ACH deposits are free. Instant payouts carry a 1.5% fee capped at $25 per transfer.
29
+ </Text>
30
+ </Accordion.Item>
31
+ <Accordion.Item color={2} border="all" trigger="Tax documents" value="tax-docs">
32
+ <Text tone="muted">
33
+ Annual 1099 forms publish by January 31. Download prior-year statements from Account Settings.
34
+ </Text>
35
+ </Accordion.Item>
36
+ </Accordion>
37
+ </Stack>
38
+
39
+ <Surface
40
+ render={<Stack direction="row" hAlign="space-between" vAlign="center" />}
41
+ color={2}
42
+ hPadding="l"
43
+ vPadding="m"
44
+ >
45
+ <Button variant="secondary">View all statements</Button>
46
+ <Button>Contact support</Button>
47
+ </Surface>
48
+ </Stack>
49
+ </Surface>
50
+ ]]></tsx>
51
+ <notes>From `editor/preview-grid/blocks/payout-help`. Compose via `Accordion.Item` only — no public Header/Trigger/Panel. `multiple` + `defaultValue` from Base UI root. Item `color`/`border` forward to Surface when `useSurface` (default).</notes>
52
+ </example>
53
+
54
+ <example title="Sidebar advanced section">
55
+ <tsx><![CDATA[
56
+ <Accordion>
57
+ <Accordion.Item
58
+ value="advanced"
59
+ trigger="Advanced"
60
+ iconClosed={<CircleWarning />}
61
+ iconOpen={<RouteAlert />}
62
+ color={1}
63
+ radius="m"
64
+ >
65
+ <Stack rowGap="m" vPadding="xs">
66
+ {/* advanced controls */}
67
+ </Stack>
68
+ </Accordion.Item>
69
+ </Accordion>
70
+ ]]></tsx>
71
+ <notes>From `editor/sidebar/sidebar` advancedAccordion. Single Item with custom open/closed icons + Surface `color`/`radius`. Drop studio store / section registry chrome.</notes>
8
72
  </example>
9
73
  </patterns>
@@ -39,10 +39,10 @@
39
39
  <prop name="Item.useSurface" kind="react">
40
40
  <description>When `true`, wraps the item in `Surface` (optional open-block background via `color`). When `false`, renders without `Surface` so consumers can insert `Separator` between items; island styling is skipped for that item.</description>
41
41
  </prop>
42
- <css_var suffix="island-gap">
42
+ <prop name="island-gap" kind="css">
43
43
  <description>Gap between separated Surface islands when islands={true}.</description>
44
- </css_var>
45
- <css_var suffix="radius">
44
+ </prop>
45
+ <prop name="radius" kind="css">
46
46
  <description>Corner radius for Surface island block edges when useSurface is true.</description>
47
- </css_var>
47
+ </prop>
48
48
  </props>
@@ -1,8 +1,12 @@
1
1
  <?xml version="1.0" encoding="UTF-8"?>
2
2
  <usage surface="accordion">
3
- <do>Progressive disclosure for related content sections in one surface</do>
4
- <do>FAQ or settings groups where only one section may be open by default</do>
5
- <do>Multiple open sections when `multiple` is enabled</do>
6
- <dont>Trying to compose separate public `Accordion.Header`, `Accordion.Trigger`, or `Accordion.Panel` exports</dont>
3
+ <do>Progressive disclosure for FAQ or settings groups in one surface</do>
4
+ <do>Compose only via `Accordion` + `Accordion.Item` — put panel body (Text, Stack of controls, …) as Item children; pass visible label via Item `trigger`</do>
5
+ <do>FAQ chrome: outer Surface + Stack header (Title/Text) + Accordion; Item `color` / `border` / `radius` forward to Surface when `useSurface` (default)</do>
6
+ <do>Separated islands with root `islands`; attached block corners when `islands={false}`</do>
7
+ <do>Insert `Separator` between items when `Item` `useSurface={false}`</do>
8
+ <do>Multiple open sections with root `multiple` (+ `defaultValue` / `value` as needed)</do>
9
+ <dont>Trying to compose separate public `Accordion.Header`, `Accordion.Trigger`, or `Accordion.Panel` exports — those stay inside `Accordion.Item`</dont>
7
10
  <dont>Rendering an item without trigger text and without an external aria-label strategy</dont>
11
+ <dont>Using Accordion for primary navigation that should be links, Tabs, or routes</dont>
8
12
  </usage>
@@ -1,7 +1,54 @@
1
1
  <?xml version="1.0" encoding="UTF-8"?>
2
2
  <patterns surface="annotate">
3
- <example title="Annotate structure">
4
- <tsx><![CDATA[<Annotate note="…">…</Annotate>]]></tsx>
5
- <notes>Public assembly hint from legacy guide; not API authority.</notes>
3
+ <!-- Sources: viraui-app/components — cleaned (no handlers, no giant SVG payloads, no swatch layout CSS). -->
4
+
5
+ <example title="QR callout (device pairing)">
6
+ <tsx><![CDATA[
7
+ <Surface border="all" color={1} radius="l" hPadding="m" vPadding="m">
8
+ <Stack rowGap="m" expandChildren>
9
+ <Stack rowGap="m" vAlign="start" hPadding="l" vPadding={['2xl', 'l']} hAlign="center">
10
+ <Annotate color="blue" note="Scan me!" side="top-end" arrowOffsetY="25px">
11
+ <Surface color="var(--global-foreground)" radius="l" hPadding="m" vPadding="m">
12
+ {/* QR / code graphic */}
13
+ </Surface>
14
+ </Annotate>
15
+
16
+ <Stack vPadding="m" rowGap="xs" hAlign="center">
17
+ <Title align="center" size="6" render={<h6 />}>
18
+ Scan to connect your mobile device
19
+ </Title>
20
+ <Text size="s" align="center" maxWidth="20rem" tone="muted">
21
+ Open the Ledger mobile app and scan this code to link your device.
22
+ </Text>
23
+ </Stack>
24
+ </Stack>
25
+
26
+ <Button variant="secondary">Got it</Button>
27
+ </Stack>
28
+ </Surface>
29
+ ]]></tsx>
30
+ <notes>From `editor/preview-grid/blocks/device-pairing`. Annotate wraps the QR Surface; `note` is decorative only. Collapse the inline SVG to a comment slot.</notes>
31
+ </example>
32
+
33
+ <example title="CTA nudge (empty team)">
34
+ <tsx><![CDATA[
35
+ <Annotate color="green" note="start here" side="bottom-end" arrowOffsetY="-25px">
36
+ <Button>Invite Members</Button>
37
+ </Annotate>
38
+ ]]></tsx>
39
+ <notes>From `editor/preview-grid/blocks/empty-team`. Point at a primary CTA. Drop Badge toggle / onClick kitchen chrome — keep Annotate + Button.</notes>
40
+ </example>
41
+
42
+ <example title="Inline mark in copy">
43
+ <tsx><![CDATA[
44
+ <Text size="s" tone="muted">
45
+ Designers love packing{' '}
46
+ <Annotate color="yellow" mark note="look here" side="top-end">
47
+ quirky glyphs
48
+ </Annotate>{' '}
49
+ into test phrases. This is a preview of the theme voice, contrast, and color rhythm.
50
+ </Text>
51
+ ]]></tsx>
52
+ <notes>From `editor/preview-grid/blocks/theme-preview`. `mark` highlighter behind inline phrase; note stays decorative. Drop swatch grid shell from this hint.</notes>
6
53
  </example>
7
54
  </patterns>