@viraui/react 2026.7.1 → 2026.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/catalog.json +9 -3
- package/dist/components/button/button.css +1 -1
- package/dist/components/direction-provider/index.d.ts +2 -0
- package/dist/components/direction-provider/index.js +2 -0
- package/dist/components/index.d.ts +1 -0
- package/dist/components/menu/menu-popup.d.ts +2 -2
- package/dist/components/menu/menu.css +1 -1
- package/dist/components/progressive-blur/progressive-blur.css +1 -1
- package/dist/components/prose/prose.d.ts +4 -1
- package/dist/components/select/select-group.js +1 -1
- package/dist/components/select/select.css +1 -1
- package/dist/components/select/select.js +4 -1
- package/dist/components/spinner/spinner.d.ts +6 -1
- package/dist/components/spinner/variants/arc.css +1 -0
- package/dist/components/spinner/variants/arc.d.ts +2 -0
- package/dist/components/spinner/variants/arc.js +19 -0
- package/dist/components/spinner/variants/arc.module.js +8 -0
- package/dist/components/spinner/variants/atom.css +1 -0
- package/dist/components/spinner/variants/atom.d.ts +6 -0
- package/dist/components/spinner/variants/atom.js +40 -0
- package/dist/components/spinner/variants/atom.module.js +8 -0
- package/dist/components/spinner/variants/blocks.css +1 -0
- package/dist/components/spinner/variants/blocks.d.ts +2 -0
- package/dist/components/spinner/variants/blocks.js +25 -0
- package/dist/components/spinner/variants/blocks.module.js +8 -0
- package/dist/components/spinner/variants/bouncing-dots.css +1 -0
- package/dist/components/spinner/variants/bouncing-dots.d.ts +2 -0
- package/dist/components/spinner/variants/bouncing-dots.js +21 -0
- package/dist/components/spinner/variants/bouncing-dots.module.js +8 -0
- package/dist/components/spinner/variants/cascade.css +1 -0
- package/dist/components/spinner/variants/cascade.d.ts +2 -0
- package/dist/components/spinner/variants/cascade.js +34 -0
- package/dist/components/spinner/variants/cascade.module.js +8 -0
- package/dist/components/spinner/variants/circular-dots.css +1 -0
- package/dist/components/spinner/variants/circular-dots.d.ts +2 -0
- package/dist/components/spinner/variants/circular-dots.js +26 -0
- package/dist/components/spinner/variants/circular-dots.module.js +8 -0
- package/dist/components/spinner/variants/classic-v2.css +1 -0
- package/dist/components/spinner/variants/classic-v2.d.ts +2 -0
- package/dist/components/spinner/variants/classic-v2.js +24 -0
- package/dist/components/spinner/variants/classic-v2.module.js +8 -0
- package/dist/components/spinner/variants/classic.css +1 -0
- package/dist/components/spinner/variants/classic.d.ts +2 -0
- package/dist/components/spinner/variants/classic.js +22 -0
- package/dist/components/spinner/variants/classic.module.js +8 -0
- package/dist/components/spinner/variants/clock.css +1 -0
- package/dist/components/spinner/variants/clock.d.ts +2 -0
- package/dist/components/spinner/variants/clock.js +18 -0
- package/dist/components/spinner/variants/clock.module.js +8 -0
- package/dist/components/spinner/variants/comet.css +1 -0
- package/dist/components/spinner/variants/comet.d.ts +2 -0
- package/dist/components/spinner/variants/comet.js +33 -0
- package/dist/components/spinner/variants/comet.module.js +10 -0
- package/dist/components/spinner/variants/compass.css +1 -0
- package/dist/components/spinner/variants/compass.d.ts +2 -0
- package/dist/components/spinner/variants/compass.js +16 -0
- package/dist/components/spinner/variants/compass.module.js +8 -0
- package/dist/components/spinner/variants/dual.css +1 -0
- package/dist/components/spinner/variants/dual.d.ts +2 -0
- package/dist/components/spinner/variants/dual.js +25 -0
- package/dist/components/spinner/variants/dual.module.js +10 -0
- package/dist/components/spinner/variants/eclipse.css +1 -0
- package/dist/components/spinner/variants/eclipse.d.ts +6 -0
- package/dist/components/spinner/variants/eclipse.js +21 -0
- package/dist/components/spinner/variants/eclipse.module.js +9 -0
- package/dist/components/spinner/variants/flip.css +1 -0
- package/dist/components/spinner/variants/flip.d.ts +2 -0
- package/dist/components/spinner/variants/flip.js +17 -0
- package/dist/components/spinner/variants/flip.module.js +8 -0
- package/dist/components/spinner/variants/gather.css +1 -0
- package/dist/components/spinner/variants/gather.d.ts +2 -0
- package/dist/components/spinner/variants/gather.js +50 -0
- package/dist/components/spinner/variants/gather.module.js +11 -0
- package/dist/components/spinner/variants/index.d.ts +9 -1
- package/dist/components/spinner/variants/index.js +96 -10
- package/dist/components/spinner/variants/leap.css +1 -0
- package/dist/components/spinner/variants/leap.d.ts +6 -0
- package/dist/components/spinner/variants/leap.js +27 -0
- package/dist/components/spinner/variants/leap.module.js +8 -0
- package/dist/components/spinner/variants/linear-dots.css +1 -0
- package/dist/components/spinner/variants/linear-dots.d.ts +2 -0
- package/dist/components/spinner/variants/linear-dots.js +21 -0
- package/dist/components/spinner/variants/linear-dots.module.js +8 -0
- package/dist/components/spinner/variants/loading.css +1 -0
- package/dist/components/spinner/variants/loading.d.ts +2 -0
- package/dist/components/spinner/variants/loading.js +50 -0
- package/dist/components/spinner/variants/loading.module.js +8 -0
- package/dist/components/spinner/variants/morph.css +1 -0
- package/dist/components/spinner/variants/morph.d.ts +2 -0
- package/dist/components/spinner/variants/morph.js +17 -0
- package/dist/components/spinner/variants/morph.module.js +8 -0
- package/dist/components/spinner/variants/orbit.css +1 -0
- package/dist/components/spinner/variants/orbit.d.ts +2 -0
- package/dist/components/spinner/variants/orbit.js +24 -0
- package/dist/components/spinner/variants/orbit.module.js +8 -0
- package/dist/components/spinner/variants/pulse.css +1 -0
- package/dist/components/spinner/variants/pulse.d.ts +2 -0
- package/dist/components/spinner/variants/pulse.js +19 -0
- package/dist/components/spinner/variants/pulse.module.js +8 -0
- package/dist/components/spinner/variants/radar.css +1 -0
- package/dist/components/spinner/variants/radar.d.ts +2 -0
- package/dist/components/spinner/variants/radar.js +53 -0
- package/dist/components/spinner/variants/radar.module.js +8 -0
- package/dist/components/spinner/variants/ring.css +1 -0
- package/dist/components/spinner/variants/ring.d.ts +2 -0
- package/dist/components/spinner/variants/ring.js +24 -0
- package/dist/components/spinner/variants/ring.module.js +8 -0
- package/dist/components/spinner/variants/ripple.css +1 -0
- package/dist/components/spinner/variants/ripple.d.ts +2 -0
- package/dist/components/spinner/variants/ripple.js +23 -0
- package/dist/components/spinner/variants/ripple.module.js +8 -0
- package/dist/components/spinner/variants/slide.css +1 -0
- package/dist/components/spinner/variants/slide.d.ts +2 -0
- package/dist/components/spinner/variants/slide.js +24 -0
- package/dist/components/spinner/variants/slide.module.js +8 -0
- package/dist/components/spinner/variants/snake.css +1 -0
- package/dist/components/spinner/variants/snake.d.ts +2 -0
- package/dist/components/spinner/variants/snake.js +19 -0
- package/dist/components/spinner/variants/snake.module.js +11 -0
- package/dist/components/spinner/variants/swirl.css +1 -0
- package/dist/components/spinner/variants/swirl.d.ts +2 -0
- package/dist/components/spinner/variants/swirl.js +35 -0
- package/dist/components/spinner/variants/swirl.module.js +8 -0
- package/dist/components/spinner/variants/trace.css +1 -0
- package/dist/components/spinner/variants/trace.d.ts +2 -0
- package/dist/components/spinner/variants/trace.js +28 -0
- package/dist/components/spinner/variants/trace.module.js +8 -0
- package/dist/components/spinner/variants/wave.css +1 -0
- package/dist/components/spinner/variants/wave.d.ts +2 -0
- package/dist/components/spinner/variants/wave.js +25 -0
- package/dist/components/spinner/variants/wave.module.js +8 -0
- package/dist/components/stack/stack.css +1 -1
- package/dist/components/stack/stack.d.ts +15 -3
- package/dist/components/stack/stack.js +2 -1
- package/dist/components/surface/surface.css +1 -1
- package/dist/components/text/text.css +1 -1
- package/dist/components/text/text.d.ts +10 -2
- package/dist/components/title/title.d.ts +7 -0
- package/dist/index.js +2 -1
- package/dist/preflight.css +1 -1
- package/dist/specs/PROTOCOL.md +1 -1
- package/dist/specs/activity-hints.xml +4 -4
- package/dist/specs/components/accordion/props.xml +2 -2
- package/dist/specs/components/accordion/usage.xml +2 -0
- package/dist/specs/components/autocomplete/patterns.xml +4 -4
- package/dist/specs/components/autocomplete/props.xml +2 -2
- package/dist/specs/components/autocomplete/usage.xml +1 -1
- package/dist/specs/components/button/patterns.xml +2 -2
- package/dist/specs/components/button/props.xml +4 -4
- package/dist/specs/components/button/usage.xml +2 -1
- package/dist/specs/components/chip/patterns.xml +2 -2
- package/dist/specs/components/chip/props.xml +2 -2
- package/dist/specs/components/chip/usage.xml +2 -0
- package/dist/specs/components/direction-provider/a11y.xml +6 -0
- package/dist/specs/components/direction-provider/meta.xml +20 -0
- package/dist/specs/components/direction-provider/patterns.xml +27 -0
- package/dist/specs/components/direction-provider/props.xml +18 -0
- package/dist/specs/components/direction-provider/usage.xml +10 -0
- package/dist/specs/components/disclosure/patterns.xml +2 -2
- package/dist/specs/components/disclosure/props.xml +2 -2
- package/dist/specs/components/disclosure/usage.xml +2 -0
- package/dist/specs/components/glow/patterns.xml +1 -1
- package/dist/specs/components/grid/patterns.xml +3 -3
- package/dist/specs/components/icon-button/props.xml +4 -4
- package/dist/specs/components/icon-button/usage.xml +3 -1
- package/dist/specs/components/menu/patterns.xml +18 -18
- package/dist/specs/components/menu/props.xml +5 -5
- package/dist/specs/components/menu/usage.xml +3 -1
- package/dist/specs/components/meter/patterns.xml +1 -1
- package/dist/specs/components/progressive-blur/usage.xml +2 -0
- package/dist/specs/components/prose/meta.xml +1 -1
- package/dist/specs/components/prose/patterns.xml +34 -10
- package/dist/specs/components/prose/props.xml +3 -1
- package/dist/specs/components/prose/usage.xml +4 -1
- package/dist/specs/components/select/patterns.xml +2 -2
- package/dist/specs/components/select/props.xml +2 -2
- package/dist/specs/components/select/usage.xml +1 -0
- package/dist/specs/components/slider/patterns.xml +1 -1
- package/dist/specs/components/spinner/props.xml +1 -1
- package/dist/specs/components/spinner/usage.xml +1 -1
- package/dist/specs/components/stack/patterns.xml +102 -4
- package/dist/specs/components/stack/props.xml +9 -3
- package/dist/specs/components/stack/usage.xml +7 -3
- package/dist/specs/components/surface/patterns.xml +3 -3
- package/dist/specs/components/surface/usage.xml +1 -1
- package/dist/specs/components/tabs/patterns.xml +3 -3
- package/dist/specs/components/tabs/props.xml +1 -1
- package/dist/specs/components/tabs/usage.xml +2 -1
- package/dist/specs/components/text/meta.xml +2 -1
- package/dist/specs/components/text/patterns.xml +19 -16
- package/dist/specs/components/text/props.xml +8 -6
- package/dist/specs/components/text/usage.xml +9 -3
- package/dist/specs/components/textfield/patterns.xml +3 -3
- package/dist/specs/components/textfield/props.xml +2 -2
- package/dist/specs/components/textfield/usage.xml +2 -1
- package/dist/specs/components/title/meta.xml +2 -1
- package/dist/specs/components/title/patterns.xml +11 -10
- package/dist/specs/components/title/props.xml +5 -4
- package/dist/specs/components/title/usage.xml +8 -3
- package/dist/specs/components/toggle-button/patterns.xml +8 -8
- package/dist/specs/components/toggle-button/props.xml +3 -3
- package/dist/specs/components/toggle-button/usage.xml +2 -0
- package/dist/specs/components/toggle-group/patterns.xml +3 -3
- package/dist/specs/components/tooltip/patterns.xml +7 -7
- package/dist/specs/foundation/attributes.xml +24 -4
- package/dist/specs/foundation/bootstrap.xml +1 -1
- package/dist/specs/foundation/modules.xml +14 -5
- package/dist/specs/foundation/theme-topics.xml +3 -3
- package/dist/specs/foundation/toggles.xml +3 -3
- package/dist/specs/index.xml +14 -22
- package/dist/specs/patterns/compose-layout-first.xml +1 -1
- package/package.json +2 -2
- package/dist/components/spinner/variants/bars.d.ts +0 -2
- package/dist/components/spinner/variants/bars.js +0 -134
- package/dist/components/spinner/variants/dot-grid.css +0 -1
- package/dist/components/spinner/variants/dot-grid.d.ts +0 -2
- package/dist/components/spinner/variants/dot-grid.js +0 -57
- package/dist/components/spinner/variants/dot-grid.module.js +0 -16
- package/dist/components/spinner/variants/dots.d.ts +0 -2
- package/dist/components/spinner/variants/dots.js +0 -189
- package/dist/specs/patterns/equal-width-actions.xml +0 -22
- package/dist/specs/patterns/page-chrome.xml +0 -34
- package/dist/specs/patterns/stack-as-surface.xml +0 -37
|
@@ -49,6 +49,8 @@ export type TitleProps = React.ComponentPropsWithoutRef<'span'> & {
|
|
|
49
49
|
color?: string;
|
|
50
50
|
/**
|
|
51
51
|
* Controls line height through foundation leading tokens.
|
|
52
|
+
* Default `m`; prefer `s` on large wrapping titles and always inside Prose.
|
|
53
|
+
* Prefer this prop over CSS `line-height`.
|
|
52
54
|
*
|
|
53
55
|
* @defaultValue 'm'
|
|
54
56
|
*/
|
|
@@ -62,6 +64,9 @@ export type TitleProps = React.ComponentPropsWithoutRef<'span'> & {
|
|
|
62
64
|
align?: React.CSSProperties['textAlign'];
|
|
63
65
|
/**
|
|
64
66
|
* Constrains the maximum inline size of the rendered text block.
|
|
67
|
+
* Prefer for readable wrapping titles (~10–12 words/line) over CSS `max-width`.
|
|
68
|
+
* Prefer `ch` (not `rem`) in patterns/examples. Width tracks `size` — smaller presets → narrower cap;
|
|
69
|
+
* never one fixed measure for every size. Shared columns may use parent Stack `maxWidth` instead.
|
|
65
70
|
*
|
|
66
71
|
* @defaultValue No max width constraint.
|
|
67
72
|
*/
|
|
@@ -90,6 +95,8 @@ export type TitleProps = React.ComponentPropsWithoutRef<'span'> & {
|
|
|
90
95
|
transform?: React.CSSProperties['textTransform'];
|
|
91
96
|
/**
|
|
92
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.
|
|
93
100
|
*
|
|
94
101
|
* @defaultValue false
|
|
95
102
|
*/
|
package/dist/index.js
CHANGED
|
@@ -24,6 +24,7 @@ import { DialogIndentBackground } from "./components/dialog/dialog-indent-backgr
|
|
|
24
24
|
import { DialogSheet } from "./components/dialog/dialog-sheet.js";
|
|
25
25
|
import { DialogTrigger } from "./components/dialog/dialog-trigger.js";
|
|
26
26
|
import { Dialog } from "./components/dialog/dialog.js";
|
|
27
|
+
import { DirectionProvider, useDirection } from "./components/direction-provider/index.js";
|
|
27
28
|
import { Disclosure } from "./components/disclosure/disclosure.js";
|
|
28
29
|
import { ELEVATION_DEFAULTS } from "./core/elevation/elevation-types.js";
|
|
29
30
|
import { getElevationProps } from "./core/elevation/get-elevation-props.js";
|
|
@@ -72,4 +73,4 @@ import { ToggleGroup } from "./components/toggle-group/toggle-group.js";
|
|
|
72
73
|
import { Typewriter } from "./components/typewriter/typewriter.js";
|
|
73
74
|
import { TooltipContent } from "./components/tooltip/tooltip-content.js";
|
|
74
75
|
import { Tooltip, TooltipProvider, TooltipTrigger } from "./components/tooltip/tooltip.js";
|
|
75
|
-
export { Accordion, Annotate, Autocomplete, Avatar, AvatarGroup, Badge, Beam, Bleed, BreakpointsProvider, Button, ButtonLink, Checkbox, CheckboxGroup, Chip, ClampText, Dialog, DialogClose, DialogIndent, DialogIndentBackground, DialogSheet, DialogTrigger, Disclosure, ELEVATION_DEFAULTS, Elevator, Fieldset, FitText, Glow, Grid, IconButton, IconButtonLink, LinearProgress, Masonry, Menu, MenuCheckboxItem, MenuGroup, MenuItem, MenuLinkItem, MenuPopup, MenuRadioGroup, MenuRadioItem, MenuSeparator, MenuSubmenu, MenuSubmenuTrigger, MenuTrigger, Meter, NumberField, OTPField, Popover, PopoverClose, PopoverDescription, PopoverSheet, PopoverTitle, PopoverTrigger, ProgressiveBlur, Prose, Radio, RadioGroup, Select, Separator, Shimmer, Skeleton, Slider, Spinner, Stack, StaticNoise, Surface, Switch, Tabs, Text, Textarea, Textfield, Title, Toast, ToggleButton, ToggleGroup, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, Typewriter, getElevationProps, useBreakpoints };
|
|
76
|
+
export { Accordion, Annotate, Autocomplete, Avatar, AvatarGroup, Badge, Beam, Bleed, BreakpointsProvider, Button, ButtonLink, Checkbox, CheckboxGroup, Chip, ClampText, Dialog, DialogClose, DialogIndent, DialogIndentBackground, DialogSheet, DialogTrigger, DirectionProvider, Disclosure, ELEVATION_DEFAULTS, Elevator, Fieldset, FitText, Glow, Grid, IconButton, IconButtonLink, LinearProgress, Masonry, Menu, MenuCheckboxItem, MenuGroup, MenuItem, MenuLinkItem, MenuPopup, MenuRadioGroup, MenuRadioItem, MenuSeparator, MenuSubmenu, MenuSubmenuTrigger, MenuTrigger, Meter, NumberField, OTPField, Popover, PopoverClose, PopoverDescription, PopoverSheet, PopoverTitle, PopoverTrigger, ProgressiveBlur, Prose, Radio, RadioGroup, Select, Separator, Shimmer, Skeleton, Slider, Spinner, Stack, StaticNoise, Surface, Switch, Tabs, Text, Textarea, Textfield, Title, Toast, ToggleButton, ToggleGroup, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, Typewriter, getElevationProps, useBreakpoints, useDirection };
|
package/dist/preflight.css
CHANGED
|
@@ -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%)}}}
|
package/dist/specs/PROTOCOL.md
CHANGED
|
@@ -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
|
|
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={<Surface />}`).
|
|
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="stretch" cover both-axis fill (open stack patterns + usage)</forbid>
|
|
68
68
|
<forbid>Passing render={<div />} (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>
|
|
@@ -22,10 +22,10 @@
|
|
|
22
22
|
<description>Resting background for the item card, forwarded to the wrapping `Surface` when `useSurface` is `true`. Omit for no background.</description>
|
|
23
23
|
</prop>
|
|
24
24
|
<prop name="Item.iconClosed" kind="react">
|
|
25
|
-
<description>Decorative icon shown when the item is closed.</description>
|
|
25
|
+
<description>Decorative icon shown when the item is closed. Omit glyph `size` / width / height unless expressly overriding — prefer host/chrome default.</description>
|
|
26
26
|
</prop>
|
|
27
27
|
<prop name="Item.iconOpen" kind="react">
|
|
28
|
-
<description>Decorative icon shown when the item is open.</description>
|
|
28
|
+
<description>Decorative icon shown when the item is open. Omit glyph `size` / width / height unless expressly overriding — prefer host/chrome default.</description>
|
|
29
29
|
</prop>
|
|
30
30
|
<prop name="Item.iconPosition" kind="react">
|
|
31
31
|
<description>Side of the trigger label where the expand/collapse icon is rendered.</description>
|
|
@@ -6,7 +6,9 @@
|
|
|
6
6
|
<do>Separated islands with root `islands`; attached block corners when `islands={false}`</do>
|
|
7
7
|
<do>Insert `Separator` between items when `Item` `useSurface={false}`</do>
|
|
8
8
|
<do>Multiple open sections with root `multiple` (+ `defaultValue` / `value` as needed)</do>
|
|
9
|
+
<do>Omit `size` / width / height on Item `iconClosed` / `iconOpen` glyphs unless expressly overriding — prefer chrome/host default</do>
|
|
9
10
|
<dont>Trying to compose separate public `Accordion.Header`, `Accordion.Trigger`, or `Accordion.Panel` exports — those stay inside `Accordion.Item`</dont>
|
|
11
|
+
<dont>Passing `size="1rem"` on every Accordion icon by habit — omit unless expressly overriding</dont>
|
|
10
12
|
<dont>Rendering an item without trigger text and without an external aria-label strategy</dont>
|
|
11
13
|
<dont>Using Accordion for a single expandable section — use Disclosure</dont>
|
|
12
14
|
<dont>Using Accordion for primary navigation that should be links, Tabs, or routes</dont>
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
placeholder="Search by name…"
|
|
12
12
|
items={reviewers}
|
|
13
13
|
itemToStringValue={(person) => person.label}
|
|
14
|
-
startAddon={<Magnifier aria-hidden
|
|
14
|
+
startAddon={<Magnifier aria-hidden />}
|
|
15
15
|
>
|
|
16
16
|
{(person) => (
|
|
17
17
|
<Autocomplete.Item
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
placeholder="SaaS, travel, contractors…"
|
|
37
37
|
items={expenseCategories}
|
|
38
38
|
itemToStringValue={(category) => category.label}
|
|
39
|
-
startAddon={<Magnifier aria-hidden
|
|
39
|
+
startAddon={<Magnifier aria-hidden />}
|
|
40
40
|
>
|
|
41
41
|
{(category) => (
|
|
42
42
|
<Autocomplete.Item key={category.id} value={category}>
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
placeholder="Paris, Austin, Singapore…"
|
|
58
58
|
items={transferDesks}
|
|
59
59
|
itemToStringValue={(desk) => desk.label}
|
|
60
|
-
startAddon={<Magnifier aria-hidden
|
|
60
|
+
startAddon={<Magnifier aria-hidden />}
|
|
61
61
|
>
|
|
62
62
|
{(group) => (
|
|
63
63
|
<Autocomplete.Group key={group.value} items={group.items} label={group.value}>
|
|
@@ -85,7 +85,7 @@
|
|
|
85
85
|
items={results}
|
|
86
86
|
itemToStringValue={(article) => article.title}
|
|
87
87
|
placeholder="Wire limits, SEPA, tax forms…"
|
|
88
|
-
startAddon={<Magnifier aria-hidden
|
|
88
|
+
startAddon={<Magnifier aria-hidden />}
|
|
89
89
|
status={
|
|
90
90
|
<Stack columnGap="s" direction="row" vAlign="center">
|
|
91
91
|
<Spinner aria-hidden size="s" />
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
<description>Content rendered inside baked `Autocomplete.Empty` when the filtered list has no items.</description>
|
|
26
26
|
</prop>
|
|
27
27
|
<prop name="endAddon" kind="react">
|
|
28
|
-
<description>Trailing decoration (icon, button). Buttons must use `type="button"
|
|
28
|
+
<description>Trailing decoration (icon, button). Buttons must use `type="button"`. Omit glyph `size` / width / height on icons unless expressly overriding; IconButton/Button hosts own SVG size via CSS.</description>
|
|
29
29
|
</prop>
|
|
30
30
|
<prop name="error" kind="react">
|
|
31
31
|
<description>Error copy rendered with `Field.Error` and `Text` in the same slot as `description`. Replaces description while the field is invalid and dirty.</description>
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
<description>Ref forwarded to the autocomplete input.</description>
|
|
53
53
|
</prop>
|
|
54
54
|
<prop name="startAddon" kind="react">
|
|
55
|
-
<description>Leading decoration (prefix text, icon). Not a second field control.</description>
|
|
55
|
+
<description>Leading decoration (prefix text, icon). Not a second field control. Omit glyph `size` / width / height on icons unless expressly overriding the icon-library default.</description>
|
|
56
56
|
</prop>
|
|
57
57
|
<prop name="status" kind="react">
|
|
58
58
|
<description>Content rendered inside baked `Autocomplete.Status` (async / limit messaging). Keep the slot mounted; update children when status changes.</description>
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
<do>Prefer Autocomplete over Select when users may type a value not in the list (tags, categories, search)</do>
|
|
5
5
|
<do>Form section: Fieldset legend + Autocomplete with sibling Textfield/Select when they share one section — Stack owns gap</do>
|
|
6
6
|
<do>Fill a form column via a parent Stack `fullWidth` / `expandChildren` (Autocomplete has no `fullWidth` prop) — not CSS `width: 100%`</do>
|
|
7
|
-
<do>`startAddon` / `endAddon` for leading/trailing chrome (same control-group pattern as Textfield) — IconButton/Button addons use `size="s"` and `type="button"
|
|
7
|
+
<do>`startAddon` / `endAddon` for leading/trailing chrome (same control-group pattern as Textfield) — IconButton/Button addons use control `size="s"` and `type="button"`; omit glyph `size` / width / height on icons</do>
|
|
8
8
|
<do>Grouped suggestion lists via `Autocomplete.Group` + `Autocomplete.Collection`; item rows via `Autocomplete.Item` `addon` (e.g. Avatar)</do>
|
|
9
9
|
<do>Async or limited result lists: pass `empty` for no-match copy; keep root `status` mounted and update its children — Spinner + Text inside `status` is fine</do>
|
|
10
10
|
<do>Custom portal host (iframe preview, shadow root, or app overlay root) via `container` on the portal-owning public part</do>
|
|
@@ -81,10 +81,10 @@
|
|
|
81
81
|
<example title="Flat addon links (clone)">
|
|
82
82
|
<tsx><![CDATA[
|
|
83
83
|
<Stack hAlign="start" rowGap="2xs">
|
|
84
|
-
<Button addon={<CircleImage
|
|
84
|
+
<Button addon={<CircleImage />} variant="flat" size="s">
|
|
85
85
|
Open with GitHub Desktop
|
|
86
86
|
</Button>
|
|
87
|
-
<Button addon={<ArrowDown
|
|
87
|
+
<Button addon={<ArrowDown />} variant="flat" size="s">
|
|
88
88
|
Download ZIP
|
|
89
89
|
</Button>
|
|
90
90
|
</Stack>
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
<item>Forcing full panel width with CSS `width: 100%` / `w-full` — wrap in Stack with `fullWidth` and/or `expandChildren` (see stack units)</item>
|
|
14
14
|
</when_not_to_use>
|
|
15
15
|
<prop name="addon" kind="react">
|
|
16
|
-
<description>Decorative addon rendered alongside the button label. Pass any React element; use a named icon from `@viraui/icons/react` or `<Chip />` for status chips
|
|
16
|
+
<description>Decorative addon rendered alongside the button label. Pass any React element; use a named icon from `@viraui/icons/react` or `<Chip />` for status chips. Omit glyph `size` / width / height — Button CSS sizes SVG via `--vui-button-icon-size`.</description>
|
|
17
17
|
</prop>
|
|
18
18
|
<prop name="addonPosition" kind="react">
|
|
19
19
|
<description>Controls whether the addon appears before or after the label.</description>
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
<description>Selects the visual treatment for the button.</description>
|
|
32
32
|
</prop>
|
|
33
33
|
<prop name="addon" kind="react">
|
|
34
|
-
<description>Decorative addon rendered alongside the link label. (button-link)</description>
|
|
34
|
+
<description>Decorative addon rendered alongside the link label. Omit glyph `size` / width / height — host CSS sizes SVG. (button-link)</description>
|
|
35
35
|
</prop>
|
|
36
36
|
<prop name="addonPosition" kind="react">
|
|
37
37
|
<description>Controls whether the addon appears before or after the label. (button-link)</description>
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
<description>Button block size; size prop presets via data attributes.</description>
|
|
62
62
|
</prop>
|
|
63
63
|
<prop name="icon-size" kind="css">
|
|
64
|
-
<description>Addon icon size inside the button.</description>
|
|
64
|
+
<description>Addon icon size inside the button (`--vui-button-icon-size`). Prefer this over setting `size` on the glyph ReactNode.</description>
|
|
65
65
|
</prop>
|
|
66
66
|
<prop name="padding-block" kind="css">
|
|
67
67
|
<description>Vertical padding inside the button.</description>
|
|
@@ -85,7 +85,7 @@
|
|
|
85
85
|
<description>Button block size; size prop presets via data attributes. (button-link)</description>
|
|
86
86
|
</prop>
|
|
87
87
|
<prop name="icon-size" kind="css">
|
|
88
|
-
<description>Addon icon size inside the button. (button-link)</description>
|
|
88
|
+
<description>Addon icon size inside the button (`--vui-button-icon-size`). Prefer this over setting `size` on the glyph ReactNode. (button-link)</description>
|
|
89
89
|
</prop>
|
|
90
90
|
<prop name="padding-block" kind="css">
|
|
91
91
|
<description>Vertical padding inside the button. (button-link)</description>
|
|
@@ -8,10 +8,11 @@
|
|
|
8
8
|
<do>Dialog / sheet action strips: Stack row of Button + ButtonLink; Cancel via `Dialog.Close render={<Button variant="secondary" />}`</do>
|
|
9
9
|
<do>Primary Chip addons inside a primary Button — set `data-mode="inverted"` on the Chip so its fill contrasts</do>
|
|
10
10
|
<do>Navigation that should look like Button — use ButtonLink (framework Link via `render`; sets `data-no-link-style` so preflight underline does not fight button paint)</do>
|
|
11
|
+
<do>Omit `size` / width / height on `addon` icons — host CSS sets `--vui-button-icon-size` from control `size`; set glyph size only to expressly override</do>
|
|
11
12
|
<dont>Using Button without children as icon-only — prefer IconButton</dont>
|
|
12
13
|
<dont>Using Button with `render={<a />}` for links — Base UI enforces button semantics; use ButtonLink</dont>
|
|
13
14
|
<dont>Inventing `width: 100%` / `inline-size: 100%` / `w-full` / `.fullWidth` / size-fill `className` (e.g. `.Submit`) on Button when a parent Stack can own the fill</dont>
|
|
14
|
-
<dont>
|
|
15
|
+
<dont>Passing `size={16}` / `size="1rem"` (or width/height) on every `addon` icon — Button CSS sizes SVG descendants via `--vui-button-icon-size`</dont>
|
|
15
16
|
<dont>Mixing `pill` with custom border-radius overrides that fight `data-pill` styling</dont>
|
|
16
17
|
<dont>Primary Chip addon inside a primary Button without `data-mode="inverted"` — chip fill matches the button and disappears</dont>
|
|
17
18
|
<dont>Forcing `role="button"` on a link</dont>
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
Deploying
|
|
11
11
|
</Chip>
|
|
12
12
|
<Chip variant="yellow">Queued</Chip>
|
|
13
|
-
<Chip variant="red" addon={<Xmark
|
|
13
|
+
<Chip variant="red" addon={<Xmark />}>
|
|
14
14
|
Failed
|
|
15
15
|
</Chip>
|
|
16
16
|
<Chip variant="salmon">Rolled back</Chip>
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
$0.00
|
|
31
31
|
</Title>
|
|
32
32
|
</Stack>
|
|
33
|
-
<Chip variant="outline" addon={<CircleCross
|
|
33
|
+
<Chip variant="outline" addon={<CircleCross color="var(--highlight-yellow)" />}>
|
|
34
34
|
Pending Setup
|
|
35
35
|
</Chip>
|
|
36
36
|
</Stack>
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
<item>Long-form text content that should wrap like body copy — use Text</item>
|
|
12
12
|
</when_not_to_use>
|
|
13
13
|
<prop name="addon" kind="react">
|
|
14
|
-
<description>Decorative addon rendered alongside the chip label
|
|
14
|
+
<description>Decorative addon rendered alongside the chip label. Omit glyph `size` / width / height — Chip CSS sizes SVG via `--vui-chip-icon-size`.</description>
|
|
15
15
|
</prop>
|
|
16
16
|
<prop name="addonPosition" kind="react">
|
|
17
17
|
<description>Controls whether the addon appears before or after the label.</description>
|
|
@@ -44,6 +44,6 @@
|
|
|
44
44
|
<description>Fixed chip block size.</description>
|
|
45
45
|
</prop>
|
|
46
46
|
<prop name="icon-size" kind="css">
|
|
47
|
-
<description>Decorative addon icon size.</description>
|
|
47
|
+
<description>Decorative addon icon size (`--vui-chip-icon-size`). Prefer this over setting `size` on the glyph ReactNode.</description>
|
|
48
48
|
</prop>
|
|
49
49
|
</props>
|
|
@@ -4,10 +4,12 @@
|
|
|
4
4
|
<do>Metadata, category, status, or inline tag-like presentation in Stack rows with Text / Title</do>
|
|
5
5
|
<do>Color-coded status via highlight `variant` values (`green`, `red`, `yellow`, …) or `primary` / `secondary` / `outline`</do>
|
|
6
6
|
<do>Primary Chip as Button `addon` — set `data-mode="inverted"` on the Chip when the Button is primary so fills contrast</do>
|
|
7
|
+
<do>Omit `size` / width / height on `addon` icons — Chip CSS sets `--vui-chip-icon-size`; set glyph size only to expressly override</do>
|
|
7
8
|
<do>Equal-width Chip clusters: wrap in Stack with `fullWidth` and/or `expandChildren` — never per-Chip width CSS</do>
|
|
8
9
|
<do>Polymorphic label root via `render` (default `div`; Chip sets `data-no-link-style` so Chip-as-`<a>` keeps chip chrome)</do>
|
|
9
10
|
<dont>Using Chip as a button replacement for clickable actions — use Button or IconButton</dont>
|
|
10
11
|
<dont>Expecting `addonPosition` to have any effect when `addon` is omitted</dont>
|
|
12
|
+
<dont>Passing `size={16}` / width / height on every Chip `addon` icon — Chip CSS sizes SVG descendants</dont>
|
|
11
13
|
<dont>Introducing custom size variants instead of the fixed compact height</dont>
|
|
12
14
|
<dont>Re-adding a one-off destructive variant instead of `variant="red"`</dont>
|
|
13
15
|
<dont>Primary Chip inside a primary Button without `data-mode="inverted"` — chip fill matches the button and disappears</dont>
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<a11y surface="direction-provider">
|
|
3
|
+
<rule>Not an APG widget — direction context only; keep accessible names and semantics when flipping LTR/RTL</rule>
|
|
4
|
+
<rule>Pair provider `direction="rtl"` with document `dir="rtl"` so CSS logical properties and portaled overlays stay consistent for assistive tech and visual layout</rule>
|
|
5
|
+
<rule>Do not rely on mirrored chrome alone to communicate meaning that must stay in the accessible name</rule>
|
|
6
|
+
</a11y>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<meta id="direction-provider" title="DirectionProvider" category="layout" shared_contract="direction-provider">
|
|
3
|
+
<summary>Transparent re-export of Base UI DirectionProvider and useDirection. Enables RTL behavior for Base UI–backed components; does not set HTML dir or CSS direction — pair with document dir=rtl on a portal ancestor (usually html).</summary>
|
|
4
|
+
<exports>
|
|
5
|
+
<export name="DirectionProvider" />
|
|
6
|
+
<export name="useDirection" />
|
|
7
|
+
</exports>
|
|
8
|
+
<related>
|
|
9
|
+
<ref id="menu" />
|
|
10
|
+
<ref id="slider" />
|
|
11
|
+
<ref id="select" />
|
|
12
|
+
</related>
|
|
13
|
+
<units>
|
|
14
|
+
<unit kind="a11y" href="a11y.xml" />
|
|
15
|
+
<unit kind="props" href="props.xml" />
|
|
16
|
+
<unit kind="usage" href="usage.xml" />
|
|
17
|
+
<unit kind="patterns" href="patterns.xml" />
|
|
18
|
+
</units>
|
|
19
|
+
<base_ui href="https://base-ui.com/react/utils/direction-provider#api-reference" />
|
|
20
|
+
</meta>
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<patterns surface="direction-provider">
|
|
3
|
+
<example title="RTL subtree with Slider">
|
|
4
|
+
<tsx><![CDATA[
|
|
5
|
+
<div dir="rtl">
|
|
6
|
+
<DirectionProvider direction="rtl">
|
|
7
|
+
<Slider defaultValue={25} label="Volume" />
|
|
8
|
+
</DirectionProvider>
|
|
9
|
+
</div>
|
|
10
|
+
]]></tsx>
|
|
11
|
+
<notes>Transparent Base UI re-export. Provider feeds Base UI context; `dir` on an ancestor owns HTML/CSS direction. For app-wide RTL set `dir` on `html`. Upstream: https://base-ui.com/react/utils/direction-provider</notes>
|
|
12
|
+
</example>
|
|
13
|
+
|
|
14
|
+
<example title="Read direction in a portal-safe hook">
|
|
15
|
+
<tsx><![CDATA[
|
|
16
|
+
function DirectionLabel() {
|
|
17
|
+
const direction = useDirection();
|
|
18
|
+
return <Text size="s">Direction: {direction}</Text>;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
<DirectionProvider direction="rtl">
|
|
22
|
+
<DirectionLabel />
|
|
23
|
+
</DirectionProvider>
|
|
24
|
+
]]></tsx>
|
|
25
|
+
<notes>`useDirection` reads the provider context — useful when portaled trees are outside a local `dir` wrapper.</notes>
|
|
26
|
+
</example>
|
|
27
|
+
</patterns>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<props surface="direction-provider">
|
|
3
|
+
<when_to_use>
|
|
4
|
+
<item>RTL apps that need Base UI–backed Vira menus, sliders, selects, and other direction-aware primitives to flip behavior</item>
|
|
5
|
+
<item>Reading the active text direction in portaled trees via `useDirection` when `dir` on html is not enough</item>
|
|
6
|
+
</when_to_use>
|
|
7
|
+
<when_not_to_use>
|
|
8
|
+
<item>Expecting this provider alone to flip HTML/CSS layout — also set `dir="rtl"` (or `direction: rtl`) on a portal ancestor, usually `<html>`</item>
|
|
9
|
+
<item>Mandatory root chrome — opt-in like BreakpointsProvider; not part of Dialog/Tooltip/Toast overlay shell</item>
|
|
10
|
+
<item>Inventing a Vira wrapper API — this surface is a transparent Base UI re-export</item>
|
|
11
|
+
</when_not_to_use>
|
|
12
|
+
<prop name="children" kind="react">
|
|
13
|
+
<description>Tree that should receive Base UI direction context. Pass-through from Base UI.</description>
|
|
14
|
+
</prop>
|
|
15
|
+
<prop name="direction" kind="react">
|
|
16
|
+
<description>Reading direction: `ltr` (default) or `rtl`. Pass-through from Base UI — see upstream API.</description>
|
|
17
|
+
</prop>
|
|
18
|
+
</props>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<usage surface="direction-provider">
|
|
3
|
+
<do>Import `DirectionProvider` / `useDirection` from `@viraui/react` — transparent Base UI re-export; full API → https://base-ui.com/react/utils/direction-provider</do>
|
|
4
|
+
<do>Wrap the app (or RTL subtree) in `DirectionProvider direction="rtl"` and set `dir="rtl"` on a portal ancestor (usually `<html>`) so body-mounted popups inherit CSS direction</do>
|
|
5
|
+
<do>Use `useDirection` when a portaled component needs the context direction without reading the DOM `dir` attribute</do>
|
|
6
|
+
<dont>Assuming `DirectionProvider` sets HTML `dir` or CSS `direction` — it only feeds Base UI context</dont>
|
|
7
|
+
<dont>Setting `dir="rtl"` only on a local wrapper when popups portal to `document.body` — use `html` / document root</dont>
|
|
8
|
+
<dont>Importing `@base-ui/react/direction-provider` directly in Vira apps when `@viraui/react` already re-exports it</dont>
|
|
9
|
+
<dont>Treating this as required overlay bootstrap — Dialog/Tooltip/Toast providers stay separate; DirectionProvider is opt-in for RTL</dont>
|
|
10
|
+
</usage>
|
|
@@ -10,10 +10,10 @@
|
|
|
10
10
|
<item>Primary navigation that should use links, Tabs, or routes</item>
|
|
11
11
|
</when_not_to_use>
|
|
12
12
|
<prop name="Trigger.restingIcon" kind="react">
|
|
13
|
-
<description>Decorative icon while the panel is closed. Defaults to ChromeChevronEnd when both icon slots are omitted.</description>
|
|
13
|
+
<description>Decorative icon while the panel is closed. Defaults to ChromeChevronEnd when both icon slots are omitted. Omit glyph `size` / width / height — Disclosure CSS sizes SVG in the icon box.</description>
|
|
14
14
|
</prop>
|
|
15
15
|
<prop name="Trigger.openIcon" kind="react">
|
|
16
|
-
<description>Decorative icon while the panel is open. Defaults to ChromeChevronDown when both icon slots are omitted. When only restingIcon is set, that icon shows in both states.</description>
|
|
16
|
+
<description>Decorative icon while the panel is open. Defaults to ChromeChevronDown when both icon slots are omitted. When only restingIcon is set, that icon shows in both states. Omit glyph `size` / width / height — host CSS sizes SVG.</description>
|
|
17
17
|
</prop>
|
|
18
18
|
<prop name="Trigger.interpolateIcons" kind="react">
|
|
19
19
|
<description>When dual icons are present, crossfade and light-rotate between them (`data-interpolate="true"`). When false, swap instantly with no transition.</description>
|
|
@@ -4,8 +4,10 @@
|
|
|
4
4
|
<do>Spread Surface chrome on Trigger (`color`, `hoverColor`, `border`, `radius`, padding) when using the default host</do>
|
|
5
5
|
<do>Supply Panel children layout (Stack/padding) yourself — Panel has no default content padding</do>
|
|
6
6
|
<do>Use `restingIcon` / `openIcon` / `interpolateIcons` for ToggleButton-style icon pairs; omit both for chrome chevron End/Down</do>
|
|
7
|
+
<do>Omit `size` / width / height on Trigger icon glyphs — Disclosure CSS sizes SVG in the icon box; set glyph size only to expressly override</do>
|
|
7
8
|
<do>Pass Trigger `render` when replacing the Surface compose entirely</do>
|
|
8
9
|
<dont>Using Accordion for a single section — Accordion is multi-item</dont>
|
|
9
10
|
<dont>Expecting Accordion-like default Panel padding from Disclosure.Panel</dont>
|
|
11
|
+
<dont>Passing `size="1rem"` / width / height on every Trigger icon glyph — host CSS sizes SVG descendants</dont>
|
|
10
12
|
<dont>Relying on icon animation alone for open/closed meaning under reduced motion</dont>
|
|
11
13
|
</usage>
|
|
@@ -38,13 +38,13 @@
|
|
|
38
38
|
<Surface border="all" color={1} radius="l" hPadding="m" vPadding="m">
|
|
39
39
|
<Grid columns={7} rows={6} columnGap="m" rowGap="m">
|
|
40
40
|
<Grid.Item render={<Stack hAlign="center" vAlign="center" />}>
|
|
41
|
-
<IconButton aria-label="Home" icon={<House
|
|
41
|
+
<IconButton aria-label="Home" icon={<House aria-hidden />} variant="flat" />
|
|
42
42
|
</Grid.Item>
|
|
43
43
|
<Grid.Item render={<Stack hAlign="center" vAlign="center" />}>
|
|
44
|
-
<IconButton aria-label="Search" icon={<Magnifier
|
|
44
|
+
<IconButton aria-label="Search" icon={<Magnifier aria-hidden />} variant="flat" />
|
|
45
45
|
</Grid.Item>
|
|
46
46
|
<Grid.Item render={<Stack hAlign="center" vAlign="center" />}>
|
|
47
|
-
<IconButton aria-label="Settings" icon={<Gear
|
|
47
|
+
<IconButton aria-label="Settings" icon={<Gear aria-hidden />} variant="flat" />
|
|
48
48
|
</Grid.Item>
|
|
49
49
|
{/* more IconButtons… */}
|
|
50
50
|
</Grid>
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
<item>Temporally swap icons after user interactions with temporal pressed state, like copy feedback. Use ToggleButton instead</item>
|
|
13
13
|
</when_not_to_use>
|
|
14
14
|
<prop name="icon" kind="react">
|
|
15
|
-
<description>Icon rendered as the sole visible control content
|
|
15
|
+
<description>Icon rendered as the sole visible control content. Omit glyph `size` / width / height — host CSS sizes SVG via `--vui-button-icon-size`.</description>
|
|
16
16
|
</prop>
|
|
17
17
|
<prop name="loading" kind="react">
|
|
18
18
|
<description>Shows a centered spinner overlay while preserving the original content width.</description>
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
<description>Selects the visual treatment for the button.</description>
|
|
28
28
|
</prop>
|
|
29
29
|
<prop name="icon" kind="react">
|
|
30
|
-
<description>Icon rendered as the sole visible control content. (icon-button-link)</description>
|
|
30
|
+
<description>Icon rendered as the sole visible control content. Omit glyph `size` / width / height — host CSS sizes SVG. (icon-button-link)</description>
|
|
31
31
|
</prop>
|
|
32
32
|
<prop name="loading" kind="react">
|
|
33
33
|
<description>Shows a centered spinner overlay while preserving the original content width. Sets `aria-disabled` / `aria-busy` for loading chrome; link stays activatable. (icon-button-link)</description>
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
<description>Button block size; size prop presets via data attributes.</description>
|
|
55
55
|
</prop>
|
|
56
56
|
<prop name="icon-size" kind="css">
|
|
57
|
-
<description>Addon icon size inside the button.</description>
|
|
57
|
+
<description>Addon icon size inside the button (`--vui-button-icon-size`). Prefer this over setting `size` on the glyph ReactNode.</description>
|
|
58
58
|
</prop>
|
|
59
59
|
<prop name="padding-block" kind="css">
|
|
60
60
|
<description>Vertical padding inside the button.</description>
|
|
@@ -78,7 +78,7 @@
|
|
|
78
78
|
<description>Button block size; size prop presets via data attributes. (icon-button-link)</description>
|
|
79
79
|
</prop>
|
|
80
80
|
<prop name="icon-size" kind="css">
|
|
81
|
-
<description>Addon icon size inside the button. (icon-button-link)</description>
|
|
81
|
+
<description>Addon icon size inside the button (`--vui-button-icon-size`). Prefer this over setting `size` on the glyph ReactNode. (icon-button-link)</description>
|
|
82
82
|
</prop>
|
|
83
83
|
<prop name="padding-block" kind="css">
|
|
84
84
|
<description>Vertical padding inside the button. (icon-button-link)</description>
|
|
@@ -3,8 +3,9 @@
|
|
|
3
3
|
<do>Compact toolbar or chrome actions identified only by icon</do>
|
|
4
4
|
<do>Same size, variant, and loading model as Button without a visible label</do>
|
|
5
5
|
<do>Decorative glyph with an explicit accessible name on the root (`aria-label` / `aria-labelledby`)</do>
|
|
6
|
+
<do>Omit `size` / width / height on the `icon` glyph — host CSS sizes SVG via `--vui-button-icon-size`; set glyph size only to expressly override</do>
|
|
6
7
|
<do>Toolbar / zoom / chrome clusters: Stack row of IconButtons inside Surface — gap via Stack, not per-control CSS</do>
|
|
7
|
-
<do>Textfield `endAddon` / `startAddon` for compact field chrome (e.g. copy) — keep addon control `size="s"
|
|
8
|
+
<do>Textfield `endAddon` / `startAddon` for compact field chrome (e.g. copy) — keep addon control `size="s"` (control size, not glyph size)</do>
|
|
8
9
|
<do>Menu / overlay triggers via `Menu.Trigger render={<IconButton … />}` (and peers with the same pattern)</do>
|
|
9
10
|
<do>Icon-only navigation — use IconButtonLink (framework Link via `render`)</do>
|
|
10
11
|
<dont>Passing `children`, `addon`, or `addonPosition` — not part of the public API; use `icon`</dont>
|
|
@@ -12,5 +13,6 @@
|
|
|
12
13
|
<dont>Using IconButton for persistent or temporal pressed state — use ToggleButton</dont>
|
|
13
14
|
<dont>Using IconButton with `render={<a />}` for links — use IconButtonLink</dont>
|
|
14
15
|
<dont>Omitting both `aria-label` and `aria-labelledby`</dont>
|
|
16
|
+
<dont>Passing `size={16}` / `size="1rem"` (or width/height) on the `icon` glyph — IconButton CSS sizes SVG descendants</dont>
|
|
15
17
|
<dont>Inventing `width: 100%` / `inline-size: 100%` / `w-full` / size-fill `className` (e.g. `.Social`) on IconButton — it is intentionally square; Stack owns gap/align only</dont>
|
|
16
18
|
</usage>
|