@papit/treeview
v0.0.11
Published
Accessible tree view for nested lists such as file explorers and navigation, following the WAI-ARIA tree pattern. Supports expand and collapse, single or multiple selection, full keyboard navigation and typeahead.
Maintainers
Readme
@papit/treeview
Accessible tree view for nested lists such as file explorers and navigation, following the WAI-ARIA tree pattern. Supports expand and collapse, single or multiple selection, full keyboard navigation and typeahead.
Installation
npm install @papit/treeviewUsage
Import
import "@papit/treeview";This registers both pap-treeview and pap-treeitem.
With pap-treeitem
Nest pap-treeitem elements to make branches. A branch gets a caret icon and indents its children.
<pap-treeview aria-label="File explorer">
<pap-treeitem>README.md</pap-treeitem>
<pap-treeitem>
src
<pap-treeitem>index.ts</pap-treeitem>
<pap-treeitem>style.css</pap-treeitem>
</pap-treeitem>
</pap-treeview>The caret is pap-icon name="caret-down", which loads /caret-down.svg. Serve asset/icons/caret-down.svg from your site root, or register the icon yourself (see @papit/icon).
With plain HTML
Any element works as an item. Nest a role="group" inside it for a branch, and set aria-expanded="true" to start open.
<pap-treeview aria-label="File explorer">
<li role="treeitem">README.md</li>
<li role="treeitem" aria-expanded="true">
<span>src</span>
<ul role="group">
<li role="treeitem">index.ts</li>
<li role="treeitem">style.css</li>
</ul>
</li>
</pap-treeview>Multiple selection
<pap-treeview mode="multiple" aria-label="Files to upload">…</pap-treeview>Attributes / Properties
pap-treeview
| Attribute | Property | Type | Default | Description |
| ------------------ | ------------- | ---------------------------- | ------------ | ------------------------------------------------------------------- |
| mode | mode | "single" \| "multiple" | "single" | Selection mode. multiple sets aria-multiselectable="true" |
| strict | strict | boolean | false | Only register elements that already have role="treeitem"; otherwise every child of a group becomes an item |
| aria-orientation | orientation | "horizontal" \| "vertical" | "vertical" | Reflected for assistive tech; the keys stay the same |
Selection lives in the DOM: a selected item has aria-selected="true", an unselected one has no aria-selected. Expansion is aria-expanded on the item.
pap-treeitem
No attributes of its own. The tree sets role, tabindex, aria-expanded and aria-selected on it.
Events
All are plain Events.
| Event | Target | Description |
| ---------- | ------------ | ----------------------------------------------- |
| active | the tree | Focus moved into the tree |
| inactive | the tree | Focus left the tree |
| enter | the item | Enter was pressed on the item |
document.querySelector("pap-treeitem").addEventListener("enter", e => {
console.log("open", e.target.textContent.trim());
});Slots
| Element | Slot | Description |
| -------------- | --------- | -------------------------------------------------------------- |
| pap-treeview | (default) | Top-level items |
| pap-treeitem | (default) | The label. Nested pap-treeitems are moved to group for you |
| pap-treeitem | group | Child items |
Styling
| Element | Part | Description |
| -------------- | --------- | -------------------------------------------- |
| pap-treeitem | content | The row: caret and label |
| pap-treeitem | group | The role="group" wrapper of child items |
| Custom property | Default | Description |
| --------------- | ----------- | ---------------------------------------------------- |
| --depth | 0rem | Left padding of the row; grows by --space-4 per level |
The focused pap-treeitem row gets a 2px --focus-color outline.
Keyboard Interaction
| Key | Behavior |
| ------------------ | -------------------------------------------------------------------- |
| Tab | Enters the tree on the last focused item, then leaves it |
| ArrowDown | Next visible item |
| ArrowUp | Previous visible item |
| ArrowRight | Closed branch: expand. Open branch: first child. Leaf: nothing |
| ArrowLeft | Open branch: collapse. Otherwise: parent item |
| Home | First visible item |
| End | Last visible item |
| Enter | Branch: toggle expand. Leaf: select. Fires enter on the item |
| Space | Select (single) or toggle selection (multiple) |
| Printable character | Typeahead: next visible item whose label starts with the typed text |
Mouse: clicking a branch toggles it, clicking a leaf selects it.
Accessibility
This component implements the ARIA Tree View Pattern and manages:
role="tree"on the host,role="treeitem"on every itemaria-expandedon branches (defaults to"false")aria-selectedandaria-multiselectable- roving tabindex, so the tree is a single tab stop
Give the tree an accessible name with aria-label or aria-labelledby.
Reference: https://www.w3.org/WAI/ARIA/apg/patterns/treeview/
License
Licensed under the @Papit License 1.0 Copyright (c) 2024 Henry Pap (@onkelhoy)
Key points
- ✅ Free to use in commercial projects
- ✅ Free to modify and distribute
- ✅ Attribution required
- ❌ Cannot resell the component itself as a standalone product
See the LICENSE file for full details.
Related Components
- @papit/web-component Core utilities, decorators, and base component class.
- @papit/icon Renders the branch caret.
