esc
navigate select
Browse documentation

Icons

TreeKit doesn't bundle an icon set or force one on you — pass any React node: an SVG, an emoji, or a component from your own icon library.

Engineering
Frontend
React
Vue
Svelte
Show code
<TreeKit data={data} icons={{ leafIcon: "🧩" }} />
PropTypeDefaultDescription
icons.expandIconReactNodechevron ▶Replaces the chevron shown for an expanded node.
icons.collapseIconReactNodechevron ▼Replaces the chevron shown for a collapsed node.
icons.leafIconReactNode | (node) => ReactNodeIcon for nodes without children. Can be static or computed per node.
icons.loadingIconReactNodespinnerShown in the chevron slot while onLoadChildren is pending.
icons.checkedIcon / uncheckedIcon / indeterminateIconReactNodeReserved for custom checkbox renderers built on the exported Checkbox primitive.

Per-node icons

For icons that vary node-by-node in a way icons.leafIcon can't express (e.g. an open vs. closed folder), set icon directly on the node when you build your data — it always takes priority over the icons prop:

src
components
Button.tsx
Input.tsx
Modal.tsx
index.ts
package.json
README.md
Show code
const data = fileTree.map((node) => ({
  ...node,
  icon: node.children ? <FolderIcon /> : <FileIcon />,
}));

<TreeKit data={data} variant="connected" />

Because node.icon is a plain ReactNode rather than a component reference, it composes naturally with any icon library — lucide-react, @radix-ui/react-icons, a custom SVG sprite — without TreeKit needing to know it exists.

import { Folder, File } from "lucide-react";

const data = fileTree.map((node) => ({
  ...node,
  icon: node.children ? <Folder size={15} /> : <File size={15} />,
}));