Tree

SvTree: a file explorer with cascading tri-state checkboxes and a single-select highlight; keyboard up/down move, left/right collapse/expand.

A live, editable Svelte 5 component example from the SvGrid gallery (Layout). Read the SvGrid UI component docs for the full API.

What this example shows

SvTree - a production file explorer with cascading tri-state checkboxes and a single-select highlight. Keyboard: up/down move, left/right collapse/expand. Copy-paste ready.

Imports, features and API used

Imports: @svgrid/grid

Source code (321-tree.svelte)

<script lang="ts">
  /**
   * SvTree - a production file explorer with cascading tri-state checkboxes and a
   * single-select highlight. Keyboard: up/down move, left/right collapse/expand.
   * Copy-paste ready.
   */
  import { SvTree } from '@svgrid/grid'
  import type { SvTreeNode } from '@svgrid/grid'

  const nodes: SvTreeNode[] = [
    { id: 'src', label: 'src', children: [
      { id: 'comp', label: 'components', children: [
        { id: 'grid', label: 'Grid.svelte' },
        { id: 'toolbar', label: 'Toolbar.svelte' },
      ] },
      { id: 'lib', label: 'lib', children: [
        { id: 'api', label: 'api.ts' },
        { id: 'utils', label: 'utils.ts' },
      ] },
      { id: 'main', label: 'main.ts' },
    ] },
    { id: 'public', label: 'public', children: [
      { id: 'logo', label: 'logo.svg' },
      { id: 'favicon', label: 'favicon.ico' },
    ] },
    { id: 'readme', label: 'README.md' },
  ]
  let selected = $state<string | null>('grid')
  let checked = $state<string[]>(['api'])
  let expanded = $state<string[]>(['src', 'comp', 'lib'])
</script>

<div class="wrap">
  <header>
    <h2>Tree</h2>
    <p>A hierarchical view (WAI-ARIA tree) with a built-in search box (type to filter, matches auto-expand), cascading tri-state checkboxes and keyboard nav.</p>
  </header>

  <div class="cols">
    <div class="card">
      <SvTree {nodes} {selected} checkable {checked} expandedIds={expanded} searchable searchPlaceholder="Search files..."
        onSelect={(id) => (selected = id)}
        onCheck={(ids) => (checked = ids)}
        onToggle={(id, open) => (expanded = open ? [...expanded, id] : expanded.filter((e) => e !== id))} />
    </div>
    <aside class="side">
      <div><span class="k">Selected</span><strong>{selected ?? '-'}</strong></div>
      <div><span class="k">Checked ({checked.length})</span><strong>{checked.join(', ') || '-'}</strong></div>
    </aside>
  </div>
</div>

<style>
  .wrap { padding: 20px; max-width: 640px; display: flex; flex-direction: column; gap: 16px; }
  header h2 { margin: 0 0 4px; font-size: 20px; font-weight: 700; }
  header p { margin: 0; color: var(--sg-muted, #64748b); font-size: 13.5px; line-height: 1.5; }
  .cols { display: flex; gap: 24px; align-items: flex-start; flex-wrap: wrap; }
  .side { flex: 1; min-width: 160px; display: flex; flex-direction: column; gap: 14px; }
  .side .k { display: block; font-size: 11px; text-transform: uppercase; letter-spacing: 0.03em; color: var(--sg-muted, #94a3b8); margin-bottom: 2px; }
  .side strong { font-size: 13px; word-break: break-word; }
</style>

View this example on GitHub

Related documentation

Related articles

More Layout examples

  • Account & security settings console - A real SaaS settings surface composed from the UI kit: SvMenubar app bar, promise + Undo-action toasts on save, SvPopconfirm on destructive rows, SvHoverCard teammate previews, and frame input adornments (leading icons, prefix affixes, masked API key). Profile / Team / Security tabs over SvCard + SvStat.
  • Invoice builder - An adornment-heavy money form: currency prefixes, % suffixes, masked tax IDs (frame adornments), line items with SvPopconfirm delete + Undo action toasts, live SvStat totals, an SvHoverCard tax hint, and a promise toast on Send. Pure UI-kit composition.
  • Operations KPI dashboard - A KPI console: SvStat + SvSparkline tiles, an SvGauge SLA dial, SvHoverCard drill-down previews per service, an SvMenubar toolbar (View / Range / Actions) and a promise toast on Refresh. Pure UI-kit composition, no grid dependency.
  • Form: rich field types - SvForm reaching the whole input suite from one schema - phone, country, mask, combobox, radio, slider, tags, datetime and file - plus per-field help text, a readonly field, column span, and a promise toast on submit.
  • Form: cascading fields - SvForm dependent selects - a child list derives from the parent value via a function `options`, and `dependsOn` clears the child when the parent changes so a stale selection never lingers. Country -> State -> City.