{"slug":"tree-view","title":"Tree View","description":"Using the tree view machine in your project.","contentType":"component","framework":"react","content":"The TreeView component provides a hierarchical view of data, similar to a file\nsystem explorer. It allows users to expand and collapse branches, select\nindividual or multiple nodes, and traverse the hierarchy using keyboard\nnavigation.\n\n## Resources\n\n\n[Latest version: v1.35.3](https://www.npmjs.com/package/@zag-js/tree-view)\n[Logic Visualizer](https://zag-visualizer.vercel.app/tree-view)\n[Source Code](https://github.com/chakra-ui/zag/tree/main/packages/machines/tree-view)\n\n\n\n**Features**\n\n- Display hierarchical data in a tree structure\n- Expand or collapse nodes\n- Supports keyboard navigation\n- Select single or multiple nodes (depending on the selection mode)\n- Perform actions on the nodes, such as deleting them or performing some other\n  operation\n\n## Installation\n\nInstall the tree view package:\n\n```bash\nnpm install @zag-js/tree-view @zag-js/react\n# or\nyarn add @zag-js/tree-view @zag-js/react\n```\n\n## Anatomy\n\nCheck the tree view anatomy and part names.\n\n\n\n## Usage\n\nImport the tree view package:\n\n```jsx\nimport * as tree from \"@zag-js/tree-view\"\n```\n\nThe tree view package exports two key functions:\n\n- `machine` - State machine logic.\n- `connect` - Maps machine state to JSX props and event handlers.\n\nThen use the framework integration helpers:\n\n### Create the tree collection\n\nUse the `collection` function to create a tree collection. This creates a tree\nfactory that the component uses for traversal.\n\n```ts\nimport * as tree from \"@zag-js/tree-view\"\n\ninterface Node {\n  id: string\n  name: string\n  children?: Node[]\n}\n\nconst collection = tree.collection<Node>({\n  nodeToValue: (node) => node.id,\n  nodeToString: (node) => node.name,\n  rootNode: {\n    id: \"ROOT\",\n    name: \"\",\n    children: [\n      {\n        id: \"node_modules\",\n        name: \"node_modules\",\n        children: [\n          { id: \"node_modules/zag-js\", name: \"zag-js\" },\n          { id: \"node_modules/pandacss\", name: \"panda\" },\n          {\n            id: \"node_modules/@types\",\n            name: \"@types\",\n            children: [\n              { id: \"node_modules/@types/react\", name: \"react\" },\n              { id: \"node_modules/@types/react-dom\", name: \"react-dom\" },\n            ],\n          },\n        ],\n      },\n    ],\n  },\n})\n```\n\n### Create the tree view\n\nPass the tree collection to the machine to create the tree view.\n\n```tsx\nimport { normalizeProps, useMachine } from \"@zag-js/react\"\nimport * as tree from \"@zag-js/tree-view\"\nimport { FileIcon, FolderIcon, ChevronRightIcon } from \"lucide-react\"\nimport { useId } from \"react\"\n\n// 1. Create the tree collection\n\ninterface Node {\n  id: string\n  name: string\n  children?: Node[]\n}\n\nconst collection = tree.collection<Node>({\n  // ...\n})\n\n// 2. Create the recursive tree node\n\ninterface TreeNodeProps {\n  node: Node\n  indexPath: number[]\n  api: tree.Api\n}\n\nconst TreeNode = (props: TreeNodeProps): JSX.Element => {\n  const { node, indexPath, api } = props\n\n  const nodeProps = { indexPath, node }\n  const nodeState = api.getNodeState(nodeProps)\n\n  if (nodeState.isBranch) {\n    return (\n      <div {...api.getBranchProps(nodeProps)}>\n        <div {...api.getBranchControlProps(nodeProps)}>\n          <FolderIcon />\n          <span {...api.getBranchTextProps(nodeProps)}>{node.name}</span>\n          <span {...api.getBranchIndicatorProps(nodeProps)}>\n            <ChevronRightIcon />\n          </span>\n        </div>\n        <div {...api.getBranchContentProps(nodeProps)}>\n          <div {...api.getBranchIndentGuideProps(nodeProps)} />\n          {node.children?.map((childNode, index) => (\n            <TreeNode\n              key={childNode.id}\n              node={childNode}\n              indexPath={[...indexPath, index]}\n              api={api}\n            />\n          ))}\n        </div>\n      </div>\n    )\n  }\n\n  return (\n    <div {...api.getItemProps(nodeProps)}>\n      <FileIcon /> {node.name}\n    </div>\n  )\n}\n\n// 3. Create the tree view\n\nexport function TreeView() {\n  const service = useMachine(tree.machine, { id: useId(), collection })\n  const api = tree.connect(service, normalizeProps)\n\n  return (\n    <div {...api.getRootProps()}>\n      <h3 {...api.getLabelProps()}>My Documents</h3>\n      <div {...api.getTreeProps()}>\n        {collection.rootNode.children?.map((node, index) => (\n          <TreeNode key={node.id} node={node} indexPath={[index]} api={api} />\n        ))}\n      </div>\n    </div>\n  )\n}\n```\n\n### Expanding and Collapsing Nodes\n\nBy default, the tree view will expand or collapse when clicking the branch\ncontrol. To control the expanded state of the tree view, use the `api.expand`\nand `api.collapse` methods.\n\n> **Note:** The array parameter contains individual node values/IDs, not paths.\n> All nodes specified in the array will be collapsed or expanded.\n\n```tsx\napi.expand([\"node_modules/zag-js\"]) // expand a single node by its value/ID\napi.expand([\"node_modules/zag-js\", \"node_modules/pandacss\"]) // expand multiple nodes by their values/IDs\napi.expand() // expand all nodes\n\napi.collapse([\"node_modules/@types\"]) // collapse a single node by its value/ID\napi.collapse([\"node_modules/@types\", \"node_modules/pandacss\"]) // collapse multiple nodes by their values/IDs\napi.collapse() // collapse all nodes\n```\n\n### Multiple selection\n\nThe tree view supports multiple selection. To enable this, set the\n`selectionMode` to `multiple`.\n\n```tsx {2}\nconst service = useMachine(tree.machine, {\n  selectionMode: \"multiple\",\n})\n```\n\n### Setting the default expanded nodes\n\nTo set the default expanded nodes, use `defaultExpandedValue`.\n\n```tsx {2}\nconst service = useMachine(tree.machine, {\n  defaultExpandedValue: [\"node_modules/pandacss\"],\n})\n```\n\n### Setting the default selected nodes\n\nTo set the default selected nodes, use `defaultSelectedValue`.\n\n```tsx {2}\nconst service = useMachine(tree.machine, {\n  defaultSelectedValue: [\"node_modules/pandacss\"],\n})\n```\n\n### Controlled expanded and selected values\n\nUse controlled props when expansion or selection is managed externally.\n\n```tsx\nconst service = useMachine(tree.machine, {\n  collection,\n  expandedValue,\n  selectedValue,\n  onExpandedChange(details) {\n    setExpandedValue(details.expandedValue)\n  },\n  onSelectionChange(details) {\n    setSelectedValue(details.selectedValue)\n  },\n})\n```\n\n### Indentation Guide\n\nWhen rendering a branch node in the tree view, you can render the `indentGuide`\nelement by using the `api.getBranchIndentGuideProps()` function.\n\n```tsx {9}\n<div {...api.getBranchProps(nodeProps)}>\n  <div {...api.getBranchControlProps(nodeProps)}>\n    <FolderIcon />\n    {node.name}\n    <span {...api.getBranchIndicatorProps(nodeProps)}>\n      <ChevronRightIcon />\n    </span>\n  </div>\n  <div {...api.getBranchContentProps(nodeProps)}>\n    <div {...api.getBranchIndentGuideProps(nodeProps)} />\n    {node.children.map((childNode, index) => (\n      <TreeNode\n        key={childNode.id}\n        node={childNode}\n        indexPath={[...indexPath, index]}\n        api={api}\n      />\n    ))}\n  </div>\n</div>\n```\n\n### Listening for selection\n\nWhen a node is selected, the `onSelectionChange` callback is invoked with the\nselected nodes.\n\n```jsx {2-5}\nconst service = useMachine(tree.machine, {\n  onSelectionChange(details) {\n    // details => { focusedValue, selectedValue, selectedNodes }\n    console.log(\"selected nodes:\", details.selectedNodes)\n  },\n})\n```\n\n### Listening for expanding and collapsing\n\nWhen a node is expanded or collapsed, the `onExpandedChange` callback is invoked\nwith the expanded nodes.\n\n```jsx {2-5}\nconst service = useMachine(tree.machine, {\n  onExpandedChange(details) {\n    // details => { focusedValue, expandedValue, expandedNodes }\n    console.log(\"expanded nodes:\", details.expandedNodes)\n  },\n})\n```\n\n### Listening for focus and checked changes\n\nUse `onFocusChange` and `onCheckedChange` when you need focus/checkbox state.\n\n```tsx\nconst service = useMachine(tree.machine, {\n  onFocusChange(details) {\n    // details => { focusedValue, focusedNode }\n    console.log(details.focusedValue)\n  },\n  onCheckedChange(details) {\n    // details => { checkedValue: string[] }\n    console.log(details.checkedValue)\n  },\n})\n```\n\n### Programmatic tree control\n\nUse the connected API for imperative interactions.\n\n```tsx\napi.expand([\"node_modules\"])\napi.collapse([\"node_modules/@types\"])\napi.select([\"node_modules/pandacss\"])\napi.deselect([\"node_modules/pandacss\"])\napi.focus(\"node_modules\")\napi.toggleChecked(\"node_modules\", true)\n```\n\n### Controlling branch click behavior\n\nSet `expandOnClick` to control whether clicking a branch toggles expansion.\n\n```tsx\nconst service = useMachine(tree.machine, {\n  collection,\n  expandOnClick: false,\n})\n```\n\n### Controlling typeahead\n\nSet `typeahead` to disable keyboard typeahead matching.\n\n```tsx\nconst service = useMachine(tree.machine, {\n  collection,\n  typeahead: false,\n})\n```\n\n### Lazy Loading\n\n> **Added in v1.15.0**\n\nLazy loading is a feature that allows the tree view to load children of a node\non demand. This helps to improve the initial load time and memory usage.\n\nTo use this, you need to provide the following:\n\n- `loadChildren` — A function that is used to load the children of a node.\n- `onLoadChildrenComplete` — A callback that is called when the children of a\n  node are loaded. Used to update the tree collection.\n- `onLoadChildrenError` — A callback that is called when loading fails.\n- `childrenCount` — A number that indicates the number of children of a branch\n  node.\n\n```tsx\nfunction TreeAsync() {\n  const [collection, setCollection] = useState(\n    tree.collection({\n      nodeToValue: (node) => node.id,\n      nodeToString: (node) => node.name,\n      rootNode: {\n        id: \"ROOT\",\n        name: \"\",\n        children: [\n          { id: \"node_modules\", name: \"node_modules\", childrenCount: 3 },\n          { id: \"src\", name: \"src\", childrenCount: 2 },\n        ],\n      },\n    }),\n  )\n\n  const service = useMachine(tree.machine, {\n    id: useId(),\n    collection,\n    async loadChildren({ valuePath, signal }) {\n      const url = `/api/file-system/${valuePath.join(\"/\")}`\n      const response = await fetch(url, { signal })\n      const data = await response.json()\n      return data.children\n    },\n    onLoadChildrenComplete({ collection }) {\n      setCollection(collection)\n    },\n    onLoadChildrenError({ nodes }) {\n      console.error(\"Failed to load:\", nodes)\n    },\n  })\n\n  // ...\n}\n```\n\n### Renaming Nodes\n\nThe tree view supports renaming node labels inline, perfect for file explorers,\ncontent management systems, and other applications where users need to edit item\nnames.\n\nTo enable renaming:\n\n1. Add the rename input to your tree node component\n2. Handle the `onRenameComplete` callback to update your collection\n\n```tsx\nimport { normalizeProps, useMachine } from \"@zag-js/react\"\nimport * as tree from \"@zag-js/tree-view\"\nimport { FileIcon, FolderIcon, ChevronRightIcon } from \"lucide-react\"\nimport { useId, useState } from \"react\"\n\n// 1. Create the tree collection with state\n\ninterface Node {\n  id: string\n  name: string\n  children?: Node[]\n}\n\nconst initialCollection = tree.collection<Node>({\n  nodeToValue: (node) => node.id,\n  nodeToString: (node) => node.name,\n  rootNode: {\n    id: \"ROOT\",\n    name: \"\",\n    children: [\n      { id: \"README.md\", name: \"README.md\" },\n      { id: \"package.json\", name: \"package.json\" },\n    ],\n  },\n})\n\n// 2. Create the tree node with rename input\n\ninterface TreeNodeProps {\n  node: Node\n  indexPath: number[]\n  api: tree.Api\n}\n\nconst TreeNode = (props: TreeNodeProps): JSX.Element => {\n  const { node, indexPath, api } = props\n\n  const nodeProps = { indexPath, node }\n  const nodeState = api.getNodeState(nodeProps)\n\n  if (nodeState.isBranch) {\n    return (\n      <div {...api.getBranchProps(nodeProps)}>\n        <div {...api.getBranchControlProps(nodeProps)}>\n          <FolderIcon />\n          <span\n            {...api.getBranchTextProps(nodeProps)}\n            style={{ display: nodeState.renaming ? \"none\" : \"inline\" }}\n          >\n            {node.name}\n          </span>\n          <input {...api.getNodeRenameInputProps(nodeProps)} />\n          <span {...api.getBranchIndicatorProps(nodeProps)}>\n            <ChevronRightIcon />\n          </span>\n        </div>\n        <div {...api.getBranchContentProps(nodeProps)}>\n          <div {...api.getBranchIndentGuideProps(nodeProps)} />\n          {node.children?.map((childNode, index) => (\n            <TreeNode\n              key={childNode.id}\n              node={childNode}\n              indexPath={[...indexPath, index]}\n              api={api}\n            />\n          ))}\n        </div>\n      </div>\n    )\n  }\n\n  return (\n    <div {...api.getItemProps(nodeProps)}>\n      <FileIcon />\n      <span\n        {...api.getItemTextProps(nodeProps)}\n        style={{ display: nodeState.renaming ? \"none\" : \"inline\" }}\n      >\n        {node.name}\n      </span>\n      <input {...api.getNodeRenameInputProps(nodeProps)} />\n    </div>\n  )\n}\n\n// 3. Setup rename handlers\n\nexport function TreeView() {\n  const [collection, setCollection] = useState(initialCollection)\n\n  const service = useMachine(tree.machine, {\n    id: useId(),\n    collection,\n    onRenameComplete: (details) => {\n      // Update the collection with the new label\n      const node = collection.at(details.indexPath)\n      const updatedCollection = collection.replace(details.indexPath, {\n        ...node,\n        name: details.label,\n      })\n      setCollection(updatedCollection)\n    },\n  })\n\n  const api = tree.connect(service, normalizeProps)\n\n  return (\n    <div {...api.getRootProps()}>\n      <h3 {...api.getLabelProps()}>My Documents</h3>\n      <p>Press F2 to rename any file or folder</p>\n      <div {...api.getTreeProps()}>\n        {collection.rootNode.children?.map((node, index) => (\n          <TreeNode key={node.id} node={node} indexPath={[index]} api={api} />\n        ))}\n      </div>\n    </div>\n  )\n}\n```\n\n### Controlling which nodes can be renamed\n\nUse the `canRename` callback to control which nodes are renameable based on node\ntype or custom logic.\n\n```tsx {3-6}\nconst service = useMachine(tree.machine, {\n  collection,\n  canRename(node, indexPath) {\n    // Only allow renaming leaf nodes (files), not branches (folders)\n    return !node.children\n  },\n})\n```\n\n### Validating rename input\n\nUse the `onBeforeRename` callback to validate the new name before accepting the\nchange. Return `false` to reject the rename.\n\n```tsx {3-14}\nconst service = useMachine(tree.machine, {\n  collection,\n  onBeforeRename(details) {\n    // Prevent empty names (label is already trimmed)\n    if (!details.label) return false\n\n    // Prevent duplicate names\n    const parent = getParentNode(details.indexPath)\n    const hasDuplicate = parent.children.some(\n      (child) => child.name === details.label && child.id !== details.value,\n    )\n    return !hasDuplicate\n  },\n})\n```\n\n### Tracking rename events\n\nUse the `onRenameStart` callback to track when users start renaming, useful for\nanalytics or showing contextual hints.\n\n```tsx {3-6}\nconst service = useMachine(tree.machine, {\n  collection,\n  onRenameStart(details) {\n    console.log(\"Started renaming:\", details.node.name)\n    trackEvent(\"tree_rename_started\")\n  },\n})\n```\n\n**Features:**\n\n- Press `F2` to enter rename mode\n- Press `Enter` to submit or `Escape` to cancel\n- Blur automatically submits changes\n- Empty or whitespace-only names are automatically rejected\n- Labels are automatically trimmed before callbacks\n- IME composition events are properly handled\n- `data-renaming` attribute added for styling\n\n## Methods and Properties\n\n### Machine Context\n\nThe tree view machine exposes the following context properties:\n\n**`collection`**\nType: `TreeCollection<T>`\nDescription: The tree collection data\n\n**`ids`**\nType: `Partial<{ root: string; tree: string; label: string; node: (value: string) => string; }>`\nDescription: The ids of the tree elements. Useful for composition.\n\n**`expandedValue`**\nType: `string[]`\nDescription: The controlled expanded node ids\n\n**`defaultExpandedValue`**\nType: `string[]`\nDescription: The initial expanded node ids when rendered.\nUse when you don't need to control the expanded node value.\n\n**`selectedValue`**\nType: `string[]`\nDescription: The controlled selected node value\n\n**`defaultSelectedValue`**\nType: `string[]`\nDescription: The initial selected node value when rendered.\nUse when you don't need to control the selected node value.\n\n**`defaultCheckedValue`**\nType: `string[]`\nDescription: The initial checked node value when rendered.\nUse when you don't need to control the checked node value.\n\n**`checkedValue`**\nType: `string[]`\nDescription: The controlled checked node value\n\n**`defaultFocusedValue`**\nType: `string`\nDescription: The initial focused node value when rendered.\nUse when you don't need to control the focused node value.\n\n**`focusedValue`**\nType: `string`\nDescription: The value of the focused node\n\n**`selectionMode`**\nType: `\"single\" | \"multiple\"`\nDescription: Whether the tree supports multiple selection\n- \"single\": only one node can be selected\n- \"multiple\": multiple nodes can be selected\n\n**`onExpandedChange`**\nType: `(details: ExpandedChangeDetails<T>) => void`\nDescription: Called when the tree is opened or closed\n\n**`onSelectionChange`**\nType: `(details: SelectionChangeDetails<T>) => void`\nDescription: Called when the selection changes\n\n**`onFocusChange`**\nType: `(details: FocusChangeDetails<T>) => void`\nDescription: Called when the focused node changes\n\n**`onCheckedChange`**\nType: `(details: CheckedChangeDetails) => void`\nDescription: Called when the checked value changes\n\n**`canRename`**\nType: `(node: T, indexPath: IndexPath) => boolean`\nDescription: Function to determine if a node can be renamed\n\n**`onRenameStart`**\nType: `(details: RenameStartDetails<T>) => void`\nDescription: Called when a node starts being renamed\n\n**`onBeforeRename`**\nType: `(details: RenameCompleteDetails) => boolean`\nDescription: Called before a rename is completed. Return false to prevent the rename.\n\n**`onRenameComplete`**\nType: `(details: RenameCompleteDetails) => void`\nDescription: Called when a node label rename is completed\n\n**`onLoadChildrenComplete`**\nType: `(details: LoadChildrenCompleteDetails<T>) => void`\nDescription: Called when a node finishes loading children\n\n**`onLoadChildrenError`**\nType: `(details: LoadChildrenErrorDetails<T>) => void`\nDescription: Called when loading children fails for one or more nodes\n\n**`expandOnClick`**\nType: `boolean`\nDescription: Whether clicking on a branch should open it or not\n\n**`typeahead`**\nType: `boolean`\nDescription: Whether the tree supports typeahead search\n\n**`loadChildren`**\nType: `(details: LoadChildrenDetails<T>) => Promise<T[]>`\nDescription: Function to load children for a node asynchronously.\nWhen provided, branches will wait for this promise to resolve before expanding.\n\n**`scrollToIndexFn`**\nType: `(details: ScrollToIndexDetails<T>) => void`\nDescription: Function to scroll to a specific index.\nUseful for virtualized tree views.\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### Machine API\n\nThe tree view `api` exposes the following methods:\n\n**`collection`**\nType: `TreeCollection<V>`\nDescription: The tree collection data\n\n**`expandedValue`**\nType: `string[]`\nDescription: The value of the expanded nodes.\n\n**`setExpandedValue`**\nType: `(value: string[]) => void`\nDescription: Sets the expanded value\n\n**`selectedValue`**\nType: `string[]`\nDescription: The value of the selected nodes.\n\n**`setSelectedValue`**\nType: `(value: string[]) => void`\nDescription: Sets the selected value\n\n**`checkedValue`**\nType: `string[]`\nDescription: The value of the checked nodes\n\n**`toggleChecked`**\nType: `(value: string, isBranch: boolean) => void`\nDescription: Toggles the checked value of a node\n\n**`setChecked`**\nType: `(value: string[]) => void`\nDescription: Sets the checked value of a node\n\n**`clearChecked`**\nType: `VoidFunction`\nDescription: Clears the checked value of a node\n\n**`getCheckedMap`**\nType: `() => CheckedValueMap`\nDescription: Returns the checked details of branch and leaf nodes\n\n**`getVisibleNodes`**\nType: `() => VisibleNode<V>[]`\nDescription: Returns the visible nodes as a flat array of nodes and their index path.\nUseful for rendering virtualized tree views.\n\n**`expand`**\nType: `(value?: string[]) => void`\nDescription: Function to expand nodes.\nIf no value is provided, all nodes will be expanded\n\n**`collapse`**\nType: `(value?: string[]) => void`\nDescription: Function to collapse nodes\nIf no value is provided, all nodes will be collapsed\n\n**`select`**\nType: `(value?: string[]) => void`\nDescription: Function to select nodes\nIf no value is provided, all nodes will be selected\n\n**`deselect`**\nType: `(value?: string[]) => void`\nDescription: Function to deselect nodes\nIf no value is provided, all nodes will be deselected\n\n**`focus`**\nType: `(value: string) => void`\nDescription: Function to focus a node by value\n\n**`selectParent`**\nType: `(value: string) => void`\nDescription: Function to select the parent node of the focused node\n\n**`expandParent`**\nType: `(value: string) => void`\nDescription: Function to expand the parent node of the focused node\n\n**`startRenaming`**\nType: `(value: string) => void`\nDescription: Function to start renaming a node by value\n\n**`submitRenaming`**\nType: `(value: string, label: string) => void`\nDescription: Function to submit the rename and update the node label\n\n**`cancelRenaming`**\nType: `() => void`\nDescription: Function to cancel renaming without changes\n\n### Data Attributes\n\n**`Item`**\n\n**`data-scope`**: tree-view\n**`data-part`**: item\n**`data-path`**: The path of the item\n**`data-value`**: The value of the item\n**`data-focus`**: Present when focused\n**`data-selected`**: Present when selected\n**`data-disabled`**: Present when disabled\n**`data-renaming`**: \n**`data-depth`**: The depth of the item\n\n**`ItemText`**\n\n**`data-scope`**: tree-view\n**`data-part`**: item-text\n**`data-disabled`**: Present when disabled\n**`data-selected`**: Present when selected\n**`data-focus`**: Present when focused\n\n**`ItemIndicator`**\n\n**`data-scope`**: tree-view\n**`data-part`**: item-indicator\n**`data-disabled`**: Present when disabled\n**`data-selected`**: Present when selected\n**`data-focus`**: Present when focused\n\n**`Branch`**\n\n**`data-scope`**: tree-view\n**`data-part`**: branch\n**`data-depth`**: The depth of the item\n**`data-branch`**: \n**`data-value`**: The value of the item\n**`data-path`**: The path of the item\n**`data-selected`**: Present when selected\n**`data-state`**: \"open\" | \"closed\"\n**`data-disabled`**: Present when disabled\n**`data-loading`**: Present when loading\n\n**`BranchIndicator`**\n\n**`data-scope`**: tree-view\n**`data-part`**: branch-indicator\n**`data-state`**: \"open\" | \"closed\"\n**`data-disabled`**: Present when disabled\n**`data-selected`**: Present when selected\n**`data-focus`**: Present when focused\n**`data-loading`**: Present when loading\n\n**`BranchTrigger`**\n\n**`data-scope`**: tree-view\n**`data-part`**: branch-trigger\n**`data-disabled`**: Present when disabled\n**`data-state`**: \"open\" | \"closed\"\n**`data-value`**: The value of the item\n**`data-loading`**: Present when loading\n\n**`BranchControl`**\n\n**`data-scope`**: tree-view\n**`data-part`**: branch-control\n**`data-path`**: The path of the item\n**`data-state`**: \"open\" | \"closed\"\n**`data-disabled`**: Present when disabled\n**`data-selected`**: Present when selected\n**`data-focus`**: Present when focused\n**`data-renaming`**: \n**`data-value`**: The value of the item\n**`data-depth`**: The depth of the item\n**`data-loading`**: Present when loading\n\n**`BranchText`**\n\n**`data-scope`**: tree-view\n**`data-part`**: branch-text\n**`data-disabled`**: Present when disabled\n**`data-state`**: \"open\" | \"closed\"\n**`data-loading`**: Present when loading\n\n**`BranchContent`**\n\n**`data-scope`**: tree-view\n**`data-part`**: branch-content\n**`data-state`**: \"open\" | \"closed\"\n**`data-depth`**: The depth of the item\n**`data-path`**: The path of the item\n**`data-value`**: The value of the item\n\n**`BranchIndentGuide`**\n\n**`data-scope`**: tree-view\n**`data-part`**: branch-indent-guide\n**`data-depth`**: The depth of the item\n\n**`NodeCheckbox`**\n\n**`data-scope`**: tree-view\n**`data-part`**: node-checkbox\n**`data-state`**: \"checked\" | \"unchecked\" | \"indeterminate\"\n**`data-disabled`**: Present when disabled\n\n### CSS Variables\n\n<CssVarTable name=\"tree-view\" />\n\n## Accessibility\n\nAdheres to the\n[Tree View WAI-ARIA design pattern](https://www.w3.org/WAI/ARIA/apg/patterns/treeview).\n\n### Keyboard Interactions\n\n**`Tab`**\nDescription: Moves focus to the tree view, placing the first tree view item in focus.\n\n**`Enter + Space`**\nDescription: Selects the item or branch node\n\n**`ArrowDown`**\nDescription: Moves focus to the next node\n\n**`ArrowUp`**\nDescription: Moves focus to the previous node\n\n**`ArrowRight`**\nDescription: When focus is on a closed branch node, opens the branch.<br> When focus is on an open branch node, moves focus to the first item node.\n\n**`ArrowLeft`**\nDescription: When focus is on an open branch node, closes the node.<br> When focus is on an item or branch node, moves focus to its parent branch node.\n\n**`Home`**\nDescription: Moves focus to first node without opening or closing a node.\n\n**`End`**\nDescription: Moves focus to the last node that can be focused without expanding any nodes that are closed.\n\n**`a-z + A-Z`**\nDescription: Focus moves to the next node with a name that starts with the typed character. The search logic ignores nodes that are descendants of closed branch.\n\n**`*`**\nDescription: Expands all sibling nodes that are at the same depth as the focused node.\n\n**`Shift + ArrowDown`**\nDescription: Moves focus to and toggles the selection state of the next node.\n\n**`Shift + ArrowUp`**\nDescription: Moves focus to and toggles the selection state of the previous node.\n\n**`Ctrl + A`**\nDescription: Selects all nodes in the tree. If all nodes are selected, unselects all nodes.","package":"@zag-js/tree-view","editUrl":"https://github.com/chakra-ui/zag/edit/main/website/data/components/tree-view.mdx"}