Upgrading from 1.x
Version 2.0 is a major release. Most apps only need to check the first two items below.
Breaking changes
- Controlled mode is now fully controlled. When you pass
data, the tree renders exactly that data, so selections only appear once you pass the tree fromonChangeback in asdata. In 1.x the tree kept its own copy and updated it even if you ignoredonChange. If you don't want to manage the state, usedefaultData. - Parents with disabled children are mixed, not checked. With chained selection, checking a parent whose disabled child is unchecked now makes the parent mixed (
null) instead of checked, so its value always reflects its subtree. Clicking it again unchecks its enabled descendants. A parent whose descendants are all disabled is now shown as disabled, since it can never change (in 1.x it could be checked on its own). See Disabled nodes. onChangereceives a structurally shared tree, and is only called when something changed. Changed nodes and their ancestors are new objects; every other node is the same object as before. In 1.x every change produced a full deep copy. Your input data is still never modified, so treat the result as immutable.- Nodes no longer contain a
_parentIDproperty. - Expansion state is managed by TreeSelect.
TreeNodenow receivesexpanded,onExpandedChange,treeItemPropsand its nested nodes aschildren, instead of keeping its own state and rendering its children itself. A 1.x-style custom node that renders its own children still works, but isn't part of keyboard navigation. If it spreads its remaining props onto a DOM element, destructure the new props first. See Custom nodes. - Changing
defaultExpandedafter the first render now expands or collapses every node. In 1.x it only affected nodes rendered afterward. - New DOM structure and ARIA roles. The root has
role="tree", each node hasrole="treeitem", and nested nodes are wrapped in an element withrole="group". The label no longer hasrole="button", the checkbox is removed from the tab order, and the expand icon is hidden from assistive technology. Update CSS selectors that relied on nested nodes being direct children of their parent. - The stylesheet no longer resets global styles. 1.x shipped Tailwind's Preflight reset, which changed styles across the whole page. If your app relied on it, add a reset yourself (for example Tailwind's
@import "tailwindcss"). - Styles are built with Tailwind CSS 4. The default styles use modern CSS (such as
@propertyand individual transform properties) and need Safari 16.4+, Chrome 111+ or Firefox 128+. - Package exports are restricted. Only the main entry point and the stylesheet can be imported. Import styles from
@attebyte/react-tree-select/style.css; the olddist/style.csspath still works. - License changed from GPL-3.0 to MIT.
2.1.0
dataanddefaultDataaccept a single root node as well as an array.onChangereports the tree in the same shape you passed in, so a controlled single-root tree works withonChange={setRoot}.- The stylesheet no longer affects elements outside the tree. In 2.0.0 its utility classes (such as
basis-full) were unlayered and unprefixed, so they matched and overrode identically named classes in the consuming app, including Tailwind 4 responsive variants. Classes are now prefixed withrts:and live in thecomponentscascade layer. See Customization.
New features
- Keyboard navigation and screen reader support following the WAI-ARIA tree view pattern.
getSelectedIDsandgetSelectedNodeshelpers.- Expansion state survives collapsing and reopening a parent.
- Nodes can contain values that can't be cloned, such as functions or class instances.
- Controlled data renders on the first render and on the server.
- Much faster updates on large trees; see the large tree example.
- A smaller package: the bundle no longer includes its dependencies (69 KB to 17 KB of JavaScript), and the stylesheet only contains the component's own styles (14 KB to 3 KB).
- Type declarations work with
"moduleResolution": "node16"and"nodenext", and the package can be loaded withrequire()in Node.js and Jest.