Skip to main content
Copy for LLM

Tree View

A hierarchical list for displaying nested data structures — file trees, category hierarchies, organization charts. Implements the full WAI-ARIA Tree View pattern with keyboard navigation.

Basic Usage

Simple file tree
  • src
      • Button.php
      • Input.php
      • helpers.php
      • ButtonTest.php

With Icons

Pass semantic icon aliases to indicate file types:

Tree with icons
  • Documents
    • Report.pdf
    • Budget.xlsx
    • photo.jpg

Pre-expanded Nodes

Use the expanded prop to open branch nodes by default — great for surfacing the most relevant level of a hierarchy without forcing a click:

Pre-expanded branches
  • Workspace
    • Pinned
      • Dashboard
      • Reports
      • 2024
      • 2023

Handling Selection

Listen to the tree-node-select event to respond to user selections. It fires for a click and for keyboard activation alike, so one handler covers both:

<x-wirekit::tree-view @tree-node-select="console.log($event.detail.label)">
    <x-wirekit::tree-view.node label="Option A" />
    <x-wirekit::tree-view.node label="Option B" />
</x-wirekit::tree-view>

Dynamic Data

Build trees from a Livewire property using recursive Blade:

// In your Livewire component
public array $tree = [
    ['label' => 'src', 'children' => [
        ['label' => 'App.php'],
        ['label' => 'routes', 'children' => [
            ['label' => 'web.php'],
        ]],
    ]],
];
{{-- In your Blade view --}}
<x-wirekit::tree-view>
    @foreach($tree as $node)
        @include('partials.tree-node', ['node' => $node])
    @endforeach
</x-wirekit::tree-view>
{{-- partials/tree-node.blade.php --}}
<x-wirekit::tree-view.node :label="$node['label']">
    @if(!empty($node['children']))
        @foreach($node['children'] as $child)
            @include('partials.tree-node', ['node' => $child])
        @endforeach
    @endif
</x-wirekit::tree-view.node>

Tree View Props

Prop Type Default Description
label string|null null Names the tree. A role="tree" is announced by its name and nothing else, so two unnamed trees on a page are two identical "tree"s. Falls back to a translated default; aria-labelledby on the tag works too
scope string|null null Scoped personalization key

Node Props

Prop Type Default Description
label string '' Node display text
icon string|null null Semantic icon alias
expanded bool false Whether branch node starts expanded
selected bool false Whether node starts selected
scope string|null null Scoped personalization key

Slots

Slot Purpose
default Child nodes (makes this a branch node)

Events

Event Detail Description
tree-node-select { label: string } Dispatched when a node is activated — Enter, Space, or a click. One event per activation, whichever gesture produced it

Accessibility

  • Container uses role="tree" — screen readers announce "tree"
  • Each node uses role="treeitem" on the row that receives focus — a screen reader announces the role and state of the focused element, so the two have to be the same element
  • Branch nodes have aria-expanded="true" or "false" — state announced on focus
  • Nested children wrapped in role="group", tied back to their branch row with aria-owns — screen readers convey nesting
  • Decorative chevrons/spacers marked aria-hidden="true"
  • Focus ring visible on keyboard navigation
  • Full keyboard pattern: arrows, Home, End, Enter, Space, and type-ahead

Keyboard Interaction

The tree view implements the full WAI-ARIA Tree View keyboard pattern:

Key Action
Tab Move focus into the tree
ArrowDown / ArrowUp Move to the next / previous visible node
ArrowRight (collapsed branch) Expand the branch
ArrowRight (expanded branch) Move focus to the first child
ArrowLeft (expanded branch) Collapse the branch
ArrowLeft (collapsed leaf) Move focus to the parent
Home / End Jump to first / last visible node
Enter / Space Activate the focused node (toggles expand/collapse on a branch)
Type a character Type-ahead to focus the next node starting with that character

Pitfalls

  • Don't put more than ~500 nodes in a single tree. WAI-ARIA Authoring Practices warn that virtual focus management degrades for large trees. Lazy-load child nodes on expand.
  • Don't use <x-wirekit::tree-view> for non-hierarchical data. Flat lists belong in <x-wirekit::data-list>; the tree's aria-level semantics will mislead screen readers.

Design Tokens

Element Token
Font family --font-wk-sans
Text size --text-wk-md
Text color --color-wk-text
Muted text (chevron) --color-wk-text-muted
Hover and selected background --color-wk-bg-active
Focus ring --color-wk-ring / --ring-wk-width
Node padding --padding-wk-x-sm / --padding-wk-y-sm
Border radius --radius-wk-sm
Transition --transition-wk-duration

Customization

This component reads no config/wirekit.php keys — every option is a prop. Style it through the design tokens above, or scope a variant with the scope prop.

An empty 'tree-view' => [] block in the config is not an override point: pasting one changes nothing.

Further Reading

Updated in WireKit v2.66.0 (2026-10-13)

Was this page helpful?

Thank you for your feedback!

Voting requires cookies or local storage. What we store