Skip to main content
You are viewing Pre-Alpha documentation.
Vuetify0 Logo
Theme
Mode
Palettes
Accessibility
Vuetify One

Sign in to Vuetify One

Access premium tools across the Vuetify ecosystem — Bin, Play, Studio, and more.

Not a subscriber? See what's included

Treeview

A compound component for building accessible hierarchical tree interfaces with expand/collapse and selection support.


Renders elementAdvancedMar 24, 2026

Usage

The Treeview component provides a compound pattern for building accessible tree structures. It uses the createNested composable internally for hierarchical state management — tracking parent-child relationships, open/close state, and cascade selection.

  •  Fruits
  •  Vegetables
  •  Bread
<script setup lang="ts">
  import { Treeview } from '@vuetify/v0'

  const items = [
    {
      name: 'Fruits',
      children: [
        { name: 'Apple' },
        { name: 'Banana' },
        { name: 'Orange' },
      ],
    },
    {
      name: 'Vegetables',
      children: [
        { name: 'Carrot' },
        { name: 'Broccoli' },
      ],
    },
    { name: 'Bread' },
  ]
</script>

<template>
  <Treeview.Root multiple>
    <Treeview.List class="text-sm text-on-surface select-none">
      <Treeview.Item
        v-for="item in items"
        :key="item.name"
        class="py-0.5"
        :value="item.name"
      >
        <div class="inline-flex items-center gap-1.5">
          <Treeview.Activator
            v-if="item.children"
            class="inline-flex items-center border-none bg-transparent p-0 cursor-pointer text-on-surface hover:text-primary"
          >
            <Treeview.Cue v-slot="{ attrs }">
              <svg
                v-bind="attrs"
                class="size-3.5 opacity-60 transition-transform data-[state=open]:rotate-90"
                fill="none"
                stroke="currentColor"
                viewBox="0 0 24 24"
              ><path d="M9 5l7 7-7 7" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" /></svg>
            </Treeview.Cue>
          </Treeview.Activator>

          <span v-else class="inline-block w-3.5" />

          <Treeview.Checkbox v-slot="{ attrs, isSelected, isMixed }" renderless>
            <span
              v-bind="attrs"
              class="size-4 inline-flex items-center justify-center border rounded-sm text-xs leading-none cursor-pointer shrink-0"
              :class="isSelected || isMixed ? 'bg-primary text-on-primary border-primary' : 'border-on-surface/40'"
            >{{ isMixed ? '−' : isSelected ? '✓' : '\u00A0' }}</span>
          </Treeview.Checkbox>

          <span>{{ item.name }}</span>
        </div>

        <Treeview.Content v-if="item.children">
          <Treeview.Group class="pl-5">
            <Treeview.Item
              v-for="child in item.children"
              :key="child.name"
              class="py-0.5"
              :value="child.name"
            >
              <div class="inline-flex items-center gap-1.5">
                <span class="inline-block w-3.5" />

                <Treeview.Checkbox v-slot="{ attrs, isSelected }" renderless>
                  <span
                    v-bind="attrs"
                    class="size-4 inline-flex items-center justify-center border rounded-sm text-xs leading-none cursor-pointer shrink-0"
                    :class="isSelected ? 'bg-primary text-on-primary border-primary' : 'border-on-surface/40'"
                  >{{ isSelected ? '✓' : '\u00A0' }}</span>
                </Treeview.Checkbox>

                <span>{{ child.name }}</span>
              </div>
            </Treeview.Item>
          </Treeview.Group>
        </Treeview.Content>
      </Treeview.Item>
    </Treeview.List>
  </Treeview.Root>
</template>

Anatomy

vue
<script setup lang="ts">
  import { Treeview } from '@vuetify/v0'
</script>

<template>
  <Treeview.Root>
    <Treeview.List>
      <Treeview.Item>
        <Treeview.Activator>
          <Treeview.Cue />
          Label
        </Treeview.Activator>

        <Treeview.Content>
          <Treeview.Group>
            <Treeview.Item>
              <Treeview.Activator>Leaf</Treeview.Activator>
            </Treeview.Item>
          </Treeview.Group>
        </Treeview.Content>
      </Treeview.Item>
    </Treeview.List>
  </Treeview.Root>
</template>

For trees with selection, add Treeview.Checkbox and Treeview.Indicator:

vue
<script setup lang="ts">
  import { Treeview } from '@vuetify/v0'
</script>

<template>
  <Treeview.Root>
    <Treeview.List>
      <Treeview.Item>
        <Treeview.Activator>
          <Treeview.Cue />
        </Treeview.Activator>

        <Treeview.Checkbox>
          <Treeview.Indicator />
        </Treeview.Checkbox>

        Label

        <Treeview.Content>
          <Treeview.Group>
            <Treeview.Item>Leaf</Treeview.Item>
          </Treeview.Group>
        </Treeview.Content>
      </Treeview.Item>
    </Treeview.List>
  </Treeview.Root>
</template>

Examples

Settings Panel

A settings tree with functional controls built from reactive data. Click any setting to activate it and view its description in the detail pane.

  • Activationactivate from the Item slot highlights the current item. Style the active row with [data-active].

  • Functional controls — toggles and <select> dropdowns modify the reactive data directly.

  • Disabled:disabled on Treeview.Item greys out the “Experimental” category. Style with [data-disabled].

  • Depth indentation--v0-treeview-depth CSS variable on each item drives padding-left, no manual nesting needed.

  • Open/closedisOpen slot prop on Item rotates the chevron via a CSS class.

  • Recursive renderingSettingNode.vue handles both categories and leaves, recursing through Treeview.Group for nested children.

Click a setting to see its description.

Recipes

Cascade Selection

Add v-model to Treeview.Root for cascade selection. Use Treeview.Checkbox and Treeview.Indicator for tri-state checkboxes. Use Treeview.SelectAll for a tree-wide toggle.

vue
<script setup lang="ts">
  import { Treeview } from '@vuetify/v0'
  import { ref } from 'vue'

  const selected = ref<string[]>([])
</script>

<template>
  <Treeview.Root v-model="selected">
    <Treeview.SelectAll>
      <Treeview.Indicator />
      Select All
    </Treeview.SelectAll>

    <Treeview.List>
      <Treeview.Item value="users">
        <Treeview.Checkbox>
          <Treeview.Indicator />
        </Treeview.Checkbox>
        Users

        <Treeview.Group>
          <Treeview.Item value="users:view">
            <Treeview.Checkbox>
              <Treeview.Indicator />
            </Treeview.Checkbox>
            View
          </Treeview.Item>

          <Treeview.Item value="users:create">
            <Treeview.Checkbox>
              <Treeview.Indicator />
            </Treeview.Checkbox>
            Create
          </Treeview.Item>
        </Treeview.Group>
      </Treeview.Item>
    </Treeview.List>
  </Treeview.Root>
</template>

Styling with Data Attributes

All sub-components expose data attributes for CSS-driven state styling:

ComponentAttributeValues
Itemdata-selectedPresent when selected
Itemdata-disabledPresent when disabled
Itemdata-openPresent when expanded
Itemdata-activePresent when active
Activatordata-disabledPresent when disabled
Activatordata-openPresent when expanded
Checkboxdata-selectedPresent when checked
Checkboxdata-disabledPresent when disabled
Checkboxdata-mixedPresent when indeterminate
Cuedata-stateopen or closed
Indicatordata-statechecked, unchecked, or indeterminate

The --v0-treeview-depth CSS variable is set on each Item, enabling indentation:

css
.tree-item {
  padding-left: calc(var(--v0-treeview-depth) * 1rem);
}

API Reference

The following API details are for all variations of the Treeview component.

Treeview.Root

Props

namespace

string | undefined

Namespace for dependency injection

disabled

boolean | undefined

Disables the entire tree

enroll

boolean | undefined

Auto-select non-disabled items on registration

mandatory

boolean | "force" | undefined

Prevents deselecting the last selected item

multiple

boolean | undefined

Allows selecting multiple items

open

NestedOpenMode | undefined

Controls how nodes expand: 'multiple' (default) or 'single' (accordion)

openAll

boolean | undefined

Auto-expand all nodes on registration

reveal

boolean | undefined

Opening a node also opens all its ancestors

selection

NestedSelectionMode | undefined

Controls how selection cascades: 'cascade' (default), 'independent', or 'leaf'

active

NestedActiveMode | undefined

Controls active/highlight mode: 'single' (default) or 'multiple'

Events

update:model-value

[value: T | T[]]

Slots

default

TreeviewRootSlotProps

Treeview.Activator

Props

namespace

string | undefined

Namespace for dependency injection

Treeview.Checkbox

Props

namespace

string | undefined

Namespace for dependency injection

Treeview.Content

Props

namespace

string | undefined

Namespace for dependency injection

Treeview.Cue

Props

namespace

string | undefined

Namespace for dependency injection

Treeview.Indicator

Props

namespace

string | undefined

Namespace for dependency injection

Treeview.Item

Props

id

ID | undefined

Unique identifier (auto-generated if not provided)

value

V | undefined

Value associated with this item

disabled

MaybeRefOrGetter<boolean> | undefined

Disables this item

namespace

string | undefined

Namespace for dependency injection

Slots

default

TreeviewItemSlotProps<V>

Treeview.List

Props

namespace

string | undefined

Namespace for dependency injection

multiselectable

boolean | undefined

Whether multiple items can be selected (sets aria-multiselectable)

label

string | undefined

Accessible label for the tree

Treeview.SelectAll

Props

label

string | undefined

Optional display label (passed through to slot and aria-label)

disabled

boolean | undefined

Disables this checkbox

namespace

string | undefined

Namespace for dependency injection

Was this page helpful?

© 2016-1970 Vuetify, LLC
Ctrl+/