File Tree

Display hierarchical file and folder structure with expand/collapse functionality.

The FileTree component displays a hierarchical file system structure with expandable folders and file selection.

Install using CLI

AI Elements Vue
shadcn-vue CLI
npx ai-elements-vue@latest add file-tree

Install Manually

Copy and paste the following files into the same folder.

FileTree.vue
FileTreeFolder.vue
FileTreeFile.vue
FileTreeIcon.vue
FileTreeName.vue
FileTreeActions.vue
context.ts
index.ts
<script setup lang="ts">
import type { HTMLAttributes } from 'vue'
import { cn } from '@repo/shadcn-vue/lib/utils'
import { provide, ref, watch } from 'vue'
import { FileTreeKey } from './context'

interface Props extends /* @vue-ignore */ HTMLAttributes {
  class?: HTMLAttributes['class']
  expanded?: Set<string>
  defaultExpanded?: Set<string>
  selectedPath?: string
}

const props = withDefaults(defineProps<Props>(), {
  defaultExpanded: () => new Set(),
})

const emit = defineEmits<{
  (e: 'update:selectedPath', path: string): void
  (e: 'expandedChange', expanded: Set<string>): void
}>()

const internalExpanded = ref(new Set(props.defaultExpanded))
const internalSelectedPath = ref(props.selectedPath)

watch(
  () => props.expanded,
  (newVal) => {
    if (newVal) {
      internalExpanded.value = newVal
    }
  },
  { immediate: true },
)

watch(
  () => props.selectedPath,
  (newVal) => {
    internalSelectedPath.value = newVal
  },
)

function togglePath(path: string) {
  const newExpanded = new Set(internalExpanded.value)
  if (newExpanded.has(path)) {
    newExpanded.delete(path)
  }
  else {
    newExpanded.add(path)
  }
  internalExpanded.value = newExpanded
  emit('expandedChange', newExpanded)
}

function onSelect(path: string) {
  internalSelectedPath.value = path
  emit('update:selectedPath', path)
}

provide(FileTreeKey, {
  expandedPaths: internalExpanded,
  togglePath,
  selectedPath: internalSelectedPath,
  onSelect,
})
</script>

<template>
  <div
    :class="cn('rounded-lg border bg-background font-mono text-sm', props.class)"
    role="tree"
    v-bind="$attrs"
  >
    <div class="p-2">
      <slot />
    </div>
  </div>
</template>

Features

  • Hierarchical file/folder display
  • Expand/collapse folders
  • Selection handling
  • Controlled and uncontrolled modes
  • Customizable icons
  • Keyboard navigation

Examples

Basic Usage

With Selection

Default Expanded

Props

<FileTree />

expandedSet<string>
Controlled set of expanded folder paths.
defaultExpandedSet<string>
Initial set of expanded folder paths.
selectedPathstring
Currently selected file/folder path.
@update:selected-path(path: string) => void
Two-way binding event when a file/folder is selected.
@expandedChange(expanded: Set<string>) => void
Callback when expanded folders change.
...propsHTMLAttributes
Spread to the container div.

<FileTreeFolder />

pathrequiredstring
Unique identifier path for the folder.
namerequiredstring
Display name of the folder.
...propsHTMLAttributes
Spread to the folder container.

<FileTreeFile />

pathrequiredstring
Unique identifier path for the file.
namerequiredstring
Display name of the file.
iconSlot
Custom icon for the file.
...propsHTMLAttributes
Spread to the file container.

<FileTreeIcon />

...propsHTMLAttributes
Spread to the icon container span.

<FileTreeName />

...propsHTMLAttributes
Spread to the name container span.

<FileTreeActions />

...propsHTMLAttributes
Spread to the actions container div.