General
Tree
Usage#
import { WdsTreeComponent } from '@wds/angular/tree';items is a property (in HTML set it from a script): a list of { id, label, children }, where an item with children is a folder. expanded lists the open folders and value is the selected item. A click on a folder expands or collapses it (wds-toggle); a click on another item selects it (wds-change).
Examples#
Default#
expanded sets the folders open at first.
import { Component } from '@angular/core';
import { WdsTreeComponent } from '@wds/angular/tree';
import { EXPANDED, FILES } from './tree-data';
@Component({
selector: 'app-tree-default-demo',
host: { class: 'block w-full max-w-xs' },
imports: [WdsTreeComponent],
template: `<wds-tree label="Project files" [items]="files" [expanded]="expanded" />`,
})
export class TreeDefaultDemo {
protected readonly files = FILES;
protected readonly expanded = EXPANDED;
}import type { WdsTreeItem } from '@wds/core/tree';
/** A sample project: folders have `children`. */
export const FILES: WdsTreeItem[] = [
{
id: 'src',
label: 'src',
children: [
{
id: 'app',
label: 'app',
children: [
{ id: 'page-tsx', label: 'page.tsx' },
{ id: 'layout-tsx', label: 'layout.tsx' },
{ id: 'loading-tsx', label: 'loading.tsx' },
],
},
{
id: 'components',
label: 'components',
children: [
{ id: 'button-tsx', label: 'button.tsx' },
{ id: 'card-tsx', label: 'card.tsx' },
{ id: 'dialog-tsx', label: 'dialog.tsx' },
],
},
{
id: 'lib',
label: 'lib',
children: [
{ id: 'utils-ts', label: 'utils.ts' },
{ id: 'api-ts', label: 'api.ts' },
],
},
{ id: 'globals-css', label: 'globals.css' },
],
},
{ id: 'public', label: 'public', children: [{ id: 'logo-svg', label: 'logo.svg' }, { id: 'hero-png', label: 'hero.png' }] },
{ id: 'package-json', label: 'package.json' },
{ id: 'readme-md', label: 'README.md' },
{ id: 'tsconfig-json', label: 'tsconfig.json' },
];
/** Folders expanded at first. */
export const EXPANDED = ['src', 'app', 'components'];Lines#
lines draws a vertical line from each open folder along its items.
import { Component } from '@angular/core';
import { WdsTreeComponent } from '@wds/angular/tree';
import { EXPANDED, FILES } from './tree-data';
@Component({
selector: 'app-tree-lines-demo',
host: { class: 'block w-full max-w-xs' },
imports: [WdsTreeComponent],
template: `<wds-tree label="Project files" lines [items]="files" [expanded]="expanded" />`,
})
export class TreeLinesDemo {
protected readonly files = FILES;
protected readonly expanded = EXPANDED;
}import type { WdsTreeItem } from '@wds/core/tree';
/** A sample project: folders have `children`. */
export const FILES: WdsTreeItem[] = [
{
id: 'src',
label: 'src',
children: [
{
id: 'app',
label: 'app',
children: [
{ id: 'page-tsx', label: 'page.tsx' },
{ id: 'layout-tsx', label: 'layout.tsx' },
{ id: 'loading-tsx', label: 'loading.tsx' },
],
},
{
id: 'components',
label: 'components',
children: [
{ id: 'button-tsx', label: 'button.tsx' },
{ id: 'card-tsx', label: 'card.tsx' },
{ id: 'dialog-tsx', label: 'dialog.tsx' },
],
},
{
id: 'lib',
label: 'lib',
children: [
{ id: 'utils-ts', label: 'utils.ts' },
{ id: 'api-ts', label: 'api.ts' },
],
},
{ id: 'globals-css', label: 'globals.css' },
],
},
{ id: 'public', label: 'public', children: [{ id: 'logo-svg', label: 'logo.svg' }, { id: 'hero-png', label: 'hero.png' }] },
{ id: 'package-json', label: 'package.json' },
{ id: 'readme-md', label: 'README.md' },
{ id: 'tsconfig-json', label: 'tsconfig.json' },
];
/** Folders expanded at first. */
export const EXPANDED = ['src', 'app', 'components'];Icons#
icons="folder" shows a folder (open or closed) and a file icon before the text.
import { Component } from '@angular/core';
import { WdsTreeComponent } from '@wds/angular/tree';
import { EXPANDED, FILES } from './tree-data';
@Component({
selector: 'app-tree-icons-demo',
host: { class: 'block w-full max-w-xs' },
imports: [WdsTreeComponent],
template: `<wds-tree label="Project files" icons="folder" [items]="files" [expanded]="expanded" />`,
})
export class TreeIconsDemo {
protected readonly files = FILES;
protected readonly expanded = EXPANDED;
}import type { WdsTreeItem } from '@wds/core/tree';
/** A sample project: folders have `children`. */
export const FILES: WdsTreeItem[] = [
{
id: 'src',
label: 'src',
children: [
{
id: 'app',
label: 'app',
children: [
{ id: 'page-tsx', label: 'page.tsx' },
{ id: 'layout-tsx', label: 'layout.tsx' },
{ id: 'loading-tsx', label: 'loading.tsx' },
],
},
{
id: 'components',
label: 'components',
children: [
{ id: 'button-tsx', label: 'button.tsx' },
{ id: 'card-tsx', label: 'card.tsx' },
{ id: 'dialog-tsx', label: 'dialog.tsx' },
],
},
{
id: 'lib',
label: 'lib',
children: [
{ id: 'utils-ts', label: 'utils.ts' },
{ id: 'api-ts', label: 'api.ts' },
],
},
{ id: 'globals-css', label: 'globals.css' },
],
},
{ id: 'public', label: 'public', children: [{ id: 'logo-svg', label: 'logo.svg' }, { id: 'hero-png', label: 'hero.png' }] },
{ id: 'package-json', label: 'package.json' },
{ id: 'readme-md', label: 'README.md' },
{ id: 'tsconfig-json', label: 'tsconfig.json' },
];
/** Folders expanded at first. */
export const EXPANDED = ['src', 'app', 'components'];File explorer#
icons="file-type" also picks the icon of a file by its extension: code, markup, styles, data, text and images. An item’s icon overrides it.
import { Component } from '@angular/core';
import { WdsTreeComponent } from '@wds/angular/tree';
import { EXPANDED, FILES } from './tree-data';
@Component({
selector: 'app-tree-file-type-demo',
host: { class: 'block w-full max-w-xs' },
imports: [WdsTreeComponent],
template: `<wds-tree label="Project files" icons="file-type" [items]="files" [expanded]="expanded" />`,
})
export class TreeFileTypeDemo {
protected readonly files = FILES;
protected readonly expanded = EXPANDED;
}import type { WdsTreeItem } from '@wds/core/tree';
/** A sample project: folders have `children`. */
export const FILES: WdsTreeItem[] = [
{
id: 'src',
label: 'src',
children: [
{
id: 'app',
label: 'app',
children: [
{ id: 'page-tsx', label: 'page.tsx' },
{ id: 'layout-tsx', label: 'layout.tsx' },
{ id: 'loading-tsx', label: 'loading.tsx' },
],
},
{
id: 'components',
label: 'components',
children: [
{ id: 'button-tsx', label: 'button.tsx' },
{ id: 'card-tsx', label: 'card.tsx' },
{ id: 'dialog-tsx', label: 'dialog.tsx' },
],
},
{
id: 'lib',
label: 'lib',
children: [
{ id: 'utils-ts', label: 'utils.ts' },
{ id: 'api-ts', label: 'api.ts' },
],
},
{ id: 'globals-css', label: 'globals.css' },
],
},
{ id: 'public', label: 'public', children: [{ id: 'logo-svg', label: 'logo.svg' }, { id: 'hero-png', label: 'hero.png' }] },
{ id: 'package-json', label: 'package.json' },
{ id: 'readme-md', label: 'README.md' },
{ id: 'tsconfig-json', label: 'tsconfig.json' },
];
/** Folders expanded at first. */
export const EXPANDED = ['src', 'app', 'components'];Plus and minus icons#
toggle-icon="plus-minus" shows plus and minus instead of the chevron.
import { Component } from '@angular/core';
import { WdsTreeComponent } from '@wds/angular/tree';
import { EXPANDED, FILES } from './tree-data';
@Component({
selector: 'app-tree-plus-minus-demo',
host: { class: 'block w-full max-w-xs' },
imports: [WdsTreeComponent],
template: `<wds-tree label="Project files" toggle-icon="plus-minus" icons="folder" [items]="files" [expanded]="expanded" />`,
})
export class TreePlusMinusDemo {
protected readonly files = FILES;
protected readonly expanded = EXPANDED;
}import type { WdsTreeItem } from '@wds/core/tree';
/** A sample project: folders have `children`. */
export const FILES: WdsTreeItem[] = [
{
id: 'src',
label: 'src',
children: [
{
id: 'app',
label: 'app',
children: [
{ id: 'page-tsx', label: 'page.tsx' },
{ id: 'layout-tsx', label: 'layout.tsx' },
{ id: 'loading-tsx', label: 'loading.tsx' },
],
},
{
id: 'components',
label: 'components',
children: [
{ id: 'button-tsx', label: 'button.tsx' },
{ id: 'card-tsx', label: 'card.tsx' },
{ id: 'dialog-tsx', label: 'dialog.tsx' },
],
},
{
id: 'lib',
label: 'lib',
children: [
{ id: 'utils-ts', label: 'utils.ts' },
{ id: 'api-ts', label: 'api.ts' },
],
},
{ id: 'globals-css', label: 'globals.css' },
],
},
{ id: 'public', label: 'public', children: [{ id: 'logo-svg', label: 'logo.svg' }, { id: 'hero-png', label: 'hero.png' }] },
{ id: 'package-json', label: 'package.json' },
{ id: 'readme-md', label: 'README.md' },
{ id: 'tsconfig-json', label: 'tsconfig.json' },
];
/** Folders expanded at first. */
export const EXPANDED = ['src', 'app', 'components'];Selection#
value is the id of the selected item; selecting another one fires wds-change. Folders are not selected. An item with disabled (here public) cannot be selected or expanded.
Selected: page-tsx
import { Component, signal } from '@angular/core';
import { WdsTreeComponent } from '@wds/angular/tree';
import type { WdsTreeItem } from '@wds/core/tree';
import { EXPANDED, FILES } from './tree-data';
/** The same project with `public` disabled. */
const ITEMS: WdsTreeItem[] = FILES.map((item) => (item.id === 'public' ? { ...item, disabled: true } : item));
@Component({
selector: 'app-tree-selection-demo',
host: { class: 'flex w-full max-w-xs flex-col gap-3' },
imports: [WdsTreeComponent],
template: `
<wds-tree label="Project files" icons="file-type" [items]="items" [expanded]="expanded" [value]="value()" (wdsChange)="value.set($event.value)" />
<p class="m-0 text-sm text-muted-foreground" aria-live="polite">Selected: {{ value() || 'none' }}</p>
`,
})
export class TreeSelectionDemo {
protected readonly items = ITEMS;
protected readonly expanded = EXPANDED;
protected readonly value = signal('page-tsx');
}import type { WdsTreeItem } from '@wds/core/tree';
/** A sample project: folders have `children`. */
export const FILES: WdsTreeItem[] = [
{
id: 'src',
label: 'src',
children: [
{
id: 'app',
label: 'app',
children: [
{ id: 'page-tsx', label: 'page.tsx' },
{ id: 'layout-tsx', label: 'layout.tsx' },
{ id: 'loading-tsx', label: 'loading.tsx' },
],
},
{
id: 'components',
label: 'components',
children: [
{ id: 'button-tsx', label: 'button.tsx' },
{ id: 'card-tsx', label: 'card.tsx' },
{ id: 'dialog-tsx', label: 'dialog.tsx' },
],
},
{
id: 'lib',
label: 'lib',
children: [
{ id: 'utils-ts', label: 'utils.ts' },
{ id: 'api-ts', label: 'api.ts' },
],
},
{ id: 'globals-css', label: 'globals.css' },
],
},
{ id: 'public', label: 'public', children: [{ id: 'logo-svg', label: 'logo.svg' }, { id: 'hero-png', label: 'hero.png' }] },
{ id: 'package-json', label: 'package.json' },
{ id: 'readme-md', label: 'README.md' },
{ id: 'tsconfig-json', label: 'tsconfig.json' },
];
/** Folders expanded at first. */
export const EXPANDED = ['src', 'app', 'components'];API References#
wds-tree#
items; a folder expands and collapses on click and with the arrow keys, an item is selected
on click or with Enter.
Attributes
| Attribute | Type | Default | Description |
|---|---|---|---|
| expanded | string[] | [] | |
| value | string | '' | '' when none is selected. Folders are not selected: a click toggles them. |
| indent | number | 20 | |
| toggle-icon.toggleIcon | WdsTreeToggleIcon | 'chevron' | |
| icons | WdsTreeIcons | 'none' | folder shows folders and files, file-type also the kind of file by its extension. |
| lines | boolean | false | |
| label | string | '' | aria-label). |
Properties
| Property | Description |
|---|---|
| itemsWdsTreeItem[] | children is a folder. |
Events
| Event | Description |
|---|---|
| wds-toggleCustomEvent<WdsTreeToggleDetail> | |
| wds-changeCustomEvent<WdsTreeChangeDetail> |
Methods
| Method | Description |
|---|---|
| expandAll() | |
| collapseAll() |
CSS parts (::part)
| Part | Description |
|---|---|
| tree | role="tree"). |
| item | role="treeitem"). |
| label |
CSS custom properties
| Property | Description |
|---|---|
| --wds-tree-line-color | lines (default --wds-border). |
| --wds-tree-folder-color |
Accessibility#
Screen reader#
role="tree" named by label. Items are treeitem elements with aria-level, aria-setsize and aria-posinset, so screen readers announce the depth and the position in the folder.
aria-expanded; other items aria-selected. A disabled item has aria-disabled and is skipped by clicks but stays in the arrow key order.
aria-hidden): the text of an item is its name.
Keyboard support#
| Key | Function |
|---|---|