Getting started
Installation
Install the package with the package manager of your choice. React 18 or 19 is required.
npm install @attebyte/react-tree-select
yarn add @attebyte/react-tree-select
pnpm add @attebyte/react-tree-select
Import the styles
Import the stylesheet once, for example in your app's entry file. It only styles the tree itself, never resets global styles, and your own classes and CSS always take priority over it (see how the default styles are scoped).
import '@attebyte/react-tree-select/style.css';
Render a tree
Pass your tree-shaped data to TreeSelect along with the names of the properties that hold each node's unique ID, label and children. Add valueProperty to make the nodes selectable: TreeSelect stores each node's checked state in that property.
Show code
import TreeSelect from '@attebyte/react-tree-select';
import { exampleData, ExampleNode } from './data';
export default function BasicExample() {
return (
<TreeSelect<ExampleNode>
defaultData={exampleData}
uniqueIDProperty='value'
labelProperty='label'
childrenProperty='children'
valueProperty='included'
aria-label='Basic example'
/>
);
}
Your data can have any shape. The example uses this type:
interface ExampleNode {
label: string;
value: number;
included?: boolean | null; // true = checked, false or undefined = unchecked, null = mixed
children?: ExampleNode[];
}
const exampleData: ExampleNode[] = [
{
label: 'Root 1',
value: 1,
children: [
{
label: 'Child 1',
value: 2,
children: [
{ label: 'Grandchild 1', value: 3 },
{ label: 'Grandchild 2', value: 4 }
]
},
{ label: 'Child 2', value: 5 }
]
},
{
label: 'Root 2',
value: 6,
children: [
{ label: 'Child 3', value: 7 },
{ label: 'Child 4', value: 8 }
]
}
];
Give every tree an accessible name with aria-label or aria-labelledby, as in the example above.
If your tree has a single root node, you can pass the node itself instead of an array.
Read the selection
defaultData makes the tree uncontrolled: it keeps track of selections itself and calls onChange with the updated tree each time something is checked. To keep the selection in your own state, use data instead; see Controlled usage.
To turn a tree into a list of selected IDs, use getSelectedIDs:
import TreeSelect, { getSelectedIDs } from '@attebyte/react-tree-select';
<TreeSelect
defaultData={exampleData}
uniqueIDProperty='value'
labelProperty='label'
childrenProperty='children'
valueProperty='included'
onChange={tree => {
const ids = getSelectedIDs(tree, {
uniqueIDProperty: 'value',
childrenProperty: 'children',
valueProperty: 'included',
mode: 'leaves'
});
console.log(ids); // e.g. [3, 4, 7]
}}
/>