@viraui/react 2026.8.0 → 2026.9.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 (44) hide show
  1. package/dist/catalog.json +3 -3
  2. package/dist/components/prose/prose.css +1 -1
  3. package/dist/components/prose/prose.d.ts +8 -0
  4. package/dist/components/prose/prose.js +2 -1
  5. package/dist/components/select/select.css +1 -1
  6. package/dist/components/stack/stack.css +1 -1
  7. package/dist/components/stack/stack.d.ts +15 -3
  8. package/dist/components/stack/stack.js +2 -1
  9. package/dist/components/surface/surface.css +1 -1
  10. package/dist/components/text/text.css +2 -2
  11. package/dist/components/text/text.d.ts +9 -6
  12. package/dist/components/text/text.js +2 -2
  13. package/dist/components/title/title.css +2 -2
  14. package/dist/components/title/title.d.ts +9 -6
  15. package/dist/components/title/title.js +2 -2
  16. package/dist/preflight.css +1 -1
  17. package/dist/specs/PROTOCOL.md +1 -1
  18. package/dist/specs/activity-hints.xml +4 -4
  19. package/dist/specs/components/progressive-blur/usage.xml +2 -2
  20. package/dist/specs/components/prose/meta.xml +1 -1
  21. package/dist/specs/components/prose/patterns.xml +1 -1
  22. package/dist/specs/components/prose/props.xml +8 -2
  23. package/dist/specs/components/prose/usage.xml +2 -1
  24. package/dist/specs/components/stack/patterns.xml +98 -0
  25. package/dist/specs/components/stack/props.xml +8 -3
  26. package/dist/specs/components/stack/usage.xml +6 -3
  27. package/dist/specs/components/surface/usage.xml +1 -1
  28. package/dist/specs/components/text/meta.xml +1 -1
  29. package/dist/specs/components/text/patterns.xml +11 -11
  30. package/dist/specs/components/text/props.xml +10 -7
  31. package/dist/specs/components/text/usage.xml +2 -2
  32. package/dist/specs/components/title/meta.xml +1 -1
  33. package/dist/specs/components/title/patterns.xml +8 -8
  34. package/dist/specs/components/title/props.xml +10 -7
  35. package/dist/specs/components/title/usage.xml +3 -3
  36. package/dist/specs/foundation/attributes.xml +2 -4
  37. package/dist/specs/foundation/theme-topics.xml +3 -3
  38. package/dist/specs/foundation/toggles.xml +2 -2
  39. package/dist/specs/index.xml +4 -22
  40. package/dist/specs/patterns/compose-layout-first.xml +1 -1
  41. package/package.json +2 -2
  42. package/dist/specs/patterns/equal-width-actions.xml +0 -22
  43. package/dist/specs/patterns/page-chrome.xml +0 -34
  44. package/dist/specs/patterns/stack-as-surface.xml +0 -37
package/dist/catalog.json CHANGED
@@ -185,7 +185,7 @@
185
185
  {
186
186
  "id": "prose",
187
187
  "name": "Prose",
188
- "summary": "Text-wall grouping region (articles, docs, privacy) with heading-aware em rhythm; reading column via parent Stack `maxWidth` sized for body Text `size`.",
188
+ "summary": "Text-wall grouping region (articles, docs, privacy) with heading-aware em rhythm, region `wrap` (default `pretty`), and reading column via parent Stack `maxWidth` sized for body Text `size`.",
189
189
  "agentDocs": "./specs/components/prose/meta.xml"
190
190
  },
191
191
  {
@@ -263,7 +263,7 @@
263
263
  {
264
264
  "id": "text",
265
265
  "name": "Text",
266
- "summary": "Theme-aware body-copy primitive with tone, family, sizing, and readable-measure props (`maxWidth` / `lineHeight` / `balanced`).",
266
+ "summary": "Theme-aware body-copy primitive with tone, family, sizing, and readable-measure props (`maxWidth` / `lineHeight` / `wrap`).",
267
267
  "agentDocs": "./specs/components/text/meta.xml"
268
268
  },
269
269
  {
@@ -281,7 +281,7 @@
281
281
  {
282
282
  "id": "title",
283
283
  "name": "Title",
284
- "summary": "Theme-aware heading and display typography with readable-measure props (`maxWidth` / `lineHeight` / `balanced`).",
284
+ "summary": "Theme-aware heading and display typography with readable-measure props (`maxWidth` / `lineHeight` / `wrap`).",
285
285
  "agentDocs": "./specs/components/title/meta.xml"
286
286
  },
287
287
  {
@@ -1 +1 @@
1
- @layer viraui.preflight, viraui.components, viraui.overrides;@layer viraui.components{@property --vui-prose-align{syntax:"*";inherits:false;initial-value:start}@property --vui-prose-gap-blocks{syntax:"<length>";inherits:true;initial-value:2em}@property --vui-prose-gap-heading-start{syntax:"<length>";inherits:true;initial-value:1.3em}@property --vui-prose-gap-heading-end{syntax:"<length>";inherits:true;initial-value:.8em}.viraui__prose-module__Prose_8yO9h{--vui-prose-gap-blocks:2em;--vui-prose-gap-heading-start:1.3em;--vui-prose-gap-heading-end:0.8em;&[data-prose-gap=s]{--vui-prose-gap-blocks:1em;--vui-prose-gap-heading-start:0.7em;--vui-prose-gap-heading-end:0.3em}&[data-prose-gap=m]{--vui-prose-gap-blocks:1.5em;--vui-prose-gap-heading-start:1em;--vui-prose-gap-heading-end:0.6em}&[data-prose-has-align=true]{text-align:var(--vui-prose-align)}&>:is(h1,h2,h3,h4,h5,h6,hgroup,ul,ol,dd,p,figure,img,pre,table,fieldset,blockquote,picture,div):where(:not(:first-child)){margin-block:var(--vui-prose-gap-blocks)}&>:is(h1,h2,h3,h4,h5,h6)+*{margin-block-start:var(--vui-prose-gap-heading-start)}&>:is(h1,h2,h3,h4,h5,h6){margin-block-end:var(--vui-prose-gap-heading-end);text-box:trim-both cap alphabetic}}}
1
+ @layer viraui.preflight, viraui.components, viraui.overrides;@layer viraui.components{@property --vui-prose-align{syntax:"*";inherits:false;initial-value:start}@property --vui-prose-wrap{syntax:"*";inherits:true;initial-value:pretty}@property --vui-prose-gap-blocks{syntax:"<length>";inherits:true;initial-value:2em}@property --vui-prose-gap-heading-start{syntax:"<length>";inherits:true;initial-value:1.3em}@property --vui-prose-gap-heading-end{syntax:"<length>";inherits:true;initial-value:.8em}.viraui__prose-module__Prose_8yO9h{--vui-prose-gap-blocks:2em;--vui-prose-gap-heading-start:1.3em;--vui-prose-gap-heading-end:0.8em;&[data-prose-gap=s]{--vui-prose-gap-blocks:1em;--vui-prose-gap-heading-start:0.7em;--vui-prose-gap-heading-end:0.3em}&[data-prose-gap=m]{--vui-prose-gap-blocks:1.5em;--vui-prose-gap-heading-start:1em;--vui-prose-gap-heading-end:0.6em}text-wrap:var(--vui-prose-wrap);&[data-prose-has-align=true]{text-align:var(--vui-prose-align)}&>:is(h1,h2,h3,h4,h5,h6,hgroup,ul,ol,dd,p,figure,img,pre,table,fieldset,blockquote,picture,div):where(:not(:first-child)){margin-block:var(--vui-prose-gap-blocks)}&>:is(h1,h2,h3,h4,h5,h6)+*{margin-block-start:var(--vui-prose-gap-heading-start)}&>:is(h1,h2,h3,h4,h5,h6){margin-block-end:var(--vui-prose-gap-heading-end);text-box:trim-both cap alphabetic}}}
@@ -25,6 +25,14 @@ export type ProseProps = React.ComponentPropsWithoutRef<'div'> & {
25
25
  * @defaultValue Inherits parent `text-align`.
26
26
  */
27
27
  align?: React.CSSProperties['textAlign'];
28
+ /**
29
+ * Controls CSS `text-wrap` on the Prose root (inherits to descendants unless a child overrides).
30
+ * Default `pretty` for orphan-aware article walls. Prefer `balance` only on short multi-line
31
+ * blocks that need even line lengths. Single-line metrics stay on child Text/Title `whiteSpace`.
32
+ *
33
+ * @defaultValue 'pretty'
34
+ */
35
+ wrap?: React.CSSProperties['textWrap'];
28
36
  /**
29
37
  * Replaces the default `div` root using Base UI render semantics.
30
38
  *
@@ -4,10 +4,11 @@ import { clsx } from "../../core/clsx.js";
4
4
  import prose_module_default from "./prose.module.js";
5
5
  import { useRender } from "@base-ui/react/use-render";
6
6
  //#region src/components/prose/prose.tsx
7
- var Prose = ({ align, className, gap = "l", ref, render, style, ...otherProps }) => {
7
+ var Prose = ({ align, className, gap = "l", ref, render, style, wrap = "pretty", ...otherProps }) => {
8
8
  const hasAlign = align !== void 0;
9
9
  const dynamicStyle = {
10
10
  ...hasAlign && { "--vui-prose-align": align },
11
+ "--vui-prose-wrap": wrap,
11
12
  ...style
12
13
  };
13
14
  return useRender({
@@ -1 +1 @@
1
- @layer viraui.preflight, viraui.components, viraui.overrides;@layer viraui.components{@property --vui-select-input-height{syntax:"<length>";inherits:true;initial-value:0}@property --vui-select-control-group-background{syntax:"<color>";inherits:true;initial-value:#0000}@property --vui-select-control-group-color{syntax:"<color>";inherits:true;initial-value:#0000}@property --vui-select-control-group-border-color{syntax:"<color>";inherits:true;initial-value:#0000}@property --vui-select-control-group-border-radius{syntax:"<length-percentage>";inherits:true;initial-value:0}@property --vui-select-trigger-padding-inline-start{syntax:"<length>";inherits:true;initial-value:0}@property --vui-select-trigger-padding-inline-end{syntax:"<length>";inherits:true;initial-value:0}@property --vui-select-list-border-radius{syntax:"<length-percentage>";inherits:true;initial-value:0}@property --vui-select-list-padding{syntax:"<length>";inherits:true;initial-value:0}@property --__select-list-appear-offset{syntax:"<length>";inherits:false;initial-value:8px}.viraui__select-module__Select_eXv4Y{--vui-select-input-height:var(--space-2xl);--vui-select-control-group-background:var(--base-1);--vui-select-control-group-color:var(--global-foreground);--vui-select-control-group-border-color:var(--global-contrast);--vui-select-control-group-border-radius:var(--radius-m);--vui-select-trigger-padding-inline-start:calc(var(--space-s) + var(--space-xs));--vui-select-trigger-padding-inline-end:var(--space-xs);--vui-field-label-padding-inline:calc((var(--vui-select-control-group-border-radius) + 0px) / 2);max-block-size:min-content;z-index:0;&:has([required]) .viraui__select-module__Label_-Y1fR{&:after{content:" *";color:var(--highlight-red)}&:dir(rtl){&:after{content:none}&:before{content:"* ";color:var(--highlight-red)}}}&[data-invalid]>.viraui__select-module__Trigger_-wBsg:not(:disabled):not([data-disabled]){--vui-select-control-group-border-color:var(--highlight-red);box-shadow:none;outline-color:oklab(from var(--highlight-red) l a b/.5)}}.viraui__select-module__Trigger_-wBsg{box-sizing:border-box;inline-size:100%;block-size:round(to-zero,var(--vui-select-input-height),2px);padding-inline:var(--vui-select-trigger-padding-inline-start) var(--vui-select-trigger-padding-inline-end);border:1px solid var(--vui-select-control-group-border-color);border-radius:var(--vui-select-control-group-border-radius);background:var(--vui-select-control-group-background);color:var(--vui-select-control-group-color);font:inherit;text-align:start;cursor:pointer;transition:background var(--duration-instant) var(--easing-standard);&:not([data-disabled],:disabled):hover{--vui-select-control-group-background:var(--base-2)}&[data-popup-open]{outline:none}&:disabled,&[data-disabled]{--vui-select-control-group-background:var(--global-disabled-background);--vui-select-control-group-border-color:#0000;--vui-select-control-group-color:var(--global-disabled-foreground);box-shadow:none;cursor:not-allowed}}.viraui__select-module__Icon_EOwki{font-size:var(--font-scale-body-s);pointer-events:none}.viraui__select-module__Description_OmwmV{padding-inline:calc((var(--vui-select-control-group-border-radius) + 0px) / 2)}.viraui__select-module__SelectPopup_UzGXL{--vui-select-list-border-radius:var(--radius-m);--vui-select-list-padding:var(--space-xs);box-sizing:border-box;min-inline-size:var(--anchor-width);overflow:visible;color:var(--global-foreground);outline:none;position:relative;transform-origin:var(--transform-origin);transition:opacity var(--duration-instant) var(--easing-entrance),scale var(--duration-instant) var(--easing-entrance),translate var(--duration-instant) var(--easing-entrance);&[data-ending-style],&[data-starting-style]{opacity:0;scale:.96}&[data-side=bottom][data-ending-style],&[data-side=bottom][data-starting-style]{translate:0 calc(var(--__select-list-appear-offset) * -1)}&[data-side=top][data-ending-style],&[data-side=top][data-starting-style]{translate:0 var(--__select-list-appear-offset)}&[data-side=inline-start][data-ending-style],&[data-side=inline-start][data-starting-style],&[data-side=left][data-ending-style],&[data-side=left][data-starting-style]{translate:var(--__select-list-appear-offset) 0}&[data-side=inline-end][data-ending-style],&[data-side=inline-end][data-starting-style],&[data-side=right][data-ending-style],&[data-side=right][data-starting-style]{translate:calc(var(--__select-list-appear-offset) * -1) 0}&[data-side=none]{transition:none;scale:1;translate:0;opacity:1}}.viraui__select-module__ScrollArrow_kHlEi{position:absolute;inset-inline:0;z-index:1;inline-size:100%;block-size:var(--space-l);cursor:default;background:var(--base-1);border:1px solid var(--global-contrast);@container root not style(--effect-vibrancy: initial){background:oklab(from var(--base-1) l a b/80%);backdrop-filter:brightness(var(--vibrancy-brightness)) blur(calc(var(--vibrancy-blur) * 1px))}}.viraui__select-module__ScrollButton_sHBOa{pointer-events:none}.viraui__select-module__ScrollArrowUp_DGXS-{inset-block-start:0;border-radius:var(--vui-select-list-border-radius) var(--vui-select-list-border-radius) 0 0}.viraui__select-module__ScrollArrowDown_vhJy0{inset-block-end:0;border-radius:0 0 var(--vui-select-list-border-radius) var(--vui-select-list-border-radius)}.viraui__select-module__List_jdUWx{box-sizing:border-box;inline-size:100%;max-block-size:var(--available-height);scroll-padding-block:var(--vui-select-list-padding);overscroll-behavior:contain;&:focus,&:focus-visible{outline:none}}.viraui__select-module__Indicator_YNUuz{min-inline-size:var(--space-m);min-block-size:var(--space-m);inline-size:fit-content;block-size:fit-content;color:var(--global-foreground);opacity:0;transition:opacity var(--duration-fast) var(--easing-standard),transform var(--duration-fast) var(--easing-standard);&[data-selected]{opacity:1}}}@layer viraui.overrides{.viraui__select-module__Value_uWHPX{overflow:hidden;display:block;text-overflow:ellipsis;&[data-placeholder]{color:var(--global-disabled-foreground)}}.viraui__select-module__Option_KgYqz{cursor:pointer;&:focus{outline:none}&:focus-visible{outline:none;box-shadow:none}&:not([data-disabled]):hover,&:not([data-disabled])[data-highlighted]{background:var(--global-contrast);@container root not style(--effect-vibrancy: initial){background:oklab(from var(--global-contrast) l a b/8%)}}&:not([data-disabled],:hover)[data-selected]{background:light-dark(oklab(from var(--global-contrast) l a b/8%),oklab(from var(--global-contrast) l a b/5%))}&[data-disabled]{color:var(--global-disabled-foreground);cursor:not-allowed}}}
1
+ @layer viraui.preflight, viraui.components, viraui.overrides;@layer viraui.components{@property --vui-select-input-height{syntax:"<length>";inherits:true;initial-value:0}@property --vui-select-control-group-background{syntax:"<color>";inherits:true;initial-value:#0000}@property --vui-select-control-group-color{syntax:"<color>";inherits:true;initial-value:#0000}@property --vui-select-control-group-border-color{syntax:"<color>";inherits:true;initial-value:#0000}@property --vui-select-control-group-border-radius{syntax:"<length-percentage>";inherits:true;initial-value:0}@property --vui-select-trigger-padding-inline-start{syntax:"<length>";inherits:true;initial-value:0}@property --vui-select-trigger-padding-inline-end{syntax:"<length>";inherits:true;initial-value:0}@property --vui-select-list-border-radius{syntax:"<length-percentage>";inherits:true;initial-value:0}@property --vui-select-list-padding{syntax:"<length>";inherits:true;initial-value:0}@property --__select-list-appear-offset{syntax:"<length>";inherits:false;initial-value:8px}.viraui__select-module__Select_eXv4Y{--vui-select-input-height:var(--space-2xl);--vui-select-control-group-background:var(--base-1);--vui-select-control-group-color:var(--global-foreground);--vui-select-control-group-border-color:var(--global-contrast);--vui-select-control-group-border-radius:var(--radius-m);--vui-select-trigger-padding-inline-start:calc(var(--space-s) + var(--space-xs));--vui-select-trigger-padding-inline-end:var(--space-xs);--vui-field-label-padding-inline:calc((var(--vui-select-control-group-border-radius) + 0px) / 2);max-block-size:min-content;z-index:0;&:has([required]) .viraui__select-module__Label_-Y1fR{&:after{content:" *";color:var(--highlight-red)}&:dir(rtl){&:after{content:none}&:before{content:"* ";color:var(--highlight-red)}}}&[data-invalid]>.viraui__select-module__Trigger_-wBsg:not(:disabled):not([data-disabled]){--vui-select-control-group-border-color:var(--highlight-red);box-shadow:none;outline-color:oklab(from var(--highlight-red) l a b/.5)}}.viraui__select-module__Trigger_-wBsg{box-sizing:border-box;inline-size:100%;block-size:round(to-zero,var(--vui-select-input-height),2px);padding-inline:var(--vui-select-trigger-padding-inline-start) var(--vui-select-trigger-padding-inline-end);border:1px solid var(--vui-select-control-group-border-color);border-radius:var(--vui-select-control-group-border-radius);background:var(--vui-select-control-group-background);color:var(--vui-select-control-group-color);font:inherit;text-align:start;cursor:pointer;transition:background var(--duration-instant) var(--easing-standard);&:not([data-disabled],:disabled):hover{--vui-select-control-group-background:var(--base-2)}&[data-popup-open]{outline:none}&:disabled,&[data-disabled]{--vui-select-control-group-background:var(--global-disabled-background);--vui-select-control-group-border-color:#0000;--vui-select-control-group-color:var(--global-disabled-foreground);box-shadow:none;cursor:not-allowed}}.viraui__select-module__Icon_EOwki{font-size:var(--font-scale-body-s);pointer-events:none}.viraui__select-module__Description_OmwmV{padding-inline:calc((var(--vui-select-control-group-border-radius) + 0px) / 2)}.viraui__select-module__SelectPopup_UzGXL{--vui-select-list-border-radius:var(--radius-m);--vui-select-list-padding:var(--space-xs);box-sizing:border-box;min-inline-size:var(--anchor-width);overflow:visible;color:var(--global-foreground);outline:none;position:relative;transform-origin:var(--transform-origin);transition:opacity var(--duration-instant) var(--easing-entrance),scale var(--duration-instant) var(--easing-entrance),translate var(--duration-instant) var(--easing-entrance);&[data-ending-style],&[data-starting-style]{opacity:0;scale:.96}&[data-side=bottom][data-ending-style],&[data-side=bottom][data-starting-style]{translate:0 calc(var(--__select-list-appear-offset) * -1)}&[data-side=top][data-ending-style],&[data-side=top][data-starting-style]{translate:0 var(--__select-list-appear-offset)}&[data-side=inline-start][data-ending-style],&[data-side=inline-start][data-starting-style],&[data-side=left][data-ending-style],&[data-side=left][data-starting-style]{translate:var(--__select-list-appear-offset) 0}&[data-side=inline-end][data-ending-style],&[data-side=inline-end][data-starting-style],&[data-side=right][data-ending-style],&[data-side=right][data-starting-style]{translate:calc(var(--__select-list-appear-offset) * -1) 0}&[data-side=none]{transition:none;scale:1;translate:0;opacity:1}}.viraui__select-module__ScrollArrow_kHlEi{position:absolute;inset-inline:0;z-index:1;inline-size:100%;block-size:var(--space-l);cursor:default;background:var(--base-1);border:1px solid var(--global-contrast);@container root not style(--effect-vibrancy: initial){background:oklab(from var(--base-1) l a b/80%);backdrop-filter:blur(calc(var(--vibrancy-blur) * 1px))}}.viraui__select-module__ScrollButton_sHBOa{pointer-events:none}.viraui__select-module__ScrollArrowUp_DGXS-{inset-block-start:0;border-radius:var(--vui-select-list-border-radius) var(--vui-select-list-border-radius) 0 0}.viraui__select-module__ScrollArrowDown_vhJy0{inset-block-end:0;border-radius:0 0 var(--vui-select-list-border-radius) var(--vui-select-list-border-radius)}.viraui__select-module__List_jdUWx{box-sizing:border-box;inline-size:100%;max-block-size:var(--available-height);scroll-padding-block:var(--vui-select-list-padding);overscroll-behavior:contain;&:focus,&:focus-visible{outline:none}}.viraui__select-module__Indicator_YNUuz{min-inline-size:var(--space-m);min-block-size:var(--space-m);inline-size:fit-content;block-size:fit-content;color:var(--global-foreground);opacity:0;transition:opacity var(--duration-fast) var(--easing-standard),transform var(--duration-fast) var(--easing-standard);&[data-selected]{opacity:1}}}@layer viraui.overrides{.viraui__select-module__Value_uWHPX{overflow:hidden;display:block;text-overflow:ellipsis;&[data-placeholder]{color:var(--global-disabled-foreground)}}.viraui__select-module__Option_KgYqz{cursor:pointer;&:focus{outline:none}&:focus-visible{outline:none;box-shadow:none}&:not([data-disabled]):hover,&:not([data-disabled])[data-highlighted]{background:var(--global-contrast);@container root not style(--effect-vibrancy: initial){background:oklab(from var(--global-contrast) l a b/8%)}}&:not([data-disabled],:hover)[data-selected]{background:light-dark(oklab(from var(--global-contrast) l a b/8%),oklab(from var(--global-contrast) l a b/5%))}&[data-disabled]{color:var(--global-disabled-foreground);cursor:not-allowed}}}
@@ -1 +1 @@
1
- @layer viraui.preflight, viraui.components, viraui.overrides;@layer viraui.components{@property --vui-stack-row-gap{syntax:"<length>";inherits:false;initial-value:0}@property --vui-stack-column-gap{syntax:"<length>";inherits:false;initial-value:0}@property --vui-stack-h-align{syntax:"*";inherits:false;initial-value:initial}@property --vui-stack-v-align{syntax:"*";inherits:false;initial-value:initial}@property --vui-stack-padding-inline-start{syntax:"<length>";inherits:false;initial-value:0}@property --vui-stack-padding-inline-end{syntax:"<length>";inherits:false;initial-value:0}@property --vui-stack-padding-block-start{syntax:"<length>";inherits:false;initial-value:0}@property --vui-stack-padding-block-end{syntax:"<length>";inherits:false;initial-value:0}@property --vui-stack-max-width{syntax:"*";inherits:false;initial-value:none}@property --vui-stack-min-width{syntax:"*";inherits:false;initial-value:none}.viraui__stack-module__Stack_NR-Ey{display:flex;gap:var(--vui-stack-row-gap) var(--vui-stack-column-gap);flex-direction:column;align-items:var(--vui-stack-h-align);justify-content:var(--vui-stack-v-align);max-inline-size:var(--vui-stack-max-width);min-inline-size:var(--vui-stack-min-width);&[data-stack-direction=column-reverse]{flex-direction:column-reverse}&[data-stack-direction=row-reverse],&[data-stack-direction=row]{align-items:var(--vui-stack-v-align);justify-content:var(--vui-stack-h-align)}&[data-stack-direction=row]{flex-direction:row}&[data-stack-direction=row-reverse]{flex-direction:row-reverse}&[data-stack-inline=true]{display:inline-flex;flex-grow:0}:where(&[data-stack-wrap=true]){flex-wrap:wrap}:where(&[data-stack-has-padding=true]){padding:var(--vui-stack-padding-block-start) var(--vui-stack-padding-inline-end) var(--vui-stack-padding-block-end) var(--vui-stack-padding-inline-start)}:where(&[data-stack-expand-children=true]>*){flex-grow:var(--vira-flex-grow,1)}&[data-stack-full-width=true]{inline-size:100%}&[data-stack-container=true]{container:stack/inline-size}}}
1
+ @layer viraui.preflight, viraui.components, viraui.overrides;@layer viraui.components{@property --vui-stack-row-gap{syntax:"<length>";inherits:false;initial-value:0}@property --vui-stack-column-gap{syntax:"<length>";inherits:false;initial-value:0}@property --vui-stack-h-align{syntax:"*";inherits:false;initial-value:initial}@property --vui-stack-v-align{syntax:"*";inherits:false;initial-value:initial}@property --vui-stack-padding-inline-start{syntax:"<length>";inherits:false;initial-value:0}@property --vui-stack-padding-inline-end{syntax:"<length>";inherits:false;initial-value:0}@property --vui-stack-padding-block-start{syntax:"<length>";inherits:false;initial-value:0}@property --vui-stack-padding-block-end{syntax:"<length>";inherits:false;initial-value:0}@property --vui-stack-max-width{syntax:"*";inherits:false;initial-value:none}@property --vui-stack-min-width{syntax:"*";inherits:false;initial-value:none}.viraui__stack-module__Stack_NR-Ey{display:flex;gap:var(--vui-stack-row-gap) var(--vui-stack-column-gap);flex-direction:column;align-items:var(--vui-stack-h-align);justify-content:var(--vui-stack-v-align);max-inline-size:var(--vui-stack-max-width);min-inline-size:var(--vui-stack-min-width);&[data-stack-direction=column-reverse]{flex-direction:column-reverse}&[data-stack-direction=row-reverse],&[data-stack-direction=row]{align-items:var(--vui-stack-v-align);justify-content:var(--vui-stack-h-align)}&[data-stack-direction=row]{flex-direction:row}&[data-stack-direction=row-reverse]{flex-direction:row-reverse}&[data-stack-inline=true]{display:inline-flex;flex-grow:0}:where(&[data-stack-wrap=true]){flex-wrap:wrap}:where(&[data-stack-has-padding=true]){padding:var(--vui-stack-padding-block-start) var(--vui-stack-padding-inline-end) var(--vui-stack-padding-block-end) var(--vui-stack-padding-inline-start)}:where(&[data-stack-expand-children=true]>*){flex-grow:var(--vira-flex-grow,1)}&[data-stack-full-width=true]{inline-size:100%}&[data-stack-full-height=true]{block-size:100%}&[data-stack-container=true]{container:stack/inline-size}}}
@@ -47,8 +47,9 @@ export type StackProps = React.ComponentPropsWithoutRef<'div'> & {
47
47
  * Makes direct children grow along the flex main axis (`flex-grow`).
48
48
  *
49
49
  * Prefer for equal-width row actions instead of inventing width/flex CSS on each child.
50
- * Does not set the stack root's own inline size — use `fullWidth` when this stack must
51
- * fill its parent width (e.g. centered shell with `maxWidth`, or a full-bleed Button column).
50
+ * Cross-axis fill stays on `hAlign` / `vAlign="stretch"` (which prop is cross depends on
51
+ * `direction`). Does not size this root — use `fullWidth` / `fullHeight` when the Stack must
52
+ * fill its parent first so stretch has room.
52
53
  *
53
54
  * @defaultValue false
54
55
  */
@@ -59,11 +60,22 @@ export type StackProps = React.ComponentPropsWithoutRef<'div'> & {
59
60
  * Prefer this (with cross-axis stretch) so content-sized children like Button span a panel —
60
61
  * do not add `width: 100%` CSS on those children.
61
62
  * Use with `maxWidth` under a parent `hAlign="center"` for a fluid, capped, centered shell.
62
- * Orthogonal to `expandChildren` (self size vs children grow).
63
+ * Orthogonal to `expandChildren` (self size vs children grow). Pair with `fullHeight` when the
64
+ * root must fill both parent axes.
63
65
  *
64
66
  * @defaultValue false
65
67
  */
66
68
  fullWidth?: boolean;
69
+ /**
70
+ * Sets `block-size: 100%` on the stack root so it fills the parent's block size.
71
+ *
72
+ * Prefer this over `style`/`className` `height` / `block-size: 100%` on this Stack.
73
+ * Pair with `expandChildren` and cross-axis `hAlign`/`vAlign="stretch"` so children fill both
74
+ * axes without per-child size CSS. Orthogonal to `expandChildren` and `fullWidth`.
75
+ *
76
+ * @defaultValue false
77
+ */
78
+ fullHeight?: boolean;
67
79
  /**
68
80
  * Sets the gap between flex rows using the Vira space token scale.
69
81
  *
@@ -5,7 +5,7 @@ import { resolveAxisPadding } from "../../core/styles/resolve-axis-padding.js";
5
5
  import stack_module_default from "./stack.module.js";
6
6
  import { useRender } from "@base-ui/react/use-render";
7
7
  //#region src/components/stack/stack.tsx
8
- var Stack = ({ className, direction = "column", expandChildren = false, fullWidth = false, hAlign = "initial", hPadding, inline = false, maxWidth, minWidth, enableContainer, ref, render, rowGap, columnGap, style, vAlign = "initial", vPadding, wrap = false, ...otherProps }) => {
8
+ var Stack = ({ className, direction = "column", expandChildren = false, fullHeight = false, fullWidth = false, hAlign = "initial", hPadding, inline = false, maxWidth, minWidth, enableContainer, ref, render, rowGap, columnGap, style, vAlign = "initial", vPadding, wrap = false, ...otherProps }) => {
9
9
  const hasPadding = Boolean(hPadding || vPadding);
10
10
  const dynamicStyle = {
11
11
  "--vui-stack-row-gap": resolveThemeValue(rowGap, "space", 0),
@@ -30,6 +30,7 @@ var Stack = ({ className, direction = "column", expandChildren = false, fullWidt
30
30
  "data-stack-wrap": wrap ? "true" : "false",
31
31
  "data-stack-expand-children": expandChildren ? "true" : "false",
32
32
  "data-stack-full-width": fullWidth ? "true" : "false",
33
+ "data-stack-full-height": fullHeight ? "true" : "false",
33
34
  "data-stack-has-padding": hasPadding ? "true" : "false",
34
35
  className: clsx(stack_module_default.Stack, className),
35
36
  style: dynamicStyle
@@ -4,4 +4,4 @@
4
4
  )}&[data-surface-hover-color=primary]{--vui-surface-background-hover:light-dark(
5
5
  oklab(from var(--global-primary) l a b / 20%),
6
6
  oklab(from var(--global-primary) l a b / 10%)
7
- )}@container root not style(--effect-vibrancy: initial){&[data-vibrant]{background:oklab(from var(--global-background) l a b/80%)}&[data-vibrant][data-surface-has-color=true]{background:oklab(from var(--vui-surface-background) l a b/80%)}}&[data-surface-has-padding=true]{padding:var(--vui-surface-padding-block-start) var(--vui-surface-padding-inline-end) var(--vui-surface-padding-block-end) var(--vui-surface-padding-inline-start)}&[data-surface-border]{border-style:var(--vui-surface-border-style);border-color:var(--global-contrast);border-left-width:0;border-bottom-width:0;border-right-width:0;border-top-width:0}&[data-surface-border~=all]{border-width:1px}&[data-surface-border~=top]{border-top-width:1px}&[data-surface-border~=right]{border-right-width:1px}&[data-surface-border~=bottom]{border-bottom-width:1px}&[data-surface-border~=left]{border-left-width:1px}@media (hover:hover) and (pointer:fine){&[data-surface-has-hover-color=true]:hover{background:var(--vui-surface-background-hover)}}&[data-surface-container=true]{container:surface/inline-size}}}
7
+ )}@container root not style(--effect-vibrancy: initial){&[data-vibrant]{background:#0000}&[data-vibrant][data-surface-has-color=true]{background:oklab(from var(--vui-surface-background) l a b/80%)}}&[data-surface-has-padding=true]{padding:var(--vui-surface-padding-block-start) var(--vui-surface-padding-inline-end) var(--vui-surface-padding-block-end) var(--vui-surface-padding-inline-start)}&[data-surface-border]{border-style:var(--vui-surface-border-style);border-color:var(--global-contrast);border-left-width:0;border-bottom-width:0;border-right-width:0;border-top-width:0}&[data-surface-border~=all]{border-width:1px}&[data-surface-border~=top]{border-top-width:1px}&[data-surface-border~=right]{border-right-width:1px}&[data-surface-border~=bottom]{border-bottom-width:1px}&[data-surface-border~=left]{border-left-width:1px}@media (hover:hover) and (pointer:fine){&[data-surface-has-hover-color=true]:hover{background:var(--vui-surface-background-hover)}}&[data-surface-container=true]{container:surface/inline-size}}}
@@ -1,5 +1,5 @@
1
- @layer viraui.preflight, viraui.components, viraui.overrides;@layer viraui.components{@property --vui-text-align{syntax:"*";inherits:false;initial-value:start}@property --vui-text-max-width{syntax:"*";inherits:false;initial-value:none}@property --vui-text-literal-color{syntax:"<color>";inherits:false;initial-value:#0000}@property --vui-text-white-space{syntax:"*";inherits:false;initial-value:normal}@property --vui-text-letter-spacing{syntax:"normal | <length>";inherits:false;initial-value:normal}@property --vui-text-text-transform{syntax:"none | capitalize | uppercase | lowercase";inherits:false;initial-value:none}@property --vui-text-font-weight{syntax:"<number>";inherits:false;initial-value:400}@property --vui-text-font-width{syntax:"<number>";inherits:false;initial-value:100}@property --vui-text-font-opsz{syntax:"<number>";inherits:false;initial-value:16}@property --vui-text-trim{syntax:"*";inherits:false;initial-value:trim-both}@property --vui-text-trim-type{syntax:"*";inherits:false;initial-value:cap alphabetic}@property --vui-text-padding-inline-start{syntax:"<length>";inherits:false;initial-value:0}@property --vui-text-padding-inline-end{syntax:"<length>";inherits:false;initial-value:0}@property --vui-text-padding-block-start{syntax:"<length>";inherits:false;initial-value:0}@property --vui-text-padding-block-end{syntax:"<length>";inherits:false;initial-value:0}@property --vui-text-font-size{syntax:"<length>";inherits:false;initial-value:1rem}@property --vui-text-font-family{syntax:"*";inherits:false;initial-value:sans-serif}@property --vui-text-line-height{syntax:"normal | <number> | <length-percentage>";inherits:false;initial-value:normal}@property --__text-fluid{syntax:"<number>";inherits:false;initial-value:0}@property --__text-size-min{syntax:"<length>";inherits:false;initial-value:1rem}@property --__text-size-max{syntax:"<length>";inherits:false;initial-value:1rem}.viraui__text-module__Text_bS8kv{--__text-fluid:calc((100vi - 320px) / 1125px);--__text-size-min:var(--font-scale-body-s);--__text-size-max:var(--font-scale-body-m);--vui-text-font-size:clamp(
1
+ @layer viraui.preflight, viraui.components, viraui.overrides;@layer viraui.components{@property --vui-text-align{syntax:"*";inherits:false;initial-value:start}@property --vui-text-max-width{syntax:"*";inherits:false;initial-value:none}@property --vui-text-literal-color{syntax:"<color>";inherits:false;initial-value:#0000}@property --vui-text-white-space{syntax:"*";inherits:false;initial-value:normal}@property --vui-text-wrap{syntax:"*";inherits:false;initial-value:pretty}@property --vui-text-letter-spacing{syntax:"normal | <length>";inherits:false;initial-value:normal}@property --vui-text-text-transform{syntax:"none | capitalize | uppercase | lowercase";inherits:false;initial-value:none}@property --vui-text-font-weight{syntax:"<number>";inherits:false;initial-value:400}@property --vui-text-font-width{syntax:"<number>";inherits:false;initial-value:100}@property --vui-text-font-opsz{syntax:"<number>";inherits:false;initial-value:16}@property --vui-text-trim{syntax:"*";inherits:false;initial-value:trim-both}@property --vui-text-trim-type{syntax:"*";inherits:false;initial-value:cap alphabetic}@property --vui-text-padding-inline-start{syntax:"<length>";inherits:false;initial-value:0}@property --vui-text-padding-inline-end{syntax:"<length>";inherits:false;initial-value:0}@property --vui-text-padding-block-start{syntax:"<length>";inherits:false;initial-value:0}@property --vui-text-padding-block-end{syntax:"<length>";inherits:false;initial-value:0}@property --vui-text-font-size{syntax:"<length>";inherits:false;initial-value:1rem}@property --vui-text-font-family{syntax:"*";inherits:false;initial-value:sans-serif}@property --vui-text-line-height{syntax:"normal | <number> | <length-percentage>";inherits:false;initial-value:normal}@property --__text-fluid{syntax:"<number>";inherits:false;initial-value:0}@property --__text-size-min{syntax:"<length>";inherits:false;initial-value:1rem}@property --__text-size-max{syntax:"<length>";inherits:false;initial-value:1rem}.viraui__text-module__Text_bS8kv{--__text-fluid:calc((100vi - 320px) / 1125px);--__text-size-min:var(--font-scale-body-s);--__text-size-max:var(--font-scale-body-m);--vui-text-font-size:clamp(
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);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-align=true]{text-align:var(--vui-text-align)}&[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-min:var(--font-scale-body-s);--__text-size-max:var(--font-scale-body-s)}&[data-text-size=xs]{--__text-size-min:var(--font-scale-body-xs);--__text-size-max:var(--font-scale-body-xs)}& .viraui__text-module__Text_bS8kv:not([data-text-size]){font-size:inherit}& .viraui__text-module__Text_bS8kv:not([data-text-line-height]){line-height:inherit}&[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)}}}
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);letter-spacing:var(--vui-text-letter-spacing);text-transform:var(--vui-text-text-transform);text-wrap:var(--vui-text-wrap);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-selection=false]{-webkit-user-select:none;user-select:none}&[data-text-has-align=true]{text-align:var(--vui-text-align)}&[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-min:var(--font-scale-body-s);--__text-size-max:var(--font-scale-body-s)}&[data-text-size=xs]{--__text-size-min:var(--font-scale-body-xs);--__text-size-max:var(--font-scale-body-xs)}& .viraui__text-module__Text_bS8kv:not([data-text-size]){font-size:inherit}& .viraui__text-module__Text_bS8kv:not([data-text-line-height]){line-height:inherit}&[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)}}}
@@ -85,7 +85,9 @@ export type TextProps = React.ComponentPropsWithoutRef<'span'> & {
85
85
  */
86
86
  maxWidth?: string;
87
87
  /**
88
- * Controls white-space preservation and wrapping behavior.
88
+ * Controls white-space collapse/preserve (`white-space`).
89
+ * Prefer `whiteSpace="nowrap"` for single-line metrics/chrome (also collapses spaces).
90
+ * For wrapping algorithm / even line lengths use `wrap` (`text-wrap`) — not this prop.
89
91
  *
90
92
  * @defaultValue 'normal'
91
93
  */
@@ -105,13 +107,14 @@ export type TextProps = React.ComponentPropsWithoutRef<'span'> & {
105
107
  */
106
108
  transform?: React.CSSProperties['textTransform'];
107
109
  /**
108
- * Enables balanced wrapping for block-like copy.
109
- * Prefer on short wrapping UI paragraphs (hero lead, empty state, card blurb);
110
- * omit when single-line or intentional ragged.
110
+ * Controls CSS `text-wrap` (wrapping algorithm / wrap on-off).
111
+ * Default `pretty` for orphan-aware UI copy. Prefer `balance` on short multi-line
112
+ * heads/blurbs that need even line lengths. Use `wrap="nowrap"` only when you need
113
+ * no wrap without changing white-space collapse; prefer `whiteSpace="nowrap"` for metrics.
111
114
  *
112
- * @defaultValue false
115
+ * @defaultValue 'pretty'
113
116
  */
114
- balanced?: boolean;
117
+ wrap?: React.CSSProperties['textWrap'];
115
118
  /**
116
119
  * Enables text selection on the rendered copy.
117
120
  *
@@ -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, balanced = false, selection = true, className, color, family = "body", fluid = false, fontWidth, hPadding, lineHeight, maxWidth, opticalSize, ref, render, size, style, tone, tracking, transform, trim = "both", trimType = "cap alphabetic", vPadding, weight = "regular", whiteSpace = "normal", ...otherProps }) => {
7
+ var Text = ({ align, selection = true, className, color, family = "body", fluid = false, fontWidth, hPadding, lineHeight, maxWidth, opticalSize, ref, render, size, style, tone, tracking, transform, trim = "both", trimType = "cap alphabetic", vPadding, weight = "regular", whiteSpace = "normal", wrap = "pretty", ...otherProps }) => {
8
8
  const hasAlign = align !== void 0;
9
9
  const hasPadding = Boolean(hPadding || vPadding);
10
10
  const dynamicStyle = {
@@ -12,6 +12,7 @@ var Text = ({ align, balanced = false, selection = true, className, color, famil
12
12
  "--vui-text-max-width": maxWidth ?? "none",
13
13
  "--vui-text-literal-color": color,
14
14
  "--vui-text-white-space": whiteSpace,
15
+ "--vui-text-wrap": wrap,
15
16
  "--vui-text-letter-spacing": tracking,
16
17
  "--vui-text-text-transform": transform,
17
18
  "--vui-text-trim": trim ? `trim-${trim}` : "none",
@@ -34,7 +35,6 @@ var Text = ({ align, balanced = false, selection = true, className, color, famil
34
35
  "data-text-weight": typeof weight === "string" ? weight : "custom",
35
36
  "data-text-tone": tone,
36
37
  "data-text-line-height": lineHeight,
37
- "data-text-balanced": balanced ? "true" : "false",
38
38
  "data-text-selection": selection ? "true" : "false",
39
39
  "data-text-fluid": fluid ? "true" : "false",
40
40
  "data-text-has-align": hasAlign ? "true" : "false",
@@ -1,5 +1,5 @@
1
- @layer viraui.preflight, viraui.components, viraui.overrides;@layer viraui.components{@property --vui-title-align{syntax:"*";inherits:false;initial-value:start}@property --vui-title-max-width{syntax:"*";inherits:false;initial-value:none}@property --vui-title-literal-color{syntax:"<color>";inherits:false;initial-value:#0000}@property --vui-title-white-space{syntax:"*";inherits:false;initial-value:normal}@property --vui-title-font-weight{syntax:"<number>";inherits:false;initial-value:500}@property --vui-title-font-width{syntax:"<number>";inherits:false;initial-value:100}@property --vui-title-font-opsz{syntax:"<number>";inherits:false;initial-value:16}@property --vui-title-trim{syntax:"*";inherits:false;initial-value:trim-both}@property --vui-title-trim-type{syntax:"*";inherits:false;initial-value:cap alphabetic}@property --vui-title-padding-inline-start{syntax:"<length>";inherits:false;initial-value:0}@property --vui-title-padding-inline-end{syntax:"<length>";inherits:false;initial-value:0}@property --vui-title-padding-block-start{syntax:"<length>";inherits:false;initial-value:0}@property --vui-title-padding-block-end{syntax:"<length>";inherits:false;initial-value:0}@property --vui-title-font-size{syntax:"<length>";inherits:false;initial-value:1rem}@property --vui-title-line-height{syntax:"normal | <number> | <length-percentage>";inherits:false;initial-value:normal}@property --vui-title-letter-spacing{syntax:"normal | <length>";inherits:false;initial-value:normal}@property --__title-letter-spacing{syntax:"normal | <length>";inherits:false;initial-value:normal}@property --vui-title-text-transform{syntax:"none | capitalize | uppercase | lowercase";inherits:false;initial-value:none}@property --vui-title-font-family{syntax:"*";inherits:false;initial-value:sans-serif}@property --__title-fluid{syntax:"<number>";inherits:false;initial-value:0}@property --__title-size-min{syntax:"<length>";inherits:false;initial-value:1rem}@property --__title-size-max{syntax:"<length>";inherits:false;initial-value:1rem}.viraui__title-module__Title_CXMUX{--__title-fluid:calc((100vi - 320px) / 1125px);--__title-size-min:var(--font-scale-h2);--__title-size-max:var(--font-scale-h1);--vui-title-font-size:clamp(
1
+ @layer viraui.preflight, viraui.components, viraui.overrides;@layer viraui.components{@property --vui-title-align{syntax:"*";inherits:false;initial-value:start}@property --vui-title-max-width{syntax:"*";inherits:false;initial-value:none}@property --vui-title-literal-color{syntax:"<color>";inherits:false;initial-value:#0000}@property --vui-title-white-space{syntax:"*";inherits:false;initial-value:normal}@property --vui-title-wrap{syntax:"*";inherits:false;initial-value:pretty}@property --vui-title-font-weight{syntax:"<number>";inherits:false;initial-value:500}@property --vui-title-font-width{syntax:"<number>";inherits:false;initial-value:100}@property --vui-title-font-opsz{syntax:"<number>";inherits:false;initial-value:16}@property --vui-title-trim{syntax:"*";inherits:false;initial-value:trim-both}@property --vui-title-trim-type{syntax:"*";inherits:false;initial-value:cap alphabetic}@property --vui-title-padding-inline-start{syntax:"<length>";inherits:false;initial-value:0}@property --vui-title-padding-inline-end{syntax:"<length>";inherits:false;initial-value:0}@property --vui-title-padding-block-start{syntax:"<length>";inherits:false;initial-value:0}@property --vui-title-padding-block-end{syntax:"<length>";inherits:false;initial-value:0}@property --vui-title-font-size{syntax:"<length>";inherits:false;initial-value:1rem}@property --vui-title-line-height{syntax:"normal | <number> | <length-percentage>";inherits:false;initial-value:normal}@property --vui-title-letter-spacing{syntax:"normal | <length>";inherits:false;initial-value:normal}@property --__title-letter-spacing{syntax:"normal | <length>";inherits:false;initial-value:normal}@property --vui-title-text-transform{syntax:"none | capitalize | uppercase | lowercase";inherits:false;initial-value:none}@property --vui-title-font-family{syntax:"*";inherits:false;initial-value:sans-serif}@property --__title-fluid{syntax:"<number>";inherits:false;initial-value:0}@property --__title-size-min{syntax:"<length>";inherits:false;initial-value:1rem}@property --__title-size-max{syntax:"<length>";inherits:false;initial-value:1rem}.viraui__title-module__Title_CXMUX{--__title-fluid:calc((100vi - 320px) / 1125px);--__title-size-min:var(--font-scale-h2);--__title-size-max:var(--font-scale-h1);--vui-title-font-size:clamp(
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);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-align=true]{text-align:var(--vui-title-align)}&[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)}}}
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-wrap:var(--vui-title-wrap);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-align=true]{text-align:var(--vui-title-align)}&[data-title-has-tracking=true]{letter-spacing:var(--vui-title-letter-spacing)}&[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,9 @@ export type TitleProps = React.ComponentPropsWithoutRef<'span'> & {
72
72
  */
73
73
  maxWidth?: string;
74
74
  /**
75
- * Controls white-space preservation and wrapping behavior.
75
+ * Controls white-space collapse/preserve (`white-space`).
76
+ * Prefer `whiteSpace="nowrap"` for single-line metrics/chrome (also collapses spaces).
77
+ * For wrapping algorithm / even line lengths use `wrap` (`text-wrap`) — not this prop.
76
78
  *
77
79
  * @defaultValue 'normal'
78
80
  */
@@ -94,13 +96,14 @@ export type TitleProps = React.ComponentPropsWithoutRef<'span'> & {
94
96
  */
95
97
  transform?: React.CSSProperties['textTransform'];
96
98
  /**
97
- * Enables balanced wrapping for block-like titles.
98
- * Prefer on short wrapping heads (hero, empty state, section);
99
- * omit for single-line / `whiteSpace="nowrap"` metrics.
99
+ * Controls CSS `text-wrap` (wrapping algorithm / wrap on-off).
100
+ * Default `pretty` for orphan-aware titles. Prefer `balance` on short multi-line
101
+ * heads that need even line lengths. Use `wrap="nowrap"` only when you need no wrap
102
+ * without changing white-space collapse; prefer `whiteSpace="nowrap"` for metrics.
100
103
  *
101
- * @defaultValue false
104
+ * @defaultValue 'pretty'
102
105
  */
103
- balanced?: boolean;
106
+ wrap?: React.CSSProperties['textWrap'];
104
107
  /**
105
108
  * Enables text selection on the rendered copy.
106
109
  *
@@ -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, 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 }) => {
7
+ var Title = ({ align, 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", wrap = "pretty", ...otherProps }) => {
8
8
  const hasAlign = align !== void 0;
9
9
  const hasPadding = Boolean(hPadding || vPadding);
10
10
  const hasTracking = tracking !== void 0;
@@ -13,6 +13,7 @@ var Title = ({ align, balanced = false, selection = true, className, color, flui
13
13
  "--vui-title-max-width": maxWidth ?? "none",
14
14
  "--vui-title-literal-color": color,
15
15
  "--vui-title-white-space": whiteSpace,
16
+ "--vui-title-wrap": wrap,
16
17
  ...hasTracking && { "--vui-title-letter-spacing": tracking },
17
18
  "--vui-title-text-transform": transform,
18
19
  "--vui-title-trim": trim ? `trim-${trim}` : "none",
@@ -32,7 +33,6 @@ var Title = ({ align, balanced = false, selection = true, className, color, flui
32
33
  ...otherProps,
33
34
  "data-title-size": size,
34
35
  "data-title-line-height": lineHeight,
35
- "data-title-balanced": balanced ? "true" : "false",
36
36
  "data-title-selection": selection ? "true" : "false",
37
37
  "data-title-fluid": fluid ? "true" : "false",
38
38
  "data-title-has-align": hasAlign ? "true" : "false",
@@ -1,4 +1,4 @@
1
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
2
  var(--font-scale-body-s),
3
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}}::-webkit-scrollbar-track{background-color:var(--scrollbar-track)}: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;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%)}}}}
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}}::-webkit-scrollbar-track{background-color:var(--scrollbar-track)}: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;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=true]{backdrop-filter:blur(calc(var(--vibrancy-blur) * 1px)) saturate(150%)}}}
@@ -44,7 +44,7 @@ Prefer opening via package export / that `dist/specs/` tree. The `version` attri
44
44
  Consumer agents build screens **with** ViraUI — public parts, compounds, and props from the units — not **around** it with immediate CSS overrides.
45
45
 
46
46
  1. Index → activity load → open `meta` / `props` / `usage` for every Vira surface you touch **before** JSX that invents classNames or a CSS module targeting those roots.
47
- 2. Prefer another Vira part or public prop over custom CSS (layout → `Stack`/`Grid`/`Masonry`/`Bleed`/`Surface`; fill → `fullWidth` / `expandChildren`; one-sided inset → `hPadding`/`vPadding` `[start, end]` tuples — not `paddingBlock*`/`paddingInline*` style; type → `Text`/`Title` props; chrome → `Surface` / `Elevator`).
47
+ 2. Prefer another Vira part or public prop over custom CSS (layout → `Stack`/`Grid`/`Masonry`/`Bleed`/`Surface`; fill → `fullWidth` / `fullHeight` / `expandChildren` + stretch align — open Stack `patterns.xml` / `usage` when children must fill both axes; never invent `width`/`height: 100%` CSS; one-sided inset → `hPadding`/`vPadding` `[start, end]` tuples — not `paddingBlock*`/`paddingInline*` style; type → `Text`/`Title` props; chrome → `Surface` / `Elevator` or Stack `render={&lt;Surface /&gt;}`).
48
48
  3. **Omit `render` when it restates the component’s default root.** Confirm the default in that surface’s `props`/`usage` (e.g. Stack → `div`). Do **not** write `render={<div />}` on Stack, or any other `render={<SameDefault />}` noop. Use `render` only to change the host (semantic tag, `Surface`, another component).
49
49
  4. Custom CSS defaults to **app chrome the system does not own** (page backdrop image, document scrollport, one-off marketing layout). It is **not** a license to reshape Vira control geometry, reinvent owned props, or “fix” controls that already look correct under theme + preflight — **unless the consumer expressly requests** that override / personalization. A future override layer will own formal customization hooks; until then, still open `props`/`usage` first and apply only the asked CSS.
50
50
  5. If `usage.xml` lists a **dont** against the CSS you are about to write and the consumer did **not** expressly override that guidance — stop. Do not ship it.
@@ -56,15 +56,15 @@
56
56
  <load>
57
57
  <step open="index.xml" note="category=pattern + stack/surface/grid/masonry/bleed" />
58
58
  <step open="patterns/compose-layout-first.xml" />
59
- <step open="patterns/stack-as-surface.xml" when="border/fill/radius on a flex cluster" />
60
- <step open="patterns/page-chrome.xml" when="page shell / semantic tags" />
61
- <step open="patterns/equal-width-actions.xml" when="full-bleed or equal action rows" />
62
59
  <step open="patterns/card-grid.xml" when="CSS grid tracks / card walls" />
63
60
  <step open="patterns/settings-panel.xml" when="settings / form panels" />
61
+ <step open="patterns/settings-row.xml" when="label + control settings rows" />
62
+ <step open="components/stack/patterns.xml" when="Stack-owned: Surface render, page chrome, equal-width actions, both-axes fill / height 100% temptation" />
64
63
  <step unit="usage" note="confirm stack/surface/grid (etc.) do/dont after pattern" />
65
- <step unit="props" note="verify spacing / render / fullWidth names" />
64
+ <step unit="props" note="verify spacing / render / fullWidth / fullHeight / expandChildren names" />
66
65
  </load>
67
66
  <forbid>Inventing display:flex / display:grid / CSS gap/padding/paddingBlock*/paddingInline*/border chrome when Stack, Grid, Masonry, Bleed, or Surface cover it — one-sided inset → hPadding/vPadding [start, end] tuples</forbid>
67
+ <forbid>Inventing width/height / inline-size/block-size:100% / w-full on Stack or children when fullWidth / fullHeight / expandChildren + hAlign/vAlign=&quot;stretch&quot; cover both-axis fill (open stack patterns + usage)</forbid>
68
68
  <forbid>Passing render={&lt;div /&gt;} (or any render that matches the component default root) — omit render; use it only for a different host</forbid>
69
69
  </activity>
70
70
  </activity_hints>
@@ -4,10 +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>Rounded scroll shells: clip with Surface `overflow` + `radius`, mount ProgressiveBlur as a sibling overlay, set matching `border-radius` on the blur root (layers inherit)</do>
7
+ <do>Match a rounded Surface by setting `border-radius` on the ProgressiveBlur root — layers inherit it</do>
8
8
  <dont>Leaving the ProgressiveBlur root `position: static` so absolute layers escape the intended overlay box</dont>
9
9
  <dont>Driving layout size or scroll behavior from inside the overlay</dont>
10
10
  <dont>Scattering ProgressiveBlur across many cards or stacking full-viewport instances</dont>
11
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</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>
13
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>Text-wall grouping region (articles, docs, privacy) with heading-aware em rhythm; reading column via parent Stack `maxWidth` sized for body Text `size`.</summary>
3
+ <summary>Text-wall grouping region (articles, docs, privacy) with heading-aware em rhythm, region `wrap` (default `pretty`), and reading column via parent Stack `maxWidth` sized for body Text `size`.</summary>
4
4
  <exports>
5
5
  <export name="Prose" />
6
6
  </exports>
@@ -36,7 +36,7 @@
36
36
  </Prose>
37
37
  </Stack>
38
38
  ]]></tsx>
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>
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` / `wrap`).</notes>
40
40
  </example>
41
41
 
42
42
  <example title="Density and region align">
@@ -3,12 +3,12 @@
3
3
  <when_to_use>
4
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
- <item>Optional `gap` density (`s` / `m` / `l`) and region `align` (Title/Text that omit `align` inherit it)</item>
6
+ <item>Optional `gap` density (`s` / `m` / `l`), region `align` (Title/Text that omit `align` inherit it), and region `wrap` (default `pretty`; inherits to descendants)</item>
7
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>
8
8
  </when_to_use>
9
9
  <when_not_to_use>
10
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>
11
+ <item>Short card/hero blurbs “for leading” — use Text/Title `lineHeight` / `maxWidth` / `wrap` instead</item>
12
12
  <item>Restyling type, lists, links, or tables — stay on Title / Text / consumer CSS</item>
13
13
  <item>Markdown parse or sanitize — Prose only spaces matching direct children</item>
14
14
  </when_not_to_use>
@@ -18,6 +18,9 @@
18
18
  <prop name="gap" kind="react">
19
19
  <description>Em density for heading-aware vertical rhythm (`s` &lt; `m` &lt; `l`).</description>
20
20
  </prop>
21
+ <prop name="wrap" kind="react">
22
+ <description>Controls CSS `text-wrap` on the Prose root (inherits to descendants unless a child overrides). Default `pretty` for orphan-aware article walls. Prefer `balance` only on short multi-line blocks that need even line lengths. Single-line metrics stay on child Text/Title `whiteSpace`.</description>
23
+ </prop>
21
24
  <prop name="ref" kind="react">
22
25
  <description>Ref forwarded to the rendered prose root element.</description>
23
26
  </prop>
@@ -36,4 +39,7 @@
36
39
  <prop name="gap-heading-start" kind="css">
37
40
  <description>Gap after a heading onto the next sibling (`--vui-prose-gap-heading-start`). Default `1.3em` (`l`).</description>
38
41
  </prop>
42
+ <prop name="wrap" kind="css">
43
+ <description>Text-wrap on the Prose root (`--vui-prose-wrap`; inherits). Prefer the `wrap` React prop; default `pretty`.</description>
44
+ </prop>
39
45
  </props>
@@ -6,10 +6,11 @@
6
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>
7
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>
8
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>
9
+ <do>Default Prose `wrap` is `pretty` (inherits to children). Prefer `wrap=&quot;balance&quot;` only when short multi-line blocks in the region need even line lengths; single-line metrics use child Text/Title `whiteSpace=&quot;nowrap&quot;`</do>
9
10
  <dont>Using Stack `rowGap` as article rhythm — one gap cannot split heading→body vs body→body</dont>
10
11
  <dont>Expecting default Title/Text `span` hosts to join rhythm — they are not heading/block tags</dont>
11
12
  <dont>Setting `as` — replace the root with `render` only</dont>
12
13
  <dont>Setting `align` on every Title/Text inside Prose when one Prose `align` covers the region</dont>
13
14
  <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>
15
+ <dont>Wrapping a short UI blurb in Prose “for leading” — use Text/Title `lineHeight` / `maxWidth` / `wrap` instead</dont>
15
16
  </usage>