Tree
Tree presents nested data as an expandable hierarchy so users can locate, select, and act on nodes one level at a time.
Example index.htmlEntry main.js
<div class="tree" role="tree" aria-label="Project files">
<div
role="treeitem"
aria-label="src"
aria-expanded="true"
aria-selected="false"
data-value="src"
>
<div data-tree-row>
<svg aria-hidden="true"><!-- folder icon --></svg>
<span data-tree-label>src</span>
</div>
<div role="group">
<div
role="treeitem"
aria-label="tree.js"
aria-selected="true"
data-value="src/tree.js"
>
<div data-tree-row>
<svg aria-hidden="true"><!-- file icon --></svg>
<span data-tree-label>tree.js</span>
</div>
</div>
</div>
</div>
</div>import "@a3s-lab/ui/a3s.css";
import "@a3s-lab/ui/all";Controller The browser runtime initializes the public DOM controller; documented HTML events, state, and methods remain the source of truth.
Usage
Tree is an A3S application component for file explorers, resource hierarchies, and nested configuration. It is intentionally distinct from Accordion: focus moves between visible nodes, selection is explicit, and branches expose a parent-child hierarchy to assistive technology.
Include CSS Import Tailwind and one complete A3S UI style bundle.
@import "tailwindcss" ;
@import "@a3s-lab/ui/a3s.css" ; Or import only the base CSS, Tree component CSS, and one style pack.
@import "tailwindcss" ;
@import "@a3s-lab/ui/base.css" ;
@import "@a3s-lab/ui/components/tree.css" ;
@import "@a3s-lab/ui/styles/a3s.css" ;
Include JavaScript Load the complete runtime bundle, or load the runtime before the Tree controller.
< script src = "/assets/js/runtime.min.js" defer ></ script >
< script src = "/assets/js/tree.min.js" defer ></ script >
Add the tree HTML < div class = "tree" role = "tree" aria-label = "Project files" >
< div
role = "treeitem"
aria-label = "src"
aria-expanded = "true"
aria-selected = "false"
data-value = "src"
>
< div data-tree-row >
< svg aria-hidden = "true" > <!-- folder icon --> </ svg >
< span data-tree-label >src</ span >
</ div >
< div role = "group" >
< div
role = "treeitem"
aria-label = "tree.js"
aria-selected = "true"
data-value = "src/tree.js"
>
< div data-tree-row >
< svg aria-hidden = "true" > <!-- file icon --> </ svg >
< span data-tree-label >tree.js</ span >
</ div >
</ div >
</ div >
</ div >
</ div >
i A3S extension Tree is not currently provided by the upstream systems A3S UI follows. A3S UI
defines a small semantic HTML contract instead of porting a framework-specific
component API.
Parameters
The controller owns tabindex, synchronizes child-group visibility with aria-expanded, and keeps exactly one enabled visible node in the Tab order.
JavaScript API
const tree = document .querySelector ( "#project-tree" );
const item = tree .querySelector ( '[data-value="src/components"]' );
tree .expand (item , true );
tree .select (item , true );
tree .refresh ();
Selection emits a bubbling change event with { item, value }. Expansion emits a3s:tree-toggle with { item, value, expanded }.
States and variants
Disabled nodes
Set aria-disabled="true" on a tree item. Disabled nodes remain visible but are skipped by pointer interaction, arrow navigation, and typeahead.
RTL
<div
id="tree-demo-rtl"
class="tree"
role="tree"
aria-label="ملفات المشروع"
dir="rtl"
>
<div
role="treeitem"
aria-label="المصدر"
aria-expanded="true"
aria-selected="false"
data-value="src"
>
<div data-tree-row>
<svg
class="lucide lucide-folder"
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M2 6a2 2 0 0 1 2-2h5l2 2h9a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2Z" />
</svg>
<span data-tree-label>المصدر</span>
<span data-tree-meta>عنصران</span>
</div>
<div role="group">
<div
role="treeitem"
aria-label="المكونات"
aria-selected="true"
data-value="components"
>
<div data-tree-row>
<svg
class="lucide lucide-folder"
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M2 6a2 2 0 0 1 2-2h5l2 2h9a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2Z" />
</svg>
<span data-tree-label>المكونات</span>
</div>
</div>
<div
role="treeitem"
aria-label="الفهرس"
aria-selected="false"
data-value="index"
>
<div data-tree-row>
<svg
class="lucide lucide-file"
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5L14.5 2z" />
<polyline points="14 2 14 8 20 8" />
</svg>
<span data-tree-label>الفهرس</span>
</div>
</div>
</div>
</div>
</div>
Logical indentation, guide lines, and chevrons follow document direction. In RTL, ArrowLeft expands or enters a branch and ArrowRight collapses or returns to its parent.
Accessibility
Keep tree items as direct children of the root or a direct child role="group".
Give every item a concise accessible name. An explicit aria-label prevents descendant groups or trailing metadata from becoming part of a branch name.
Do not place buttons, links, or form controls inside a tree row. The tree item itself owns focus and selection.
Use Tree for hierarchical choices. Use Accordion for independent disclosure sections and Sidebar for page navigation.