{"slug":"cascade-select","title":"Cascade Select","description":"Using the cascade select machine in your project.","contentType":"component","framework":"react","content":"A cascade select component allows users to select from hierarchical data through\nmultiple linked levels of dropdown menus.\n\n## Resources\n\n\n[Latest version: v1.39.1](https://www.npmjs.com/package/@zag-js/cascade-select)\n[Logic Visualizer](https://zag-visualizer.vercel.app/cascade-select)\n[Source Code](https://github.com/chakra-ui/zag/tree/main/packages/machines/cascade-select)\n\n\n\n**Features**\n\n- Supports hierarchical data with unlimited depth levels\n- Full keyboard navigation across all levels with arrow keys\n- Supports single and multiple selections\n- Supports both click and hover triggering modes\n- Supports looping keyboard navigation\n- Built-in accessibility with ARIA roles and keyboard interactions\n- Supports disabled items and read-only state\n- Form integration with hidden input element\n- Supports right-to-left direction\n\n## Installation\n\nInstall the cascade select package:\n\n```bash\nnpm install @zag-js/cascade-select @zag-js/react\n# or\nyarn add @zag-js/cascade-select @zag-js/react\n```\n\n## Anatomy\n\nCheck the cascade select anatomy and part names.\n\n> Each part includes a `data-part` attribute to help identify them in the DOM.\n\n\n\n## Usage\n\nImport the cascade select package:\n\n```tsx\nimport * as cascadeSelect from \"@zag-js/cascade-select\"\n```\n\nThese are the key exports:\n\n- `machine` - State machine logic.\n- `connect` - Maps machine state to JSX props and event handlers.\n- `collection` - Creates a tree collection from your hierarchical data.\n\n### Create the collection\n\nUse the `collection` function to create a tree collection from your hierarchical\ndata. Pass a `rootNode` along with functions to extract each node's value,\nstring label, and children.\n\n```ts\nimport * as cascadeSelect from \"@zag-js/cascade-select\"\n\ninterface Node {\n  label: string\n  value: string\n  children?: Node[]\n}\n\nconst collection = cascadeSelect.collection<Node>({\n  nodeToValue: (node) => node.value,\n  nodeToString: (node) => node.label,\n  nodeToChildren: (node) => node.children,\n  rootNode: {\n    label: \"ROOT\",\n    value: \"ROOT\",\n    children: [\n      {\n        label: \"North America\",\n        value: \"north-america\",\n        children: [\n          {\n            label: \"United States\",\n            value: \"us\",\n            children: [\n              { label: \"New York\", value: \"ny\" },\n              { label: \"California\", value: \"ca\" },\n            ],\n          },\n          { label: \"Canada\", value: \"canada\" },\n        ],\n      },\n      {\n        label: \"Africa\",\n        value: \"africa\",\n        children: [\n          { label: \"Nigeria\", value: \"ng\" },\n          { label: \"Kenya\", value: \"ke\" },\n        ],\n      },\n    ],\n  },\n})\n```\n\n### Create the cascade select\n\n> Pass a unique `id` to `useMachine` so generated element ids stay predictable.\n\nThen use the framework integration helpers:\n\n```tsx\nimport * as cascadeSelect from \"@zag-js/cascade-select\"\nimport { normalizeProps, Portal, useMachine } from \"@zag-js/react\"\nimport { JSX, useId } from \"react\"\n\n// 1. Create the collection (see above)\nconst collection = cascadeSelect.collection<Node>({\n  // ...\n})\n\n// 2. Create the recursive tree node\n\ninterface TreeNodeProps {\n  node: Node\n  indexPath?: number[]\n  value?: string[]\n  api: cascadeSelect.Api\n}\n\nconst TreeNode = (props: TreeNodeProps): JSX.Element => {\n  const { node, indexPath = [], value = [], api } = props\n\n  const nodeProps = { indexPath, value, item: node }\n  const nodeState = api.getItemState(nodeProps)\n  const children = collection.getNodeChildren(node)\n\n  return (\n    <>\n      <ul {...api.getListProps(nodeProps)}>\n        {children.map((item, index) => {\n          const itemProps = {\n            indexPath: [...indexPath, index],\n            value: [...value, collection.getNodeValue(item)],\n            item,\n          }\n          const itemState = api.getItemState(itemProps)\n          return (\n            <li key={collection.getNodeValue(item)} {...api.getItemProps(itemProps)}>\n              <span {...api.getItemTextProps(itemProps)}>{item.label}</span>\n              {itemState.hasChildren && <span>›</span>}\n              <span {...api.getItemIndicatorProps(itemProps)}>✓</span>\n            </li>\n          )\n        })}\n      </ul>\n      {nodeState.highlightedChild &&\n        collection.isBranchNode(nodeState.highlightedChild) && (\n          <TreeNode\n            node={nodeState.highlightedChild}\n            api={api}\n            indexPath={[...indexPath, nodeState.highlightedIndex]}\n            value={[...value, collection.getNodeValue(nodeState.highlightedChild)]}\n          />\n        )}\n    </>\n  )\n}\n\n// 3. Create the cascade select\n\nexport function CascadeSelect() {\n  const service = useMachine(cascadeSelect.machine, {\n    id: useId(),\n    collection,\n  })\n\n  const api = cascadeSelect.connect(service, normalizeProps)\n\n  return (\n    <div {...api.getRootProps()}>\n      <label {...api.getLabelProps()}>Location</label>\n      <div {...api.getControlProps()}>\n        <button {...api.getTriggerProps()}>\n          <span>{api.valueAsString || \"Select location\"}</span>\n          <span {...api.getIndicatorProps()}>▼</span>\n        </button>\n        <button {...api.getClearTriggerProps()}>✕</button>\n      </div>\n      <Portal>\n        <div {...api.getPositionerProps()}>\n          <div {...api.getContentProps()}>\n            <TreeNode node={collection.rootNode} api={api} />\n          </div>\n        </div>\n      </Portal>\n    </div>\n  )\n}\n```\n\n### Setting the initial value\n\nUse the `defaultValue` property to set the initial value of the cascade select.\n\n> The `value` property must be an array of string paths. Each path is an array\n> of values from the root to the selected leaf item.\n\n```tsx {4}\nconst service = useMachine(cascadeSelect.machine, {\n  id: useId(),\n  collection,\n  defaultValue: [[\"north-america\", \"us\", \"ny\"]],\n})\n```\n\n### Controlled selection\n\nUse `value` and `onValueChange` for controlled selection state.\n\n```tsx\nconst service = useMachine(cascadeSelect.machine, {\n  id: useId(),\n  collection,\n  value,\n  onValueChange(details) {\n    setValue(details.value)\n  },\n})\n```\n\n### Selecting multiple values\n\nTo allow selecting multiple values, set the `multiple` property to `true`.\n\n```tsx {4}\nconst service = useMachine(cascadeSelect.machine, {\n  id: useId(),\n  collection,\n  multiple: true,\n})\n```\n\n### Hover triggering\n\nBy default, items are highlighted when clicked. To highlight items on hover\ninstead (like a traditional cascading menu), set the `highlightTrigger` property\nto `\"hover\"`.\n\n```tsx {4}\nconst service = useMachine(cascadeSelect.machine, {\n  id: useId(),\n  collection,\n  highlightTrigger: \"hover\",\n})\n```\n\n### Allowing parent selection\n\nBy default, only leaf nodes (items without children) can be selected. To allow\nparent (branch) nodes to also be selectable, set `allowParentSelection` to\n`true`.\n\n```tsx {4}\nconst service = useMachine(cascadeSelect.machine, {\n  id: useId(),\n  collection,\n  allowParentSelection: true,\n})\n```\n\n### Close on select\n\nBy default, the menu closes when you select an item. Set `closeOnSelect` to\n`false` to keep it open.\n\n```tsx {4}\nconst service = useMachine(cascadeSelect.machine, {\n  id: useId(),\n  collection,\n  closeOnSelect: false,\n})\n```\n\n### Looping the keyboard navigation\n\nBy default, arrow-key navigation stops at the first and last items. Set\n`loopFocus: true` to loop back around.\n\n```tsx {4}\nconst service = useMachine(cascadeSelect.machine, {\n  id: useId(),\n  collection,\n  loopFocus: true,\n})\n```\n\n### Listening for highlight changes\n\nWhen an item is highlighted with the pointer or keyboard, use the\n`onHighlightChange` to listen for the change and do something with it.\n\n```tsx {3-6}\nconst service = useMachine(cascadeSelect.machine, {\n  id: useId(),\n  onHighlightChange(details) {\n    // details => { highlightedValue: string[], highlightedItems: Item[] }\n    console.log(details)\n  },\n})\n```\n\n### Setting the initial highlighted path\n\nUse `defaultHighlightedValue` to set the initially highlighted path.\n\n```tsx\nconst service = useMachine(cascadeSelect.machine, {\n  id: useId(),\n  collection,\n  defaultHighlightedValue: [\"north-america\", \"us\"],\n})\n```\n\n### Controlled highlighted path\n\nUse `highlightedValue` and `onHighlightChange` to control highlighting\nexternally.\n\n```tsx\nconst service = useMachine(cascadeSelect.machine, {\n  id: useId(),\n  collection,\n  highlightedValue,\n  onHighlightChange(details) {\n    setHighlightedValue(details.highlightedValue)\n  },\n})\n```\n\n### Listening for selection changes\n\nWhen an item is selected, use the `onValueChange` property to listen for the\nchange and do something with it.\n\n```tsx {4-7}\nconst service = useMachine(cascadeSelect.machine, {\n  id: useId(),\n  collection,\n  onValueChange(details) {\n    // details => { value: string[][], items: Item[][] }\n    console.log(details)\n  },\n})\n```\n\n### Listening for open and close events\n\nUse `onOpenChange` to listen for open and close events.\n\n```tsx {4-7}\nconst service = useMachine(cascadeSelect.machine, {\n  id: useId(),\n  collection,\n  onOpenChange(details) {\n    // details => { open: boolean, value: string[][] }\n    console.log(details)\n  },\n})\n```\n\n### Controlling open state\n\nUse `open` and `onOpenChange` for controlled open state, or `defaultOpen` for an\nuncontrolled initial state.\n\n```tsx\nconst service = useMachine(cascadeSelect.machine, {\n  id: useId(),\n  collection,\n  open,\n  onOpenChange({ open }) {\n    setOpen(open)\n  },\n})\n```\n\n```tsx\nconst service = useMachine(cascadeSelect.machine, {\n  id: useId(),\n  collection,\n  defaultOpen: true,\n})\n```\n\n### Positioning submenu panels\n\nUse `positioning` to configure placement and collision behavior.\n\n```tsx\nconst service = useMachine(cascadeSelect.machine, {\n  id: useId(),\n  collection,\n  positioning: {\n    placement: \"right-start\",\n    gutter: 4,\n  },\n})\n```\n\n### Custom scroll behavior\n\nUse `scrollToIndexFn` to customize how each level scrolls highlighted items into\nview.\n\n```tsx\nconst service = useMachine(cascadeSelect.machine, {\n  id: useId(),\n  collection,\n  scrollToIndexFn(details) {\n    // details => { index, depth, immediate? }\n    customScroll(details)\n  },\n})\n```\n\n### Customizing the trigger label\n\nUse `formatValue` to control how selected paths are rendered in the trigger.\n\n```tsx\nconst service = useMachine(cascadeSelect.machine, {\n  id: useId(),\n  collection,\n  formatValue(selectedItems) {\n    return selectedItems\n      .map((path) => path.map((item) => item.label).join(\" / \"))\n      .join(\", \")\n  },\n})\n```\n\n### Usage within a form\n\nTo use cascade select in a form, pass `name`. A hidden input is rendered with\n`getHiddenInputProps()`.\n\n```tsx {4}\nconst service = useMachine(cascadeSelect.machine, {\n  id: useId(),\n  collection,\n  name: \"location\",\n})\n\n// In your JSX\n<input {...api.getHiddenInputProps()} />\n```\n\nIf the hidden input belongs to a different form element, also set `form`.\n\n```tsx\nconst service = useMachine(cascadeSelect.machine, {\n  id: useId(),\n  collection,\n  name: \"location\",\n  form: \"checkout-form\",\n})\n```\n\n### Validation and read-only state\n\nUse `readOnly`, `required`, and `invalid` to control interaction and form state.\n\n```tsx\nconst service = useMachine(cascadeSelect.machine, {\n  id: useId(),\n  collection,\n  readOnly: true,\n  required: true,\n  invalid: false,\n})\n```\n\n## Styling guide\n\nEach cascade select part includes a `data-part` attribute you can target in CSS.\n\n### Open and closed state\n\nWhen the cascade select is open, the trigger and content is given a `data-state`\nattribute.\n\n```css\n[data-part=\"trigger\"][data-state=\"open|closed\"] {\n  /* styles for open or closed state */\n}\n\n[data-part=\"content\"][data-state=\"open|closed\"] {\n  /* styles for open or closed state */\n}\n```\n\n### Selected state\n\nItems are given a `data-state` attribute, indicating whether they are selected.\n\n```css\n[data-part=\"item\"][data-state=\"checked|unchecked\"] {\n  /* styles for selected or unselected state */\n}\n```\n\n### Highlighted state\n\nWhen an item is highlighted, via keyboard navigation or pointer, it is given a\n`data-highlighted` attribute.\n\n```css\n[data-part=\"item\"][data-highlighted] {\n  /* styles for highlighted state */\n}\n```\n\n### Branch items\n\nWhen an item has children (is a branch node), it is given a `data-has-children`\nattribute.\n\n```css\n[data-part=\"item\"][data-has-children] {\n  /* styles for items with children (branch nodes) */\n}\n```\n\n### Invalid state\n\nWhen the cascade select is invalid, the label and trigger is given a\n`data-invalid` attribute.\n\n```css\n[data-part=\"label\"][data-invalid] {\n  /* styles for invalid state */\n}\n\n[data-part=\"trigger\"][data-invalid] {\n  /* styles for invalid state */\n}\n```\n\n### Disabled state\n\nWhen the cascade select is disabled, the trigger and label is given a\n`data-disabled` attribute.\n\n```css\n[data-part=\"trigger\"][data-disabled] {\n  /* styles for disabled state */\n}\n\n[data-part=\"label\"][data-disabled] {\n  /* styles for disabled label state */\n}\n\n[data-part=\"item\"][data-disabled] {\n  /* styles for disabled item state */\n}\n```\n\n### Empty state\n\nWhen no option is selected, the trigger is given a `data-placeholder-shown`\nattribute.\n\n```css\n[data-part=\"trigger\"][data-placeholder-shown] {\n  /* styles for empty state */\n}\n```\n\n## Methods and Properties\n\n### Machine Context\n\nThe cascade select machine exposes the following context properties:\n\n**`collection`**\nType: `TreeCollection<T>`\nDescription: The tree collection data\n\n**`ids`**\nType: `Partial<{ root: string; label: string; control: string; trigger: string; indicator: string; clearTrigger: string; positioner: string; content: string; hiddenInput: string; list(valuePath: string): string; item(valuePath: string): string; }>`\nDescription: The ids of the cascade-select elements. Useful for composition.\n\n**`name`**\nType: `string`\nDescription: The name attribute of the underlying input element\n\n**`form`**\nType: `string`\nDescription: The form attribute of the underlying input element\n\n**`value`**\nType: `string[][]`\nDescription: The controlled value of the cascade-select\n\n**`defaultValue`**\nType: `string[][]`\nDescription: The initial value of the cascade-select when rendered.\nUse when you don't need to control the value.\n\n**`highlightedValue`**\nType: `string[]`\nDescription: The controlled highlighted value of the cascade-select\n\n**`defaultHighlightedValue`**\nType: `string[]`\nDescription: The initial highlighted value of the cascade-select when rendered.\n\n**`multiple`**\nType: `boolean`\nDescription: Whether to allow multiple selections\n\n**`open`**\nType: `boolean`\nDescription: The controlled open state of the cascade-select\n\n**`defaultOpen`**\nType: `boolean`\nDescription: The initial open state of the cascade-select when rendered.\nUse when you don't need to control the open state.\n\n**`highlightTrigger`**\nType: `\"click\" | \"hover\"`\nDescription: What triggers highlighting of items\n\n**`closeOnSelect`**\nType: `boolean`\nDescription: Whether the cascade-select should close when an item is selected\n\n**`loopFocus`**\nType: `boolean`\nDescription: Whether the cascade-select should loop focus when navigating with keyboard\n\n**`disabled`**\nType: `boolean`\nDescription: Whether the cascade-select is disabled\n\n**`readOnly`**\nType: `boolean`\nDescription: Whether the cascade-select is read-only\n\n**`required`**\nType: `boolean`\nDescription: Whether the cascade-select is required\n\n**`invalid`**\nType: `boolean`\nDescription: Whether the cascade-select is invalid\n\n**`positioning`**\nType: `PositioningOptions`\nDescription: The positioning options for the cascade-select content\n\n**`scrollToIndexFn`**\nType: `(details: ScrollToIndexDetails) => void`\nDescription: Function to scroll to a specific index in a list\n\n**`formatValue`**\nType: `(selectedItems: T[][]) => string`\nDescription: Function to format the display value\n\n**`onValueChange`**\nType: `(details: ValueChangeDetails<T>) => void`\nDescription: Called when the value changes\n\n**`onHighlightChange`**\nType: `(details: HighlightChangeDetails<T>) => void`\nDescription: Called when the highlighted value changes\n\n**`onOpenChange`**\nType: `(details: OpenChangeDetails) => void`\nDescription: Called when the open state changes\n\n**`allowParentSelection`**\nType: `boolean`\nDescription: Whether parent (branch) items can be selectable\n\n**`dir`**\nType: `\"ltr\" | \"rtl\"`\nDescription: The document's text/writing direction.\n\n**`id`**\nType: `string`\nDescription: The unique identifier of the machine.\n\n**`getRootNode`**\nType: `() => ShadowRoot | Node | Document`\nDescription: A root node to correctly resolve document in custom environments. E.x.: Iframes, Electron.\n\n**`onPointerDownOutside`**\nType: `(event: PointerDownOutsideEvent) => void`\nDescription: Function called when the pointer is pressed down outside the component\n\n**`onFocusOutside`**\nType: `(event: FocusOutsideEvent) => void`\nDescription: Function called when the focus is moved outside the component\n\n**`onInteractOutside`**\nType: `(event: InteractOutsideEvent) => void`\nDescription: Function called when an interaction happens outside the component\n\n### Machine API\n\nThe cascade select `api` exposes the following methods:\n\n**`collection`**\nType: `TreeCollection<V>`\nDescription: The tree collection data\n\n**`open`**\nType: `boolean`\nDescription: Whether the cascade-select is open\n\n**`focused`**\nType: `boolean`\nDescription: Whether the cascade-select is focused\n\n**`multiple`**\nType: `boolean`\nDescription: Whether the cascade-select allows multiple selections\n\n**`disabled`**\nType: `boolean`\nDescription: Whether the cascade-select is disabled\n\n**`highlightedValue`**\nType: `string[]`\nDescription: The value of the highlighted item\n\n**`highlightedItems`**\nType: `V[]`\nDescription: The items along the highlighted path\n\n**`selectedItems`**\nType: `V[][]`\nDescription: The selected items\n\n**`hasSelectedItems`**\nType: `boolean`\nDescription: Whether there's a selected option\n\n**`empty`**\nType: `boolean`\nDescription: Whether the cascade-select value is empty\n\n**`value`**\nType: `string[][]`\nDescription: The current value of the cascade-select\n\n**`valueAsString`**\nType: `string`\nDescription: The current value as text\n\n**`focus`**\nType: `() => void`\nDescription: Function to focus on the select input\n\n**`reposition`**\nType: `(options?: Partial<PositioningOptions>) => void`\nDescription: Function to set the positioning options of the cascade-select\n\n**`setOpen`**\nType: `(open: boolean) => void`\nDescription: Function to open the cascade-select\n\n**`setHighlightValue`**\nType: `(value: string | string[]) => void`\nDescription: Function to set the highlighted value (path or single value to find)\n\n**`clearHighlightValue`**\nType: `() => void`\nDescription: Function to clear the highlighted value\n\n**`selectValue`**\nType: `(value: string[]) => void`\nDescription: Function to select a value\n\n**`setValue`**\nType: `(value: string[][]) => void`\nDescription: Function to set the value\n\n**`clearValue`**\nType: `(value?: string[]) => void`\nDescription: Function to clear the value\n\n**`getItemState`**\nType: `(props: ItemProps<V>) => ItemState<V>`\nDescription: Returns the state of a cascade-select item\n\n### Data Attributes\n\n**`Root`**\n\n**`data-scope`**: cascade-select\n**`data-part`**: root\n**`data-disabled`**: Present when disabled\n**`data-readonly`**: Present when read-only\n**`data-invalid`**: Present when invalid\n**`data-state`**: \"open\" | \"closed\"\n\n**`Label`**\n\n**`data-scope`**: cascade-select\n**`data-part`**: label\n**`data-disabled`**: Present when disabled\n**`data-readonly`**: Present when read-only\n**`data-invalid`**: Present when invalid\n\n**`Control`**\n\n**`data-scope`**: cascade-select\n**`data-part`**: control\n**`data-disabled`**: Present when disabled\n**`data-focus`**: Present when focused\n**`data-readonly`**: Present when read-only\n**`data-invalid`**: Present when invalid\n**`data-state`**: \"open\" | \"closed\"\n\n**`Trigger`**\n\n**`data-scope`**: cascade-select\n**`data-part`**: trigger\n**`data-state`**: \"open\" | \"closed\"\n**`data-disabled`**: Present when disabled\n**`data-readonly`**: Present when read-only\n**`data-invalid`**: Present when invalid\n**`data-focus`**: Present when focused\n**`data-placement`**: The placement of the trigger\n**`data-placeholder-shown`**: Present when placeholder is shown\n\n**`ClearTrigger`**\n\n**`data-scope`**: cascade-select\n**`data-part`**: clear-trigger\n**`data-disabled`**: Present when disabled\n**`data-readonly`**: Present when read-only\n**`data-invalid`**: Present when invalid\n\n**`Content`**\n\n**`data-scope`**: cascade-select\n**`data-part`**: content\n**`data-activedescendant`**: The id the active descendant of the content\n**`data-state`**: \"open\" | \"closed\"\n\n**`List`**\n\n**`data-scope`**: cascade-select\n**`data-part`**: list\n**`data-depth`**: The depth of the item\n\n**`Indicator`**\n\n**`data-scope`**: cascade-select\n**`data-part`**: indicator\n**`data-state`**: \"open\" | \"closed\"\n**`data-disabled`**: Present when disabled\n**`data-readonly`**: Present when read-only\n**`data-invalid`**: Present when invalid\n\n**`Item`**\n\n**`data-scope`**: cascade-select\n**`data-part`**: item\n**`data-value`**: The value of the item\n**`data-disabled`**: Present when disabled\n**`data-highlighted`**: Present when highlighted\n**`data-selected`**: Present when selected\n**`data-depth`**: The depth of the item\n**`data-state`**: \"checked\" | \"unchecked\"\n**`data-type`**: The type of the item\n**`data-index-path`**: \n\n**`ItemText`**\n\n**`data-scope`**: cascade-select\n**`data-part`**: item-text\n**`data-value`**: The value of the item\n**`data-highlighted`**: Present when highlighted\n**`data-state`**: \"checked\" | \"unchecked\"\n**`data-disabled`**: Present when disabled\n\n**`ItemIndicator`**\n\n**`data-scope`**: cascade-select\n**`data-part`**: item-indicator\n**`data-value`**: The value of the item\n**`data-highlighted`**: Present when highlighted\n**`data-type`**: The type of the item\n**`data-state`**: \"checked\" | \"unchecked\"\n\n**`ValueText`**\n\n**`data-scope`**: cascade-select\n**`data-part`**: value-text\n**`data-disabled`**: Present when disabled\n**`data-invalid`**: Present when invalid\n**`data-focus`**: Present when focused\n\n### CSS Variables\n\n<CssVarTable name=\"cascade-select\" />\n\n## Accessibility\n\nAdheres to the\n[ListBox WAI-ARIA design pattern](https://www.w3.org/WAI/ARIA/apg/patterns/listbox).\n\n### Keyboard Interactions\n\n**`Space`**\nDescription: <span>When focus is on trigger, opens the cascade select and focuses the first item.<br />When focus is on the content, selects the highlighted item.</span>\n\n**`Enter`**\nDescription: <span>When focus is on trigger, opens the cascade select and focuses the first item.<br />When focus is on content, selects the highlighted item.</span>\n\n**`ArrowDown`**\nDescription: <span>When focus is on trigger, opens the cascade select.<br />When focus is on content, moves focus to the next item in the current level.</span>\n\n**`ArrowUp`**\nDescription: <span>When focus is on trigger, opens the cascade select and focuses the last item.<br />When focus is on content, moves focus to the previous item in the current level.</span>\n\n**`ArrowRight`**\nDescription: <span>When focus is on a branch item, expands the next level and moves focus into it.</span>\n\n**`ArrowLeft`**\nDescription: <span>When focus is on a nested level, collapses it and moves focus back to the parent.<br />When focus is at the root level, closes the cascade select.</span>\n\n**`Home`**\nDescription: <span>Moves focus to the first item in the current level.</span>\n\n**`End`**\nDescription: <span>Moves focus to the last item in the current level.</span>\n\n**`Esc`**\nDescription: <span>Closes the cascade select and moves focus to trigger.</span>","package":"@zag-js/cascade-select","editUrl":"https://github.com/chakra-ui/zag/edit/main/website/data/components/cascade-select.mdx"}