Skip to main content
Mantı UI logoMantı UIv0.12.1
Studio

TreeView

Pass nested items; branches contain children and leaves do not. The machine manages expansion, selection, and arrow keys.

Use the icon render prop to display node and state-aware icons.

import { TreeView } from '@manti-ui/react';

const tree = [
  {
    value: 'recipes',
    label: 'recipes',
    children: [
      {
        value: 'steamed',
        label: 'steamed',
        children: [
          { value: 'manti', label: 'manti.md' },
          { value: 'momo', label: 'momo.md' },
        ],
      },
      {
        value: 'boiled',
        label: 'boiled',
        children: [{ value: 'pelmeni', label: 'pelmeni.md' }],
      },
    ],
  },
  {
    value: 'sauces',
    label: 'sauces',
    children: [
      { value: 'yogurt', label: 'garlic-yogurt.md' },
      { value: 'chili-oil', label: 'chili-oil.md' },
    ],
  },
  { value: 'README', label: 'README.md' },
];

const folderClosed = (
  <svg width="16" height="16" viewBox="0 0 16 16" aria-hidden="true">
    <path
      d="M1.75 4.5c0-.69.56-1.25 1.25-1.25h2.84c.4 0 .77.18 1 .5l.66.86c.24.31.6.49 1 .49h4.5c.69 0 1.25.56 1.25 1.25v5.4c0 .69-.56 1.25-1.25 1.25H3c-.69 0-1.25-.56-1.25-1.25V4.5Z"
      fill="none"
      stroke="currentColor"
      strokeWidth="1.3"
      strokeLinejoin="round"
    />
  </svg>
);

const folderOpen = (
  <svg width="16" height="16" viewBox="0 0 16 16" aria-hidden="true">
    <path
      d="M1.75 5V4c0-.69.56-1.25 1.25-1.25h2.84c.4 0 .77.18 1 .5l.66.86c.24.31.6.49 1 .49h4c.69 0 1.25.56 1.25 1.25v.65"
      fill="none"
      stroke="currentColor"
      strokeWidth="1.3"
      strokeLinejoin="round"
    />
    <path
      d="M2.6 6.5h11.2c.42 0 .73.4.63.81l-.97 4.2c-.13.57-.64.99-1.23.99H3.2c-.59 0-1.1-.42-1.23-.99l-.97-4.2c-.1-.41.21-.81.63-.81H2.6Z"
      fill="none"
      stroke="currentColor"
      strokeWidth="1.3"
      strokeLinejoin="round"
    />
  </svg>
);

const file = (
  <svg width="16" height="16" viewBox="0 0 16 16" aria-hidden="true">
    <path
      d="M4 1.75h4.3c.27 0 .52.1.71.3l3.2 3.2c.19.18.29.43.29.7v8c0 .69-.56 1.25-1.25 1.25H4c-.69 0-1.25-.56-1.25-1.25V3c0-.69.56-1.25 1.25-1.25Z"
      fill="none"
      stroke="currentColor"
      strokeWidth="1.3"
      strokeLinejoin="round"
    />
    <path
      d="M8.5 2v3c0 .41.34.75.75.75h3"
      fill="none"
      stroke="currentColor"
      strokeWidth="1.3"
      strokeLinecap="round"
      strokeLinejoin="round"
    />
  </svg>
);

export default function TreeViewBasic() {
  return (
    <TreeView
      items={tree}
      label="Cookbook"
      variant="primary"
      selectionMode="single"
      defaultExpandedValue={['recipes', 'steamed']}
      icon={(_node, { isBranch, expanded }) =>
        isBranch ? (expanded ? folderOpen : folderClosed) : file
      }
    />
  );
}

API

PropTypeDefaultDescription
itemsTreeNode[]Top-level nodes. Branches carry a `children` array.
labelReactNodeOptional label above the tree.
variantMantiVariant'primary'Selected-node variant.
icon(node: TreeNode, state: TreeNodeState) => ReactNodeRender an icon before each node label, e.g. folder/file icons. Receives the node and its live state (`isBranch`, `expanded`, `selected`).
selectionMode'single' | 'multiple''single'Single or multiple selection.
defaultExpandedValuestring[]Values of branches expanded by default.
defaultSelectedValuestring[]Values selected by default.
onSelectionChange(value: string[]) => voidCalled whenever the selection changes.

Styling

Anatomy

PartSelectorDescription
root[data-scope="tree-view"][data-part="root"]The outer wrapper that owns the variant.
label[data-scope="tree-view"][data-part="label"]The optional heading above the tree.
tree[data-scope="tree-view"][data-part="tree"]The tree container.
branch[data-scope="tree-view"][data-part="branch"]A node that has children.
branch-control[data-scope="tree-view"][data-part="branch-control"]The clickable row of a branch.
branch-indicator[data-scope="tree-view"][data-part="branch-indicator"]The expand/collapse chevron.
node-icon[data-scope="tree-view"][data-part="node-icon"]The optional leading icon rendered by the `icon` prop.
branch-text[data-scope="tree-view"][data-part="branch-text"]A branch label.
branch-content[data-scope="tree-view"][data-part="branch-content"]The nested children of a branch.
item[data-scope="tree-view"][data-part="item"]A leaf node.
item-text[data-scope="tree-view"][data-part="item-text"]A leaf label.

Tokens

TokenControls
--manti-tree-view-gapgap
--manti-tree-view-tree-gaptree gap
--manti-tree-view-label-font-sizelabel font size
--manti-tree-view-item-gapitem gap
--manti-tree-view-item-padding-yitem padding y
--manti-tree-view-item-padding-xitem padding x
--manti-tree-view-item-radiusitem radius
--manti-tree-view-item-font-sizeitem font size
--manti-tree-view-branch-indentbranch indent
--manti-tree-view-leaf-indentleaf indent

Last updated

Built end-to-end with Manti UI components and design tokens. Manti UI is a framework-agnostic design system on Zag.js.

GitHub