Tree
<sl-tree> | SlTree
Trees allow you to display a hierarchical list of selectable tree items. Items with children can be expanded and collapsed as desired by the user.
Examples
Basic Tree
<sl-tree> <sl-tree-item> Deciduous <sl-tree-item>Birch</sl-tree-item> <sl-tree-item> Maple <sl-tree-item>Field maple</sl-tree-item> <sl-tree-item>Red maple</sl-tree-item> <sl-tree-item>Sugar maple</sl-tree-item> </sl-tree-item> <sl-tree-item>Oak</sl-tree-item> </sl-tree-item> <sl-tree-item> Coniferous <sl-tree-item>Cedar</sl-tree-item> <sl-tree-item>Pine</sl-tree-item> <sl-tree-item>Spruce</sl-tree-item> </sl-tree-item> <sl-tree-item> Non-trees <sl-tree-item>Bamboo</sl-tree-item> <sl-tree-item>Cactus</sl-tree-item> <sl-tree-item>Fern</sl-tree-item> </sl-tree-item> </sl-tree>
sl-tree sl-tree-item | Deciduous sl-tree-item Birch sl-tree-item | Maple sl-tree-item Field maple sl-tree-item Red maple sl-tree-item Sugar maple sl-tree-item Oak sl-tree-item | Coniferous sl-tree-item Cedar sl-tree-item Pine sl-tree-item Spruce sl-tree-item | Non-trees sl-tree-item Bamboo sl-tree-item Cactus sl-tree-item Fern
import SlTree from '@teamshares/shoelace/dist/react/tree'; import SlTreeItem from '@teamshares/shoelace/dist/react/tree-item'; const App = () => ( <SlTree> <SlTreeItem> Deciduous <SlTreeItem>Birch</SlTreeItem> <SlTreeItem> Maple <SlTreeItem>Field maple</SlTreeItem> <SlTreeItem>Red maple</SlTreeItem> <SlTreeItem>Sugar maple</SlTreeItem> </SlTreeItem> <SlTreeItem>Oak</SlTreeItem> </SlTreeItem> <SlTreeItem> Coniferous <SlTreeItem>Cedar</SlTreeItem> <SlTreeItem>Pine</SlTreeItem> <SlTreeItem>Spruce</SlTreeItem> </SlTreeItem> <SlTreeItem> Non-trees <SlTreeItem>Bamboo</SlTreeItem> <SlTreeItem>Cactus</SlTreeItem> <SlTreeItem>Fern</SlTreeItem> </SlTreeItem> </SlTree> );
Selection Modes
The selection
attribute lets you change the selection behavior of the tree.
- Use
single
to allow the selection of a single item (default). - Use
multiple
to allow the selection of multiple items. - Use
leaf
to only allow leaf nodes to be selected.
<sl-select id="selection-mode" value="single" label="Selection"> <sl-option value="single">Single</sl-option> <sl-option value="multiple">Multiple</sl-option> <sl-option value="leaf">Leaf</sl-option> </sl-select> <br /> <sl-tree class="tree-selectable"> <sl-tree-item> Item 1 <sl-tree-item> Item A <sl-tree-item>Item Z</sl-tree-item> <sl-tree-item>Item Y</sl-tree-item> <sl-tree-item>Item X</sl-tree-item> </sl-tree-item> <sl-tree-item>Item B</sl-tree-item> <sl-tree-item>Item C</sl-tree-item> </sl-tree-item> <sl-tree-item>Item 2</sl-tree-item> <sl-tree-item>Item 3</sl-tree-item> </sl-tree> <script> const selectionMode = document.querySelector('#selection-mode'); const tree = document.querySelector('.tree-selectable'); selectionMode.addEventListener('sl-change', () => { tree.querySelectorAll('sl-tree-item').forEach(item => (item.selected = false)); tree.selection = selectionMode.value; }); </script>
sl-select#selection-mode value="single" label="Selection" sl-option value="single" Single sl-option value="multiple" Multiple sl-option value="leaf" Leaf br sl-tree.tree-selectable sl-tree-item | Item 1 sl-tree-item | Item A sl-tree-item Item Z sl-tree-item Item Y sl-tree-item Item X sl-tree-item Item B sl-tree-item Item C sl-tree-item Item 2 sl-tree-item Item 3 javascript: const selectionMode = document.querySelector(#selection-mode); const tree = document.querySelector(.tree-selectable); selectionMode.addEventListener(sl-change, () => { tree.querySelectorAll(sl-tree-item).forEach(item => (item.selected = false)); tree.selection = selectionMode.value; });
import SlTree from '@teamshares/shoelace/dist/react/tree'; import SlTreeItem from '@teamshares/shoelace/dist/react/tree-item'; const App = () => { const [selection, setSelection] = useState('single'); return ( <> <SlSelect label="Selection" value={selection} onSlChange={event => setSelection(event.target.value)}> <SlMenuItem value="single">single</SlMenuItem> <SlMenuItem value="multiple">multiple</SlMenuItem> <SlMenuItem value="leaf">leaf</SlMenuItem> </SlSelect> <br /> <SlTree selection={selection}> <SlTreeItem> Item 1 <SlTreeItem> Item A <SlTreeItem>Item Z</SlTreeItem> <SlTreeItem>Item Y</SlTreeItem> <SlTreeItem>Item X</SlTreeItem> </SlTreeItem> <SlTreeItem>Item B</SlTreeItem> <SlTreeItem>Item C</SlTreeItem> </SlTreeItem> <SlTreeItem>Item 2</SlTreeItem> <SlTreeItem>Item 3</SlTreeItem> </SlTree> </> ); };
Showing Indent Guides
Indent guides can be drawn by setting --indent-guide-width
. You can also change the color,
offset, and style, using --indent-guide-color
, --indent-guide-style
, and
--indent-guide-offset
, respectively.
<sl-tree class="tree-with-lines"> <sl-tree-item expanded> Deciduous <sl-tree-item>Birch</sl-tree-item> <sl-tree-item expanded> Maple <sl-tree-item>Field maple</sl-tree-item> <sl-tree-item>Red maple</sl-tree-item> <sl-tree-item>Sugar maple</sl-tree-item> </sl-tree-item> <sl-tree-item>Oak</sl-tree-item> </sl-tree-item> <sl-tree-item> Coniferous <sl-tree-item>Cedar</sl-tree-item> <sl-tree-item>Pine</sl-tree-item> <sl-tree-item>Spruce</sl-tree-item> </sl-tree-item> <sl-tree-item> Non-trees <sl-tree-item>Bamboo</sl-tree-item> <sl-tree-item>Cactus</sl-tree-item> <sl-tree-item>Fern</sl-tree-item> </sl-tree-item> </sl-tree> <style> .tree-with-lines { --indent-guide-width: 1px; } </style>
sl-tree.tree-with-lines sl-tree-item expanded="true" | Deciduous sl-tree-item Birch sl-tree-item expanded="true" | Maple sl-tree-item Field maple sl-tree-item Red maple sl-tree-item Sugar maple sl-tree-item Oak sl-tree-item | Coniferous sl-tree-item Cedar sl-tree-item Pine sl-tree-item Spruce sl-tree-item | Non-trees sl-tree-item Bamboo sl-tree-item Cactus sl-tree-item Fern css: .tree-with-lines { --indent-guide-width: 1px; }
import SlTree from '@teamshares/shoelace/dist/react/tree'; import SlTreeItem from '@teamshares/shoelace/dist/react/tree-item'; const App = () => ( <SlTree class="tree-with-lines" style={{ '--indent-guide-width': '1px' }}> <SlTreeItem expanded> Deciduous <SlTreeItem>Birch</SlTreeItem> <SlTreeItem expanded> Maple <SlTreeItem>Field maple</SlTreeItem> <SlTreeItem>Red maple</SlTreeItem> <SlTreeItem>Sugar maple</SlTreeItem> </SlTreeItem> <SlTreeItem>Oak</SlTreeItem> </SlTreeItem> <SlTreeItem> Coniferous <SlTreeItem>Cedar</SlTreeItem> <SlTreeItem>Pine</SlTreeItem> <SlTreeItem>Spruce</SlTreeItem> </SlTreeItem> <SlTreeItem> Non-trees <SlTreeItem>Bamboo</SlTreeItem> <SlTreeItem>Cactus</SlTreeItem> <SlTreeItem>Fern</SlTreeItem> </SlTreeItem> </SlTree> );
Lazy Loading
Use the lazy
attribute on a tree item to indicate that the content is not yet present and will
be loaded later. When the user tries to expand the node, the loading
state is set to
true
and the sl-lazy-load
event will be emitted to allow you to load data
asynchronously. The item will remain in a loading state until its content is changed.
If you want to disable this behavior after the first load, simply remove the lazy
attribute
and, on the next expand, the existing content will be shown instead.
<sl-tree> <sl-tree-item lazy>Available Trees</sl-tree-item> </sl-tree> <script type="module"> const lazyItem = document.querySelector('sl-tree-item[lazy]'); lazyItem.addEventListener('sl-lazy-load', () => { // Simulate asynchronous loading setTimeout(() => { const subItems = ['Birch', 'Cedar', 'Maple', 'Pine']; for (const item of subItems) { const treeItem = document.createElement('sl-tree-item'); treeItem.innerText = item; lazyItem.append(treeItem); } // Disable lazy mode once the content has been loaded lazyItem.lazy = false; }, 1000); }); </script>
sl-tree sl-tree-item lazy="true" Available Trees <script type="module"> const lazyItem = document.querySelector('sl-tree-item[lazy]'); lazyItem.addEventListener('sl-lazy-load', () => { // Simulate asynchronous loading setTimeout(() => { const subItems = ['Birch', 'Cedar', 'Maple', 'Pine']; for (const item of subItems) { const treeItem = document.createElement('sl-tree-item'); treeItem.innerText = item; lazyItem.append(treeItem); } // Disable lazy mode once the content has been loaded lazyItem.lazy = false; }, 1000); }); </script>
import SlTree from '@teamshares/shoelace/dist/react/tree'; import SlTreeItem from '@teamshares/shoelace/dist/react/tree-item'; const App = () => { const [childItems, setChildItems] = useState([]); const [lazy, setLazy] = useState(true); const handleLazyLoad = () => { // Simulate asynchronous loading setTimeout(() => { setChildItems(['Birch', 'Cedar', 'Maple', 'Pine']); // Disable lazy mode once the content has been loaded setLazy(false); }, 1000); }; return ( <SlTree> <SlTreeItem lazy={lazy} onSlLazyLoad={handleLazyLoad}> Available Trees {childItems.map(item => ( <SlTreeItem>{item}</SlTreeItem> ))} </SlTreeItem> </SlTree> ); };
Customizing the Expand and Collapse Icons
Use the expand-icon
and collapse-icon
slots to change the expand and collapse
icons, respectively. To disable the animation, override the rotate
property on the
expand-button
part as shown below.
<sl-tree class="custom-icons"> <sl-icon name="plus" slot="expand-icon"></sl-icon> <sl-icon name="minus" slot="collapse-icon"></sl-icon> <sl-tree-item> Deciduous <sl-tree-item>Birch</sl-tree-item> <sl-tree-item> Maple <sl-tree-item>Field maple</sl-tree-item> <sl-tree-item>Red maple</sl-tree-item> <sl-tree-item>Sugar maple</sl-tree-item> </sl-tree-item> <sl-tree-item>Oak</sl-tree-item> </sl-tree-item> <sl-tree-item> Coniferous <sl-tree-item>Cedar</sl-tree-item> <sl-tree-item>Pine</sl-tree-item> <sl-tree-item>Spruce</sl-tree-item> </sl-tree-item> <sl-tree-item> Non-trees <sl-tree-item>Bamboo</sl-tree-item> <sl-tree-item>Cactus</sl-tree-item> <sl-tree-item>Fern</sl-tree-item> </sl-tree-item> </sl-tree> <style> .custom-icons sl-tree-item::part(expand-button) { /* Disable the expand/collapse animation */ rotate: none; } </style>
sl-tree.custom-icons sl-icon name="plus" slot="expand-icon" sl-icon name="minus" slot="collapse-icon" sl-tree-item | Deciduous sl-tree-item Birch sl-tree-item | Maple sl-tree-item Field maple sl-tree-item Red maple sl-tree-item Sugar maple sl-tree-item Oak sl-tree-item | Coniferous sl-tree-item Cedar sl-tree-item Pine sl-tree-item Spruce sl-tree-item | Non-trees sl-tree-item Bamboo sl-tree-item Cactus sl-tree-item Fern css: .custom-icons sl-tree-item::part(expand-button) { /* Disable the expand/collapse animation */ rotate: none; }
import SlTree from '@teamshares/shoelace/dist/react/tree'; import SlTreeItem from '@teamshares/shoelace/dist/react/tree-item'; const App = () => ( <SlTree> <SlIcon name="plus" slot="expand-icon"></SlIcon> <SlIcon name="minus" slot="collapse-icon"></SlIcon> <SlTreeItem> Deciduous <SlTreeItem>Birch</SlTreeItem> <SlTreeItem> Maple <SlTreeItem>Field maple</SlTreeItem> <SlTreeItem>Red maple</SlTreeItem> <SlTreeItem>Sugar maple</SlTreeItem> </SlTreeItem> <SlTreeItem>Oak</SlTreeItem> </SlTreeItem> <SlTreeItem> Coniferous <SlTreeItem>Cedar</SlTreeItem> <SlTreeItem>Pine</SlTreeItem> <SlTreeItem>Spruce</SlTreeItem> </SlTreeItem> <SlTreeItem> Non-trees <SlTreeItem>Bamboo</SlTreeItem> <SlTreeItem>Cactus</SlTreeItem> <SlTreeItem>Fern</SlTreeItem> </SlTreeItem> </SlTree> );
With Icons
Decorative icons can be used before labels to provide hints for each node.
<sl-tree class="tree-with-icons"> <sl-tree-item expanded> <sl-icon name="folder"></sl-icon> Documents <sl-tree-item> <sl-icon name="folder"> </sl-icon> Photos <sl-tree-item> <sl-icon name="photo"></sl-icon> birds.jpg </sl-tree-item> <sl-tree-item> <sl-icon name="photo"></sl-icon> kitten.jpg </sl-tree-item> <sl-tree-item> <sl-icon name="photo"></sl-icon> puppy.jpg </sl-tree-item> </sl-tree-item> <sl-tree-item> <sl-icon name="folder"></sl-icon> Writing <sl-tree-item> <sl-icon name="document-text"></sl-icon> draft.txt </sl-tree-item> <sl-tree-item> <sl-icon name="document-arrow-down"></sl-icon> final.pdf </sl-tree-item> <sl-tree-item> <sl-icon name="document-chart-bar"></sl-icon> sales.xls </sl-tree-item> </sl-tree-item> </sl-tree-item> </sl-tree>
sl-tree.tree-with-icons sl-tree-item expanded="true" sl-icon name="folder" | Documents sl-tree-item sl-icon name="folder" | Photos sl-tree-item sl-icon name="photo" | birds.jpg sl-tree-item sl-icon name="photo" | kitten.jpg sl-tree-item sl-icon name="photo" | puppy.jpg sl-tree-item sl-icon name="folder" | Writing sl-tree-item sl-icon name="document-text" | draft.txt sl-tree-item sl-icon name="document-arrow-down" | final.pdf sl-tree-item sl-icon name="document-chart-bar" | sales.xls
import SlIcon from '@teamshares/shoelace/dist/react/icon'; import SlTree from '@teamshares/shoelace/dist/react/tree'; import SlTreeItem from '@teamshares/shoelace/dist/react/tree-item'; const App = () => { return ( <SlTree class="tree-with-icons"> <SlTreeItem expanded> <SlIcon name="folder" /> Root <SlTreeItem> <SlIcon name="folder" /> Folder 1<SlTreeItem> <SlIcon name="files" /> File 1 - 1 </SlTreeItem> <SlTreeItem disabled> <SlIcon name="files" /> File 1 - 2 </SlTreeItem> <SlTreeItem> <SlIcon name="files" /> File 1 - 3 </SlTreeItem> </SlTreeItem> <SlTreeItem> <SlIcon name="files" /> Folder 2<SlTreeItem> <SlIcon name="files" /> File 2 - 1 </SlTreeItem> <SlTreeItem> <SlIcon name="files" /> File 2 - 2 </SlTreeItem> </SlTreeItem> <SlTreeItem> <SlIcon name="files" /> File 1 </SlTreeItem> </SlTreeItem> </SlTree> ); };
Importing
If you’re using the autoloader or the traditional loader, you can ignore this section. Otherwise, feel free to use any of the following snippets to cherry pick this component.
To import this component from the CDN using a script tag:
<script type="module" src="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@2.1.0/cdn/components/tree/tree.js"></script>
To import this component from the CDN using a JavaScript import:
import 'https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@2.1.0/cdn/components/tree/tree.js';
To import this component using a bundler:
import '@shoelace-style/shoelace/dist/components/tree/tree.js';
To import this component as a React component:
import SlTree from '@shoelace-style/shoelace/dist/react/tree';
Slots
Name | Description |
---|---|
(default) | The default slot. |
expand-icon
|
The icon to show when the tree item is expanded. Works best with <sl-icon> .
|
collapse-icon
|
The icon to show when the tree item is collapsed. Works best with <sl-icon> .
|
Learn more about using slots.
Properties
Scroll right to see the entire table
Name | Description | Reflects | Type | Default |
---|---|---|---|---|
selection
|
The selection behavior of the tree. Single selection allows only one node to be selected at a time. Multiple displays checkboxes and allows more than one node to be selected. Leaf allows only leaf nodes to be selected. |
'single' | 'multiple' | 'leaf'
|
'single'
|
|
updateComplete
|
A read-only promise that resolves when the component has finished updating. |
Learn more about attributes and properties.
Events
Name | React Event | Description | Event Detail |
---|---|---|---|
sl-selection-change
|
onSlSelectionChange
|
Emitted when a tree item is selected or deselected. |
{ selection: SlTreeItem[] }
|
Learn more about events.
Custom Properties
Name | Description | Default |
---|---|---|
--indent-size
|
The size of the indentation for nested items. | var(–sl-spacing-medium) |
--indent-guide-color
|
The color of the indentation line. | var(–sl-color-neutral-200) |
--indent-guide-offset
|
The amount of vertical spacing to leave between the top and bottom of the indentation line’s starting position. | 0 |
--indent-guide-style
|
The style of the indentation line, e.g. solid, dotted, dashed. | solid |
--indent-guide-width
|
The width of the indentation line. | 0 |
Learn more about customizing CSS custom properties.
Parts
Name | Description |
---|---|
base
|
The component’s base wrapper. |
Learn more about customizing CSS parts.