Basic tree
import { html, atom, renderApp } from 'mates';
import { Tree, Text } from 'mates-ui';
import { DataObjectIcon, DescriptionIcon, FolderIcon, LockIcon, StyleIcon } from 'mates-icons';
const FILE_TREE = [
{ id: "root-src", label: "src", icon: FolderIcon(), children: [
{ id: "root-lib", label: "lib", icon: FolderIcon(), children: [
{ id: "f-tree", label: "tree", icon: FolderIcon(), children: [
{ id: "f-tree-ts", label: "tree.ts", icon: DescriptionIcon() },
{ id: "f-tree-css", label: "tree.css", icon: StyleIcon() },
],
},
{ id: "f-index", label: "index.ts", icon: DescriptionIcon() },
],
},
{ id: "root-demo", label: "demo", icon: FolderIcon(), children: [
{ id: "f-app", label: "app.ts", icon: DescriptionIcon() },
],
},
],
},
{ id: "pkg", label: "package.json", icon: DataObjectIcon() },
{ id: "disabled-node", label: "locked-config (disabled)", icon: LockIcon(), disabled: true },
];
const App = () => {
const expanded = atom(["root-src", "root-lib", "f-tree"]);
const selected = atom("f-tree-ts");
return () => html`
<x-col gap="var(--md-space-2)" style="max-width:28rem;width:100%;">
<div style="border:1px solid var(--md-color-border);border-radius:var(--md-radius-md);padding:var(--md-space-3);background:var(--md-color-surface);">
${Tree({ nodes: FILE_TREE, expandedIds: expanded(), onExpandChange: (ids) => expanded.set(ids), selectedId: selected(), onSelect: (id) => selected.set(id), ariaLabel: "Project files" })}
</div>
${Text("Selected: " + (selected() ?? "(none)"), { type: "body-sm", color: "muted" })}
</x-col>
`;
Node selection
import { html, atom, renderApp } from 'mates';
import { Tree, Text } from 'mates-ui';
import { ButtonsAltIcon, FolderIcon, HomeIcon, InfoIcon, InputIcon, MailIcon } from 'mates-icons';
const TREE = [
{ id: "pages", label: "Pages", icon: FolderIcon(), children: [
{ id: "home", label: "Home", icon: HomeIcon() },
{ id: "about", label: "About", icon: InfoIcon() },
{ id: "contact", label: "Contact", icon: MailIcon() },
],
},
{ id: "components", label: "Components", icon: FolderIcon(), children: [
{ id: "btn", label: "Button", icon: ButtonsAltIcon() },
{ id: "input", label: "Input", icon: InputIcon() },
],
},
];
const App = () => {
const expanded = atom(["pages"]);
const selected = atom(null);
return () => html`
<x-col gap="var(--md-space-2)" style="max-width:28rem;width:100%;">
<div style="border:1px solid var(--md-color-border);border-radius:var(--md-radius-md);padding:var(--md-space-3);background:var(--md-color-surface);">
${Tree({ nodes: TREE, expandedIds: expanded(), onExpandChange: (ids) => expanded.set(ids), selectedId: selected(), onSelect: (id) => selected.set(id), ariaLabel: "Site navigation" })}
</div>
${Text(selected() ? "Selected: " + selected() : "Click a leaf node to select it.", { type: "body-sm", color: "muted" })}
</x-col>
`;
};
renderApp(App, document.getElementById('app'));
Custom icons
import { html, atom, renderApp } from 'mates';
import { Tree } from 'mates-ui';
import { ArticleIcon, FontDownloadIcon, ImageIcon, InterestsIcon, Inventory2Icon, SettingsIcon } from 'mates-icons';
const ICON_TREE = [
{ id: "assets", label: "assets", icon: Inventory2Icon(), children: [
{ id: "img", label: "images", icon: ImageIcon() },
{ id: "fonts", label: "fonts", icon: FontDownloadIcon() },
{ id: "icons", label: "icons", icon: InterestsIcon() },
],
},
{ id: "config", label: "vite.config.ts", icon: SettingsIcon() },
{ id: "readme", label: "README.md", icon: ArticleIcon() },
];
const App = () => {
const expanded = atom(["assets"]);
return () => html`
<div style="max-width:28rem;width:100%;border:1px solid var(--md-color-border);border-radius:var(--md-radius-md);padding:var(--md-space-3);background:var(--md-color-surface);">
${Tree({ nodes: ICON_TREE, expandedIds: expanded(), onExpandChange: (ids) => expanded.set(ids), ariaLabel: "Asset tree" })}
</div>
`;
};
renderApp(App, document.getElementById('app'));
Disabled nodes
import { html, atom, renderApp } from 'mates';
import { Tree, Text } from 'mates-ui';
import { DescriptionIcon, FolderIcon, ImageIcon, LockIcon } from 'mates-icons';
const DISABLED_TREE = [
{ id: "public", label: "public", icon: FolderIcon(), children: [
{ id: "favicon", label: "favicon.ico", icon: ImageIcon() },
{ id: "robots", label: "robots.txt", icon: DescriptionIcon(), disabled: true },
],
},
{ id: "src-d", label: "src", icon: FolderIcon(), disabled: true, children: [
{ id: "main-d", label: "main.ts", icon: DescriptionIcon() },
],
},
{ id: "env", label: ".env (disabled)", icon: LockIcon(), disabled: true },
];
const App = () => {
const expanded = atom([]);
return () => html`
<x-col gap="var(--md-space-2)" style="max-width:28rem;width:100%;">
<div style="border:1px solid var(--md-color-border);border-radius:var(--md-radius-md);padding:var(--md-space-3);background:var(--md-color-surface);">
${Tree({ nodes: DISABLED_TREE, expandedIds: expanded(), onExpandChange: (ids) => expanded.set(ids), ariaLabel: "Disabled nodes demo" })}
</div>
${Text("Disabled nodes cannot be expanded or selected.", { type: "body-sm", color: "muted" })}
</x-col>
`;
};
renderApp(App, document.getElementById('app'));