Tree
An accessible hierarchy with disclosure, bounded logical indentation, and truthful drag-and-drop previews.
Project files
A small expanded branch shows the hierarchy without filling the card.
Code
<link
rel="component"
href="@threadlabs/looma/components/ui-tree/ui-tree.html"
>
<link
rel="component"
href="@threadlabs/looma/components/ui-tree-item/ui-tree-item.html"
>
<ui-tree
label="Project files"
>
<ui-tree-item
item-id="project"
label="Project"
expanded
>
<ui-tree-item
item-id="guide"
label="Guide"
></ui-tree-item>
<ui-tree-item
item-id="notes"
label="Notes"
></ui-tree-item>
</ui-tree-item>
</ui-tree><script setup>
import { UiTree, UiTreeItem } from "@threadlabs/looma";
</script>
<template>
<UiTree
label="Project files"
>
<UiTreeItem
item-id="project"
label="Project"
:expanded="true"
>
<UiTreeItem
item-id="guide"
label="Guide"
/>
<UiTreeItem
item-id="notes"
label="Notes"
/>
</UiTreeItem>
</UiTree>
</template>import { UiTree, UiTreeItem } from "@threadlabs/looma";
export default function Example() {
return <UiTree
label="Project files"
>
<UiTreeItem
itemId="project"
label="Project"
expanded
>
<UiTreeItem
itemId="guide"
label="Guide"
/>
<UiTreeItem
itemId="notes"
label="Notes"
/>
</UiTreeItem>
</UiTree>;
}/** @jsxImportSource preact */
import { UiTree, UiTreeItem } from "@threadlabs/looma";
export default function Example() {
return <UiTree
label="Project files"
>
<UiTreeItem
itemId="project"
label="Project"
expanded
>
<UiTreeItem
itemId="guide"
label="Guide"
/>
<UiTreeItem
itemId="notes"
label="Notes"
/>
</UiTreeItem>
</UiTree>;
}<script>
import { UiTree, UiTreeItem } from "@threadlabs/looma";
</script>
<UiTree
label="Project files"
>
<UiTreeItem
itemId="project"
label="Project"
expanded
>
<UiTreeItem
itemId="guide"
label="Guide"
/>
<UiTreeItem
itemId="notes"
label="Notes"
/>
</UiTreeItem>
</UiTree>import { Component } from "@angular/core";
import { UiTree, UiTreeItem } from "@threadlabs/looma";
@Component({
selector: "example-view",
standalone: true,
imports: [UiTree, UiTreeItem],
template: `
<div
ui-tree
[label]="'Project files'"
>
<div
ui-tree-item
[itemId]="'project'"
[label]="'Project'"
[expanded]="true"
>
<div
ui-tree-item
[itemId]="'guide'"
[label]="'Guide'"
></div>
<div
ui-tree-item
[itemId]="'notes'"
[label]="'Notes'"
></div>
</div>
</div>
`,
})
export default class Example {}Default
A labelled tree of items with leading icons; folders start collapsed and nesting depth is unrestricted.
Code
<link
rel="component"
href="@threadlabs/looma/components/ui-tree/ui-tree.html"
>
<link
rel="component"
href="@threadlabs/looma/components/ui-tree-item/ui-tree-item.html"
>
<ui-tree
label="Project files"
>
<ui-tree-item
item-id="docs"
label="docs"
>
<svg
slot="leading"
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"
></path>
</svg>
<ui-tree-item
item-id="guide"
label="guide.md"
>
<svg
slot="leading"
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
</ui-tree-item>
<ui-tree-item
item-id="api"
label="api.md"
>
<svg
slot="leading"
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
</ui-tree-item>
</ui-tree-item>
<ui-tree-item
item-id="src"
label="src"
>
<svg
slot="leading"
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"
></path>
</svg>
<ui-tree-item
item-id="index"
label="index.ts"
>
<svg
slot="leading"
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
</ui-tree-item>
</ui-tree-item>
<ui-tree-item
item-id="readme"
label="README.md"
>
<svg
slot="leading"
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
</ui-tree-item>
</ui-tree><script setup>
import { UiTree, UiTreeItem } from "@threadlabs/looma";
</script>
<template>
<UiTree
label="Project files"
>
<UiTreeItem
item-id="docs"
label="docs"
>
<template #leading>
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"
></path>
</svg>
</template>
<UiTreeItem
item-id="guide"
label="guide.md"
>
<template #leading>
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
</template>
</UiTreeItem>
<UiTreeItem
item-id="api"
label="api.md"
>
<template #leading>
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
</template>
</UiTreeItem>
</UiTreeItem>
<UiTreeItem
item-id="src"
label="src"
>
<template #leading>
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"
></path>
</svg>
</template>
<UiTreeItem
item-id="index"
label="index.ts"
>
<template #leading>
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
</template>
</UiTreeItem>
</UiTreeItem>
<UiTreeItem
item-id="readme"
label="README.md"
>
<template #leading>
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
</template>
</UiTreeItem>
</UiTree>
</template>import { UiTree, UiTreeItem } from "@threadlabs/looma";
export default function Example() {
return <UiTree
label="Project files"
>
<UiTreeItem
itemId="docs"
label="docs"
slots={{
leading: <svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"
/>
</svg>,
}}
>
<UiTreeItem
itemId="guide"
label="guide.md"
slots={{
leading: <svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
/>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
/>
</svg>,
}}
>{" "}{" "}</UiTreeItem>
<UiTreeItem
itemId="api"
label="api.md"
slots={{
leading: <svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
/>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
/>
</svg>,
}}
>{" "}{" "}</UiTreeItem>
</UiTreeItem>
<UiTreeItem
itemId="src"
label="src"
slots={{
leading: <svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"
/>
</svg>,
}}
>
<UiTreeItem
itemId="index"
label="index.ts"
slots={{
leading: <svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
/>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
/>
</svg>,
}}
>{" "}{" "}</UiTreeItem>
</UiTreeItem>
<UiTreeItem
itemId="readme"
label="README.md"
slots={{
leading: <svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
/>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
/>
</svg>,
}}
>{" "}{" "}</UiTreeItem>
</UiTree>;
}/** @jsxImportSource preact */
import { UiTree, UiTreeItem } from "@threadlabs/looma";
export default function Example() {
return <UiTree
label="Project files"
>
<UiTreeItem
itemId="docs"
label="docs"
slots={{
leading: <svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"
/>
</svg>,
}}
>
<UiTreeItem
itemId="guide"
label="guide.md"
slots={{
leading: <svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
/>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
/>
</svg>,
}}
>{" "}{" "}</UiTreeItem>
<UiTreeItem
itemId="api"
label="api.md"
slots={{
leading: <svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
/>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
/>
</svg>,
}}
>{" "}{" "}</UiTreeItem>
</UiTreeItem>
<UiTreeItem
itemId="src"
label="src"
slots={{
leading: <svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"
/>
</svg>,
}}
>
<UiTreeItem
itemId="index"
label="index.ts"
slots={{
leading: <svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
/>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
/>
</svg>,
}}
>{" "}{" "}</UiTreeItem>
</UiTreeItem>
<UiTreeItem
itemId="readme"
label="README.md"
slots={{
leading: <svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
/>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
/>
</svg>,
}}
>{" "}{" "}</UiTreeItem>
</UiTree>;
}<script>
import { UiTree, UiTreeItem } from "@threadlabs/looma";
</script>
{#snippet leading()}
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"
></path>
</svg>
{/snippet}
{#snippet treeItemLeading()}
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
{/snippet}
{#snippet treeItemLeading2()}
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
{/snippet}
{#snippet treeItemLeading3()}
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"
></path>
</svg>
{/snippet}
{#snippet treeItemLeading4()}
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
{/snippet}
{#snippet treeItemLeading5()}
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
{/snippet}
<UiTree
label="Project files"
>
<UiTreeItem
itemId="docs"
label="docs"
slots={{ leading }}
>
<UiTreeItem
itemId="guide"
label="guide.md"
slots={{ leading: treeItemLeading }}
> </UiTreeItem>
<UiTreeItem
itemId="api"
label="api.md"
slots={{ leading: treeItemLeading2 }}
> </UiTreeItem>
</UiTreeItem>
<UiTreeItem
itemId="src"
label="src"
slots={{ leading: treeItemLeading3 }}
>
<UiTreeItem
itemId="index"
label="index.ts"
slots={{ leading: treeItemLeading4 }}
> </UiTreeItem>
</UiTreeItem>
<UiTreeItem
itemId="readme"
label="README.md"
slots={{ leading: treeItemLeading5 }}
> </UiTreeItem>
</UiTree>import { Component } from "@angular/core";
import { UiTree, UiTreeItem } from "@threadlabs/looma";
@Component({
selector: "example-view",
standalone: true,
imports: [UiTree, UiTreeItem],
template: `
<div
ui-tree
[label]="'Project files'"
>
<div
ui-tree-item
[itemId]="'docs'"
[label]="'docs'"
>
<ng-container ngProjectAs="[slot='leading']">
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"
></path>
</svg>
</ng-container>
<div
ui-tree-item
[itemId]="'guide'"
[label]="'guide.md'"
>
<ng-container ngProjectAs="[slot='leading']">
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
</ng-container>
</div>
<div
ui-tree-item
[itemId]="'api'"
[label]="'api.md'"
>
<ng-container ngProjectAs="[slot='leading']">
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
</ng-container>
</div>
</div>
<div
ui-tree-item
[itemId]="'src'"
[label]="'src'"
>
<ng-container ngProjectAs="[slot='leading']">
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"
></path>
</svg>
</ng-container>
<div
ui-tree-item
[itemId]="'index'"
[label]="'index.ts'"
>
<ng-container ngProjectAs="[slot='leading']">
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
</ng-container>
</div>
</div>
<div
ui-tree-item
[itemId]="'readme'"
[label]="'README.md'"
>
<ng-container ngProjectAs="[slot='leading']">
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
</ng-container>
</div>
</div>
`,
})
export default class Example {}Expanded and selected items
Items carrying expanded start open; selected marks the current item.
Code
<link
rel="component"
href="@threadlabs/looma/components/ui-tree/ui-tree.html"
>
<link
rel="component"
href="@threadlabs/looma/components/ui-tree-item/ui-tree-item.html"
>
<ui-tree
label="Project files"
>
<ui-tree-item
item-id="docs"
label="docs"
expanded
>
<svg
slot="leading"
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"
></path>
</svg>
<ui-tree-item
item-id="guide"
label="guide.md"
selected
>
<svg
slot="leading"
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
</ui-tree-item>
<ui-tree-item
item-id="api"
label="api.md"
>
<svg
slot="leading"
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
</ui-tree-item>
</ui-tree-item>
<ui-tree-item
item-id="src"
label="src"
>
<svg
slot="leading"
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"
></path>
</svg>
<ui-tree-item
item-id="index"
label="index.ts"
>
<svg
slot="leading"
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
</ui-tree-item>
</ui-tree-item>
<ui-tree-item
item-id="readme"
label="README.md"
>
<svg
slot="leading"
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
</ui-tree-item>
</ui-tree><script setup>
import { UiTree, UiTreeItem } from "@threadlabs/looma";
</script>
<template>
<UiTree
label="Project files"
>
<UiTreeItem
item-id="docs"
label="docs"
:expanded="true"
>
<template #leading>
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"
></path>
</svg>
</template>
<UiTreeItem
item-id="guide"
label="guide.md"
:selected="true"
>
<template #leading>
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
</template>
</UiTreeItem>
<UiTreeItem
item-id="api"
label="api.md"
>
<template #leading>
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
</template>
</UiTreeItem>
</UiTreeItem>
<UiTreeItem
item-id="src"
label="src"
>
<template #leading>
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"
></path>
</svg>
</template>
<UiTreeItem
item-id="index"
label="index.ts"
>
<template #leading>
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
</template>
</UiTreeItem>
</UiTreeItem>
<UiTreeItem
item-id="readme"
label="README.md"
>
<template #leading>
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
</template>
</UiTreeItem>
</UiTree>
</template>import { UiTree, UiTreeItem } from "@threadlabs/looma";
export default function Example() {
return <UiTree
label="Project files"
>
<UiTreeItem
itemId="docs"
label="docs"
expanded
slots={{
leading: <svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"
/>
</svg>,
}}
>
<UiTreeItem
itemId="guide"
label="guide.md"
selected
slots={{
leading: <svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
/>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
/>
</svg>,
}}
>{" "}{" "}</UiTreeItem>
<UiTreeItem
itemId="api"
label="api.md"
slots={{
leading: <svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
/>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
/>
</svg>,
}}
>{" "}{" "}</UiTreeItem>
</UiTreeItem>
<UiTreeItem
itemId="src"
label="src"
slots={{
leading: <svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"
/>
</svg>,
}}
>
<UiTreeItem
itemId="index"
label="index.ts"
slots={{
leading: <svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
/>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
/>
</svg>,
}}
>{" "}{" "}</UiTreeItem>
</UiTreeItem>
<UiTreeItem
itemId="readme"
label="README.md"
slots={{
leading: <svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
/>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
/>
</svg>,
}}
>{" "}{" "}</UiTreeItem>
</UiTree>;
}/** @jsxImportSource preact */
import { UiTree, UiTreeItem } from "@threadlabs/looma";
export default function Example() {
return <UiTree
label="Project files"
>
<UiTreeItem
itemId="docs"
label="docs"
expanded
slots={{
leading: <svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"
/>
</svg>,
}}
>
<UiTreeItem
itemId="guide"
label="guide.md"
selected
slots={{
leading: <svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
/>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
/>
</svg>,
}}
>{" "}{" "}</UiTreeItem>
<UiTreeItem
itemId="api"
label="api.md"
slots={{
leading: <svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
/>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
/>
</svg>,
}}
>{" "}{" "}</UiTreeItem>
</UiTreeItem>
<UiTreeItem
itemId="src"
label="src"
slots={{
leading: <svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"
/>
</svg>,
}}
>
<UiTreeItem
itemId="index"
label="index.ts"
slots={{
leading: <svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
/>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
/>
</svg>,
}}
>{" "}{" "}</UiTreeItem>
</UiTreeItem>
<UiTreeItem
itemId="readme"
label="README.md"
slots={{
leading: <svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
/>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
/>
</svg>,
}}
>{" "}{" "}</UiTreeItem>
</UiTree>;
}<script>
import { UiTree, UiTreeItem } from "@threadlabs/looma";
</script>
{#snippet leading()}
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"
></path>
</svg>
{/snippet}
{#snippet treeItemLeading()}
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
{/snippet}
{#snippet treeItemLeading2()}
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
{/snippet}
{#snippet treeItemLeading3()}
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"
></path>
</svg>
{/snippet}
{#snippet treeItemLeading4()}
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
{/snippet}
{#snippet treeItemLeading5()}
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
{/snippet}
<UiTree
label="Project files"
>
<UiTreeItem
itemId="docs"
label="docs"
expanded
slots={{ leading }}
>
<UiTreeItem
itemId="guide"
label="guide.md"
selected
slots={{ leading: treeItemLeading }}
> </UiTreeItem>
<UiTreeItem
itemId="api"
label="api.md"
slots={{ leading: treeItemLeading2 }}
> </UiTreeItem>
</UiTreeItem>
<UiTreeItem
itemId="src"
label="src"
slots={{ leading: treeItemLeading3 }}
>
<UiTreeItem
itemId="index"
label="index.ts"
slots={{ leading: treeItemLeading4 }}
> </UiTreeItem>
</UiTreeItem>
<UiTreeItem
itemId="readme"
label="README.md"
slots={{ leading: treeItemLeading5 }}
> </UiTreeItem>
</UiTree>import { Component } from "@angular/core";
import { UiTree, UiTreeItem } from "@threadlabs/looma";
@Component({
selector: "example-view",
standalone: true,
imports: [UiTree, UiTreeItem],
template: `
<div
ui-tree
[label]="'Project files'"
>
<div
ui-tree-item
[itemId]="'docs'"
[label]="'docs'"
[expanded]="true"
>
<ng-container ngProjectAs="[slot='leading']">
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"
></path>
</svg>
</ng-container>
<div
ui-tree-item
[itemId]="'guide'"
[label]="'guide.md'"
[selected]="true"
>
<ng-container ngProjectAs="[slot='leading']">
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
</ng-container>
</div>
<div
ui-tree-item
[itemId]="'api'"
[label]="'api.md'"
>
<ng-container ngProjectAs="[slot='leading']">
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
</ng-container>
</div>
</div>
<div
ui-tree-item
[itemId]="'src'"
[label]="'src'"
>
<ng-container ngProjectAs="[slot='leading']">
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"
></path>
</svg>
</ng-container>
<div
ui-tree-item
[itemId]="'index'"
[label]="'index.ts'"
>
<ng-container ngProjectAs="[slot='leading']">
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
</ng-container>
</div>
</div>
<div
ui-tree-item
[itemId]="'readme'"
[label]="'README.md'"
>
<ng-container ngProjectAs="[slot='leading']">
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
</ng-container>
</div>
</div>
`,
})
export default class Example {}max-depth="2" and hover-expand-delay="300"
With sortable items, hover a row to reveal its drag handle. Max-depth rejects drops that would nest deeper than two levels; hover-expand-delay opens a collapsed folder after 300ms of drag hover.
Code
<link
rel="component"
href="@threadlabs/looma/components/ui-tree/ui-tree.html"
>
<link
rel="component"
href="@threadlabs/looma/components/ui-tree-item/ui-tree-item.html"
>
<ui-tree
label="Sortable files"
max-depth="2"
hover-expand-delay="300"
>
<ui-tree-item
item-id="docs"
label="docs"
expanded
sortable
container
>
<svg
slot="leading"
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"
></path>
</svg>
<ui-tree-item
item-id="guide"
label="guide.md"
sortable
>
<svg
slot="leading"
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
</ui-tree-item>
<ui-tree-item
item-id="api"
label="api.md"
sortable
>
<svg
slot="leading"
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
</ui-tree-item>
</ui-tree-item>
<ui-tree-item
item-id="readme"
label="README.md"
sortable
>
<svg
slot="leading"
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
</ui-tree-item>
</ui-tree><script setup>
import { UiTree, UiTreeItem } from "@threadlabs/looma";
</script>
<template>
<UiTree
label="Sortable files"
:max-depth="2"
:hover-expand-delay="300"
>
<UiTreeItem
item-id="docs"
label="docs"
:expanded="true"
:sortable="true"
:container="true"
>
<template #leading>
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"
></path>
</svg>
</template>
<UiTreeItem
item-id="guide"
label="guide.md"
:sortable="true"
>
<template #leading>
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
</template>
</UiTreeItem>
<UiTreeItem
item-id="api"
label="api.md"
:sortable="true"
>
<template #leading>
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
</template>
</UiTreeItem>
</UiTreeItem>
<UiTreeItem
item-id="readme"
label="README.md"
:sortable="true"
>
<template #leading>
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
</template>
</UiTreeItem>
</UiTree>
</template>import { UiTree, UiTreeItem } from "@threadlabs/looma";
export default function Example() {
return <UiTree
label="Sortable files"
maxDepth={2}
hoverExpandDelay={300}
>
<UiTreeItem
itemId="docs"
label="docs"
expanded
sortable
container
slots={{
leading: <svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"
/>
</svg>,
}}
>
<UiTreeItem
itemId="guide"
label="guide.md"
sortable
slots={{
leading: <svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
/>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
/>
</svg>,
}}
>{" "}{" "}</UiTreeItem>
<UiTreeItem
itemId="api"
label="api.md"
sortable
slots={{
leading: <svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
/>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
/>
</svg>,
}}
>{" "}{" "}</UiTreeItem>
</UiTreeItem>
<UiTreeItem
itemId="readme"
label="README.md"
sortable
slots={{
leading: <svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
/>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
/>
</svg>,
}}
>{" "}{" "}</UiTreeItem>
</UiTree>;
}/** @jsxImportSource preact */
import { UiTree, UiTreeItem } from "@threadlabs/looma";
export default function Example() {
return <UiTree
label="Sortable files"
maxDepth={2}
hoverExpandDelay={300}
>
<UiTreeItem
itemId="docs"
label="docs"
expanded
sortable
container
slots={{
leading: <svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"
/>
</svg>,
}}
>
<UiTreeItem
itemId="guide"
label="guide.md"
sortable
slots={{
leading: <svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
/>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
/>
</svg>,
}}
>{" "}{" "}</UiTreeItem>
<UiTreeItem
itemId="api"
label="api.md"
sortable
slots={{
leading: <svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
/>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
/>
</svg>,
}}
>{" "}{" "}</UiTreeItem>
</UiTreeItem>
<UiTreeItem
itemId="readme"
label="README.md"
sortable
slots={{
leading: <svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
/>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
/>
</svg>,
}}
>{" "}{" "}</UiTreeItem>
</UiTree>;
}<script>
import { UiTree, UiTreeItem } from "@threadlabs/looma";
</script>
{#snippet leading()}
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"
></path>
</svg>
{/snippet}
{#snippet treeItemLeading()}
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
{/snippet}
{#snippet treeItemLeading2()}
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
{/snippet}
{#snippet treeItemLeading3()}
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
{/snippet}
<UiTree
label="Sortable files"
maxDepth={2}
hoverExpandDelay={300}
>
<UiTreeItem
itemId="docs"
label="docs"
expanded
sortable
container
slots={{ leading }}
>
<UiTreeItem
itemId="guide"
label="guide.md"
sortable
slots={{ leading: treeItemLeading }}
> </UiTreeItem>
<UiTreeItem
itemId="api"
label="api.md"
sortable
slots={{ leading: treeItemLeading2 }}
> </UiTreeItem>
</UiTreeItem>
<UiTreeItem
itemId="readme"
label="README.md"
sortable
slots={{ leading: treeItemLeading3 }}
> </UiTreeItem>
</UiTree>import { Component } from "@angular/core";
import { UiTree, UiTreeItem } from "@threadlabs/looma";
@Component({
selector: "example-view",
standalone: true,
imports: [UiTree, UiTreeItem],
template: `
<div
ui-tree
[label]="'Sortable files'"
[maxDepth]="2"
[hoverExpandDelay]="300"
>
<div
ui-tree-item
[itemId]="'docs'"
[label]="'docs'"
[expanded]="true"
[sortable]="true"
[container]="true"
>
<ng-container ngProjectAs="[slot='leading']">
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"
></path>
</svg>
</ng-container>
<div
ui-tree-item
[itemId]="'guide'"
[label]="'guide.md'"
[sortable]="true"
>
<ng-container ngProjectAs="[slot='leading']">
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
</ng-container>
</div>
<div
ui-tree-item
[itemId]="'api'"
[label]="'api.md'"
[sortable]="true"
>
<ng-container ngProjectAs="[slot='leading']">
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
</ng-container>
</div>
</div>
<div
ui-tree-item
[itemId]="'readme'"
[label]="'README.md'"
[sortable]="true"
>
<ng-container ngProjectAs="[slot='leading']">
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
</ng-container>
</div>
</div>
`,
})
export default class Example {}marquee
With marquee, a name too long for its row scrolls while that row is hovered or keyboard focused, rests at the end, then scrolls again. A name that fits beside its controls does not move.
Code
<link
rel="component"
href="@threadlabs/looma/components/ui-tree/ui-tree.html"
>
<link
rel="component"
href="@threadlabs/looma/components/ui-tree-item/ui-tree-item.html"
>
<link
rel="component"
href="@threadlabs/looma/components/ui-icon-button/ui-icon-button.html"
>
<ui-tree
label="Pages"
marquee
style="width: 15rem"
>
<ui-tree-item
item-id="overview"
label="Overview"
>
<ui-icon-button
slot="actions"
label="More actions for the overview"
size="sm"
>
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="currentColor"
>
<circle
cx="5"
cy="12"
r="1.6"
></circle>
<circle
cx="12"
cy="12"
r="1.6"
></circle>
<circle
cx="19"
cy="12"
r="1.6"
></circle>
</svg>
</ui-icon-button>
</ui-tree-item>
<ui-tree-item
item-id="handbook"
label="How to Use This Handbook and Everything Inside It"
>
<ui-icon-button
slot="actions"
label="More actions for the handbook"
size="sm"
>
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="currentColor"
>
<circle
cx="5"
cy="12"
r="1.6"
></circle>
<circle
cx="12"
cy="12"
r="1.6"
></circle>
<circle
cx="19"
cy="12"
r="1.6"
></circle>
</svg>
</ui-icon-button>
</ui-tree-item>
</ui-tree><script setup>
import { UiIconButton, UiTree, UiTreeItem } from "@threadlabs/looma";
</script>
<template>
<UiTree
label="Pages"
:marquee="true"
style="width: 15rem"
>
<UiTreeItem
item-id="overview"
label="Overview"
>
<template #actions>
<UiIconButton
label="More actions for the overview"
size="sm"
>
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="currentColor"
>
<circle
cx="5"
cy="12"
r="1.6"
></circle>
<circle
cx="12"
cy="12"
r="1.6"
></circle>
<circle
cx="19"
cy="12"
r="1.6"
></circle>
</svg>
</UiIconButton>
</template>
</UiTreeItem>
<UiTreeItem
item-id="handbook"
label="How to Use This Handbook and Everything Inside It"
>
<template #actions>
<UiIconButton
label="More actions for the handbook"
size="sm"
>
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="currentColor"
>
<circle
cx="5"
cy="12"
r="1.6"
></circle>
<circle
cx="12"
cy="12"
r="1.6"
></circle>
<circle
cx="19"
cy="12"
r="1.6"
></circle>
</svg>
</UiIconButton>
</template>
</UiTreeItem>
</UiTree>
</template>import { UiIconButton, UiTree, UiTreeItem } from "@threadlabs/looma";
export default function Example() {
return <UiTree
label="Pages"
marquee
style={{"width":"15rem"}}
>
<UiTreeItem
itemId="overview"
label="Overview"
slots={{
actions: <UiIconButton
label="More actions for the overview"
size="sm"
>
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="currentColor"
>
<circle
cx="5"
cy="12"
r="1.6"
/>
<circle
cx="12"
cy="12"
r="1.6"
/>
<circle
cx="19"
cy="12"
r="1.6"
/>
</svg>
</UiIconButton>,
}}
>{" "}{" "}</UiTreeItem>
<UiTreeItem
itemId="handbook"
label="How to Use This Handbook and Everything Inside It"
slots={{
actions: <UiIconButton
label="More actions for the handbook"
size="sm"
>
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="currentColor"
>
<circle
cx="5"
cy="12"
r="1.6"
/>
<circle
cx="12"
cy="12"
r="1.6"
/>
<circle
cx="19"
cy="12"
r="1.6"
/>
</svg>
</UiIconButton>,
}}
>{" "}{" "}</UiTreeItem>
</UiTree>;
}/** @jsxImportSource preact */
import { UiIconButton, UiTree, UiTreeItem } from "@threadlabs/looma";
export default function Example() {
return <UiTree
label="Pages"
marquee
style={{"width":"15rem"}}
>
<UiTreeItem
itemId="overview"
label="Overview"
slots={{
actions: <UiIconButton
label="More actions for the overview"
size="sm"
>
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="currentColor"
>
<circle
cx="5"
cy="12"
r="1.6"
/>
<circle
cx="12"
cy="12"
r="1.6"
/>
<circle
cx="19"
cy="12"
r="1.6"
/>
</svg>
</UiIconButton>,
}}
>{" "}{" "}</UiTreeItem>
<UiTreeItem
itemId="handbook"
label="How to Use This Handbook and Everything Inside It"
slots={{
actions: <UiIconButton
label="More actions for the handbook"
size="sm"
>
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="currentColor"
>
<circle
cx="5"
cy="12"
r="1.6"
/>
<circle
cx="12"
cy="12"
r="1.6"
/>
<circle
cx="19"
cy="12"
r="1.6"
/>
</svg>
</UiIconButton>,
}}
>{" "}{" "}</UiTreeItem>
</UiTree>;
}<script>
import { UiIconButton, UiTree, UiTreeItem } from "@threadlabs/looma";
</script>
{#snippet actions()}
<UiIconButton
label="More actions for the overview"
size="sm"
>
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="currentColor"
>
<circle
cx="5"
cy="12"
r="1.6"
></circle>
<circle
cx="12"
cy="12"
r="1.6"
></circle>
<circle
cx="19"
cy="12"
r="1.6"
></circle>
</svg>
</UiIconButton>
{/snippet}
{#snippet treeItemActions()}
<UiIconButton
label="More actions for the handbook"
size="sm"
>
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="currentColor"
>
<circle
cx="5"
cy="12"
r="1.6"
></circle>
<circle
cx="12"
cy="12"
r="1.6"
></circle>
<circle
cx="19"
cy="12"
r="1.6"
></circle>
</svg>
</UiIconButton>
{/snippet}
<UiTree
label="Pages"
marquee
style="width: 15rem"
>
<UiTreeItem
itemId="overview"
label="Overview"
slots={{ actions }}
> </UiTreeItem>
<UiTreeItem
itemId="handbook"
label="How to Use This Handbook and Everything Inside It"
slots={{ actions: treeItemActions }}
> </UiTreeItem>
</UiTree>import { Component } from "@angular/core";
import { UiIconButton, UiTree, UiTreeItem } from "@threadlabs/looma";
@Component({
selector: "example-view",
standalone: true,
imports: [UiTree, UiTreeItem, UiIconButton],
template: `
<div
ui-tree
[label]="'Pages'"
[marquee]="true"
style="width: 15rem"
>
<div
ui-tree-item
[itemId]="'overview'"
[label]="'Overview'"
>
<ng-container ngProjectAs="[slot='actions']">
<button
ui-icon-button
[label]="'More actions for the overview'"
[size]="'sm'"
>
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="currentColor"
>
<circle
cx="5"
cy="12"
r="1.6"
></circle>
<circle
cx="12"
cy="12"
r="1.6"
></circle>
<circle
cx="19"
cy="12"
r="1.6"
></circle>
</svg>
</button>
</ng-container>
</div>
<div
ui-tree-item
[itemId]="'handbook'"
[label]="'How to Use This Handbook and Everything Inside It'"
>
<ng-container ngProjectAs="[slot='actions']">
<button
ui-icon-button
[label]="'More actions for the handbook'"
[size]="'sm'"
>
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="currentColor"
>
<circle
cx="5"
cy="12"
r="1.6"
></circle>
<circle
cx="12"
cy="12"
r="1.6"
></circle>
<circle
cx="19"
cy="12"
r="1.6"
></circle>
</svg>
</button>
</ng-container>
</div>
</div>
`,
})
export default class Example {}Link rows
An icon in leading and a link in label. The whole leaf row follows the link, and with marquee only the name scrolls; the icon stays put.
Code
<link
rel="component"
href="@threadlabs/looma/components/ui-tree/ui-tree.html"
>
<link
rel="component"
href="@threadlabs/looma/components/ui-tree-item/ui-tree-item.html"
>
<link
rel="component"
href="@threadlabs/looma/components/ui-icon/ui-icon.html"
>
<ui-tree
label="Pages"
marquee
style="width: 15rem"
>
<ui-tree-item
item-id="welcome"
label="Welcome"
>
<ui-icon
slot="leading"
name="pilcrow"
></ui-icon>
<a
slot="label"
href="#welcome"
>Welcome</a>
</ui-tree-item>
<ui-tree-item
item-id="handbook"
label="How to Use This Handbook and Everything Inside It"
>
<ui-icon
slot="leading"
name="pilcrow"
></ui-icon>
<a
slot="label"
href="#handbook"
>How to Use This Handbook and Everything Inside It</a>
</ui-tree-item>
</ui-tree><script setup>
import { UiIcon, UiTree, UiTreeItem } from "@threadlabs/looma";
</script>
<template>
<UiTree
label="Pages"
:marquee="true"
style="width: 15rem"
>
<UiTreeItem
item-id="welcome"
label="Welcome"
>
<template #leading>
<UiIcon
name="pilcrow"
/>
</template>
<template #label>
<a
href="#welcome"
>Welcome</a>
</template>
</UiTreeItem>
<UiTreeItem
item-id="handbook"
label="How to Use This Handbook and Everything Inside It"
>
<template #leading>
<UiIcon
name="pilcrow"
/>
</template>
<template #label>
<a
href="#handbook"
>How to Use This Handbook and Everything Inside It</a>
</template>
</UiTreeItem>
</UiTree>
</template>import { UiIcon, UiTree, UiTreeItem } from "@threadlabs/looma";
export default function Example() {
return <UiTree
label="Pages"
marquee
style={{"width":"15rem"}}
>
<UiTreeItem
itemId="welcome"
label="Welcome"
slots={{
leading: <UiIcon
name="pilcrow"
/>,
label: <a
href="#welcome"
>Welcome</a>,
}}
>{" "}{" "}{" "}</UiTreeItem>
<UiTreeItem
itemId="handbook"
label="How to Use This Handbook and Everything Inside It"
slots={{
leading: <UiIcon
name="pilcrow"
/>,
label: <a
href="#handbook"
>How to Use This Handbook and Everything Inside It</a>,
}}
>{" "}{" "}{" "}</UiTreeItem>
</UiTree>;
}/** @jsxImportSource preact */
import { UiIcon, UiTree, UiTreeItem } from "@threadlabs/looma";
export default function Example() {
return <UiTree
label="Pages"
marquee
style={{"width":"15rem"}}
>
<UiTreeItem
itemId="welcome"
label="Welcome"
slots={{
leading: <UiIcon
name="pilcrow"
/>,
label: <a
href="#welcome"
>Welcome</a>,
}}
>{" "}{" "}{" "}</UiTreeItem>
<UiTreeItem
itemId="handbook"
label="How to Use This Handbook and Everything Inside It"
slots={{
leading: <UiIcon
name="pilcrow"
/>,
label: <a
href="#handbook"
>How to Use This Handbook and Everything Inside It</a>,
}}
>{" "}{" "}{" "}</UiTreeItem>
</UiTree>;
}<script>
import { UiIcon, UiTree, UiTreeItem } from "@threadlabs/looma";
</script>
{#snippet leading()}
<UiIcon
name="pilcrow"
/>
{/snippet}
{#snippet label()}
<a
href="#welcome"
>Welcome</a>
{/snippet}
{#snippet treeItemLeading()}
<UiIcon
name="pilcrow"
/>
{/snippet}
{#snippet treeItemLabel()}
<a
href="#handbook"
>How to Use This Handbook and Everything Inside It</a>
{/snippet}
<UiTree
label="Pages"
marquee
style="width: 15rem"
>
<UiTreeItem
itemId="welcome"
label="Welcome"
slots={{ leading, label }}
> </UiTreeItem>
<UiTreeItem
itemId="handbook"
label="How to Use This Handbook and Everything Inside It"
slots={{ leading: treeItemLeading, label: treeItemLabel }}
> </UiTreeItem>
</UiTree>import { Component } from "@angular/core";
import { UiIcon, UiTree, UiTreeItem } from "@threadlabs/looma";
@Component({
selector: "example-view",
standalone: true,
imports: [UiTree, UiTreeItem, UiIcon],
template: `
<div
ui-tree
[label]="'Pages'"
[marquee]="true"
style="width: 15rem"
>
<div
ui-tree-item
[itemId]="'welcome'"
[label]="'Welcome'"
>
<ng-container ngProjectAs="[slot='leading']">
<span
ui-icon
name="pilcrow"
></span>
</ng-container>
<ng-container ngProjectAs="[slot='label']">
<a
href="#welcome"
>Welcome</a>
</ng-container>
</div>
<div
ui-tree-item
[itemId]="'handbook'"
[label]="'How to Use This Handbook and Everything Inside It'"
>
<ng-container ngProjectAs="[slot='leading']">
<span
ui-icon
name="pilcrow"
></span>
</ng-container>
<ng-container ngProjectAs="[slot='label']">
<a
href="#handbook"
>How to Use This Handbook and Everything Inside It</a>
</ng-container>
</div>
</div>
`,
})
export default class Example {}Move with clicks or keys
Activate a grip and choose another row with a click, or use Up/Down and Enter. This example applies reorder requests to the authored tree.
Code
<link
rel="component"
href="@threadlabs/looma/components/ui-tree/ui-tree.html"
>
<link
rel="component"
href="@threadlabs/looma/components/ui-tree-item/ui-tree-item.html"
>
<ui-tree
label="Pages"
>
<ui-tree-item
item-id="overview"
label="Overview"
sortable
></ui-tree-item>
<ui-tree-item
item-id="details"
label="Details"
sortable
></ui-tree-item>
<ui-tree-item
item-id="history"
label="History"
sortable
></ui-tree-item>
</ui-tree><script setup>
import { UiTree, UiTreeItem } from "@threadlabs/looma";
</script>
<template>
<UiTree
label="Pages"
>
<UiTreeItem
item-id="overview"
label="Overview"
:sortable="true"
/>
<UiTreeItem
item-id="details"
label="Details"
:sortable="true"
/>
<UiTreeItem
item-id="history"
label="History"
:sortable="true"
/>
</UiTree>
</template>import { UiTree, UiTreeItem } from "@threadlabs/looma";
export default function Example() {
return <UiTree
label="Pages"
>
<UiTreeItem
itemId="overview"
label="Overview"
sortable
/>
<UiTreeItem
itemId="details"
label="Details"
sortable
/>
<UiTreeItem
itemId="history"
label="History"
sortable
/>
</UiTree>;
}/** @jsxImportSource preact */
import { UiTree, UiTreeItem } from "@threadlabs/looma";
export default function Example() {
return <UiTree
label="Pages"
>
<UiTreeItem
itemId="overview"
label="Overview"
sortable
/>
<UiTreeItem
itemId="details"
label="Details"
sortable
/>
<UiTreeItem
itemId="history"
label="History"
sortable
/>
</UiTree>;
}<script>
import { UiTree, UiTreeItem } from "@threadlabs/looma";
</script>
<UiTree
label="Pages"
>
<UiTreeItem
itemId="overview"
label="Overview"
sortable
/>
<UiTreeItem
itemId="details"
label="Details"
sortable
/>
<UiTreeItem
itemId="history"
label="History"
sortable
/>
</UiTree>import { Component } from "@angular/core";
import { UiTree, UiTreeItem } from "@threadlabs/looma";
@Component({
selector: "example-view",
standalone: true,
imports: [UiTree, UiTreeItem],
template: `
<div
ui-tree
[label]="'Pages'"
>
<div
ui-tree-item
[itemId]="'overview'"
[label]="'Overview'"
[sortable]="true"
></div>
<div
ui-tree-item
[itemId]="'details'"
[label]="'Details'"
[sortable]="true"
></div>
<div
ui-tree-item
[itemId]="'history'"
[label]="'History'"
[sortable]="true"
></div>
</div>
`,
})
export default class Example {}Multiple selection
A selectable tree shows checkboxes. This example applies each select request to its authored items so multiple choices stay checked.
Code
<link
rel="component"
href="@threadlabs/looma/components/ui-tree/ui-tree.html"
>
<link
rel="component"
href="@threadlabs/looma/components/ui-tree-item/ui-tree-item.html"
>
<ui-tree
label="Documents"
selection="multiple"
>
<ui-tree-item
item-id="reports"
label="Reports"
expanded
>
<ui-tree-item
item-id="quarterly"
label="Quarterly"
selected
></ui-tree-item>
<ui-tree-item
item-id="annual"
label="Annual"
></ui-tree-item>
</ui-tree-item>
<ui-tree-item
item-id="notes"
label="Notes"
></ui-tree-item>
</ui-tree><script setup>
import { UiTree, UiTreeItem } from "@threadlabs/looma";
</script>
<template>
<UiTree
label="Documents"
selection="multiple"
>
<UiTreeItem
item-id="reports"
label="Reports"
:expanded="true"
>
<UiTreeItem
item-id="quarterly"
label="Quarterly"
:selected="true"
/>
<UiTreeItem
item-id="annual"
label="Annual"
/>
</UiTreeItem>
<UiTreeItem
item-id="notes"
label="Notes"
/>
</UiTree>
</template>import { UiTree, UiTreeItem } from "@threadlabs/looma";
export default function Example() {
return <UiTree
label="Documents"
selection="multiple"
>
<UiTreeItem
itemId="reports"
label="Reports"
expanded
>
<UiTreeItem
itemId="quarterly"
label="Quarterly"
selected
/>
<UiTreeItem
itemId="annual"
label="Annual"
/>
</UiTreeItem>
<UiTreeItem
itemId="notes"
label="Notes"
/>
</UiTree>;
}/** @jsxImportSource preact */
import { UiTree, UiTreeItem } from "@threadlabs/looma";
export default function Example() {
return <UiTree
label="Documents"
selection="multiple"
>
<UiTreeItem
itemId="reports"
label="Reports"
expanded
>
<UiTreeItem
itemId="quarterly"
label="Quarterly"
selected
/>
<UiTreeItem
itemId="annual"
label="Annual"
/>
</UiTreeItem>
<UiTreeItem
itemId="notes"
label="Notes"
/>
</UiTree>;
}<script>
import { UiTree, UiTreeItem } from "@threadlabs/looma";
</script>
<UiTree
label="Documents"
selection="multiple"
>
<UiTreeItem
itemId="reports"
label="Reports"
expanded
>
<UiTreeItem
itemId="quarterly"
label="Quarterly"
selected
/>
<UiTreeItem
itemId="annual"
label="Annual"
/>
</UiTreeItem>
<UiTreeItem
itemId="notes"
label="Notes"
/>
</UiTree>import { Component } from "@angular/core";
import { UiTree, UiTreeItem } from "@threadlabs/looma";
@Component({
selector: "example-view",
standalone: true,
imports: [UiTree, UiTreeItem],
template: `
<div
ui-tree
[label]="'Documents'"
[selection]="'multiple'"
>
<div
ui-tree-item
[itemId]="'reports'"
[label]="'Reports'"
[expanded]="true"
>
<div
ui-tree-item
[itemId]="'quarterly'"
[label]="'Quarterly'"
[selected]="true"
></div>
<div
ui-tree-item
[itemId]="'annual'"
[label]="'Annual'"
></div>
</div>
<div
ui-tree-item
[itemId]="'notes'"
[label]="'Notes'"
></div>
</div>
`,
})
export default class Example {}Default
Each item renders its label, an optional leading icon, and a disclosure control when it has children.
Code
<link
rel="component"
href="@threadlabs/looma/components/ui-tree/ui-tree.html"
>
<link
rel="component"
href="@threadlabs/looma/components/ui-tree-item/ui-tree-item.html"
>
<ui-tree
label="Project files"
>
<ui-tree-item
item-id="docs"
label="docs"
expanded
>
<svg
slot="leading"
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"
></path>
</svg>
<ui-tree-item
item-id="guide"
label="guide.md"
>
<svg
slot="leading"
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
</ui-tree-item>
<ui-tree-item
item-id="api"
label="api.md"
>
<svg
slot="leading"
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
</ui-tree-item>
</ui-tree-item>
<ui-tree-item
item-id="src"
label="src"
>
<svg
slot="leading"
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"
></path>
</svg>
<ui-tree-item
item-id="index"
label="index.ts"
>
<svg
slot="leading"
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
</ui-tree-item>
</ui-tree-item>
<ui-tree-item
item-id="readme"
label="README.md"
>
<svg
slot="leading"
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
</ui-tree-item>
</ui-tree><script setup>
import { UiTree, UiTreeItem } from "@threadlabs/looma";
</script>
<template>
<UiTree
label="Project files"
>
<UiTreeItem
item-id="docs"
label="docs"
:expanded="true"
>
<template #leading>
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"
></path>
</svg>
</template>
<UiTreeItem
item-id="guide"
label="guide.md"
>
<template #leading>
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
</template>
</UiTreeItem>
<UiTreeItem
item-id="api"
label="api.md"
>
<template #leading>
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
</template>
</UiTreeItem>
</UiTreeItem>
<UiTreeItem
item-id="src"
label="src"
>
<template #leading>
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"
></path>
</svg>
</template>
<UiTreeItem
item-id="index"
label="index.ts"
>
<template #leading>
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
</template>
</UiTreeItem>
</UiTreeItem>
<UiTreeItem
item-id="readme"
label="README.md"
>
<template #leading>
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
</template>
</UiTreeItem>
</UiTree>
</template>import { UiTree, UiTreeItem } from "@threadlabs/looma";
export default function Example() {
return <UiTree
label="Project files"
>
<UiTreeItem
itemId="docs"
label="docs"
expanded
slots={{
leading: <svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"
/>
</svg>,
}}
>
<UiTreeItem
itemId="guide"
label="guide.md"
slots={{
leading: <svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
/>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
/>
</svg>,
}}
>{" "}{" "}</UiTreeItem>
<UiTreeItem
itemId="api"
label="api.md"
slots={{
leading: <svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
/>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
/>
</svg>,
}}
>{" "}{" "}</UiTreeItem>
</UiTreeItem>
<UiTreeItem
itemId="src"
label="src"
slots={{
leading: <svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"
/>
</svg>,
}}
>
<UiTreeItem
itemId="index"
label="index.ts"
slots={{
leading: <svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
/>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
/>
</svg>,
}}
>{" "}{" "}</UiTreeItem>
</UiTreeItem>
<UiTreeItem
itemId="readme"
label="README.md"
slots={{
leading: <svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
/>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
/>
</svg>,
}}
>{" "}{" "}</UiTreeItem>
</UiTree>;
}/** @jsxImportSource preact */
import { UiTree, UiTreeItem } from "@threadlabs/looma";
export default function Example() {
return <UiTree
label="Project files"
>
<UiTreeItem
itemId="docs"
label="docs"
expanded
slots={{
leading: <svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"
/>
</svg>,
}}
>
<UiTreeItem
itemId="guide"
label="guide.md"
slots={{
leading: <svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
/>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
/>
</svg>,
}}
>{" "}{" "}</UiTreeItem>
<UiTreeItem
itemId="api"
label="api.md"
slots={{
leading: <svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
/>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
/>
</svg>,
}}
>{" "}{" "}</UiTreeItem>
</UiTreeItem>
<UiTreeItem
itemId="src"
label="src"
slots={{
leading: <svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"
/>
</svg>,
}}
>
<UiTreeItem
itemId="index"
label="index.ts"
slots={{
leading: <svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
/>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
/>
</svg>,
}}
>{" "}{" "}</UiTreeItem>
</UiTreeItem>
<UiTreeItem
itemId="readme"
label="README.md"
slots={{
leading: <svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
/>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
/>
</svg>,
}}
>{" "}{" "}</UiTreeItem>
</UiTree>;
}<script>
import { UiTree, UiTreeItem } from "@threadlabs/looma";
</script>
{#snippet leading()}
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"
></path>
</svg>
{/snippet}
{#snippet treeItemLeading()}
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
{/snippet}
{#snippet treeItemLeading2()}
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
{/snippet}
{#snippet treeItemLeading3()}
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"
></path>
</svg>
{/snippet}
{#snippet treeItemLeading4()}
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
{/snippet}
{#snippet treeItemLeading5()}
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
{/snippet}
<UiTree
label="Project files"
>
<UiTreeItem
itemId="docs"
label="docs"
expanded
slots={{ leading }}
>
<UiTreeItem
itemId="guide"
label="guide.md"
slots={{ leading: treeItemLeading }}
> </UiTreeItem>
<UiTreeItem
itemId="api"
label="api.md"
slots={{ leading: treeItemLeading2 }}
> </UiTreeItem>
</UiTreeItem>
<UiTreeItem
itemId="src"
label="src"
slots={{ leading: treeItemLeading3 }}
>
<UiTreeItem
itemId="index"
label="index.ts"
slots={{ leading: treeItemLeading4 }}
> </UiTreeItem>
</UiTreeItem>
<UiTreeItem
itemId="readme"
label="README.md"
slots={{ leading: treeItemLeading5 }}
> </UiTreeItem>
</UiTree>import { Component } from "@angular/core";
import { UiTree, UiTreeItem } from "@threadlabs/looma";
@Component({
selector: "example-view",
standalone: true,
imports: [UiTree, UiTreeItem],
template: `
<div
ui-tree
[label]="'Project files'"
>
<div
ui-tree-item
[itemId]="'docs'"
[label]="'docs'"
[expanded]="true"
>
<ng-container ngProjectAs="[slot='leading']">
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"
></path>
</svg>
</ng-container>
<div
ui-tree-item
[itemId]="'guide'"
[label]="'guide.md'"
>
<ng-container ngProjectAs="[slot='leading']">
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
</ng-container>
</div>
<div
ui-tree-item
[itemId]="'api'"
[label]="'api.md'"
>
<ng-container ngProjectAs="[slot='leading']">
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
</ng-container>
</div>
</div>
<div
ui-tree-item
[itemId]="'src'"
[label]="'src'"
>
<ng-container ngProjectAs="[slot='leading']">
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"
></path>
</svg>
</ng-container>
<div
ui-tree-item
[itemId]="'index'"
[label]="'index.ts'"
>
<ng-container ngProjectAs="[slot='leading']">
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
</ng-container>
</div>
</div>
<div
ui-tree-item
[itemId]="'readme'"
[label]="'README.md'"
>
<ng-container ngProjectAs="[slot='leading']">
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
</ng-container>
</div>
</div>
`,
})
export default class Example {}container
Container marks an item that can hold children even while empty, so it still accepts items dropped inside it.
Code
<link
rel="component"
href="@threadlabs/looma/components/ui-tree/ui-tree.html"
>
<link
rel="component"
href="@threadlabs/looma/components/ui-tree-item/ui-tree-item.html"
>
<ui-tree
label="Sortable files"
>
<ui-tree-item
item-id="archive"
label="archive"
container
sortable
>
<svg
slot="leading"
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"
></path>
</svg>
</ui-tree-item>
<ui-tree-item
item-id="notes"
label="notes.md"
sortable
>
<svg
slot="leading"
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
</ui-tree-item>
</ui-tree><script setup>
import { UiTree, UiTreeItem } from "@threadlabs/looma";
</script>
<template>
<UiTree
label="Sortable files"
>
<UiTreeItem
item-id="archive"
label="archive"
:container="true"
:sortable="true"
>
<template #leading>
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"
></path>
</svg>
</template>
</UiTreeItem>
<UiTreeItem
item-id="notes"
label="notes.md"
:sortable="true"
>
<template #leading>
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
</template>
</UiTreeItem>
</UiTree>
</template>import { UiTree, UiTreeItem } from "@threadlabs/looma";
export default function Example() {
return <UiTree
label="Sortable files"
>
<UiTreeItem
itemId="archive"
label="archive"
container
sortable
slots={{
leading: <svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"
/>
</svg>,
}}
>{" "}{" "}</UiTreeItem>
<UiTreeItem
itemId="notes"
label="notes.md"
sortable
slots={{
leading: <svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
/>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
/>
</svg>,
}}
>{" "}{" "}</UiTreeItem>
</UiTree>;
}/** @jsxImportSource preact */
import { UiTree, UiTreeItem } from "@threadlabs/looma";
export default function Example() {
return <UiTree
label="Sortable files"
>
<UiTreeItem
itemId="archive"
label="archive"
container
sortable
slots={{
leading: <svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"
/>
</svg>,
}}
>{" "}{" "}</UiTreeItem>
<UiTreeItem
itemId="notes"
label="notes.md"
sortable
slots={{
leading: <svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
/>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
/>
</svg>,
}}
>{" "}{" "}</UiTreeItem>
</UiTree>;
}<script>
import { UiTree, UiTreeItem } from "@threadlabs/looma";
</script>
{#snippet leading()}
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"
></path>
</svg>
{/snippet}
{#snippet treeItemLeading()}
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
{/snippet}
<UiTree
label="Sortable files"
>
<UiTreeItem
itemId="archive"
label="archive"
container
sortable
slots={{ leading }}
> </UiTreeItem>
<UiTreeItem
itemId="notes"
label="notes.md"
sortable
slots={{ leading: treeItemLeading }}
> </UiTreeItem>
</UiTree>import { Component } from "@angular/core";
import { UiTree, UiTreeItem } from "@threadlabs/looma";
@Component({
selector: "example-view",
standalone: true,
imports: [UiTree, UiTreeItem],
template: `
<div
ui-tree
[label]="'Sortable files'"
>
<div
ui-tree-item
[itemId]="'archive'"
[label]="'archive'"
[container]="true"
[sortable]="true"
>
<ng-container ngProjectAs="[slot='leading']">
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"
></path>
</svg>
</ng-container>
</div>
<div
ui-tree-item
[itemId]="'notes'"
[label]="'notes.md'"
[sortable]="true"
>
<ng-container ngProjectAs="[slot='leading']">
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
</ng-container>
</div>
</div>
`,
})
export default class Example {}disabled
A disabled item stays visible but cannot be selected, expanded, or dragged.
Code
<link
rel="component"
href="@threadlabs/looma/components/ui-tree/ui-tree.html"
>
<link
rel="component"
href="@threadlabs/looma/components/ui-tree-item/ui-tree-item.html"
>
<ui-tree
label="Project files"
>
<ui-tree-item
item-id="docs"
label="docs"
expanded
>
<svg
slot="leading"
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"
></path>
</svg>
<ui-tree-item
item-id="guide"
label="guide.md"
>
<svg
slot="leading"
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
</ui-tree-item>
<ui-tree-item
item-id="api"
label="api.md"
>
<svg
slot="leading"
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
</ui-tree-item>
</ui-tree-item>
<ui-tree-item
item-id="src"
label="src"
>
<svg
slot="leading"
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"
></path>
</svg>
<ui-tree-item
item-id="index"
label="index.ts"
>
<svg
slot="leading"
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
</ui-tree-item>
</ui-tree-item>
<ui-tree-item
item-id="readme"
label="README.md"
disabled
>
<svg
slot="leading"
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
</ui-tree-item>
</ui-tree><script setup>
import { UiTree, UiTreeItem } from "@threadlabs/looma";
</script>
<template>
<UiTree
label="Project files"
>
<UiTreeItem
item-id="docs"
label="docs"
:expanded="true"
>
<template #leading>
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"
></path>
</svg>
</template>
<UiTreeItem
item-id="guide"
label="guide.md"
>
<template #leading>
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
</template>
</UiTreeItem>
<UiTreeItem
item-id="api"
label="api.md"
>
<template #leading>
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
</template>
</UiTreeItem>
</UiTreeItem>
<UiTreeItem
item-id="src"
label="src"
>
<template #leading>
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"
></path>
</svg>
</template>
<UiTreeItem
item-id="index"
label="index.ts"
>
<template #leading>
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
</template>
</UiTreeItem>
</UiTreeItem>
<UiTreeItem
item-id="readme"
label="README.md"
:disabled="true"
>
<template #leading>
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
</template>
</UiTreeItem>
</UiTree>
</template>import { UiTree, UiTreeItem } from "@threadlabs/looma";
export default function Example() {
return <UiTree
label="Project files"
>
<UiTreeItem
itemId="docs"
label="docs"
expanded
slots={{
leading: <svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"
/>
</svg>,
}}
>
<UiTreeItem
itemId="guide"
label="guide.md"
slots={{
leading: <svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
/>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
/>
</svg>,
}}
>{" "}{" "}</UiTreeItem>
<UiTreeItem
itemId="api"
label="api.md"
slots={{
leading: <svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
/>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
/>
</svg>,
}}
>{" "}{" "}</UiTreeItem>
</UiTreeItem>
<UiTreeItem
itemId="src"
label="src"
slots={{
leading: <svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"
/>
</svg>,
}}
>
<UiTreeItem
itemId="index"
label="index.ts"
slots={{
leading: <svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
/>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
/>
</svg>,
}}
>{" "}{" "}</UiTreeItem>
</UiTreeItem>
<UiTreeItem
itemId="readme"
label="README.md"
disabled
slots={{
leading: <svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
/>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
/>
</svg>,
}}
>{" "}{" "}</UiTreeItem>
</UiTree>;
}/** @jsxImportSource preact */
import { UiTree, UiTreeItem } from "@threadlabs/looma";
export default function Example() {
return <UiTree
label="Project files"
>
<UiTreeItem
itemId="docs"
label="docs"
expanded
slots={{
leading: <svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"
/>
</svg>,
}}
>
<UiTreeItem
itemId="guide"
label="guide.md"
slots={{
leading: <svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
/>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
/>
</svg>,
}}
>{" "}{" "}</UiTreeItem>
<UiTreeItem
itemId="api"
label="api.md"
slots={{
leading: <svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
/>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
/>
</svg>,
}}
>{" "}{" "}</UiTreeItem>
</UiTreeItem>
<UiTreeItem
itemId="src"
label="src"
slots={{
leading: <svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"
/>
</svg>,
}}
>
<UiTreeItem
itemId="index"
label="index.ts"
slots={{
leading: <svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
/>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
/>
</svg>,
}}
>{" "}{" "}</UiTreeItem>
</UiTreeItem>
<UiTreeItem
itemId="readme"
label="README.md"
disabled
slots={{
leading: <svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
/>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
/>
</svg>,
}}
>{" "}{" "}</UiTreeItem>
</UiTree>;
}<script>
import { UiTree, UiTreeItem } from "@threadlabs/looma";
</script>
{#snippet leading()}
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"
></path>
</svg>
{/snippet}
{#snippet treeItemLeading()}
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
{/snippet}
{#snippet treeItemLeading2()}
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
{/snippet}
{#snippet treeItemLeading3()}
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"
></path>
</svg>
{/snippet}
{#snippet treeItemLeading4()}
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
{/snippet}
{#snippet treeItemLeading5()}
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
{/snippet}
<UiTree
label="Project files"
>
<UiTreeItem
itemId="docs"
label="docs"
expanded
slots={{ leading }}
>
<UiTreeItem
itemId="guide"
label="guide.md"
slots={{ leading: treeItemLeading }}
> </UiTreeItem>
<UiTreeItem
itemId="api"
label="api.md"
slots={{ leading: treeItemLeading2 }}
> </UiTreeItem>
</UiTreeItem>
<UiTreeItem
itemId="src"
label="src"
slots={{ leading: treeItemLeading3 }}
>
<UiTreeItem
itemId="index"
label="index.ts"
slots={{ leading: treeItemLeading4 }}
> </UiTreeItem>
</UiTreeItem>
<UiTreeItem
itemId="readme"
label="README.md"
disabled
slots={{ leading: treeItemLeading5 }}
> </UiTreeItem>
</UiTree>import { Component } from "@angular/core";
import { UiTree, UiTreeItem } from "@threadlabs/looma";
@Component({
selector: "example-view",
standalone: true,
imports: [UiTree, UiTreeItem],
template: `
<div
ui-tree
[label]="'Project files'"
>
<div
ui-tree-item
[itemId]="'docs'"
[label]="'docs'"
[expanded]="true"
>
<ng-container ngProjectAs="[slot='leading']">
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"
></path>
</svg>
</ng-container>
<div
ui-tree-item
[itemId]="'guide'"
[label]="'guide.md'"
>
<ng-container ngProjectAs="[slot='leading']">
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
</ng-container>
</div>
<div
ui-tree-item
[itemId]="'api'"
[label]="'api.md'"
>
<ng-container ngProjectAs="[slot='leading']">
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
</ng-container>
</div>
</div>
<div
ui-tree-item
[itemId]="'src'"
[label]="'src'"
>
<ng-container ngProjectAs="[slot='leading']">
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"
></path>
</svg>
</ng-container>
<div
ui-tree-item
[itemId]="'index'"
[label]="'index.ts'"
>
<ng-container ngProjectAs="[slot='leading']">
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
</ng-container>
</div>
</div>
<div
ui-tree-item
[itemId]="'readme'"
[label]="'README.md'"
[disabled]="true"
>
<ng-container ngProjectAs="[slot='leading']">
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
</ng-container>
</div>
</div>
`,
})
export default class Example {}Actions slot
Content in the actions slot sits at the end of the row, such as a per-item menu button.
Code
<link
rel="component"
href="@threadlabs/looma/components/ui-tree/ui-tree.html"
>
<link
rel="component"
href="@threadlabs/looma/components/ui-tree-item/ui-tree-item.html"
>
<link
rel="component"
href="@threadlabs/looma/components/ui-icon-button/ui-icon-button.html"
>
<ui-tree
label="Project files"
>
<ui-tree-item
item-id="docs"
label="docs"
expanded
>
<svg
slot="leading"
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"
></path>
</svg>
<ui-icon-button
slot="actions"
label="More actions for docs"
size="sm"
>
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="currentColor"
>
<circle
cx="5"
cy="12"
r="1.6"
></circle>
<circle
cx="12"
cy="12"
r="1.6"
></circle>
<circle
cx="19"
cy="12"
r="1.6"
></circle>
</svg>
</ui-icon-button>
<ui-tree-item
item-id="guide"
label="guide.md"
>
<svg
slot="leading"
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
<ui-icon-button
slot="actions"
label="More actions for guide.md"
size="sm"
>
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="currentColor"
>
<circle
cx="5"
cy="12"
r="1.6"
></circle>
<circle
cx="12"
cy="12"
r="1.6"
></circle>
<circle
cx="19"
cy="12"
r="1.6"
></circle>
</svg>
</ui-icon-button>
</ui-tree-item>
</ui-tree-item>
</ui-tree><script setup>
import { UiIconButton, UiTree, UiTreeItem } from "@threadlabs/looma";
</script>
<template>
<UiTree
label="Project files"
>
<UiTreeItem
item-id="docs"
label="docs"
:expanded="true"
>
<template #leading>
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"
></path>
</svg>
</template>
<template #actions>
<UiIconButton
label="More actions for docs"
size="sm"
>
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="currentColor"
>
<circle
cx="5"
cy="12"
r="1.6"
></circle>
<circle
cx="12"
cy="12"
r="1.6"
></circle>
<circle
cx="19"
cy="12"
r="1.6"
></circle>
</svg>
</UiIconButton>
</template>
<UiTreeItem
item-id="guide"
label="guide.md"
>
<template #leading>
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
</template>
<template #actions>
<UiIconButton
label="More actions for guide.md"
size="sm"
>
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="currentColor"
>
<circle
cx="5"
cy="12"
r="1.6"
></circle>
<circle
cx="12"
cy="12"
r="1.6"
></circle>
<circle
cx="19"
cy="12"
r="1.6"
></circle>
</svg>
</UiIconButton>
</template>
</UiTreeItem>
</UiTreeItem>
</UiTree>
</template>import { UiIconButton, UiTree, UiTreeItem } from "@threadlabs/looma";
export default function Example() {
return <UiTree
label="Project files"
>
<UiTreeItem
itemId="docs"
label="docs"
expanded
slots={{
leading: <svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"
/>
</svg>,
actions: <UiIconButton
label="More actions for docs"
size="sm"
>
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="currentColor"
>
<circle
cx="5"
cy="12"
r="1.6"
/>
<circle
cx="12"
cy="12"
r="1.6"
/>
<circle
cx="19"
cy="12"
r="1.6"
/>
</svg>
</UiIconButton>,
}}
>
<UiTreeItem
itemId="guide"
label="guide.md"
slots={{
leading: <svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
/>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
/>
</svg>,
actions: <UiIconButton
label="More actions for guide.md"
size="sm"
>
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="currentColor"
>
<circle
cx="5"
cy="12"
r="1.6"
/>
<circle
cx="12"
cy="12"
r="1.6"
/>
<circle
cx="19"
cy="12"
r="1.6"
/>
</svg>
</UiIconButton>,
}}
>{" "}{" "}{" "}</UiTreeItem>
</UiTreeItem>
</UiTree>;
}/** @jsxImportSource preact */
import { UiIconButton, UiTree, UiTreeItem } from "@threadlabs/looma";
export default function Example() {
return <UiTree
label="Project files"
>
<UiTreeItem
itemId="docs"
label="docs"
expanded
slots={{
leading: <svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"
/>
</svg>,
actions: <UiIconButton
label="More actions for docs"
size="sm"
>
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="currentColor"
>
<circle
cx="5"
cy="12"
r="1.6"
/>
<circle
cx="12"
cy="12"
r="1.6"
/>
<circle
cx="19"
cy="12"
r="1.6"
/>
</svg>
</UiIconButton>,
}}
>
<UiTreeItem
itemId="guide"
label="guide.md"
slots={{
leading: <svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
/>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
/>
</svg>,
actions: <UiIconButton
label="More actions for guide.md"
size="sm"
>
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="currentColor"
>
<circle
cx="5"
cy="12"
r="1.6"
/>
<circle
cx="12"
cy="12"
r="1.6"
/>
<circle
cx="19"
cy="12"
r="1.6"
/>
</svg>
</UiIconButton>,
}}
>{" "}{" "}{" "}</UiTreeItem>
</UiTreeItem>
</UiTree>;
}<script>
import { UiIconButton, UiTree, UiTreeItem } from "@threadlabs/looma";
</script>
{#snippet leading()}
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"
></path>
</svg>
{/snippet}
{#snippet actions()}
<UiIconButton
label="More actions for docs"
size="sm"
>
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="currentColor"
>
<circle
cx="5"
cy="12"
r="1.6"
></circle>
<circle
cx="12"
cy="12"
r="1.6"
></circle>
<circle
cx="19"
cy="12"
r="1.6"
></circle>
</svg>
</UiIconButton>
{/snippet}
{#snippet treeItemLeading()}
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
{/snippet}
{#snippet treeItemActions()}
<UiIconButton
label="More actions for guide.md"
size="sm"
>
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="currentColor"
>
<circle
cx="5"
cy="12"
r="1.6"
></circle>
<circle
cx="12"
cy="12"
r="1.6"
></circle>
<circle
cx="19"
cy="12"
r="1.6"
></circle>
</svg>
</UiIconButton>
{/snippet}
<UiTree
label="Project files"
>
<UiTreeItem
itemId="docs"
label="docs"
expanded
slots={{ leading, actions }}
>
<UiTreeItem
itemId="guide"
label="guide.md"
slots={{ leading: treeItemLeading, actions: treeItemActions }}
> </UiTreeItem>
</UiTreeItem>
</UiTree>import { Component } from "@angular/core";
import { UiIconButton, UiTree, UiTreeItem } from "@threadlabs/looma";
@Component({
selector: "example-view",
standalone: true,
imports: [UiTree, UiTreeItem, UiIconButton],
template: `
<div
ui-tree
[label]="'Project files'"
>
<div
ui-tree-item
[itemId]="'docs'"
[label]="'docs'"
[expanded]="true"
>
<ng-container ngProjectAs="[slot='leading']">
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"
></path>
</svg>
</ng-container>
<ng-container ngProjectAs="[slot='actions']">
<button
ui-icon-button
[label]="'More actions for docs'"
[size]="'sm'"
>
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="currentColor"
>
<circle
cx="5"
cy="12"
r="1.6"
></circle>
<circle
cx="12"
cy="12"
r="1.6"
></circle>
<circle
cx="19"
cy="12"
r="1.6"
></circle>
</svg>
</button>
</ng-container>
<div
ui-tree-item
[itemId]="'guide'"
[label]="'guide.md'"
>
<ng-container ngProjectAs="[slot='leading']">
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path
d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
></path>
<path
d="M14 2v4a2 2 0 0 0 2 2h4"
></path>
</svg>
</ng-container>
<ng-container ngProjectAs="[slot='actions']">
<button
ui-icon-button
[label]="'More actions for guide.md'"
[size]="'sm'"
>
<svg
aria-hidden="true"
viewBox="0 0 24 24"
fill="currentColor"
>
<circle
cx="5"
cy="12"
r="1.6"
></circle>
<circle
cx="12"
cy="12"
r="1.6"
></circle>
<circle
cx="19"
cy="12"
r="1.6"
></circle>
</svg>
</button>
</ng-container>
</div>
</div>
</div>
`,
})
export default class Example {}Lazy branch
An empty branch can expand and report busy while the application loads its children after the expand event.
Code
<link
rel="component"
href="@threadlabs/looma/components/ui-tree/ui-tree.html"
>
<link
rel="component"
href="@threadlabs/looma/components/ui-tree-item/ui-tree-item.html"
>
<ui-tree
label="Folders"
>
<ui-tree-item
item-id="remote"
label="Remote folder"
lazy
></ui-tree-item>
</ui-tree><script setup>
import { UiTree, UiTreeItem } from "@threadlabs/looma";
</script>
<template>
<UiTree
label="Folders"
>
<UiTreeItem
item-id="remote"
label="Remote folder"
:lazy="true"
/>
</UiTree>
</template>import { UiTree, UiTreeItem } from "@threadlabs/looma";
export default function Example() {
return <UiTree
label="Folders"
>
<UiTreeItem
itemId="remote"
label="Remote folder"
lazy
/>
</UiTree>;
}/** @jsxImportSource preact */
import { UiTree, UiTreeItem } from "@threadlabs/looma";
export default function Example() {
return <UiTree
label="Folders"
>
<UiTreeItem
itemId="remote"
label="Remote folder"
lazy
/>
</UiTree>;
}<script>
import { UiTree, UiTreeItem } from "@threadlabs/looma";
</script>
<UiTree
label="Folders"
>
<UiTreeItem
itemId="remote"
label="Remote folder"
lazy
/>
</UiTree>import { Component } from "@angular/core";
import { UiTree, UiTreeItem } from "@threadlabs/looma";
@Component({
selector: "example-view",
standalone: true,
imports: [UiTree, UiTreeItem],
template: `
<div
ui-tree
[label]="'Folders'"
>
<div
ui-tree-item
[itemId]="'remote'"
[label]="'Remote folder'"
[lazy]="true"
></div>
</div>
`,
})
export default class Example {}Persistent actions
A status stays visible at the end of the row while the title fades beneath it, even before hover or focus.
Code
<link
rel="component"
href="@threadlabs/looma/components/ui-tree/ui-tree.html"
>
<link
rel="component"
href="@threadlabs/looma/components/ui-tree-item/ui-tree-item.html"
>
<link
rel="component"
href="@threadlabs/looma/components/ui-badge/ui-badge.html"
>
<ui-tree
label="Project files"
>
<ui-tree-item
item-id="guide"
label="A long project guide name that continues beneath its status"
actions-visible
>
<ui-badge
slot="actions"
tone="info"
variant="outline"
size="xs"
>3</ui-badge>
</ui-tree-item>
</ui-tree><script setup>
import { UiBadge, UiTree, UiTreeItem } from "@threadlabs/looma";
</script>
<template>
<UiTree
label="Project files"
>
<UiTreeItem
item-id="guide"
label="A long project guide name that continues beneath its status"
:actions-visible="true"
>
<template #actions>
<UiBadge
tone="info"
variant="outline"
size="xs"
>3</UiBadge>
</template>
</UiTreeItem>
</UiTree>
</template>import { UiBadge, UiTree, UiTreeItem } from "@threadlabs/looma";
export default function Example() {
return <UiTree
label="Project files"
>
<UiTreeItem
itemId="guide"
label="A long project guide name that continues beneath its status"
actionsVisible
slots={{
actions: <UiBadge
tone="info"
variant="outline"
size="xs"
>3</UiBadge>,
}}
>{" "}{" "}</UiTreeItem>
</UiTree>;
}/** @jsxImportSource preact */
import { UiBadge, UiTree, UiTreeItem } from "@threadlabs/looma";
export default function Example() {
return <UiTree
label="Project files"
>
<UiTreeItem
itemId="guide"
label="A long project guide name that continues beneath its status"
actionsVisible
slots={{
actions: <UiBadge
tone="info"
variant="outline"
size="xs"
>3</UiBadge>,
}}
>{" "}{" "}</UiTreeItem>
</UiTree>;
}<script>
import { UiBadge, UiTree, UiTreeItem } from "@threadlabs/looma";
</script>
{#snippet actions()}
<UiBadge
tone="info"
variant="outline"
size="xs"
>3</UiBadge>
{/snippet}
<UiTree
label="Project files"
>
<UiTreeItem
itemId="guide"
label="A long project guide name that continues beneath its status"
actionsVisible
slots={{ actions }}
> </UiTreeItem>
</UiTree>import { Component } from "@angular/core";
import { UiBadge, UiTree, UiTreeItem } from "@threadlabs/looma";
@Component({
selector: "example-view",
standalone: true,
imports: [UiTree, UiTreeItem, UiBadge],
template: `
<div
ui-tree
[label]="'Project files'"
>
<div
ui-tree-item
[itemId]="'guide'"
[label]="'A long project guide name that continues beneath its status'"
[actionsVisible]="true"
>
<ng-container ngProjectAs="[slot='actions']">
<span
ui-badge
[tone]="'info'"
[variant]="'outline'"
[size]="'xs'"
>3</span>
</ng-container>
</div>
</div>
`,
})
export default class Example {}API
Package: @threadlabs/looma · Native root: div
Attributes
| Name | Description | Property | Type | Default | Allowed values |
|---|---|---|---|---|---|
density | Compact trades padding and type size for rows that fit more on screen. | density | keyword | comfortable | comfortable, compact |
hover-expand-delay | How long, in milliseconds, a dragged item must hover over the middle of a collapsed branch before the branch opens to receive it. 0 opens it at once. | hoverExpandDelay | number | 700 | — |
label | The tree's accessible name, announced when focus enters it. Name what the tree holds. | label | string | Tree | — |
marquee | Scrolls a name too long for its row while that row is hovered or keyboard focused, rests at the end, then scrolls it again. Off by default: a tree of names that fit should not move. An item may set its own marquee to opt in or out on its own. | marquee | boolean | false | — |
max-depth | The deepest level a drag may produce, counting the top level as 1. A drop that would place the dragged item, or any item beneath it, deeper than this is refused and reported as reorder-rejected. 0 means no limit. | maxDepth | number | 0 | — |
move-activation | Which handle activations start guided moving. click preserves two-click moving with any pointer. keyboard-touch leaves ordinary mouse and pen clicks inert while retaining keyboard activation and touch taps. Actual pointer dragging works in either mode. Guided moves show Cancel on the source row; Escape or reactivating that source handle also cancels without requesting a reorder. | moveActivation | keyword | click | click, keyboard-touch |
selection | How selection works. None keeps rows for navigation and expansion; single requests one selected item; multiple shows checkboxes and requests an item with its descendants. The application owns each Tree Item's selected state and responds to select. Single-selection rows also request activate on a row click or Enter, including an already selected row. Space requests selection only; controls and disabled rows do not activate. | selection | keyword | none | none, single, multiple |
Framework props
| Name | Type | Default | Allowed values |
|---|---|---|---|
density | "comfortable" | "compact" | comfortable | comfortable, compact |
hoverExpandDelay | number | 700 | — |
label | string | Tree | — |
marquee | boolean | false | — |
maxDepth | number | 0 | — |
moveActivation | "click" | "keyboard-touch" | click | click, keyboard-touch |
selection | "none" | "single" | "multiple" | none | none, single, multiple |
Events
| Name | Detail | Description |
|---|---|---|
activate | object
| Emitted with the declared detail payload. |
reorder | object
| Emitted with the declared detail payload. |
reorder-rejected | object
| Emitted with the declared detail payload. |
select | object
| Emitted when a selectable option becomes active. |
Slots
| Name | Purpose |
|---|---|
default | Default child content. |
Design tokens
Set shared theme properties on a theme boundary. Component hooks apply only to their owning component.
Component tokens
| Token | Declared values | Fallback |
|---|---|---|
--ui-tree-drop-color | — | — |
--ui-tree-gutter | — | 0px |
--ui-tree-indent | — | — |
Shared tokens
| Token | Fallback |
|---|---|
--ui-control-size-sm | — |
--ui-font-size-sm | — |
--ui-space-2 | — |
--ui-text-secondary | — |
Tree Item API
The row primitive used inside ui-tree.
Package: @threadlabs/looma · Native root: div
Attributes
| Name | Description | Property | Type | Default | Allowed values |
|---|---|---|---|---|---|
accepts | A comma-separated list of the dragType values this branch accepts dropped inside it. Empty accepts any type. It does not affect drops before or after the item. | accepts | string | | — |
actions-visible | Keeps the actions slot visible before hover or focus, for persistent status or controls. The label fades beneath its measured width on pointer devices; touch rows retain a separate actions column with a short end fade. Does not change keyboard navigation or start the marquee. | actionsVisible | boolean | false | — |
container | Makes the item a branch even before it has children: it gets the expand button and aria-expanded, and accepts drops inside it. An item with nested items is a branch without it. | container | boolean | false | — |
disabled | Makes the item unavailable: faded, skipped by keyboard navigation, unable to expand or be dragged, and closed to drops inside it. | disabled | boolean | false | — |
drag-type | The item's kind, for drag rules: it can be dropped before or after only items of the same type, and inside a branch only if that branch's accepts allows it. Reported as sourceType and targetType. | dragType | string | item | — |
drop-depth | Overrides the level this item counts as when the tree checks maxDepth for a drop onto it. Unset, its level in the rendered tree is used; set it when the item sits deeper in the real hierarchy than the rendered tree shows. | dropDepth | number | — | — |
drop-scope | Names the list the item sits in, such as its parent's id, and is reported as sourceScope and targetScope in the tree's reorder events, so a handler can tell a reorder within one list from a move between lists. It never restricts where an item can be dropped; dragType and accepts do that. | dropScope | string | | — |
expanded | Whether the branch shows its children, initially or when set externally. The expand button, a click on the row, and the arrow keys toggle it from there, each reported as an expand event. Only meaningful for a branch. | expanded | boolean | false | — |
item-id | The item's identifier, reported as sourceId and targetId in the tree's reorder events and as id in its expand event. A sortable item needs one to be dragged, and a drop onto an item without one is not reported. | itemId | string | | — |
label | The item's accessible name, also shown as the row text unless the label slot supplies content. | label | string | | — |
lazy | Keeps an empty item expandable while its children are supplied later. Expanding emits expand; the item is aria-busy until child Tree Items are appended. Clear lazy if loading finishes with no children. | lazy | boolean | false | — |
marquee | Scrolls a name too long for its row while a pointer hovers the row or keyboard focus is in it, rests at the end, then scrolls it again from the start. A touch does not start it. Off by default: a tree of short names should not move, and a product decides whether reading the whole name matters more than a still list. | marquee | boolean | false | — |
selected | Marks the item selected: it sets aria-selected and highlights the row. This is controlled state; respond to the parent Tree's select request by updating it. | selected | boolean | false | — |
sortable | Gives the item a move handle. Drag it, or activate it according to the tree's moveActivation and choose a target by a second click or the keyboard. A guided move exposes Cancel on this row. The tree reports reorder and leaves moving the item to you. Needs itemId; disabled items show no handle. | sortable | boolean | false | — |
subtree-depth | Overrides how many levels sit beneath this item when the tree checks maxDepth for a drag of it. Unset, the tree counts the rendered descendants; set it when some are not rendered, such as children that load later. | subtreeDepth | number | — | — |
Framework props
| Name | Type | Default | Allowed values |
|---|---|---|---|
accepts | string | | — |
actionsVisible | boolean | false | — |
container | boolean | false | — |
disabled | boolean | false | — |
dragType | string | item | — |
dropDepth | number | — | — |
dropScope | string | | — |
expanded | boolean | false | — |
itemId | string | | — |
label | string | | — |
lazy | boolean | false | — |
marquee | boolean | false | — |
selected | boolean | false | — |
sortable | boolean | false | — |
subtreeDepth | number | — | — |
Events
| Name | Detail | Description |
|---|---|---|
expand | object
| Emitted with the declared detail payload. |
Slots
| Name | Purpose |
|---|---|
leading | Named content for the leading region. |
label | Named content for the label region. |
actions | Named content for the actions region. |
default | Default child content. |
Design tokens
Set shared theme properties on a theme boundary. Component hooks apply only to their owning component.
Component tokens
| Token | Declared values | Fallback |
|---|---|---|
--ui-tree-item-font-size | — | var(--ui-font-size-sm) |
--ui-tree-item-label-padding-block | — | var(--ui-space-1) |
--ui-tree-item-label-padding-inline | — | var(--ui-space-2) |
--ui-tree-item-min-block-size | 32px | 44px | — |
Shared tokens
| Token | Fallback |
|---|---|
--ui-accent-line-width | — |
--ui-accent-solid | — |
--ui-accent-subtle | — |
--ui-border-width | — |
--ui-disabled-surface | — |
--ui-disabled-text | — |
--ui-focus-ring | — |
--ui-focus-width | — |
--ui-font-size-sm | — |
--ui-motion-base | — |
--ui-motion-ease | — |
--ui-motion-fast | — |
--ui-radius-round | — |
--ui-radius-sm | — |
--ui-selection-border | — |
--ui-selection-radius | — |
--ui-selection-surface | — |
--ui-selection-text | — |
--ui-space-1 | — |
--ui-space-2 | — |
--ui-surface-elevated | — |
--ui-surface-hover | — |
--ui-surface-muted | — |
--ui-text-muted | — |
--ui-text-primary | — |
--ui-text-secondary | — |