@viraui/react 2026.0.8 → 2026.0.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/dist/catalog.json +2 -2
  2. package/dist/components/accordion/accordion-item.d.ts +7 -0
  3. package/dist/components/accordion/accordion-item.js +7 -1
  4. package/dist/components/accordion/accordion.css +1 -1
  5. package/dist/components/accordion/accordion.guide.json +9 -0
  6. package/dist/components/autocomplete/autocomplete.guide.json +1 -0
  7. package/dist/components/avatar/avatar.guide.json +1 -0
  8. package/dist/components/button/button.guide.json +1 -0
  9. package/dist/components/checkbox/checkbox.guide.json +1 -0
  10. package/dist/components/dialog/dialog.guide.json +1 -0
  11. package/dist/components/fieldset/fieldset.guide.json +1 -0
  12. package/dist/components/linear-progress/linear-progress.guide.json +1 -0
  13. package/dist/components/menu/menu.guide.json +1 -0
  14. package/dist/components/meter/meter.guide.json +1 -0
  15. package/dist/components/popover/popover.guide.json +1 -0
  16. package/dist/components/radio/radio.guide.json +1 -0
  17. package/dist/components/select/select.guide.json +4 -1
  18. package/dist/components/slider/slider.guide.json +1 -0
  19. package/dist/components/stack/stack.css +1 -1
  20. package/dist/components/stack/stack.d.ts +12 -0
  21. package/dist/components/stack/stack.guide.json +7 -3
  22. package/dist/components/stack/stack.js +2 -1
  23. package/dist/components/surface/surface.css +1 -1
  24. package/dist/components/surface/surface.d.ts +12 -0
  25. package/dist/components/surface/surface.guide.json +5 -2
  26. package/dist/components/surface/surface.js +2 -1
  27. package/dist/components/switch/switch.guide.json +1 -0
  28. package/dist/components/tabs/tabs.guide.json +1 -0
  29. package/dist/components/textarea/textarea.guide.json +1 -0
  30. package/dist/components/textfield/textfield.guide.json +1 -0
  31. package/dist/components/toast/toast.guide.json +1 -0
  32. package/dist/components/toggle-button/toggle-button.guide.json +1 -0
  33. package/dist/components/toggle-group/toggle-group.guide.json +1 -0
  34. package/dist/components/tooltip/tooltip.guide.json +1 -0
  35. package/package.json +2 -2
package/dist/catalog.json CHANGED
@@ -185,7 +185,7 @@
185
185
  {
186
186
  "id": "stack",
187
187
  "name": "Stack",
188
- "summary": "Flex layout primitive for arranging children with token spacing, alignment, and padding; root is a named CSS container query context (`stack`).",
188
+ "summary": "Flex layout primitive for arranging children with token spacing, alignment, and padding; optionally enables a named CSS container query context (`stack`) via `enableContainer`.",
189
189
  "guidePath": "./components/stack/stack.guide.json"
190
190
  },
191
191
  {
@@ -197,7 +197,7 @@
197
197
  {
198
198
  "id": "surface",
199
199
  "name": "Surface",
200
- "summary": "Presentational container with token background, optional border, radius, and padding; nested surfaces use radius=\"auto\" for concentric corners; root is a named CSS container query context (`surface`).",
200
+ "summary": "Presentational container with token background, optional border, radius, and padding; nested surfaces use radius=\"auto\" for concentric corners; optionally enables a named CSS container query context (`surface`) via `enableContainer`.",
201
201
  "guidePath": "./components/surface/surface.guide.json"
202
202
  },
203
203
  {
@@ -1,5 +1,6 @@
1
1
  import { AccordionItem } from '@base-ui/react/accordion';
2
2
  import { SurfaceProps } from '../surface';
3
+ import { ThemeTypes } from '@viraui/foundation/vira/types';
3
4
  import type * as React from 'react';
4
5
  /**
5
6
  * Public Accordion.Item props.
@@ -54,5 +55,11 @@ export type AccordionItemProps = AccordionItem.Props & {
54
55
  * @default 1
55
56
  */
56
57
  color?: SurfaceProps['color'];
58
+ /**
59
+ * Corner radius token for the wrapping `Surface` island edges when `useSurface` is `true`.
60
+ *
61
+ * @default medium
62
+ */
63
+ radius?: ThemeTypes['radius'];
57
64
  };
58
65
  export declare const AccordionItemComponent: React.FC<AccordionItemProps>;
@@ -1,4 +1,5 @@
1
1
  import { clsx } from "../../core/clsx.js";
2
+ import { resolveThemeValue } from "../../core/theme/resolve-theme-value.js";
2
3
  import { ChromeMinus, ChromePlus } from "../../internal/chrome-icons/chrome-icons.js";
3
4
  import accordion_module_default from "./accordion.module.js";
4
5
  import { Text } from "../text/text.js";
@@ -7,8 +8,12 @@ import { Surface } from "../surface/surface.js";
7
8
  import { Accordion } from "@base-ui/react/accordion";
8
9
  import { jsx, jsxs } from "react/jsx-runtime";
9
10
  //#region src/components/accordion/accordion-item.tsx
10
- var AccordionItemComponent = ({ children, className, color = 1, iconClosed = /* @__PURE__ */ jsx(ChromePlus, { size: 16 }), iconOpen = /* @__PURE__ */ jsx(ChromeMinus, { size: 16 }), iconPosition = "end", trigger, useSurface = true, ...otherProps }) => {
11
+ var AccordionItemComponent = ({ children, className, color = 1, iconClosed = /* @__PURE__ */ jsx(ChromePlus, { size: 16 }), iconOpen = /* @__PURE__ */ jsx(ChromeMinus, { size: 16 }), iconPosition = "end", radius, style, trigger, useSurface = true, ...otherProps }) => {
11
12
  const iconAtStart = iconPosition === "start";
13
+ const dynamicStyle = {
14
+ ...radius != null && { "--vui-accordion-radius": resolveThemeValue(radius, "radius", "var(--radius-medium)") },
15
+ ...style
16
+ };
12
17
  const triggerIcon = /* @__PURE__ */ jsxs("span", {
13
18
  "aria-hidden": true,
14
19
  className: accordion_module_default.IconSlot,
@@ -23,6 +28,7 @@ var AccordionItemComponent = ({ children, className, color = 1, iconClosed = /*
23
28
  return /* @__PURE__ */ jsxs(Accordion.Item, {
24
29
  className: clsx(accordion_module_default.Item, className),
25
30
  "data-use-surface": useSurface ? "true" : "false",
31
+ style: dynamicStyle,
26
32
  ...useSurface && { render: /* @__PURE__ */ jsx(Surface, {
27
33
  border: "all",
28
34
  color
@@ -1 +1 @@
1
- @layer viraui.preflight, viraui.components, viraui.overrides;@layer viraui.components{@property --vui-accordion-island-gap{syntax:"<length>";inherits:true;initial-value:0}@property --__accordion-trigger-radius{syntax:"<length-percentage>";inherits:true;initial-value:0}.viraui__accordion-module__Accordion_wFOlN{--vui-accordion-island-gap:var(--space-medium);--__accordion-trigger-radius:var(--radius-large);inline-size:100%;&:dir(rtl) .viraui__accordion-module__Trigger_4HzIb[data-stack-direction=row-reverse]{direction:ltr;flex-direction:row}}.viraui__accordion-module__Trigger_4HzIb{inline-size:100%;border:0;background:#0000;cursor:pointer;text-align:start;color:inherit;&:focus-visible{outline-offset:-4px}&[data-disabled]{cursor:not-allowed;opacity:.5}.viraui__accordion-module__Item_66o2x[data-use-surface=true] &{&:focus-visible{border-radius:var(--radius-large);outline-offset:-4px}}}.viraui__accordion-module__IconSlot_AVQq3{position:relative;flex-shrink:0;inline-size:1rem;block-size:1rem}.viraui__accordion-module__Icon_qdu2v{position:absolute;inset:0;display:grid;place-items:center;transition:opacity var(--duration-fast) var(--easing-standard),rotate var(--duration-fast) var(--easing-standard);&:first-of-type{opacity:1;rotate:0deg}&:last-of-type{opacity:0;rotate:-90deg}.viraui__accordion-module__Trigger_4HzIb[data-panel-open] &:first-of-type{opacity:0;rotate:90deg}.viraui__accordion-module__Trigger_4HzIb[data-panel-open] &:last-of-type{opacity:1;rotate:0deg}@media (prefers-reduced-motion:reduce){transition:none}}.viraui__accordion-module__Panel_U1Ofk{block-size:var(--accordion-panel-height);overflow:hidden;transition:block-size var(--duration-fast) var(--easing-standard);&[data-ending-style],&[data-starting-style]{block-size:0}@media (prefers-reduced-motion:reduce){transition:none}}}@layer viraui.overrides{.viraui__accordion-module__Item_66o2x{inline-size:100%;transition:margin var(--duration-fast) var(--easing-standard),background var(--duration-fast) var(--easing-standard),border-radius var(--duration-fast) var(--easing-standard);&[data-use-surface=true]{--vui-surface-border-radius-top-left:0;--vui-surface-border-radius-top-right:0;--vui-surface-border-radius-bottom-right:0;--vui-surface-border-radius-bottom-left:0;&:not([data-open]){--vui-surface-background:#0000}&:not([data-open])+&:not([data-open]),&[data-open]+&[data-open]{border-top-width:0}&:first-child,&:not([data-open])+&[data-open],&[data-open]+&:not([data-open]){--vui-surface-border-radius-top-left:var(--__accordion-trigger-radius);--vui-surface-border-radius-top-right:var(--__accordion-trigger-radius)}&:last-child,&:not([data-open]):has(+&[data-open]),&[data-open]:has(+&:not([data-open])){--vui-surface-border-radius-bottom-left:var(--__accordion-trigger-radius);--vui-surface-border-radius-bottom-right:var(--__accordion-trigger-radius)}&:not(:last-child):not([data-open]):has(+&[data-open]),&:not(:last-child)[data-open]:has(+&:not([data-open])){margin-block-end:var(--vui-accordion-island-gap)}}.viraui__accordion-module__Accordion_wFOlN[data-islands=false] &[data-use-surface=true]{&:not(:first-child){border-top-width:0}&:not([data-open])+&[data-open],&[data-open]+&:not([data-open]){--vui-surface-border-radius-top-left:0;--vui-surface-border-radius-top-right:0}&:not([data-open]):has(+&[data-open]),&[data-open]:has(+&:not([data-open])){--vui-surface-border-radius-bottom-left:0;--vui-surface-border-radius-bottom-right:0}&:not(:last-child):not([data-open]):has(+&[data-open]),&:not(:last-child)[data-open]:has(+&:not([data-open])){margin-block-end:0}}}}
1
+ @layer viraui.preflight, viraui.components, viraui.overrides;@layer viraui.components{@property --vui-accordion-island-gap{syntax:"<length>";inherits:true;initial-value:0}@property --vui-accordion-radius{syntax:"<length-percentage>";inherits:true;initial-value:0}.viraui__accordion-module__Accordion_wFOlN{--vui-accordion-island-gap:var(--space-medium);--vui-accordion-radius:var(--radius-medium);inline-size:100%;&:dir(rtl) .viraui__accordion-module__Trigger_4HzIb[data-stack-direction=row-reverse]{direction:ltr;flex-direction:row}}.viraui__accordion-module__Trigger_4HzIb{inline-size:100%;border:0;background:#0000;cursor:pointer;text-align:start;color:inherit;&:focus-visible{outline-offset:-4px}&[data-disabled]{cursor:not-allowed;opacity:.5}.viraui__accordion-module__Item_66o2x[data-use-surface=true] &{&:focus-visible{border-radius:var(--radius-large);outline-offset:-4px}}}.viraui__accordion-module__IconSlot_AVQq3{position:relative;flex-shrink:0;inline-size:1rem;block-size:1rem}.viraui__accordion-module__Icon_qdu2v{position:absolute;inset:0;display:grid;place-items:center;transition:opacity var(--duration-fast) var(--easing-standard),rotate var(--duration-fast) var(--easing-standard);&:first-of-type{opacity:1;rotate:0deg}&:last-of-type{opacity:0;rotate:-90deg}.viraui__accordion-module__Trigger_4HzIb[data-panel-open] &:first-of-type{opacity:0;rotate:90deg}.viraui__accordion-module__Trigger_4HzIb[data-panel-open] &:last-of-type{opacity:1;rotate:0deg}@media (prefers-reduced-motion:reduce){transition:none}}.viraui__accordion-module__Panel_U1Ofk{block-size:var(--accordion-panel-height);overflow:hidden;transition:block-size var(--duration-fast) var(--easing-standard);&[data-ending-style],&[data-starting-style]{block-size:0}@media (prefers-reduced-motion:reduce){transition:none}}}@layer viraui.overrides{.viraui__accordion-module__Item_66o2x{inline-size:100%;transition:margin var(--duration-fast) var(--easing-standard),background var(--duration-fast) var(--easing-standard),border-radius var(--duration-fast) var(--easing-standard);&[data-use-surface=true]{--vui-surface-border-radius-top-left:0;--vui-surface-border-radius-top-right:0;--vui-surface-border-radius-bottom-right:0;--vui-surface-border-radius-bottom-left:0;&:not([data-open]){--vui-surface-background:#0000}&:not([data-open])+&:not([data-open]),&[data-open]+&[data-open]{border-top-width:0}&:first-child,&:not([data-open])+&[data-open],&[data-open]+&:not([data-open]){--vui-surface-border-radius-top-left:var(--vui-accordion-radius);--vui-surface-border-radius-top-right:var(--vui-accordion-radius)}&:last-child,&:not([data-open]):has(+&[data-open]),&[data-open]:has(+&:not([data-open])){--vui-surface-border-radius-bottom-left:var(--vui-accordion-radius);--vui-surface-border-radius-bottom-right:var(--vui-accordion-radius)}&:not(:last-child):not([data-open]):has(+&[data-open]),&:not(:last-child)[data-open]:has(+&:not([data-open])){margin-block-end:var(--vui-accordion-island-gap)}}.viraui__accordion-module__Accordion_wFOlN[data-islands=false] &[data-use-surface=true]{&:not(:first-child){border-top-width:0}&:not([data-open])+&[data-open],&[data-open]+&:not([data-open]){--vui-surface-border-radius-top-left:0;--vui-surface-border-radius-top-right:0}&:not([data-open]):has(+&[data-open]),&[data-open]:has(+&:not([data-open])){--vui-surface-border-radius-bottom-left:0;--vui-surface-border-radius-bottom-right:0}&:not(:last-child):not([data-open]):has(+&[data-open]),&:not(:last-child)[data-open]:has(+&:not([data-open])){margin-block-end:0}}}}
@@ -1,5 +1,6 @@
1
1
  {
2
2
  "name": "Accordion",
3
+ "baseUIApi": "https://base-ui.com/react/components/accordion#api-reference",
3
4
  "structure": "<Accordion>\n <Accordion.Item trigger=\"…\">…</Accordion.Item>\n</Accordion>",
4
5
  "summary": "Collapsible sections grouped into open/closed blocks with optional Surface wrapping, shared corner radius, and background on open items.",
5
6
  "whenToUse": [
@@ -41,6 +42,10 @@
41
42
  "Item.iconPosition": {
42
43
  "description": "Side of the trigger label where the expand/collapse icon is rendered."
43
44
  },
45
+ "Item.radius": {
46
+ "description": "Corner radius token for the wrapping Surface island edges when useSurface is true.",
47
+ "refCss": "radius"
48
+ },
44
49
  "Item.trigger": {
45
50
  "description": "Visible trigger label rendered inside the accordion header button."
46
51
  },
@@ -51,6 +56,10 @@
51
56
  "css": {
52
57
  "island-gap": {
53
58
  "description": "Gap between separated Surface islands when islands={true}."
59
+ },
60
+ "radius": {
61
+ "description": "Corner radius for Surface island block edges when useSurface is true.",
62
+ "refReact": "Item.radius"
54
63
  }
55
64
  }
56
65
  }
@@ -1,5 +1,6 @@
1
1
  {
2
2
  "name": "Autocomplete",
3
+ "baseUIApi": "https://base-ui.com/react/components/autocomplete#api-reference",
3
4
  "structure": "<Autocomplete>\n <Autocomplete.Item value=\"…\">…</Autocomplete.Item>\n <Autocomplete.Group label=\"…\" items={[…]}>\n <Autocomplete.Collection>\n {(item) => <Autocomplete.Item value={item}>…</Autocomplete.Item>}\n </Autocomplete.Collection>\n </Autocomplete.Group>\n</Autocomplete>",
4
5
  "summary": "Field-wrapped free-form suggest input with Textfield chrome and Select-like popup list.",
5
6
  "whenToUse": [
@@ -1,5 +1,6 @@
1
1
  {
2
2
  "name": "Avatar",
3
+ "baseUIApi": "https://base-ui.com/react/components/avatar#api-reference",
3
4
  "structure": "<Avatar fallback=\"AB\" />",
4
5
  "summary": "Circular identity image or fallback for users, entities, or profile chips.",
5
6
  "whenToUse": [
@@ -1,5 +1,6 @@
1
1
  {
2
2
  "name": "Button",
3
+ "baseUIApi": "https://base-ui.com/react/components/button#api-reference",
3
4
  "structure": "<Button>Save</Button>",
4
5
  "summary": "Primary action control with size, variant, optional addon, optional pill shape, and loading state.",
5
6
  "whenToUse": [
@@ -1,5 +1,6 @@
1
1
  {
2
2
  "name": "Checkbox",
3
+ "baseUIApi": "https://base-ui.com/react/components/checkbox#api-reference",
3
4
  "structure": "<Checkbox label=\"…\" />",
4
5
  "summary": "Field.Item checkbox option for standalone fields or CheckboxGroup children.",
5
6
  "whenToUse": [
@@ -1,5 +1,6 @@
1
1
  {
2
2
  "name": "Dialog",
3
+ "baseUIApi": "https://base-ui.com/react/components/drawer#api-reference",
3
4
  "structure": "<Dialog>\n <Dialog.Trigger />\n <Dialog.Sheet title=\"…\">…</Dialog.Sheet>\n</Dialog>",
4
5
  "summary": "Compound drawer sheet with `Dialog.Trigger`, `Dialog.Sheet`, `Dialog.Close`, and Base UI pass-through `Dialog.Provider`, `Dialog.Indent`, and `Dialog.IndentBackground` for app-shell indent effects.",
5
6
  "whenToUse": [
@@ -1,5 +1,6 @@
1
1
  {
2
2
  "name": "Fieldset",
3
+ "baseUIApi": "https://base-ui.com/react/components/fieldset#api-reference",
3
4
  "structure": "<Fieldset label=\"…\">…</Fieldset>",
4
5
  "summary": "Semantic field grouping with shared legend and optional group helper copy.",
5
6
  "whenToUse": [
@@ -1,5 +1,6 @@
1
1
  {
2
2
  "name": "LinearProgress",
3
+ "baseUIApi": "https://base-ui.com/react/components/progress#api-reference",
3
4
  "structure": "<LinearProgress value={40} />",
4
5
  "summary": "Shows determinate or indeterminate progress for a task in a compact horizontal track.",
5
6
  "whenToUse": [
@@ -1,5 +1,6 @@
1
1
  {
2
2
  "name": "Menu",
3
+ "baseUIApi": "https://base-ui.com/react/components/menu#api-reference",
3
4
  "structure": "<Menu>\n <Menu.Trigger />\n <Menu.Popup>\n <Menu.Item />\n <Menu.LinkItem />\n <Menu.CheckboxItem />\n <Menu.Group label=\"…\">\n <Menu.Item />\n </Menu.Group>\n <Menu.RadioGroup>\n <Menu.RadioItem value=\"…\" />\n </Menu.RadioGroup>\n <Menu.Separator />\n <Menu.Submenu>\n <Menu.SubmenuTrigger />\n <Menu.Popup>…</Menu.Popup>\n </Menu.Submenu>\n </Menu.Popup>\n</Menu>",
4
5
  "summary": "Compound menu built on Base UI Menu with `Menu.Trigger`, `Menu.Popup`, unified item rows, groups, checkbox/radio items, nested submenus, destructive sentiment, and `Menu.createHandle` for detached triggers; `Popup` owns Portal + Positioner + Elevator/Surface Select-like list chrome.",
5
6
  "whenToUse": [
@@ -1,5 +1,6 @@
1
1
  {
2
2
  "name": "Meter",
3
+ "baseUIApi": "https://base-ui.com/react/components/meter#api-reference",
3
4
  "structure": "<Meter value={40} />",
4
5
  "summary": "Shows a determinate metric in a compact horizontal track for static capacity, level, or score values.",
5
6
  "whenToUse": [
@@ -1,5 +1,6 @@
1
1
  {
2
2
  "name": "Popover",
3
+ "baseUIApi": "https://base-ui.com/react/components/popover#api-reference",
3
4
  "structure": "<Popover>\n <Popover.Trigger />\n <Popover.Sheet title=\"…\">…</Popover.Sheet>\n</Popover>",
4
5
  "summary": "Compound popover built on Base UI Popover with `Popover.Trigger`, `Popover.Sheet`, `Popover.Close`, `Popover.Title`, `Popover.Description`, and `Popover.createHandle` for detached and multiple triggers; `Sheet` encapsulates Portal + Positioner + Popup + Viewport + Title + Description and animates position, size, and content between triggers; `Sheet` with `unstyled` skips the built-in Surface and header so the consumer composes the popup chrome, including `Popover.Title` and `Popover.Description`.",
5
6
  "whenToUse": [
@@ -1,5 +1,6 @@
1
1
  {
2
2
  "name": "Radio",
3
+ "baseUIApi": "https://base-ui.com/react/components/radio#api-reference",
3
4
  "structure": "<RadioGroup>\n <Radio value=\"…\" label=\"…\" />\n</RadioGroup>",
4
5
  "summary": "Mutually exclusive choice within a RadioGroup, with optional per-option label and helper text.",
5
6
  "whenToUse": [
@@ -1,5 +1,6 @@
1
1
  {
2
2
  "name": "Select",
3
+ "baseUIApi": "https://base-ui.com/react/components/select#api-reference",
3
4
  "structure": "<Select>\n <Select.Option value=\"…\">…</Select.Option>\n <Select.Group label=\"…\">\n <Select.Option value=\"…\">…</Select.Option>\n </Select.Group>\n <Select.Separator />\n</Select>",
4
5
  "summary": "Field-wrapped single-select dropdown with grouped options and field copy.",
5
6
  "whenToUse": [
@@ -23,7 +24,9 @@
23
24
  "antiPatterns": [
24
25
  "Expecting multi-select or combobox behavior",
25
26
  "Leaving the trigger without label or aria-label",
26
- "Never set the size prop (if present) of Buttons, IconButtons or other interactive elements passed as addon other than small"
27
+ "Never set the size prop (if present) of Buttons, IconButtons or other interactive elements passed as addon other than small",
28
+ "Using the Select component as a combobox, use Autocomplete instead.",
29
+ "Set alignItemWithTrigger false when options don't have a leading addon"
27
30
  ],
28
31
  "related": ["Autocomplete", "Fieldset", "Textfield", "Stack", "Surface", "Icon"],
29
32
  "properties": {
@@ -1,5 +1,6 @@
1
1
  {
2
2
  "name": "Slider",
3
+ "baseUIApi": "https://base-ui.com/react/components/slider#api-reference",
3
4
  "structure": "<Slider />",
4
5
  "summary": "Field-wrapped range input supporting single-thumb or two-thumb range selection.",
5
6
  "whenToUse": [
@@ -1 +1 @@
1
- @layer viraui.preflight, viraui.components, viraui.overrides;@layer viraui.components{@property --vui-stack-row-gap{syntax:"<length>";inherits:false;initial-value:0}@property --vui-stack-column-gap{syntax:"<length>";inherits:false;initial-value:0}@property --vui-stack-h-align{syntax:"*";inherits:false;initial-value:initial}@property --vui-stack-v-align{syntax:"*";inherits:false;initial-value:initial}@property --vui-stack-padding-inline-start{syntax:"<length>";inherits:false;initial-value:0}@property --vui-stack-padding-inline-end{syntax:"<length>";inherits:false;initial-value:0}@property --vui-stack-padding-block-start{syntax:"<length>";inherits:false;initial-value:0}@property --vui-stack-padding-block-end{syntax:"<length>";inherits:false;initial-value:0}@property --vui-stack-max-width{syntax:"*";inherits:false;initial-value:none}@property --vui-stack-min-width{syntax:"*";inherits:false;initial-value:none}.viraui__stack-module__Stack_NR-Ey{display:flex;gap:var(--vui-stack-row-gap) var(--vui-stack-column-gap);flex-direction:column;align-items:var(--vui-stack-h-align);justify-content:var(--vui-stack-v-align);max-inline-size:var(--vui-stack-max-width);min-inline-size:var(--vui-stack-min-width);&[data-stack-direction=column-reverse]{flex-direction:column-reverse}&[data-stack-direction=row-reverse],&[data-stack-direction=row]{align-items:var(--vui-stack-v-align);justify-content:var(--vui-stack-h-align)}&[data-stack-direction=row]{flex-direction:row}&[data-stack-direction=row-reverse]{flex-direction:row-reverse}&[data-stack-inline=true]{display:inline-flex;flex-grow:0}:where(&[data-stack-wrap=true]){flex-wrap:wrap}:where(&[data-stack-has-padding=true]){padding:var(--vui-stack-padding-block-start) var(--vui-stack-padding-inline-end) var(--vui-stack-padding-block-end) var(--vui-stack-padding-inline-start)}:where(&[data-stack-fill-children=true]>*){flex-grow:var(--vira-flex-grow,1)}}}
1
+ @layer viraui.preflight, viraui.components, viraui.overrides;@layer viraui.components{@property --vui-stack-row-gap{syntax:"<length>";inherits:false;initial-value:0}@property --vui-stack-column-gap{syntax:"<length>";inherits:false;initial-value:0}@property --vui-stack-h-align{syntax:"*";inherits:false;initial-value:initial}@property --vui-stack-v-align{syntax:"*";inherits:false;initial-value:initial}@property --vui-stack-padding-inline-start{syntax:"<length>";inherits:false;initial-value:0}@property --vui-stack-padding-inline-end{syntax:"<length>";inherits:false;initial-value:0}@property --vui-stack-padding-block-start{syntax:"<length>";inherits:false;initial-value:0}@property --vui-stack-padding-block-end{syntax:"<length>";inherits:false;initial-value:0}@property --vui-stack-max-width{syntax:"*";inherits:false;initial-value:none}@property --vui-stack-min-width{syntax:"*";inherits:false;initial-value:none}.viraui__stack-module__Stack_NR-Ey{display:flex;gap:var(--vui-stack-row-gap) var(--vui-stack-column-gap);flex-direction:column;align-items:var(--vui-stack-h-align);justify-content:var(--vui-stack-v-align);max-inline-size:var(--vui-stack-max-width);min-inline-size:var(--vui-stack-min-width);&[data-stack-direction=column-reverse]{flex-direction:column-reverse}&[data-stack-direction=row-reverse],&[data-stack-direction=row]{align-items:var(--vui-stack-v-align);justify-content:var(--vui-stack-h-align)}&[data-stack-direction=row]{flex-direction:row}&[data-stack-direction=row-reverse]{flex-direction:row-reverse}&[data-stack-inline=true]{display:inline-flex;flex-grow:0}:where(&[data-stack-wrap=true]){flex-wrap:wrap}:where(&[data-stack-has-padding=true]){padding:var(--vui-stack-padding-block-start) var(--vui-stack-padding-inline-end) var(--vui-stack-padding-block-end) var(--vui-stack-padding-inline-start)}:where(&[data-stack-fill-children=true]>*){flex-grow:var(--vira-flex-grow,1)}&[data-stack-container=true]{container:stack/size}}}
@@ -97,6 +97,18 @@ export type StackProps = React.ComponentPropsWithoutRef<'div'> & {
97
97
  * @default No min width constraint.
98
98
  */
99
99
  minWidth?: string;
100
+ /**
101
+ * Opt-in named CSS container query context for this Stack.
102
+ *
103
+ * Enables `container: stack / size` on the rendered root (via `data-stack-container="true"`),
104
+ * so descendants can use `@container stack (min-width/min-height: ...)` against this Stack size.
105
+ *
106
+ * Warning: container size containment can affect nested layout (e.g. cards inside Masonry).
107
+ * Use only when you need container queries against this specific Stack.
108
+ *
109
+ * @default false
110
+ */
111
+ enableContainer?: boolean;
100
112
  };
101
113
  export declare const Stack: React.FC<StackProps>;
102
114
  export {};
@@ -1,16 +1,17 @@
1
1
  {
2
2
  "name": "Stack",
3
3
  "structure": "<Stack>…</Stack>",
4
- "summary": "Flex layout primitive for arranging children with token spacing, alignment, and padding; root is a named CSS container query context (`stack`).",
4
+ "summary": "Flex layout primitive for arranging children with token spacing, alignment, and padding; optionally enables a named CSS container query context (`stack`) via `enableContainer`.",
5
5
  "whenToUse": [
6
6
  "Column or row layouts with token gap and alignment",
7
7
  "Composing screens and component internals without custom flex CSS",
8
8
  "Custom native root through render while keeping data-stack hooks",
9
- "Style descendants with @container stack queries when layout, gap, or typography should respond to the Stack's own inline-size and block-size instead of the viewport"
9
+ "Style descendants with `@container stack` queries when layout, gap, or typography should respond to the Stack's own inline-size and block-size instead of the viewport (set `enableContainer` on the Stack you're querying)"
10
10
  ],
11
11
  "whenNotToUse": [
12
12
  "Cases where a single component already owns required flex chrome",
13
- "Expecting the Stack root itself to grow via fillChildren"
13
+ "Expecting the Stack root itself to grow via fillChildren",
14
+ "Using `enableContainer` inside complex masonry-like layouts when you don't need container queries (size containment can change nested layout)"
14
15
  ],
15
16
  "accessibility": [
16
17
  "Stack is presentational — choose render roots that preserve correct semantics (button, list, heading)",
@@ -27,6 +28,9 @@
27
28
  "columnGap": {
28
29
  "description": "Sets the gap between flex columns using the Vira space token scale."
29
30
  },
31
+ "enableContainer": {
32
+ "description": "Opt-in named CSS container query context for this Stack (enables `container: stack / size` on the root via `data-stack-container`). Required for `@container stack (min-width/min-height: ...)` rules to react to this Stack size. Warning: container size containment can affect nested layout (e.g. cards inside Masonry). Use only when you need container queries against this specific Stack."
33
+ },
30
34
  "direction": {
31
35
  "description": "Renders children across rows or columns using the chosen flex direction."
32
36
  },
@@ -5,7 +5,7 @@ import { resolveAxisPadding } from "../../core/styles/resolve-axis-padding.js";
5
5
  import stack_module_default from "./stack.module.js";
6
6
  import { useRender } from "@base-ui/react/use-render";
7
7
  //#region src/components/stack/stack.tsx
8
- var Stack = ({ className, direction = "column", fillChildren = true, hAlign = "initial", hPadding, inline = false, maxWidth, minWidth, ref, render, rowGap, columnGap, style, vAlign = "initial", vPadding, wrap = false, ...otherProps }) => {
8
+ var Stack = ({ className, direction = "column", fillChildren = true, hAlign = "initial", hPadding, inline = false, maxWidth, minWidth, enableContainer, ref, render, rowGap, columnGap, style, vAlign = "initial", vPadding, wrap = false, ...otherProps }) => {
9
9
  const hasPadding = Boolean(hPadding || vPadding);
10
10
  const dynamicStyle = {
11
11
  "--vui-stack-row-gap": resolveThemeValue(rowGap, "space", 0),
@@ -25,6 +25,7 @@ var Stack = ({ className, direction = "column", fillChildren = true, hAlign = "i
25
25
  props: {
26
26
  ...otherProps,
27
27
  "data-stack-direction": direction,
28
+ ...enableContainer && { "data-stack-container": "true" },
28
29
  "data-stack-inline": inline ? "true" : "false",
29
30
  "data-stack-wrap": wrap ? "true" : "false",
30
31
  "data-stack-fill-children": fillChildren ? "true" : "false",
@@ -1 +1 @@
1
- @layer viraui.preflight, viraui.components, viraui.overrides;@layer viraui.components{@property --vui-surface-background{syntax:"*";inherits:false;initial-value:none}@property --vui-surface-background-hover{syntax:"*";inherits:false;initial-value:none}@property --vui-surface-border-style{syntax:"<custom-ident>";inherits:false;initial-value:solid}@property --vui-surface-overflow{syntax:"<custom-ident>";inherits:false;initial-value:visible}@property --vui-surface-border-radius{syntax:"<length-percentage>";inherits:false;initial-value:0}@property --vui-surface-border-radius-top-left{syntax:"<length-percentage>";inherits:false;initial-value:0}@property --vui-surface-border-radius-top-right{syntax:"<length-percentage>";inherits:false;initial-value:0}@property --vui-surface-border-radius-bottom-right{syntax:"<length-percentage>";inherits:false;initial-value:0}@property --vui-surface-border-radius-bottom-left{syntax:"<length-percentage>";inherits:false;initial-value:0}@property --vui-surface-padding-inline-start{syntax:"<length>";inherits:false;initial-value:0}@property --vui-surface-padding-inline-end{syntax:"<length>";inherits:false;initial-value:0}@property --vui-surface-padding-block-start{syntax:"<length>";inherits:false;initial-value:0}@property --vui-surface-padding-block-end{syntax:"<length>";inherits:false;initial-value:0}.viraui__surface-module__Surface_slEYq{--vui-surface-border-radius-top-left:var(--vui-surface-border-radius);--vui-surface-border-radius-top-right:var(--vui-surface-border-radius);--vui-surface-border-radius-bottom-right:var(--vui-surface-border-radius);--vui-surface-border-radius-bottom-left:var(--vui-surface-border-radius);--vui-surface-background-hover:var(--vui-surface-background);position:relative;overflow:var(--vui-surface-overflow);box-sizing:border-box;background:var(--vui-surface-background);border-radius:var(--vui-surface-border-radius-top-left) var(--vui-surface-border-radius-top-right) var(--vui-surface-border-radius-bottom-right) var(--vui-surface-border-radius-bottom-left);border:0;&[data-surface-color=primary]{--vui-surface-background:light-dark(oklab(from var(--global-primary) l a b/20%),oklab(from var(--global-primary) l a b/10%))}&[data-surface-hover-color=primary]{--vui-surface-background-hover:light-dark(oklab(from var(--global-primary) l a b/20%),oklab(from var(--global-primary) l a b/10%))}@container root not style(--vibrancy-enable: initial){&[data-vibrant]{background:light-dark(oklab(from var(--vui-surface-background) l a b/60%),oklab(from var(--vui-surface-background) l a b/80%))}}&[data-surface-has-padding=true]{padding:var(--vui-surface-padding-block-start) var(--vui-surface-padding-inline-end) var(--vui-surface-padding-block-end) var(--vui-surface-padding-inline-start)}&[data-surface-border]{border-style:var(--vui-surface-border-style);border-color:var(--global-contrast)}&[data-surface-border=all]{border-width:1px}&[data-surface-border=top]{border-width:1px 0 0}&[data-surface-border=right]{border-width:0 1px 0 0}&[data-surface-border=bottom]{border-width:0 0 1px}&[data-surface-border=left]{border-width:0 0 0 1px}&[data-surface-border=x]{border-width:0 1px}&[data-surface-border=y]{border-width:1px 0}@media (hover:hover) and (pointer:fine){&[data-surface-has-hover-color=true]:hover{background:var(--vui-surface-background-hover)}}}}
1
+ @layer viraui.preflight, viraui.components, viraui.overrides;@layer viraui.components{@property --vui-surface-background{syntax:"*";inherits:false;initial-value:none}@property --vui-surface-background-hover{syntax:"*";inherits:false;initial-value:none}@property --vui-surface-border-style{syntax:"<custom-ident>";inherits:false;initial-value:solid}@property --vui-surface-overflow{syntax:"<custom-ident>";inherits:false;initial-value:visible}@property --vui-surface-border-radius{syntax:"<length-percentage>";inherits:false;initial-value:0}@property --vui-surface-border-radius-top-left{syntax:"<length-percentage>";inherits:false;initial-value:0}@property --vui-surface-border-radius-top-right{syntax:"<length-percentage>";inherits:false;initial-value:0}@property --vui-surface-border-radius-bottom-right{syntax:"<length-percentage>";inherits:false;initial-value:0}@property --vui-surface-border-radius-bottom-left{syntax:"<length-percentage>";inherits:false;initial-value:0}@property --vui-surface-padding-inline-start{syntax:"<length>";inherits:false;initial-value:0}@property --vui-surface-padding-inline-end{syntax:"<length>";inherits:false;initial-value:0}@property --vui-surface-padding-block-start{syntax:"<length>";inherits:false;initial-value:0}@property --vui-surface-padding-block-end{syntax:"<length>";inherits:false;initial-value:0}.viraui__surface-module__Surface_slEYq{--vui-surface-border-radius-top-left:var(--vui-surface-border-radius);--vui-surface-border-radius-top-right:var(--vui-surface-border-radius);--vui-surface-border-radius-bottom-right:var(--vui-surface-border-radius);--vui-surface-border-radius-bottom-left:var(--vui-surface-border-radius);--vui-surface-background-hover:var(--vui-surface-background);position:relative;overflow:var(--vui-surface-overflow);box-sizing:border-box;background:var(--vui-surface-background);border-radius:var(--vui-surface-border-radius-top-left) var(--vui-surface-border-radius-top-right) var(--vui-surface-border-radius-bottom-right) var(--vui-surface-border-radius-bottom-left);border:0;&[data-surface-color=primary]{--vui-surface-background:light-dark(oklab(from var(--global-primary) l a b/20%),oklab(from var(--global-primary) l a b/10%))}&[data-surface-hover-color=primary]{--vui-surface-background-hover:light-dark(oklab(from var(--global-primary) l a b/20%),oklab(from var(--global-primary) l a b/10%))}@container root not style(--vibrancy-enable: initial){&[data-vibrant]{background:light-dark(oklab(from var(--vui-surface-background) l a b/60%),oklab(from var(--vui-surface-background) l a b/80%))}}&[data-surface-has-padding=true]{padding:var(--vui-surface-padding-block-start) var(--vui-surface-padding-inline-end) var(--vui-surface-padding-block-end) var(--vui-surface-padding-inline-start)}&[data-surface-border]{border-style:var(--vui-surface-border-style);border-color:var(--global-contrast)}&[data-surface-border=all]{border-width:1px}&[data-surface-border=top]{border-width:1px 0 0}&[data-surface-border=right]{border-width:0 1px 0 0}&[data-surface-border=bottom]{border-width:0 0 1px}&[data-surface-border=left]{border-width:0 0 0 1px}&[data-surface-border=x]{border-width:0 1px}&[data-surface-border=y]{border-width:1px 0}@media (hover:hover) and (pointer:fine){&[data-surface-has-hover-color=true]:hover{background:var(--vui-surface-background-hover)}}&[data-surface-container=true]{container:surface/size}}}
@@ -77,6 +77,18 @@ export type SurfaceProps = Omit<React.ComponentPropsWithoutRef<'div'>, 'color'>
77
77
  * @default visible
78
78
  */
79
79
  overflow?: React.CSSProperties['overflow'];
80
+ /**
81
+ * Opt-in named CSS container query context for this Surface.
82
+ *
83
+ * Enables `container: surface / size` on the rendered root (via `data-surface-container="true"`),
84
+ * so descendants can use `@container surface (min-width/min-height: ...)` against this Surface size.
85
+ *
86
+ * Warning: container size containment can affect nested layout (e.g. cards inside Masonry).
87
+ * Use only when you need container queries against this specific Surface.
88
+ *
89
+ * @default false
90
+ */
91
+ enableContainer?: boolean;
80
92
  };
81
93
  export declare const Surface: React.FC<SurfaceProps>;
82
94
  export {};
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "Surface",
3
3
  "structure": "<Surface>…</Surface>",
4
- "summary": "Presentational container with token background, optional border, radius, and padding; nested surfaces use radius=\"auto\" for concentric corners; root is a named CSS container query context (`surface`).",
4
+ "summary": "Presentational container with token background, optional border, radius, and padding; nested surfaces use radius=\"auto\" for concentric corners; optionally enables a named CSS container query context (`surface`) via `enableContainer`.",
5
5
  "whenToUse": [
6
6
  "Group content with base-level background and contrast border",
7
7
  "Popup or card chrome with optional hover background",
@@ -11,7 +11,7 @@
11
11
  "Set radius=\"auto\" on a nested Surface when its parent Surface has a radius so each corner subtracts the nearest ancestor padding and stays concentric",
12
12
  "Stack nested auto-radius Surfaces recursively; context still resolves through wrapper layout such as Stack",
13
13
  "Set overflow=\"hidden\" (or scroll/auto) when Surface must clip or scroll inner content with radius or padding",
14
- "Style descendants with @container surface queries when layout or typography should respond to the Surface's own inline-size and block-size instead of the viewport"
14
+ "Style descendants with `@container surface` queries when layout or typography should respond to the Surface's own inline-size and block-size instead of the viewport (set `enableContainer` on the Surface you're querying)"
15
15
  ],
16
16
  "whenNotToUse": [
17
17
  "Interactive control semantics without an appropriate render root",
@@ -36,6 +36,9 @@
36
36
  "border": {
37
37
  "description": "Applies the shared contrast border on the chosen side or axis. Omit for no border."
38
38
  },
39
+ "enableContainer": {
40
+ "description": "Opt-in named CSS container query context for this Surface (enables `container: surface / size` on the root). Required for `@container surface (min-width/min-height: ...)` rules to react to this Surface size. Warning: container size containment can affect nested layout (e.g. cards inside Masonry). Use only when you need container queries against this specific Surface."
41
+ },
39
42
  "borderStyle": {
40
43
  "description": "Sets the CSS border style when `border` is set."
41
44
  },
@@ -20,7 +20,7 @@ var surfaceDefaultRadiusProps = {
20
20
  style: void 0,
21
21
  vPadding: void 0
22
22
  };
23
- var Surface = ({ border, borderStyle = "solid", className, color, hPadding, hoverColor, overflow, radius, ref, render, style, vPadding, ...otherProps }) => {
23
+ var Surface = ({ border, borderStyle = "solid", className, color, hPadding, hoverColor, overflow, radius, ref, render, style, vPadding, enableContainer, ...otherProps }) => {
24
24
  const hasPadding = Boolean(hPadding || vPadding);
25
25
  const hasHoverColor = hoverColor !== void 0;
26
26
  const { contextValue, hasAutoRadius, radiusStyle } = useSurfaceRadius({
@@ -50,6 +50,7 @@ var Surface = ({ border, borderStyle = "solid", className, color, hPadding, hove
50
50
  ...hasAutoRadius && { "data-surface-radius": "auto" },
51
51
  ...isSurfaceColorToken(color) && { "data-surface-color": color },
52
52
  ...isSurfaceColorToken(hoverColor) && { "data-surface-hover-color": hoverColor },
53
+ ...enableContainer && { "data-surface-container": "true" },
53
54
  "data-surface-has-hover-color": hasHoverColor ? "true" : "false",
54
55
  "data-surface-has-padding": hasPadding ? "true" : "false",
55
56
  className: clsx(surface_module_default.Surface, className),
@@ -1,5 +1,6 @@
1
1
  {
2
2
  "name": "Switch",
3
+ "baseUIApi": "https://base-ui.com/react/components/switch#api-reference",
3
4
  "structure": "<Switch label=\"…\" />",
4
5
  "summary": "Field-wrapped toggle control with regular or small track and optional field copy.",
5
6
  "whenToUse": [
@@ -1,5 +1,6 @@
1
1
  {
2
2
  "name": "Tabs",
3
+ "baseUIApi": "https://base-ui.com/react/components/tabs#api-reference",
3
4
  "structure": "<Tabs>\n <Tabs.List>\n <Tabs.Tab value=\"a\">…</Tabs.Tab>\n </Tabs.List>\n <Tabs.Viewport>\n <Tabs.Panel value=\"a\">…</Tabs.Panel>\n </Tabs.Viewport>\n</Tabs>",
4
5
  "summary": "Compound segmented tab control with Surface list chrome, moving indicator, and animated panels.",
5
6
  "whenToUse": [
@@ -1,5 +1,6 @@
1
1
  {
2
2
  "name": "Textarea",
3
+ "baseUIApi": "https://base-ui.com/react/components/field#api-reference",
3
4
  "structure": "<Textarea />",
4
5
  "summary": "Multi-line field control with shared field copy, optional resize, and optional content sizing.",
5
6
  "whenToUse": [
@@ -1,5 +1,6 @@
1
1
  {
2
2
  "name": "Textfield",
3
+ "baseUIApi": "https://base-ui.com/react/components/input#api-reference",
3
4
  "structure": "<Textfield />",
4
5
  "summary": "Single-line field input with control-group chrome and optional addons.",
5
6
  "whenToUse": [
@@ -1,5 +1,6 @@
1
1
  {
2
2
  "name": "Toast",
3
+ "baseUIApi": "https://base-ui.com/react/components/toast#api-reference",
3
4
  "structure": "<Toast.Provider>\n <Toast.Portal>\n <Toast.Viewport>\n <Toast.Banner toast={…}>\n <Toast.Action>…</Toast.Action>\n </Toast.Banner>\n </Toast.Viewport>\n </Toast.Portal>\n</Toast.Provider>",
4
5
  "summary": "Transient notification surface with stacked or anchored placement, Banner high-level API, and optional action buttons.",
5
6
  "whenToUse": [
@@ -1,5 +1,6 @@
1
1
  {
2
2
  "name": "ToggleButton",
3
+ "baseUIApi": "https://base-ui.com/react/components/toggle#api-reference",
3
4
  "structure": "<ToggleButton restingIcon={<Plus />} aria-label=\"Pin\" />",
4
5
  "summary": "Icon-only two-state toggle that swaps resting and optional pressed icons on Base UI Toggle state; `interpolateIcons` (default false) opt-in crossfade + light rotate between dual icons.",
5
6
  "whenToUse": [
@@ -1,5 +1,6 @@
1
1
  {
2
2
  "name": "ToggleGroup",
3
+ "baseUIApi": "https://base-ui.com/react/components/toggle-group#api-reference",
3
4
  "structure": "<ToggleGroup>\n <ToggleButton restingIcon={<Plus />} aria-label=\"List\" value=\"list\" />\n</ToggleGroup>",
4
5
  "summary": "Toolbar toggle set with shared selection state; Stack direction follows orientation with zero default gap.",
5
6
  "whenToUse": [
@@ -1,5 +1,6 @@
1
1
  {
2
2
  "name": "Tooltip",
3
+ "baseUIApi": "https://base-ui.com/react/components/tooltip#api-reference",
3
4
  "structure": "<Tooltip>\n <Tooltip.Trigger />\n <Tooltip.Content />\n</Tooltip>",
4
5
  "summary": "Compound tooltip built on Base UI Tooltip with `Tooltip.Provider`, `Tooltip.Trigger`, `Tooltip.Content`, and `Tooltip.createHandle` for detached and multiple triggers; `Content` encapsulates Portal + Positioner + Popup + Viewport and animates position, size, and content between triggers.",
5
6
  "whenToUse": [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@viraui/react",
3
- "version": "2026.0.8",
3
+ "version": "2026.0.10",
4
4
  "private": false,
5
5
  "files": [
6
6
  "dist"
@@ -35,7 +35,7 @@
35
35
  "unplugin-dts": "1.0.3",
36
36
  "vite": "8.1.4",
37
37
  "vite-plugin-static-copy": "4.1.1",
38
- "@viraui/foundation": "2026.0.8",
38
+ "@viraui/foundation": "2026.0.10",
39
39
  "@viraui/icons": "2026.0.0",
40
40
  "@viraui/postcss-config": "2026.0.0",
41
41
  "@viraui/tsconfig": "2026.0.0"