Skip to content

Tree

Tree shows nested items that open and close. Click a row to select it, or Tab into the tree and use the arrow keys to move, open and close:

crates
hozo_ir
README.md

Selected: readme

TreeDemo.tsx
import { Paragraph, View } from '@hozo/core'
import { Tree, type TreeNode } from '@hozo/ui'
import { useState } from 'react'
const FILES: readonly TreeNode[] = [
{
id: 'crates',
label: 'crates',
children: [
{ id: 'ir', label: 'hozo_ir' },
{ id: 'web', label: 'hozo_web', children: [{ id: 'css', label: 'css.rs' }] },
],
},
{ id: 'packages', label: 'packages', children: [{ id: 'ui', label: 'ui' }] },
{ id: 'readme', label: 'README.md' },
]
export function TreeDemo() {
const [selected, setSelected] = useState('readme')
return (
<View className="w-full max-w-xs gap-3">
<Tree
nodes={FILES}
accessibilityLabel="Repository"
defaultExpanded={['crates']}
selectedId={selected}
onSelect={setSelected}
/>
<Paragraph className="text-sm text-hozo-text-body">{`Selected: ${selected}`}</Paragraph>
</View>
)
}
  • nodes: { id, label, children? }. A node with children is a branch that can expand.
  • defaultExpanded lists the ids that start open.
  • selectedId and onSelect hold the selected item.
  • A click selects and does not open a branch. For now, branches open and close only from the keyboard (#1143).
  • The keyboard follows the ARIA tree pattern:
    • Up and Down move between visible rows.
    • Right opens a branch, or moves into it once it is open.
    • Left closes a branch, or moves to its parent.
    • Enter selects.
    • Typing a letter moves to the next row that starts with it.
    • In a right-to-left interface, Left and Right swap.
  • The open and closed marker is drawn by CSS, not written into the label. A reader already hears “expanded” or “collapsed”, so a ▾ in the text would say it twice.
  • renderRow replaces what a row shows. It is given the row’s level and whether it is open.