@viraui/react 2026.6.4 → 2026.7.0-next.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 +12 -0
- package/dist/components/autocomplete/autocomplete.js +1 -1
- package/dist/components/basic-input/basic-input.d.ts +2 -1
- package/dist/components/basic-input/basic-input.js +7 -0
- package/dist/components/beam/beam-pulse-driver.d.ts +1 -0
- package/dist/components/beam/beam-pulse-driver.js +2 -2
- package/dist/components/beam/beam.css +1 -1
- package/dist/components/beam/beam.d.ts +5 -2
- package/dist/components/beam/beam.js +31 -26
- package/dist/components/button/button-link.js +1 -0
- package/dist/components/chip/chip.js +1 -0
- package/dist/components/dialog/dialog-sheet.js +1 -1
- package/dist/components/dialog/dialog.css +1 -1
- package/dist/components/index.d.ts +2 -0
- package/dist/components/menu/menu-link-item.js +1 -0
- package/dist/components/menu/menu-popup.js +1 -1
- package/dist/components/meter/meter.css +1 -1
- package/dist/components/meter/meter.d.ts +11 -1
- package/dist/components/meter/meter.js +2 -1
- package/dist/components/otp-field/index.d.ts +4 -0
- package/dist/components/otp-field/otp-field-input.d.ts +12 -0
- package/dist/components/otp-field/otp-field-input.js +29 -0
- package/dist/components/otp-field/otp-field-separator.d.ts +11 -0
- package/dist/components/otp-field/otp-field-separator.js +16 -0
- package/dist/components/otp-field/otp-field.css +1 -0
- package/dist/components/otp-field/otp-field.d.ts +49 -0
- package/dist/components/otp-field/otp-field.js +79 -0
- package/dist/components/otp-field/otp-field.module.js +23 -0
- package/dist/components/prose/index.d.ts +2 -0
- package/dist/components/prose/prose.css +1 -0
- package/dist/components/prose/prose.d.ts +40 -0
- package/dist/components/prose/prose.js +27 -0
- package/dist/components/prose/prose.module.js +5 -0
- package/dist/components/select/select.js +1 -1
- package/dist/components/separator/separator.d.ts +7 -0
- package/dist/components/separator/separator.js +2 -1
- package/dist/components/text/text.css +1 -1
- package/dist/components/text/text.d.ts +6 -3
- package/dist/components/text/text.js +4 -2
- package/dist/components/textfield/textfield.css +1 -1
- package/dist/components/textfield/textfield.d.ts +18 -10
- package/dist/components/textfield/textfield.js +43 -39
- package/dist/components/textfield/textfield.module.js +3 -1
- package/dist/components/title/title.css +1 -1
- package/dist/components/title/title.d.ts +2 -1
- package/dist/components/title/title.js +4 -2
- package/dist/components/toast/toast-banner.js +1 -1
- package/dist/index.js +5 -3
- package/dist/preflight.css +1 -1
- package/dist/specs/components/beam/a11y.xml +3 -3
- package/dist/specs/components/beam/props.xml +22 -1
- package/dist/specs/components/beam/usage.xml +1 -0
- package/dist/specs/components/button/usage.xml +1 -1
- package/dist/specs/components/chip/usage.xml +1 -1
- package/dist/specs/components/menu/usage.xml +1 -1
- package/dist/specs/components/meter/patterns.xml +12 -0
- package/dist/specs/components/meter/props.xml +7 -0
- package/dist/specs/components/meter/usage.xml +2 -0
- package/dist/specs/components/otp-field/a11y.xml +10 -0
- package/dist/specs/components/otp-field/meta.xml +23 -0
- package/dist/specs/components/otp-field/patterns.xml +66 -0
- package/dist/specs/components/otp-field/props.xml +29 -0
- package/dist/specs/components/otp-field/usage.xml +13 -0
- package/dist/specs/components/prose/a11y.xml +7 -0
- package/dist/specs/components/prose/meta.xml +18 -0
- package/dist/specs/components/prose/patterns.xml +59 -0
- package/dist/specs/components/prose/props.xml +37 -0
- package/dist/specs/components/prose/usage.xml +12 -0
- package/dist/specs/components/separator/props.xml +3 -0
- package/dist/specs/components/separator/usage.xml +1 -0
- package/dist/specs/components/text/patterns.xml +9 -0
- package/dist/specs/components/text/props.xml +6 -6
- package/dist/specs/components/text/usage.xml +3 -0
- package/dist/specs/components/textfield/meta.xml +1 -0
- package/dist/specs/components/textfield/props.xml +6 -1
- package/dist/specs/components/textfield/usage.xml +2 -1
- package/dist/specs/components/title/props.xml +2 -2
- package/dist/specs/components/title/usage.xml +2 -0
- package/dist/specs/components/typewriter/usage.xml +0 -1
- package/dist/specs/foundation/attributes.xml +5 -5
- package/dist/specs/foundation/modules.xml +2 -2
- package/dist/specs/index.xml +21 -1
- package/package.json +2 -2
|
@@ -2,4 +2,4 @@
|
|
|
2
2
|
var(--__title-size-min),
|
|
3
3
|
calc(var(--__title-size-min) + (var(--__title-size-max) - var(--__title-size-min)) * var(--__title-fluid)),
|
|
4
4
|
var(--__title-size-max)
|
|
5
|
-
);--vui-title-font-family:var(--font-family-heading);--vui-title-line-height:var(--font-leading-m);--__title-letter-spacing:-0.03em;margin:0;max-inline-size:var(--vui-title-max-width);font-family:var(--vui-title-font-family);font-size:var(--vui-title-font-size);line-height:var(--vui-title-line-height);letter-spacing:var(--__title-letter-spacing);text-transform:var(--vui-title-text-transform);
|
|
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)}}}
|
|
@@ -55,8 +55,9 @@ export type TitleProps = React.ComponentPropsWithoutRef<'span'> & {
|
|
|
55
55
|
lineHeight?: 'none' | 'xs' | 's' | 'm' | 'l';
|
|
56
56
|
/**
|
|
57
57
|
* Aligns text using logical alignment values.
|
|
58
|
+
* Omit so `text-align` inherits from the parent.
|
|
58
59
|
*
|
|
59
|
-
* @default
|
|
60
|
+
* @default Inherits parent `text-align`.
|
|
60
61
|
*/
|
|
61
62
|
align?: React.CSSProperties['textAlign'];
|
|
62
63
|
/**
|
|
@@ -4,11 +4,12 @@ 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
|
|
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 }) => {
|
|
8
|
+
const hasAlign = align !== void 0;
|
|
8
9
|
const hasPadding = Boolean(hPadding || vPadding);
|
|
9
10
|
const hasTracking = tracking !== void 0;
|
|
10
11
|
const dynamicStyle = {
|
|
11
|
-
"--vui-title-align": align,
|
|
12
|
+
...hasAlign && { "--vui-title-align": align },
|
|
12
13
|
"--vui-title-max-width": maxWidth ?? "none",
|
|
13
14
|
"--vui-title-literal-color": color,
|
|
14
15
|
"--vui-title-white-space": whiteSpace,
|
|
@@ -34,6 +35,7 @@ var Title = ({ align = "start", balanced = false, selection = true, className, c
|
|
|
34
35
|
"data-title-balanced": balanced ? "true" : "false",
|
|
35
36
|
"data-title-selection": selection ? "true" : "false",
|
|
36
37
|
"data-title-fluid": fluid ? "true" : "false",
|
|
38
|
+
"data-title-has-align": hasAlign ? "true" : "false",
|
|
37
39
|
"data-title-has-padding": hasPadding ? "true" : "false",
|
|
38
40
|
"data-title-has-literal-color": color ? "true" : "false",
|
|
39
41
|
"data-title-has-tracking": hasTracking ? "true" : "false",
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { clsx } from "../../core/clsx.js";
|
|
2
2
|
import { Text } from "../text/text.js";
|
|
3
3
|
import { Stack } from "../stack/stack.js";
|
|
4
|
-
import { Button } from "../button/button.js";
|
|
5
4
|
import { Surface } from "../surface/surface.js";
|
|
5
|
+
import { Button } from "../button/button.js";
|
|
6
6
|
import toast_module_default from "./toast.module.js";
|
|
7
7
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
8
8
|
import { Toast } from "@base-ui/react/toast";
|
package/dist/index.js
CHANGED
|
@@ -6,6 +6,7 @@ import { Autocomplete } from "./components/autocomplete/autocomplete.js";
|
|
|
6
6
|
import { Avatar } from "./components/avatar/avatar.js";
|
|
7
7
|
import { AvatarGroup } from "./components/avatar-group/avatar-group.js";
|
|
8
8
|
import { Badge } from "./components/badge/badge.js";
|
|
9
|
+
import { Surface } from "./components/surface/surface.js";
|
|
9
10
|
import { Beam } from "./components/beam/beam.js";
|
|
10
11
|
import { Bleed } from "./components/bleed/bleed.js";
|
|
11
12
|
import { BreakpointsProvider } from "./components/breakpoints/breakpoints-provider.js";
|
|
@@ -28,7 +29,6 @@ import { getElevationProps } from "./core/elevation/get-elevation-props.js";
|
|
|
28
29
|
import { Elevator } from "./components/elevator/elevator.js";
|
|
29
30
|
import { Fieldset } from "./components/fieldset/fieldset.js";
|
|
30
31
|
import { FitText } from "./components/fit-text/fit-text.js";
|
|
31
|
-
import { Surface } from "./components/surface/surface.js";
|
|
32
32
|
import { Glow } from "./components/glow/glow.js";
|
|
33
33
|
import { Grid } from "./components/grid/grid.js";
|
|
34
34
|
import { IconButton } from "./components/icon-button/icon-button.js";
|
|
@@ -46,9 +46,12 @@ import { MenuSeparator } from "./components/menu/menu-separator.js";
|
|
|
46
46
|
import { MenuSubmenuTrigger } from "./components/menu/menu-submenu-trigger.js";
|
|
47
47
|
import { Menu, MenuSubmenu, MenuTrigger } from "./components/menu/menu.js";
|
|
48
48
|
import { Meter } from "./components/meter/meter.js";
|
|
49
|
+
import { Textfield } from "./components/textfield/textfield.js";
|
|
50
|
+
import { OTPField } from "./components/otp-field/otp-field.js";
|
|
49
51
|
import { PopoverSheet } from "./components/popover/popover-sheet.js";
|
|
50
52
|
import { Popover, PopoverClose, PopoverDescription, PopoverTitle, PopoverTrigger } from "./components/popover/popover.js";
|
|
51
53
|
import { ProgressiveBlur } from "./components/progressive-blur/progressive-blur.js";
|
|
54
|
+
import { Prose } from "./components/prose/prose.js";
|
|
52
55
|
import { Radio } from "./components/radio/radio.js";
|
|
53
56
|
import { RadioGroup } from "./components/radio/radio-group.js";
|
|
54
57
|
import { Select } from "./components/select/select.js";
|
|
@@ -60,7 +63,6 @@ import { StaticNoise } from "./components/static-noise/static-noise.js";
|
|
|
60
63
|
import { Switch } from "./components/switch/switch.js";
|
|
61
64
|
import { Tabs } from "./components/tabs/tabs.js";
|
|
62
65
|
import { Textarea } from "./components/textarea/textarea.js";
|
|
63
|
-
import { Textfield } from "./components/textfield/textfield.js";
|
|
64
66
|
import { Title } from "./components/title/title.js";
|
|
65
67
|
import { Toast } from "./components/toast/toast.js";
|
|
66
68
|
import { ToggleButton } from "./components/toggle-button/toggle-button.js";
|
|
@@ -68,4 +70,4 @@ import { ToggleGroup } from "./components/toggle-group/toggle-group.js";
|
|
|
68
70
|
import { Typewriter } from "./components/typewriter/typewriter.js";
|
|
69
71
|
import { TooltipContent } from "./components/tooltip/tooltip-content.js";
|
|
70
72
|
import { Tooltip, TooltipProvider, TooltipTrigger } from "./components/tooltip/tooltip.js";
|
|
71
|
-
export { Accordion, Annotate, Autocomplete, Avatar, AvatarGroup, Badge, Beam, Bleed, BreakpointsProvider, Button, ButtonLink, Checkbox, CheckboxGroup, Chip, ClampText, Dialog, DialogClose, DialogIndent, DialogIndentBackground, DialogSheet, DialogTrigger, ELEVATION_DEFAULTS, Elevator, Fieldset, FitText, Glow, Grid, IconButton, IconButtonLink, LinearProgress, Masonry, Menu, MenuCheckboxItem, MenuGroup, MenuItem, MenuLinkItem, MenuPopup, MenuRadioGroup, MenuRadioItem, MenuSeparator, MenuSubmenu, MenuSubmenuTrigger, MenuTrigger, Meter, Popover, PopoverClose, PopoverDescription, PopoverSheet, PopoverTitle, PopoverTrigger, ProgressiveBlur, 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 };
|
|
73
|
+
export { Accordion, Annotate, Autocomplete, Avatar, AvatarGroup, Badge, Beam, Bleed, BreakpointsProvider, Button, ButtonLink, Checkbox, CheckboxGroup, Chip, ClampText, Dialog, DialogClose, DialogIndent, DialogIndentBackground, DialogSheet, DialogTrigger, ELEVATION_DEFAULTS, Elevator, Fieldset, FitText, Glow, Grid, IconButton, IconButtonLink, LinearProgress, Masonry, Menu, MenuCheckboxItem, MenuGroup, MenuItem, MenuLinkItem, MenuPopup, MenuRadioGroup, MenuRadioItem, MenuSeparator, MenuSubmenu, MenuSubmenuTrigger, MenuTrigger, Meter, 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 };
|
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}}:focus-visible{outline:var(--outline);outline-offset:var(--outline-offset)}body{color:var(--global-foreground);margin:0;font-size:var(--font-scale-body-m);font-optical-sizing:auto;font-family:var(--font-family-body),system-ui,sans-serif;font-variation-settings:"wght" 400;font-variant-numeric:tabular-nums;@container root not style(--effect-holofoil: initial){&:after{content:"";position:fixed;inset:0;z-index:999;background-color:#99ffd8;pointer-events:none;mix-blend-mode:multiply;contain:strict;isolation:isolate;opacity:25%;background-image:radial-gradient(at 79% 56%,#70ade6 0,#0000 50%),radial-gradient(at 61% 80%,#ee909e 0,#0000 50%),radial-gradient(at 0 63%,#fdbc68 0,#0000 50%),radial-gradient(at 6% 50%,#e5cb8a 0,#0000 50%),radial-gradient(at 23% 10%,#e5db8f 0,#0000 50%),radial-gradient(at 36% 91%,#a0eea8 0,#0000 50%),radial-gradient(at 2% 80%,#e3a47d 0,#0000 50%);@container root style(--is-light-mode: white){mix-blend-mode:color;opacity:15%}}}}::selection{background-color:var(--global-primary);color:contrast-color(var(--global-primary));text-shadow:none}img{display:block;inline-size:100%;max-inline-size:100%}svg{display:inline-flex;vertical-align:middle;&:not([fill]){fill:currentcolor}}ol ul,ul ol{font-size:medium}table{border-spacing:0;inline-size:100%;border-collapse:collapse}table[data-layout-fixed]{table-layout:fixed}table thead{box-shadow:inset 0 -3px 0 var(--base-2)}table[data-table-separators] tr+tr{border-top:1px solid var(--base-2)}table th{white-space:nowrap;font-variation-settings:"wght" 800}table :is(td,th){border:none;text-align:left;font-size:medium;padding:calc(var(--space-xs) + var(--space-2xs)) var(--space-s)}button,fieldset{padding:0;margin:0;border:0}button{appearance:none;background:none;font-size:inherit;font-family:inherit;display:inline-flex;cursor:pointer;color:inherit}}@layer viraui.preflight{@container root not style(--effect-shadows: initial){[data-elevation]{--shadow-direction:1;--shadow-opacity-factor:0.16;--extra-shadow:0 0 0 1px #0000;--shadow-color:oklch(0% 0 0);transition-property:box-shadow;transition-duration:var(--elevation-transition-duration,.16s);transition-timing-function:var(--elevation-transition-easing,ease)}[data-elevation]:where([data-elevation-direction=bottom],[data-elevation-direction=right]){--shadow-direction:1}[data-elevation]:where([data-elevation-direction=top],[data-elevation-direction=left]){--shadow-direction:-1}[data-elevation-hover="0"]:hover,[data-elevation="0"]{--y1:0px;--x1:0px;box-shadow:calc(var(--x1) * var(--shadow-direction)) calc(var(--y1) * var(--shadow-direction)) 0 oklch(from var(--shadow-color) l c h/var(--shadow-opacity-factor)),0 0 0 color-mix(in oklch,var(--shadow-color),#0000 calc(94% - var(--shadow-opacity-factor))),0 0 0 oklch(from var(--shadow-color) l c h/var(--shadow-opacity-factor)),var(--extra-shadow)}[data-elevation-hover="1"]:hover,[data-elevation-hover="2"]:hover,[data-elevation-hover="3"]:hover,[data-elevation-hover="4"]:hover,[data-elevation="1"],[data-elevation="2"],[data-elevation="3"],[data-elevation="4"]{box-shadow:calc(var(--x1) * var(--shadow-direction)) calc(var(--y1) * var(--shadow-direction)) var(--shadow-blur-1) oklab(from var(--shadow-color) l a b/.1),calc(var(--x2) * var(--shadow-direction)) calc(var(--y2) * var(--shadow-direction)) var(--shadow-blur-2) oklab(from var(--shadow-color) l a b/.08),calc(var(--x3) * var(--shadow-direction)) calc(var(--y3) * var(--shadow-direction)) var(--shadow-blur-3) oklab(from var(--shadow-color) l a b/.06),calc(var(--x4) * var(--shadow-direction)) calc(var(--y4) * var(--shadow-direction)) var(--shadow-blur-4) oklab(from var(--shadow-color) l a b/.04),calc(var(--x5) * var(--shadow-direction)) calc(var(--y5) * var(--shadow-direction)) var(--shadow-blur-5) oklab(from var(--shadow-color) l a b/.02),var(--extra-shadow)}[data-elevation-hover="1"]:hover,[data-elevation="1"]{--y1:0px;--y2:1px;--y3:1px;--y4:3px;--y5:4px;--x1:0px;--x2:0px;--x3:0px;--x4:0px;--x5:0px;--shadow-blur-1:0px;--shadow-blur-2:1px;--shadow-blur-3:1px;--shadow-blur-4:3px;--shadow-blur-5:4px}[data-elevation-hover="1"]:where([data-elevation-direction=left],[data-elevation-direction=right]):hover,[data-elevation="1"]:where([data-elevation-direction=left],[data-elevation-direction=right]){--y1:0px;--y2:0px;--y3:0px;--y4:0px;--y5:0px;--x1:0px;--x2:1px;--x3:1px;--x4:3px;--x5:4px}[data-elevation-hover="2"]:hover,[data-elevation="2"]{--y1:0px;--y2:1px;--y3:3px;--y4:5px;--y5:8px;--x1:0px;--x2:0px;--x3:0px;--x4:0px;--x5:0px;--shadow-blur-1:0px;--shadow-blur-2:1px;--shadow-blur-3:3px;--shadow-blur-4:5px;--shadow-blur-5:8px}[data-elevation-hover="2"]:where([data-elevation-direction=left],[data-elevation-direction=right]):hover,[data-elevation="2"]:where([data-elevation-direction=left],[data-elevation-direction=right]){--y1:0px;--y2:0px;--y3:0px;--y4:0px;--y5:0px;--x1:0px;--x2:1px;--x3:3px;--x4:5px;--x5:8px}[data-elevation-hover="3"]:hover,[data-elevation="3"]{--y1:1px;--y2:3px;--y3:6px;--y4:10px;--y5:16px;--x1:0px;--x2:0px;--x3:0px;--x4:0px;--x5:0px;--shadow-blur-1:1px;--shadow-blur-2:3px;--shadow-blur-3:6px;--shadow-blur-4:10px;--shadow-blur-5:16px}[data-elevation-hover="3"]:where([data-elevation-direction=left],[data-elevation-direction=right]):hover,[data-elevation="3"]:where([data-elevation-direction=left],[data-elevation-direction=right]){--y1:0px;--y2:0px;--y3:0px;--y4:0px;--y5:0px;--x1:1px;--x2:3px;--x3:6px;--x4:10px;--x5:16px}[data-elevation-hover="4"]:hover,[data-elevation="4"]{--y1:1px;--y2:5px;--y3:12px;--y4:20px;--y5:32px;--x1:0px;--x2:0px;--x3:0px;--x4:0px;--x5:0px;--shadow-blur-1:1px;--shadow-blur-2:5px;--shadow-blur-3:12px;--shadow-blur-4:20px;--shadow-blur-5:32px}[data-elevation-hover="4"]:where([data-elevation-direction=left],[data-elevation-direction=right]):hover,[data-elevation="4"]:where([data-elevation-direction=left],[data-elevation-direction=right]){--y1:0px;--y2:0px;--y3:0px;--y4:0px;--y5:0px;--x1:1px;--x2:5px;--x3:12px;--x4:20px;--x5:32px}}}@layer viraui.preflight{[data-grow=true]{--vira-flex-grow:1;flex-grow:1}[data-grow=false]{--vira-flex-grow:0;flex-grow:0}[data-shrink=true]{--vira-flex-shrink:1;flex-shrink:1}[data-shrink=false]{--vira-flex-shrink:0;flex-shrink:0}}@layer viraui.preflight{:where(p){line-height:1.5;min-block-size:.01vh;font-size:var(--font-scale-body-m)}small{font-size:.7em}b,strong{font-variation-settings:"wght" 700}:where(a:any-link):not([data-no-link-style]){text-decoration:none;color:var(--global-interactive-text);word-break:break-word;&:not([class]){background:linear-gradient(currentcolor,currentcolor) no-repeat 0 100%;background-size:0 1px;transition:background-size var(--duration-fast) var(--easing-entrance);&:focus,&:hover{background-size:100% 1px}}}del{padding:0 .4em;margin:0 .2em;background-color:oklab(from var(--highlight-red) l a b/12%);color:var(--highlight-red);box-shadow:0 0 0 1px oklab(from var(--highlight-red) l a b/50%);border-radius:var(--radius-s)}ins{background-color:oklab(from var(--highlight-green) l a b/15%);color:var(--highlight-green);box-shadow:0 0 0 1px oklab(from var(--highlight-green) l a b/50%)}ins,mark{padding:0 .4em;margin:0 .2em;text-decoration:none;border-radius:var(--radius-s)}mark{background-color:oklab(from var(--highlight-yellow) l a b/15%);color:var(--highlight-yellow);box-shadow:0 0 0 1px oklab(from var(--highlight-yellow) l a b/50%)}address{font-style:normal;line-height:inherit}dt{font-variation-settings:"wght" 600}dd{margin:0;padding:0}ul{font-size:medium;padding-left:1rem;& li::marker{font-size:inherit;text-align:right;font-variation-settings:"wght" 400;min-inline-size:var(--space-xl);color:oklab(from currentColor l a b/80%)}}ol{font-size:medium;& li::marker{font-size:inherit;font-variation-settings:"wght" 400;min-inline-size:var(--space-xl);font-variant-numeric:tabular-nums;white-space:nowrap;color:oklab(from currentColor l a b/80%)}}kbd{padding:.2em .4em;border-radius:var(--radius-s);font-variation-settings:"wght" 600;box-shadow:var(--global-contrast);background:var(--global-contrast)}abbr{text-decoration:underline dashed var(--global-primary)}label,legend{font-size:inherit}code{font-size:1em;font-family:var(--font-family-mono);&:not(:where(pre &)){background-color:var(--global-contrast);border-radius:var(--radius-s);box-shadow:var(--global-contrast);padding:.2em .4em}}pre code{box-shadow:none}s{text-decoration:line-through;color:var(--global-disabled-foreground);text-decoration-color:oklab(from var(--global-foreground) l a b/50%)}:root{color-scheme:light dark}[data-mode=dark]{--is-light-mode:#fff;color:var(--global-foreground);color-scheme:dark}[data-mode=light]{--is-light-mode:#000;color:var(--global-foreground);color-scheme:light}}@layer viraui.preflight{[data-mode=inverted]{color:var(--global-foreground);@container root style(--is-light-mode: black){color-scheme:dark}@container root style(--is-light-mode: white){color-scheme:light}}}@layer viraui.preflight{@container root not style(--effect-vibrancy: initial){[data-vibrant]{backdrop-filter:brightness(var(--vibrancy-brightness)) blur(calc(var(--vibrancy-blur) * 1px)) saturate(150%);@container root style(--is-light-mode: black){backdrop-filter:brightness(100%) blur(calc(var(--vibrancy-blur) * 1px)) saturate(150%)}}}}
|
|
4
|
+
);--font-scale-body-l:round(down, calc(1rem * pow(var(--font-body-typescale), 1)), 1px);--font-scale-body-xl:round(down, calc(1rem * pow(var(--font-body-typescale), 2)), 1px);--font-scale-body-2xl:round(down, calc(1rem * pow(var(--font-body-typescale), 3)), 1px);--font-scale-body-3xl:round(down, calc(1rem * pow(var(--font-body-typescale), 4)), 1px);--font-scale-body-4xl:round(down, calc(1rem * pow(var(--font-body-typescale), 5)), 1px);--font-scale-h6:round(down, calc(1rem * pow(var(--font-heading-typescale), 1)), 1px);--font-scale-h5:round(down, calc(1rem * pow(var(--font-heading-typescale), 2)), 1px);--font-scale-h4:round(down, calc(1rem * pow(var(--font-heading-typescale), 3)), 1px);--font-scale-h3:round(down, calc(1rem * pow(var(--font-heading-typescale), 4)), 1px);--font-scale-h2:round(down, calc(1rem * pow(var(--font-heading-typescale), 5)), 1px);--font-scale-h1:round(down, calc(1rem * pow(var(--font-heading-typescale), 6)), 1px);--font-scale-display:round(down, calc(1rem * pow(var(--font-heading-typescale), 8)), 1px)}}@layer viraui.preflight{html{--scrollbar-thumb:oklab(from var(--global-contrast) l a b / 0.3);--scrollbar-track:#0000;--outline-offset:2px;--outline-color:var(--global-outline);--outline:2px solid var(--outline-color);--is-light-mode:contrast-color(var(--global-background));font-size:var(--font-root-size);box-sizing:border-box;line-height:1.5;background-color:var(--global-background);color:var(--global-foreground);container:root/normal;scroll-behavior:smooth;@media (prefers-reduced-motion:reduce){scroll-behavior:auto}}*,:after,:before{margin:0;box-sizing:inherit;scrollbar-width:thin;scrollbar-color:var(--scrollbar-thumb) var(--scrollbar-track);@container root not style(--effect-corner-shape: initial){corner-shape:var(--__corner-shape,var(--corner-shape))}@media (prefers-reduced-motion:reduce){animation:none!important;transition:none!important}}:focus-visible{outline:var(--outline);outline-offset:var(--outline-offset)}body{color:var(--global-foreground);margin:0;font-size:var(--font-scale-body-m);font-optical-sizing:auto;font-family:var(--font-family-body),system-ui,sans-serif;font-variation-settings:"wght" 400;font-variant-numeric:tabular-nums;@container root not style(--effect-holofoil: initial){&:after{content:"";position:fixed;inset:0;z-index:999;background-color:#99ffd8;pointer-events:none;mix-blend-mode:multiply;contain:strict;isolation:isolate;opacity:25%;background-image:radial-gradient(at 79% 56%,#70ade6 0,#0000 50%),radial-gradient(at 61% 80%,#ee909e 0,#0000 50%),radial-gradient(at 0 63%,#fdbc68 0,#0000 50%),radial-gradient(at 6% 50%,#e5cb8a 0,#0000 50%),radial-gradient(at 23% 10%,#e5db8f 0,#0000 50%),radial-gradient(at 36% 91%,#a0eea8 0,#0000 50%),radial-gradient(at 2% 80%,#e3a47d 0,#0000 50%);@container root style(--is-light-mode: white){mix-blend-mode:color;opacity:15%}}}}::selection{background-color:var(--global-primary);color:contrast-color(var(--global-primary));text-shadow:none}img{display:block;inline-size:100%;max-inline-size:100%}svg{display:inline-flex;vertical-align:middle;&:not([fill]){fill:currentcolor}}ol ul,ul ol{font-size:medium}table{border-spacing:0;inline-size:100%;border-collapse:collapse}table[data-layout-fixed]{table-layout:fixed}table thead{box-shadow:inset 0 -3px 0 var(--base-2)}table[data-table-separators] tr+tr{border-top:1px solid var(--base-2)}table th{white-space:nowrap;font-variation-settings:"wght" 800}table :is(td,th){border:none;text-align:left;font-size:medium;padding:calc(var(--space-xs) + var(--space-2xs)) var(--space-s)}button,fieldset{padding:0;margin:0;border:0}button{appearance:none;background:none;font-size:inherit;font-family:inherit;display:inline-flex;cursor:pointer;color:inherit}}@layer viraui.preflight{@container root not style(--effect-shadows: initial){[data-elevation]{--shadow-direction:1;--shadow-opacity-factor:0.16;--extra-shadow:0 0 0 1px #0000;--shadow-color:oklch(0% 0 0);transition-property:box-shadow;transition-duration:var(--elevation-transition-duration,.16s);transition-timing-function:var(--elevation-transition-easing,ease)}[data-elevation]:where([data-elevation-direction=bottom],[data-elevation-direction=right]){--shadow-direction:1}[data-elevation]:where([data-elevation-direction=top],[data-elevation-direction=left]){--shadow-direction:-1}[data-elevation-hover="0"]:hover,[data-elevation="0"]{--y1:0px;--x1:0px;box-shadow:calc(var(--x1) * var(--shadow-direction)) calc(var(--y1) * var(--shadow-direction)) 0 oklch(from var(--shadow-color) l c h/var(--shadow-opacity-factor)),0 0 0 color-mix(in oklch,var(--shadow-color),#0000 calc(94% - var(--shadow-opacity-factor))),0 0 0 oklch(from var(--shadow-color) l c h/var(--shadow-opacity-factor)),var(--extra-shadow)}[data-elevation-hover="1"]:hover,[data-elevation-hover="2"]:hover,[data-elevation-hover="3"]:hover,[data-elevation-hover="4"]:hover,[data-elevation="1"],[data-elevation="2"],[data-elevation="3"],[data-elevation="4"]{box-shadow:calc(var(--x1) * var(--shadow-direction)) calc(var(--y1) * var(--shadow-direction)) var(--shadow-blur-1) oklab(from var(--shadow-color) l a b/.1),calc(var(--x2) * var(--shadow-direction)) calc(var(--y2) * var(--shadow-direction)) var(--shadow-blur-2) oklab(from var(--shadow-color) l a b/.08),calc(var(--x3) * var(--shadow-direction)) calc(var(--y3) * var(--shadow-direction)) var(--shadow-blur-3) oklab(from var(--shadow-color) l a b/.06),calc(var(--x4) * var(--shadow-direction)) calc(var(--y4) * var(--shadow-direction)) var(--shadow-blur-4) oklab(from var(--shadow-color) l a b/.04),calc(var(--x5) * var(--shadow-direction)) calc(var(--y5) * var(--shadow-direction)) var(--shadow-blur-5) oklab(from var(--shadow-color) l a b/.02),var(--extra-shadow)}[data-elevation-hover="1"]:hover,[data-elevation="1"]{--y1:0px;--y2:1px;--y3:1px;--y4:3px;--y5:4px;--x1:0px;--x2:0px;--x3:0px;--x4:0px;--x5:0px;--shadow-blur-1:0px;--shadow-blur-2:1px;--shadow-blur-3:1px;--shadow-blur-4:3px;--shadow-blur-5:4px}[data-elevation-hover="1"]:where([data-elevation-direction=left],[data-elevation-direction=right]):hover,[data-elevation="1"]:where([data-elevation-direction=left],[data-elevation-direction=right]){--y1:0px;--y2:0px;--y3:0px;--y4:0px;--y5:0px;--x1:0px;--x2:1px;--x3:1px;--x4:3px;--x5:4px}[data-elevation-hover="2"]:hover,[data-elevation="2"]{--y1:0px;--y2:1px;--y3:3px;--y4:5px;--y5:8px;--x1:0px;--x2:0px;--x3:0px;--x4:0px;--x5:0px;--shadow-blur-1:0px;--shadow-blur-2:1px;--shadow-blur-3:3px;--shadow-blur-4:5px;--shadow-blur-5:8px}[data-elevation-hover="2"]:where([data-elevation-direction=left],[data-elevation-direction=right]):hover,[data-elevation="2"]:where([data-elevation-direction=left],[data-elevation-direction=right]){--y1:0px;--y2:0px;--y3:0px;--y4:0px;--y5:0px;--x1:0px;--x2:1px;--x3:3px;--x4:5px;--x5:8px}[data-elevation-hover="3"]:hover,[data-elevation="3"]{--y1:1px;--y2:3px;--y3:6px;--y4:10px;--y5:16px;--x1:0px;--x2:0px;--x3:0px;--x4:0px;--x5:0px;--shadow-blur-1:1px;--shadow-blur-2:3px;--shadow-blur-3:6px;--shadow-blur-4:10px;--shadow-blur-5:16px}[data-elevation-hover="3"]:where([data-elevation-direction=left],[data-elevation-direction=right]):hover,[data-elevation="3"]:where([data-elevation-direction=left],[data-elevation-direction=right]){--y1:0px;--y2:0px;--y3:0px;--y4:0px;--y5:0px;--x1:1px;--x2:3px;--x3:6px;--x4:10px;--x5:16px}[data-elevation-hover="4"]:hover,[data-elevation="4"]{--y1:1px;--y2:5px;--y3:12px;--y4:20px;--y5:32px;--x1:0px;--x2:0px;--x3:0px;--x4:0px;--x5:0px;--shadow-blur-1:1px;--shadow-blur-2:5px;--shadow-blur-3:12px;--shadow-blur-4:20px;--shadow-blur-5:32px}[data-elevation-hover="4"]:where([data-elevation-direction=left],[data-elevation-direction=right]):hover,[data-elevation="4"]:where([data-elevation-direction=left],[data-elevation-direction=right]){--y1:0px;--y2:0px;--y3:0px;--y4:0px;--y5:0px;--x1:1px;--x2:5px;--x3:12px;--x4:20px;--x5:32px}}}@layer viraui.preflight{[data-grow=true]{--vira-flex-grow:1;flex-grow:1}[data-grow=false]{--vira-flex-grow:0;flex-grow:0}[data-shrink=true]{--vira-flex-shrink:1;flex-shrink:1}[data-shrink=false]{--vira-flex-shrink:0;flex-shrink:0}}@layer viraui.preflight{:where(p){line-height:1.5;min-block-size:.01vh;font-size:var(--font-scale-body-m)}small{font-size:.7em}b,strong{font-variation-settings:"wght" 700}:where(a:any-link):not([data-no-link-style]){text-decoration:none;color:var(--global-interactive-text);word-break:break-word;background:linear-gradient(currentcolor,currentcolor) no-repeat 0 100%;background-size:0 1px;transition:background-size var(--duration-fast) var(--easing-entrance);&:focus,&:hover{background-size:100% 1px}}del{padding:0 .4em;margin:0 .2em;background-color:oklab(from var(--highlight-red) l a b/12%);color:var(--highlight-red);box-shadow:0 0 0 1px oklab(from var(--highlight-red) l a b/50%);border-radius:var(--radius-s)}ins{background-color:oklab(from var(--highlight-green) l a b/15%);color:var(--highlight-green);box-shadow:0 0 0 1px oklab(from var(--highlight-green) l a b/50%)}ins,mark{padding:0 .4em;margin:0 .2em;text-decoration:none;border-radius:var(--radius-s)}mark{background-color:oklab(from var(--highlight-yellow) l a b/15%);color:var(--highlight-yellow);box-shadow:0 0 0 1px oklab(from var(--highlight-yellow) l a b/50%)}address{font-style:normal;line-height:inherit}dt{font-variation-settings:"wght" 600}dd{margin:0;padding:0}ul{font-size:medium;padding-left:1rem;& li::marker{font-size:inherit;text-align:right;font-variation-settings:"wght" 400;min-inline-size:var(--space-xl);color:oklab(from currentColor l a b/80%)}}ol{font-size:medium;& li::marker{font-size:inherit;font-variation-settings:"wght" 400;min-inline-size:var(--space-xl);font-variant-numeric:tabular-nums;white-space:nowrap;color:oklab(from currentColor l a b/80%)}}kbd{padding:.2em .4em;border-radius:var(--radius-s);font-variation-settings:"wght" 600;box-shadow:var(--global-contrast);background:var(--global-contrast)}abbr{text-decoration:underline dashed var(--global-primary)}label,legend{font-size:inherit}code{font-size:1em;font-family:var(--font-family-mono);&:not(:where(pre &)){background-color:var(--global-contrast);border-radius:var(--radius-s);box-shadow:var(--global-contrast);padding:.2em .4em}}pre code{box-shadow:none}s{text-decoration:line-through;color:var(--global-disabled-foreground);text-decoration-color:oklab(from var(--global-foreground) l a b/50%)}:root{color-scheme:light dark}[data-mode=dark]{--is-light-mode:#fff;color:var(--global-foreground);color-scheme:dark}[data-mode=light]{--is-light-mode:#000;color:var(--global-foreground);color-scheme:light}}@layer viraui.preflight{[data-mode=inverted]{color:var(--global-foreground);@container root style(--is-light-mode: black){color-scheme:dark}@container root style(--is-light-mode: white){color-scheme:light}}}@layer viraui.preflight{@container root not style(--effect-vibrancy: initial){[data-vibrant]{backdrop-filter:brightness(var(--vibrancy-brightness)) blur(calc(var(--vibrancy-blur) * 1px)) saturate(150%);@container root style(--is-light-mode: black){backdrop-filter:brightness(100%) blur(calc(var(--vibrancy-blur) * 1px)) saturate(150%)}}}}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
2
|
<a11y surface="beam">
|
|
3
|
-
<rule>Root stays in the accessibility tree; bloom layer is empty div</rule>
|
|
3
|
+
<rule>Root stays in the accessibility tree; bloom layer is an empty decorative div with aria-hidden</rule>
|
|
4
4
|
<rule>Beam is not a focus or status indicator — consumer owns accessible names and state</rule>
|
|
5
|
-
<rule>Offscreen instances pause
|
|
6
|
-
<rule>prefers-reduced-motion
|
|
5
|
+
<rule>Offscreen instances set data-paused="true" and pause motion without firing activate/deactivate</rule>
|
|
6
|
+
<rule>prefers-reduced-motion keeps a static visible rest (no looping motion); animate=false still fades the effect away</rule>
|
|
7
7
|
</a11y>
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
<description>Effect family: rotating border, bottom line travel, or pulse breathe (outside/inside).</description>
|
|
20
20
|
</prop>
|
|
21
21
|
<prop name="size" kind="react">
|
|
22
|
-
<description>
|
|
22
|
+
<description>Size preset for border geometry and pulse-inside inner glow band (small compact / medium card). Ignored for line and pulse-outside.</description>
|
|
23
23
|
</prop>
|
|
24
24
|
<prop name="color" kind="react">
|
|
25
25
|
<description>Beam color: primary → --global-primary, highlight token name → --highlight-*, colorful → upstream neon multi-stop RGB palette.</description>
|
|
@@ -81,10 +81,31 @@
|
|
|
81
81
|
<prop name="hue" kind="css">
|
|
82
82
|
<description>Pulse hue drift angle written by the shared pulse driver.</description>
|
|
83
83
|
</prop>
|
|
84
|
+
<prop name="hue-base" kind="css">
|
|
85
|
+
<description>Base hue for hue-rotate filters on glow layers.</description>
|
|
86
|
+
</prop>
|
|
87
|
+
<prop name="stroke-opacity" kind="css">
|
|
88
|
+
<description>Opacity of the stroke/conic layer; variant CSS may override.</description>
|
|
89
|
+
</prop>
|
|
90
|
+
<prop name="inner-opacity" kind="css">
|
|
91
|
+
<description>Opacity of the inner glow layer; variant CSS may override.</description>
|
|
92
|
+
</prop>
|
|
93
|
+
<prop name="bloom-opacity" kind="css">
|
|
94
|
+
<description>Opacity of the bloom layer; variant CSS may override.</description>
|
|
95
|
+
</prop>
|
|
84
96
|
<prop name="pulse-glow-sx" kind="css">
|
|
85
97
|
<description>Per-axis X scale for pulse-outside glow geometry relative to a 350×140 reference.</description>
|
|
86
98
|
</prop>
|
|
87
99
|
<prop name="pulse-glow-sy" kind="css">
|
|
88
100
|
<description>Per-axis Y scale for pulse-outside glow geometry relative to a 350×140 reference.</description>
|
|
89
101
|
</prop>
|
|
102
|
+
<prop name="pulse-glow-boost" kind="css">
|
|
103
|
+
<description>Extra pulse-outside glow intensity multiplier (internal default 1; not a React prop).</description>
|
|
104
|
+
</prop>
|
|
105
|
+
<prop name="core-blur" kind="css">
|
|
106
|
+
<description>Core glow blur radius (BorderBeam glowSize=1 default).</description>
|
|
107
|
+
</prop>
|
|
108
|
+
<prop name="bloom-blur" kind="css">
|
|
109
|
+
<description>Bloom layer blur radius (BorderBeam glowSize=1 default).</description>
|
|
110
|
+
</prop>
|
|
90
111
|
</props>
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
<do>Pick `variant` for the job: `border` spin, `line` travel, `pulse-outside` / `pulse-inside` breathe — use Glow instead when the highlight should follow the pointer</do>
|
|
6
6
|
<do>Use sparingly as a focal accent — shared pulse rAF still paints per instance; prefer one Beam per view</do>
|
|
7
7
|
<dont>Treating Beam as Surface color/padding/border chrome — nest Surface/Stack children for the real card</dont>
|
|
8
|
+
<dont>Confusing prefers-reduced-motion (static rest stays visible) with `animate={false}` (effect fades away)</dont>
|
|
8
9
|
<dont>Relying on Beam for keyboard focus or status — decorative only</dont>
|
|
9
10
|
<dont>Expecting theme light/dark auto-tuning — colors are token-driven and theme-agnostic</dont>
|
|
10
11
|
<dont>Scattering many Beam instances on one page</dont>
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
<do>Full-bleed or equal-width Buttons: wrap in Stack with `fullWidth` and/or `expandChildren` — never per-Button width CSS</do>
|
|
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
|
-
<do>Navigation that should look like Button — use ButtonLink (framework Link via `render`)</do>
|
|
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
11
|
<dont>Using Button without children as icon-only — prefer IconButton</dont>
|
|
12
12
|
<dont>Using Button with `render={<a />}` for links — Base UI enforces button semantics; use ButtonLink</dont>
|
|
13
13
|
<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>
|
|
@@ -5,7 +5,7 @@
|
|
|
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
7
|
<do>Equal-width Chip clusters: wrap in Stack with `fullWidth` and/or `expandChildren` — never per-Chip width CSS</do>
|
|
8
|
-
<do>Polymorphic label root via `render` (default `div`)</do>
|
|
8
|
+
<do>Polymorphic label root via `render` (default `div`; Chip sets `data-no-link-style` so Chip-as-`<a>` keeps chip chrome)</do>
|
|
9
9
|
<dont>Using Chip as a button replacement for clickable actions — use Button or IconButton</dont>
|
|
10
10
|
<dont>Expecting `addonPosition` to have any effect when `addon` is omitted</dont>
|
|
11
11
|
<dont>Introducing custom size variants instead of the fixed compact height</dont>
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
<usage surface="menu">
|
|
3
3
|
<do>Action menus anchored to Button or IconButton — not page-blocking flows (Dialog) or rich free-layout panels (Popover)</do>
|
|
4
4
|
<do>Nested command lists with `Menu.CheckboxItem` / `Menu.RadioGroup`+`Menu.RadioItem` (stay open on toggle by default) and `Menu.Submenu` + nested `Menu.Popup`</do>
|
|
5
|
-
<do>Mix `Menu.LinkItem` with action `Menu.Item` rows; group with `Menu.Group` / `Menu.Separator
|
|
5
|
+
<do>Mix `Menu.LinkItem` with action `Menu.Item` rows; group with `Menu.Group` / `Menu.Separator` (`LinkItem` sets `data-no-link-style`)</do>
|
|
6
6
|
<do>Account / user chip: `Menu.Trigger` as Surface/Stack (Avatar + Text) opening `Menu.Popup` with static profile header plus Items</do>
|
|
7
7
|
<do>Detached or multi-trigger menus via `Menu.createHandle`</do>
|
|
8
8
|
<do>Custom portal host (iframe preview, shadow root, or app overlay root) via `container` on `Menu.Popup`</do>
|
|
@@ -50,4 +50,16 @@
|
|
|
50
50
|
]]></tsx>
|
|
51
51
|
<notes>From preview-grid `daily-activity-goal` nested tips sheet. Meter for score-within-range; LinearProgress stays on the live activity track outside the dialog.</notes>
|
|
52
52
|
</example>
|
|
53
|
+
|
|
54
|
+
<example title="Highlight variants">
|
|
55
|
+
<tsx><![CDATA[
|
|
56
|
+
<Stack rowGap="m">
|
|
57
|
+
<Meter label="Health" renderValue value={92} variant="green" />
|
|
58
|
+
<Meter label="Latency" renderValue value={38} variant="yellow" />
|
|
59
|
+
<Meter label="Errors" renderValue value={12} variant="red" />
|
|
60
|
+
<Meter label="Quota" renderValue value={64} variant="blue" />
|
|
61
|
+
</Stack>
|
|
62
|
+
]]></tsx>
|
|
63
|
+
<notes>`variant` highlight tokens tint track wash + indicator together (Chip-aligned). Default `primary` keeps brand indicator + contrast track.</notes>
|
|
64
|
+
</example>
|
|
53
65
|
</patterns>
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
<item>Use for storage usage, battery level, capacity, or score within a known range.</item>
|
|
5
5
|
<item>Use with a label when the metric needs a visible name.</item>
|
|
6
6
|
<item>Use with `renderValue` when the formatted value should appear beside the label.</item>
|
|
7
|
+
<item>Use highlight `variant` values when the track and indicator should share a semantic color.</item>
|
|
7
8
|
</when_to_use>
|
|
8
9
|
<when_not_to_use>
|
|
9
10
|
<item>Use LinearProgress for in-progress tasks or indeterminate work.</item>
|
|
@@ -19,12 +20,18 @@
|
|
|
19
20
|
<prop name="renderValue" kind="react">
|
|
20
21
|
<description>Shows the current value beside the label. Pass `true` for Base UI default formatting, or a function matching `Meter.Value` `children` to customize the printed label.</description>
|
|
21
22
|
</prop>
|
|
23
|
+
<prop name="variant" kind="react">
|
|
24
|
+
<description>Selects track and indicator colors. `primary` uses brand primary on the indicator; highlight token names tint both track (wash) and indicator via `--highlight-*`, matching Chip highlight variants.</description>
|
|
25
|
+
</prop>
|
|
22
26
|
<prop name="indicator-color" kind="css">
|
|
23
27
|
<description>Determinate meter indicator color.</description>
|
|
24
28
|
</prop>
|
|
25
29
|
<prop name="track-background" kind="css">
|
|
26
30
|
<description>Meter track background color.</description>
|
|
27
31
|
</prop>
|
|
32
|
+
<prop name="track-opacity" kind="css">
|
|
33
|
+
<description>Highlight variant track wash opacity mix against the indicator color.</description>
|
|
34
|
+
</prop>
|
|
28
35
|
<prop name="track-size" kind="css">
|
|
29
36
|
<description>Meter track thickness on the root.</description>
|
|
30
37
|
</prop>
|
|
@@ -4,10 +4,12 @@
|
|
|
4
4
|
<do>Labeled metrics: `label` + `renderValue` + optional `description`; tune print with Base UI `format` / `locale`</do>
|
|
5
5
|
<do>Workspace stacks: Stack `rowGap` of Meters — or nest one Meter inside Surface for sheet / tip chrome</do>
|
|
6
6
|
<do>Rich labels: pass a Stack row (icon + text) as `label` when needed — no custom label CSS</do>
|
|
7
|
+
<do>Color-coded metrics via highlight `variant` (`green`, `red`, `yellow`, …) or default `primary` — tints track wash + indicator like Chip</do>
|
|
7
8
|
<do>Prefer LinearProgress for in-progress or indeterminate tasks (`value={null}`) — Meter has no indeterminate mode</do>
|
|
8
9
|
<dont>Using Meter as an interactive value control — use Slider</dont>
|
|
9
10
|
<dont>Using Meter for indeterminate or in-progress work — use LinearProgress</dont>
|
|
10
11
|
<dont>Modeling invalid or disabled meter state — Base UI Meter exposes neither</dont>
|
|
11
12
|
<dont>Hiding the metric name when multiple meters share a view</dont>
|
|
12
13
|
<dont>Passing `value={null}` — Meter `value` is required `number`</dont>
|
|
14
|
+
<dont>Reinventing highlight track/indicator colors with raw `--highlight-*` CSS when `variant` covers the token</dont>
|
|
13
15
|
</usage>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<a11y surface="otp-field">
|
|
3
|
+
<rule>One Field: visible `label` names the first slot via Field.Label / htmlFor. Do not put aria-label on the first Input.</rule>
|
|
4
|
+
<rule>Slots after the first get `aria-label` `Character N of {length}` in English when the consumer omits `aria-label`. Consumer `aria-label` wins when passed.</rule>
|
|
5
|
+
<rule>Description and error copy live on the OTPField root helper slot (dirty+invalid), not per slot.</rule>
|
|
6
|
+
<rule>`OTPField.Separator` is a separator, not an input, and is not counted in `length`.</rule>
|
|
7
|
+
<rule>Slot host is always a native `input`. Chrome is Textfield `controlOnly` (no second Field).</rule>
|
|
8
|
+
<rule>Focus ring is per active slot (`:focus`). Input `data-focused` means any slot is focused — do not paint chrome from it.</rule>
|
|
9
|
+
<rule>Invalid wiggle is one-shot chrome only. Error copy / `aria-invalid` still name the error. Reduced motion skips the animation.</rule>
|
|
10
|
+
</a11y>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<meta id="otp-field" title="OTPField" category="form" shared_contract="otp-field">
|
|
3
|
+
<summary>Field-wrapped one-time code slots. Default slots compose Textfield controlOnly; one label/helper on Root.</summary>
|
|
4
|
+
<exports>
|
|
5
|
+
<export name="OTPField" />
|
|
6
|
+
<export name="OTPField.Root" />
|
|
7
|
+
<export name="OTPField.Input" />
|
|
8
|
+
<export name="OTPField.Separator" />
|
|
9
|
+
</exports>
|
|
10
|
+
<related>
|
|
11
|
+
<ref id="textfield" />
|
|
12
|
+
<ref id="fieldset" />
|
|
13
|
+
<ref id="text" />
|
|
14
|
+
<ref id="stack" />
|
|
15
|
+
</related>
|
|
16
|
+
<units>
|
|
17
|
+
<unit kind="a11y" href="a11y.xml" />
|
|
18
|
+
<unit kind="props" href="props.xml" />
|
|
19
|
+
<unit kind="usage" href="usage.xml" />
|
|
20
|
+
<unit kind="patterns" href="patterns.xml" />
|
|
21
|
+
</units>
|
|
22
|
+
<base_ui href="https://base-ui.com/react/components/otp-field#api-reference" />
|
|
23
|
+
</meta>
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<patterns surface="otp-field">
|
|
3
|
+
<example title="Labeled six-slot code">
|
|
4
|
+
<tsx><![CDATA[
|
|
5
|
+
<OTPField.Root
|
|
6
|
+
length={6}
|
|
7
|
+
label="Verification code"
|
|
8
|
+
description="Enter the 6-character code we sent to your device."
|
|
9
|
+
>
|
|
10
|
+
{Array.from({ length: 6 }, (_, slotIndex) => (
|
|
11
|
+
<OTPField.Input key={`character-${slotIndex + 1}`} />
|
|
12
|
+
))}
|
|
13
|
+
</OTPField.Root>
|
|
14
|
+
]]></tsx>
|
|
15
|
+
<notes>Explicit Inputs. First slot uses the field label; later slots get generated names.</notes>
|
|
16
|
+
</example>
|
|
17
|
+
|
|
18
|
+
<example title="Form name + autoSubmit">
|
|
19
|
+
<tsx><![CDATA[
|
|
20
|
+
<Form>
|
|
21
|
+
<OTPField.Root length={6} name="verificationCode" label="Verification code" autoSubmit>
|
|
22
|
+
<OTPField.Input />
|
|
23
|
+
<OTPField.Input />
|
|
24
|
+
<OTPField.Input />
|
|
25
|
+
<OTPField.Input />
|
|
26
|
+
<OTPField.Input />
|
|
27
|
+
<OTPField.Input />
|
|
28
|
+
</OTPField.Root>
|
|
29
|
+
</Form>
|
|
30
|
+
]]></tsx>
|
|
31
|
+
<notes>One concatenated form value. `autoSubmit` submits when complete. `Form` is `@base-ui/react/form`.</notes>
|
|
32
|
+
</example>
|
|
33
|
+
|
|
34
|
+
<example title="Grouped slots with Separator">
|
|
35
|
+
<tsx><![CDATA[
|
|
36
|
+
<OTPField.Root length={6} label="Verification code">
|
|
37
|
+
<Stack columnGap="s" direction="row">
|
|
38
|
+
<OTPField.Input />
|
|
39
|
+
<OTPField.Input />
|
|
40
|
+
<OTPField.Input />
|
|
41
|
+
</Stack>
|
|
42
|
+
<OTPField.Separator />
|
|
43
|
+
<Stack columnGap="s" direction="row">
|
|
44
|
+
<OTPField.Input />
|
|
45
|
+
<OTPField.Input />
|
|
46
|
+
<OTPField.Input />
|
|
47
|
+
</Stack>
|
|
48
|
+
</OTPField.Root>
|
|
49
|
+
]]></tsx>
|
|
50
|
+
<notes>Separator is not an input and is not counted in `length`. Stack owns group gaps.</notes>
|
|
51
|
+
</example>
|
|
52
|
+
|
|
53
|
+
<example title="Equal-grow in a form column">
|
|
54
|
+
<tsx><![CDATA[
|
|
55
|
+
<OTPField.Root length={6} label="Verification code" fullWidth>
|
|
56
|
+
<OTPField.Input />
|
|
57
|
+
<OTPField.Input />
|
|
58
|
+
<OTPField.Input />
|
|
59
|
+
<OTPField.Input />
|
|
60
|
+
<OTPField.Input />
|
|
61
|
+
<OTPField.Input />
|
|
62
|
+
</OTPField.Root>
|
|
63
|
+
]]></tsx>
|
|
64
|
+
<notes>Default hugs. `fullWidth` fills the column and grows slots equally.</notes>
|
|
65
|
+
</example>
|
|
66
|
+
</patterns>
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<props surface="otp-field">
|
|
3
|
+
<when_to_use>
|
|
4
|
+
<item>One-time codes, verification codes, and recovery codes as a single labeled field</item>
|
|
5
|
+
<item>Numeric, alphanumeric, or masked slot entry with form `name` submit of the concatenated value</item>
|
|
6
|
+
<item>Grouped slot rows with `OTPField.Separator` and Stack, not a `groups` prop</item>
|
|
7
|
+
</when_to_use>
|
|
8
|
+
<when_not_to_use>
|
|
9
|
+
<item>Auto-generating Inputs from `length` — always list one `OTPField.Input` per slot</item>
|
|
10
|
+
<item>Per-slot label, description, or error — Field chrome is on Root only</item>
|
|
11
|
+
<item>Swapping the slot host via `render` — host is always a native `input`; chrome is Textfield `controlOnly`</item>
|
|
12
|
+
<item>Inventing CSS `width: 100%` on slots when Root `fullWidth` covers equal-grow</item>
|
|
13
|
+
</when_not_to_use>
|
|
14
|
+
<prop name="description" kind="react">
|
|
15
|
+
<description>Helper copy rendered with `Field.Description` and `Text` while the field is valid.</description>
|
|
16
|
+
</prop>
|
|
17
|
+
<prop name="error" kind="react">
|
|
18
|
+
<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>
|
|
19
|
+
</prop>
|
|
20
|
+
<prop name="fullWidth" kind="react">
|
|
21
|
+
<description>When `true`, the field is `inline-size: 100%` and the inner slot Stack uses `fullWidth` + `expandChildren` so slots grow equally. Prefer this over CSS `width: 100%` on slots.</description>
|
|
22
|
+
</prop>
|
|
23
|
+
<prop name="label" kind="react">
|
|
24
|
+
<description>Visible label rendered with shared internal `FieldLabel`. Names the first slot.</description>
|
|
25
|
+
</prop>
|
|
26
|
+
<prop name="length" kind="react">
|
|
27
|
+
<description>Required slot count for clamp, complete, and hidden validation markup. Does not spawn Inputs — list exactly this many `OTPField.Input` children.</description>
|
|
28
|
+
</prop>
|
|
29
|
+
</props>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<usage surface="otp-field">
|
|
3
|
+
<do>List exactly `length` `OTPField.Input` children (Array.from or explicit)</do>
|
|
4
|
+
<do>Put `label` / `description` / `error` on `OTPField.Root` (or `OTPField`)</do>
|
|
5
|
+
<do>Let the first slot take the field label; later slots get generated `Character N of {length}` unless you pass `aria-label`</do>
|
|
6
|
+
<do>Group slots with Stack + `OTPField.Separator` when the code is shown as chunks</do>
|
|
7
|
+
<do>Span the form column with Root `fullWidth` so slots grow equally</do>
|
|
8
|
+
<do>Keep error copy on Root — invalid wiggle is extra chrome, not the only signal</do>
|
|
9
|
+
<dont>Pass `render` on Input — slot is always a native `input`; chrome is Textfield `controlOnly`</dont>
|
|
10
|
+
<dont>Put label/description/error on each slot</dont>
|
|
11
|
+
<dont>Expect Root to auto-generate Inputs from `length`</dont>
|
|
12
|
+
<dont>Invent a `groups` prop or width CSS on slots when Stack / `fullWidth` cover layout</dont>
|
|
13
|
+
</usage>
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<a11y surface="prose">
|
|
3
|
+
<rule>Prose is grouping, not a widget — do not set a role on the root</rule>
|
|
4
|
+
<rule>Default root is a generic `div`; it does not require an accessible name</rule>
|
|
5
|
+
<rule>Landmark semantics only when the consumer replaces the root (`render={<article />}` or similar) and names the landmark if needed</rule>
|
|
6
|
+
<rule>Children keep their own roles (headings, lists, links); Prose does not restyle or re-role them</rule>
|
|
7
|
+
</a11y>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<meta id="prose" title="Prose" category="typography" shared_contract="prose">
|
|
3
|
+
<summary>Grouping region that applies heading-aware em rhythm to direct document blocks.</summary>
|
|
4
|
+
<exports>
|
|
5
|
+
<export name="Prose" />
|
|
6
|
+
</exports>
|
|
7
|
+
<related>
|
|
8
|
+
<ref id="text" />
|
|
9
|
+
<ref id="title" />
|
|
10
|
+
<ref id="stack" />
|
|
11
|
+
</related>
|
|
12
|
+
<units>
|
|
13
|
+
<unit kind="a11y" href="a11y.xml" />
|
|
14
|
+
<unit kind="props" href="props.xml" />
|
|
15
|
+
<unit kind="usage" href="usage.xml" />
|
|
16
|
+
<unit kind="patterns" href="patterns.xml" />
|
|
17
|
+
</units>
|
|
18
|
+
</meta>
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<patterns surface="prose">
|
|
3
|
+
<example title="Article with Title and Text">
|
|
4
|
+
<tsx><![CDATA[
|
|
5
|
+
<Prose render={<article />}>
|
|
6
|
+
<Title size="2" lineHeight="s" render={<h2 />}>
|
|
7
|
+
Heading-aware document rhythm
|
|
8
|
+
</Title>
|
|
9
|
+
<Text render={<p />}>
|
|
10
|
+
Direct heading and paragraph children pick up Prose gaps. Type stays on Title and Text.
|
|
11
|
+
</Text>
|
|
12
|
+
<Text render={<p />}>A second paragraph uses the block gap, not the heading-end gap.</Text>
|
|
13
|
+
</Prose>
|
|
14
|
+
]]></tsx>
|
|
15
|
+
<notes>Default `gap="l"`. Landmark via `render={<article />}`. Title in Prose uses `lineHeight="s"`. Do not wrap these blocks in Stack for rhythm.</notes>
|
|
16
|
+
</example>
|
|
17
|
+
|
|
18
|
+
<example title="Density and region align">
|
|
19
|
+
<tsx><![CDATA[
|
|
20
|
+
<Prose gap="s" align="center">
|
|
21
|
+
<Title size="3" lineHeight="s" render={<h3 />}>
|
|
22
|
+
Compact notes
|
|
23
|
+
</Title>
|
|
24
|
+
<Text render={<p />}>One Prose `align` sets the region. Omit Title/Text `align` so they inherit.</Text>
|
|
25
|
+
</Prose>
|
|
26
|
+
]]></tsx>
|
|
27
|
+
<notes>`s` < `m` < `l`. `align` maps to `--vui-prose-align` + `text-align` on the root. Title `lineHeight="s"`.</notes>
|
|
28
|
+
</example>
|
|
29
|
+
|
|
30
|
+
<example title="Line height on body">
|
|
31
|
+
<tsx><![CDATA[
|
|
32
|
+
<Prose>
|
|
33
|
+
<Title size="2" lineHeight="s" render={<h2 />}>
|
|
34
|
+
Tight heading, chosen body leading
|
|
35
|
+
</Title>
|
|
36
|
+
<Text render={<p />} lineHeight="l">
|
|
37
|
+
Headings in Prose stay on Title `lineHeight="s"`. Body leading is a Text prop — this paragraph uses `l`.
|
|
38
|
+
</Text>
|
|
39
|
+
<Text render={<p />} lineHeight="s">
|
|
40
|
+
A following paragraph can use `lineHeight="s"` when the article should sit denser.
|
|
41
|
+
</Text>
|
|
42
|
+
</Prose>
|
|
43
|
+
]]></tsx>
|
|
44
|
+
<notes>Prose does not own leading. Title inside Prose → `lineHeight="s"`. Text `lineHeight` per block.</notes>
|
|
45
|
+
</example>
|
|
46
|
+
|
|
47
|
+
<example title="Span hosts stay out">
|
|
48
|
+
<tsx><![CDATA[
|
|
49
|
+
<Prose>
|
|
50
|
+
<Title size="4" lineHeight="s">
|
|
51
|
+
This Title is a span — no Prose heading gap
|
|
52
|
+
</Title>
|
|
53
|
+
<Text>This Text is a span — no Prose block gap.</Text>
|
|
54
|
+
<Text render={<p />}>This paragraph is a matching block.</Text>
|
|
55
|
+
</Prose>
|
|
56
|
+
]]></tsx>
|
|
57
|
+
<notes>Default Title/Text hosts are `span`. Use `render` for h1–h6 / `p` when they should join rhythm. Title still `lineHeight="s"`.</notes>
|
|
58
|
+
</example>
|
|
59
|
+
</patterns>
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<props surface="prose">
|
|
3
|
+
<when_to_use>
|
|
4
|
+
<item>Long-form copy whose direct children are headings and blocks that need heading-aware vertical rhythm</item>
|
|
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>
|
|
7
|
+
</when_to_use>
|
|
8
|
+
<when_not_to_use>
|
|
9
|
+
<item>UI chrome spacing (cards, toolbars, form rows) — use Stack `rowGap` / `columnGap`</item>
|
|
10
|
+
<item>Restyling type, lists, links, or tables — stay on Title / Text / consumer CSS</item>
|
|
11
|
+
<item>Markdown parse or sanitize — Prose only spaces matching direct children</item>
|
|
12
|
+
</when_not_to_use>
|
|
13
|
+
<prop name="align" kind="react">
|
|
14
|
+
<description>Aligns the region using logical alignment values. Omit so `text-align` inherits from the parent. Title/Text children that omit `align` inherit this value.</description>
|
|
15
|
+
</prop>
|
|
16
|
+
<prop name="gap" kind="react">
|
|
17
|
+
<description>Em density for heading-aware vertical rhythm (`s` < `m` < `l`).</description>
|
|
18
|
+
</prop>
|
|
19
|
+
<prop name="ref" kind="react">
|
|
20
|
+
<description>Ref forwarded to the rendered prose root element.</description>
|
|
21
|
+
</prop>
|
|
22
|
+
<prop name="render" kind="react">
|
|
23
|
+
<description>Replaces the default `div` root using Base UI render semantics.</description>
|
|
24
|
+
</prop>
|
|
25
|
+
<prop name="align" kind="css">
|
|
26
|
+
<description>Region `text-align` (`--vui-prose-align`) when the `align` prop is set; omitted inherits parent `text-align`.</description>
|
|
27
|
+
</prop>
|
|
28
|
+
<prop name="gap-blocks" kind="css">
|
|
29
|
+
<description>Block sibling gap (`--vui-prose-gap-blocks`). Default `2em` (`l`); `s`/`m` assign smaller triples on the root.</description>
|
|
30
|
+
</prop>
|
|
31
|
+
<prop name="gap-heading-end" kind="css">
|
|
32
|
+
<description>Heading block-end gap (`--vui-prose-gap-heading-end`). Default `0.8em` (`l`).</description>
|
|
33
|
+
</prop>
|
|
34
|
+
<prop name="gap-heading-start" kind="css">
|
|
35
|
+
<description>Gap after a heading onto the next sibling (`--vui-prose-gap-heading-start`). Default `1.3em` (`l`).</description>
|
|
36
|
+
</prop>
|
|
37
|
+
</props>
|