Button
Essential button primitive that enhances semantic button markup and styling hooks. Ghost choices use the shared selection surface and text tokens for their selected visual state while the composing control owns ARIA selection semantics. Unselected disabled ghost actions stay transparent; an unavailable selected choice keeps a muted selection wash.
Default
With no properties supplied, Button uses the outline variant at its default size.
Code
<link
rel="component"
href="@threadlabs/looma/components/ui-button/ui-button.html"
>
<ui-button>Button</ui-button><script setup>
import { UiButton } from "@threadlabs/looma";
</script>
<template>
<UiButton>Button</UiButton>
</template>import { UiButton } from "@threadlabs/looma";
export default function Example() {
return <UiButton>Button</UiButton>;
}/** @jsxImportSource preact */
import { UiButton } from "@threadlabs/looma";
export default function Example() {
return <UiButton>Button</UiButton>;
}<script>
import { UiButton } from "@threadlabs/looma";
</script>
<UiButton>Button</UiButton>import { Component } from "@angular/core";
import { UiButton } from "@threadlabs/looma";
@Component({
selector: "example-view",
standalone: true,
imports: [UiButton],
template: `
<ng-template
ui-button
>Button</ng-template>
`,
})
export default class Example {}variant
Appearance sets emphasis independently from tone: solid neutral is a standard action, and danger can be an outline. Named presets combine those shared choices.
Code
<link
rel="component"
href="@threadlabs/looma/components/ui-cluster/ui-cluster.html"
>
<link
rel="component"
href="@threadlabs/looma/components/ui-button/ui-button.html"
>
<ui-cluster
gap="s"
>
<ui-button
variant="solid"
tone="accent"
>Solid</ui-button>
<ui-button
variant="outline"
tone="accent"
>Outline</ui-button>
<ui-button
variant="ghost"
tone="accent"
>Ghost</ui-button>
<ui-button
variant="danger"
>Danger</ui-button>
<ui-button
variant="solid"
tone="neutral"
>Solid neutral</ui-button>
<ui-button
variant="outline"
tone="danger"
>Danger outline</ui-button>
<ui-button
preset="primary"
>Primary</ui-button>
<ui-button
preset="standard"
>Standard</ui-button>
<ui-button
preset="quiet"
>Quiet</ui-button>
<ui-button
preset="destructive"
>Destructive</ui-button>
</ui-cluster><script setup>
import { UiButton, UiCluster } from "@threadlabs/looma";
</script>
<template>
<UiCluster
gap="s"
>
<UiButton
variant="solid"
tone="accent"
>Solid</UiButton>
<UiButton
variant="outline"
tone="accent"
>Outline</UiButton>
<UiButton
variant="ghost"
tone="accent"
>Ghost</UiButton>
<UiButton
variant="danger"
>Danger</UiButton>
<UiButton
variant="solid"
tone="neutral"
>Solid neutral</UiButton>
<UiButton
variant="outline"
tone="danger"
>Danger outline</UiButton>
<UiButton
preset="primary"
>Primary</UiButton>
<UiButton
preset="standard"
>Standard</UiButton>
<UiButton
preset="quiet"
>Quiet</UiButton>
<UiButton
preset="destructive"
>Destructive</UiButton>
</UiCluster>
</template>import { UiButton, UiCluster } from "@threadlabs/looma";
export default function Example() {
return <UiCluster
gap="s"
>
<UiButton
variant="solid"
tone="accent"
>Solid</UiButton>
<UiButton
variant="outline"
tone="accent"
>Outline</UiButton>
<UiButton
variant="ghost"
tone="accent"
>Ghost</UiButton>
<UiButton
variant="danger"
>Danger</UiButton>
<UiButton
variant="solid"
tone="neutral"
>Solid neutral</UiButton>
<UiButton
variant="outline"
tone="danger"
>Danger outline</UiButton>
<UiButton
preset="primary"
>Primary</UiButton>
<UiButton
preset="standard"
>Standard</UiButton>
<UiButton
preset="quiet"
>Quiet</UiButton>
<UiButton
preset="destructive"
>Destructive</UiButton>
</UiCluster>;
}/** @jsxImportSource preact */
import { UiButton, UiCluster } from "@threadlabs/looma";
export default function Example() {
return <UiCluster
gap="s"
>
<UiButton
variant="solid"
tone="accent"
>Solid</UiButton>
<UiButton
variant="outline"
tone="accent"
>Outline</UiButton>
<UiButton
variant="ghost"
tone="accent"
>Ghost</UiButton>
<UiButton
variant="danger"
>Danger</UiButton>
<UiButton
variant="solid"
tone="neutral"
>Solid neutral</UiButton>
<UiButton
variant="outline"
tone="danger"
>Danger outline</UiButton>
<UiButton
preset="primary"
>Primary</UiButton>
<UiButton
preset="standard"
>Standard</UiButton>
<UiButton
preset="quiet"
>Quiet</UiButton>
<UiButton
preset="destructive"
>Destructive</UiButton>
</UiCluster>;
}<script>
import { UiButton, UiCluster } from "@threadlabs/looma";
</script>
<UiCluster
gap="s"
>
<UiButton
variant="solid"
tone="accent"
>Solid</UiButton>
<UiButton
variant="outline"
tone="accent"
>Outline</UiButton>
<UiButton
variant="ghost"
tone="accent"
>Ghost</UiButton>
<UiButton
variant="danger"
>Danger</UiButton>
<UiButton
variant="solid"
tone="neutral"
>Solid neutral</UiButton>
<UiButton
variant="outline"
tone="danger"
>Danger outline</UiButton>
<UiButton
preset="primary"
>Primary</UiButton>
<UiButton
preset="standard"
>Standard</UiButton>
<UiButton
preset="quiet"
>Quiet</UiButton>
<UiButton
preset="destructive"
>Destructive</UiButton>
</UiCluster>import { Component } from "@angular/core";
import { UiButton, UiCluster } from "@threadlabs/looma";
@Component({
selector: "example-view",
standalone: true,
imports: [UiCluster, UiButton],
template: `
<div
ui-cluster
[gap]="'s'"
>
<ng-template
ui-button
[variant]="'solid'"
[tone]="'accent'"
>Solid</ng-template>
<ng-template
ui-button
[variant]="'outline'"
[tone]="'accent'"
>Outline</ng-template>
<ng-template
ui-button
[variant]="'ghost'"
[tone]="'accent'"
>Ghost</ng-template>
<ng-template
ui-button
[variant]="'danger'"
>Danger</ng-template>
<ng-template
ui-button
[variant]="'solid'"
[tone]="'neutral'"
>Solid neutral</ng-template>
<ng-template
ui-button
[variant]="'outline'"
[tone]="'danger'"
>Danger outline</ng-template>
<ng-template
ui-button
[preset]="'primary'"
>Primary</ng-template>
<ng-template
ui-button
[preset]="'standard'"
>Standard</ng-template>
<ng-template
ui-button
[preset]="'quiet'"
>Quiet</ng-template>
<ng-template
ui-button
[preset]="'destructive'"
>Destructive</ng-template>
</div>
`,
})
export default class Example {}Link
variant="link" is an inline text action: it takes the surrounding font, has no box or padding, and its underline strengthens on hover. It is still a button, with a visible focus ring.
Draft saved ·
Code
<link
rel="component"
href="@threadlabs/looma/components/ui-button/ui-button.html"
>
<p
class="demo-inline-action"
> Draft saved · <ui-button
variant="link"
>3 unpublished changes</ui-button> </p><script setup>
import { UiButton } from "@threadlabs/looma";
</script>
<template>
<p
class="demo-inline-action"
> Draft saved · <UiButton
variant="link"
>3 unpublished changes</UiButton> </p>
</template>import { UiButton } from "@threadlabs/looma";
export default function Example() {
return <p
className="demo-inline-action"
>{" Draft saved · "}<UiButton
variant="link"
>3 unpublished changes</UiButton>{" "}</p>;
}/** @jsxImportSource preact */
import { UiButton } from "@threadlabs/looma";
export default function Example() {
return <p
className="demo-inline-action"
>{" Draft saved · "}<UiButton
variant="link"
>3 unpublished changes</UiButton>{" "}</p>;
}<script>
import { UiButton } from "@threadlabs/looma";
</script>
<p
class="demo-inline-action"
> Draft saved · <UiButton
variant="link"
>3 unpublished changes</UiButton> </p>import { Component } from "@angular/core";
import { UiButton } from "@threadlabs/looma";
@Component({
selector: "example-view",
standalone: true,
imports: [UiButton],
template: `
<p
class="demo-inline-action"
> Draft saved · <ng-template
ui-button
[variant]="'link'"
>3 unpublished changes</ng-template> </p>
`,
})
export default class Example {}size
Size changes the control's height and padding (xs 24px, sm 32px, md 40px, lg 48px), not just its text. Use xs for a control that sits inside a line of small text.
Code
<link
rel="component"
href="@threadlabs/looma/components/ui-cluster/ui-cluster.html"
>
<link
rel="component"
href="@threadlabs/looma/components/ui-button/ui-button.html"
>
<ui-cluster
gap="s"
align="center"
>
<ui-button
size="xs"
>Extra small</ui-button>
<ui-button
size="sm"
>Small</ui-button>
<ui-button>Medium</ui-button>
<ui-button
size="lg"
>Large</ui-button>
</ui-cluster><script setup>
import { UiButton, UiCluster } from "@threadlabs/looma";
</script>
<template>
<UiCluster
gap="s"
align="center"
>
<UiButton
size="xs"
>Extra small</UiButton>
<UiButton
size="sm"
>Small</UiButton>
<UiButton>Medium</UiButton>
<UiButton
size="lg"
>Large</UiButton>
</UiCluster>
</template>import { UiButton, UiCluster } from "@threadlabs/looma";
export default function Example() {
return <UiCluster
gap="s"
align="center"
>
<UiButton
size="xs"
>Extra small</UiButton>
<UiButton
size="sm"
>Small</UiButton>
<UiButton>Medium</UiButton>
<UiButton
size="lg"
>Large</UiButton>
</UiCluster>;
}/** @jsxImportSource preact */
import { UiButton, UiCluster } from "@threadlabs/looma";
export default function Example() {
return <UiCluster
gap="s"
align="center"
>
<UiButton
size="xs"
>Extra small</UiButton>
<UiButton
size="sm"
>Small</UiButton>
<UiButton>Medium</UiButton>
<UiButton
size="lg"
>Large</UiButton>
</UiCluster>;
}<script>
import { UiButton, UiCluster } from "@threadlabs/looma";
</script>
<UiCluster
gap="s"
align="center"
>
<UiButton
size="xs"
>Extra small</UiButton>
<UiButton
size="sm"
>Small</UiButton>
<UiButton>Medium</UiButton>
<UiButton
size="lg"
>Large</UiButton>
</UiCluster>import { Component } from "@angular/core";
import { UiButton, UiCluster } from "@threadlabs/looma";
@Component({
selector: "example-view",
standalone: true,
imports: [UiCluster, UiButton],
template: `
<div
ui-cluster
[gap]="'s'"
[align]="'center'"
>
<ng-template
ui-button
[size]="'xs'"
>Extra small</ng-template>
<ng-template
ui-button
[size]="'sm'"
>Small</ng-template>
<ng-template
ui-button
>Medium</ng-template>
<ng-template
ui-button
[size]="'lg'"
>Large</ng-template>
</div>
`,
})
export default class Example {}disabled
Disabled buttons keep their variant but read as unavailable and ignore activation.
Code
<link
rel="component"
href="@threadlabs/looma/components/ui-cluster/ui-cluster.html"
>
<link
rel="component"
href="@threadlabs/looma/components/ui-button/ui-button.html"
>
<ui-cluster
gap="s"
>
<ui-button
disabled
>Outline</ui-button>
<ui-button
variant="solid"
disabled
>Solid</ui-button>
<ui-button
variant="danger"
disabled
>Danger</ui-button>
</ui-cluster><script setup>
import { UiButton, UiCluster } from "@threadlabs/looma";
</script>
<template>
<UiCluster
gap="s"
>
<UiButton
:disabled="true"
>Outline</UiButton>
<UiButton
variant="solid"
:disabled="true"
>Solid</UiButton>
<UiButton
variant="danger"
:disabled="true"
>Danger</UiButton>
</UiCluster>
</template>import { UiButton, UiCluster } from "@threadlabs/looma";
export default function Example() {
return <UiCluster
gap="s"
>
<UiButton
disabled
>Outline</UiButton>
<UiButton
variant="solid"
disabled
>Solid</UiButton>
<UiButton
variant="danger"
disabled
>Danger</UiButton>
</UiCluster>;
}/** @jsxImportSource preact */
import { UiButton, UiCluster } from "@threadlabs/looma";
export default function Example() {
return <UiCluster
gap="s"
>
<UiButton
disabled
>Outline</UiButton>
<UiButton
variant="solid"
disabled
>Solid</UiButton>
<UiButton
variant="danger"
disabled
>Danger</UiButton>
</UiCluster>;
}<script>
import { UiButton, UiCluster } from "@threadlabs/looma";
</script>
<UiCluster
gap="s"
>
<UiButton
disabled
>Outline</UiButton>
<UiButton
variant="solid"
disabled
>Solid</UiButton>
<UiButton
variant="danger"
disabled
>Danger</UiButton>
</UiCluster>import { Component } from "@angular/core";
import { UiButton, UiCluster } from "@threadlabs/looma";
@Component({
selector: "example-view",
standalone: true,
imports: [UiCluster, UiButton],
template: `
<div
ui-cluster
[gap]="'s'"
>
<ng-template
ui-button
[disabled]="true"
>Outline</ng-template>
<ng-template
ui-button
[variant]="'solid'"
[disabled]="true"
>Solid</ng-template>
<ng-template
ui-button
[variant]="'danger'"
[disabled]="true"
>Danger</ng-template>
</div>
`,
})
export default class Example {}align and stretch
align="start" lays content out from the start edge, like a list option; stretch fills the container's width.
Code
<link
rel="component"
href="@threadlabs/looma/components/ui-stack/ui-stack.html"
>
<link
rel="component"
href="@threadlabs/looma/components/ui-button/ui-button.html"
>
<ui-stack
gap="s"
style="max-inline-size: 22rem"
>
<ui-button
variant="ghost"
align="start"
stretch
>New page at the project root</ui-button>
<ui-button
variant="solid"
stretch
>Continue</ui-button>
</ui-stack><script setup>
import { UiButton, UiStack } from "@threadlabs/looma";
</script>
<template>
<UiStack
gap="s"
style="max-inline-size: 22rem"
>
<UiButton
variant="ghost"
align="start"
:stretch="true"
>New page at the project root</UiButton>
<UiButton
variant="solid"
:stretch="true"
>Continue</UiButton>
</UiStack>
</template>import { UiButton, UiStack } from "@threadlabs/looma";
export default function Example() {
return <UiStack
gap="s"
style={{"maxInlineSize":"22rem"}}
>
<UiButton
variant="ghost"
align="start"
stretch
>New page at the project root</UiButton>
<UiButton
variant="solid"
stretch
>Continue</UiButton>
</UiStack>;
}/** @jsxImportSource preact */
import { UiButton, UiStack } from "@threadlabs/looma";
export default function Example() {
return <UiStack
gap="s"
style={{"maxInlineSize":"22rem"}}
>
<UiButton
variant="ghost"
align="start"
stretch
>New page at the project root</UiButton>
<UiButton
variant="solid"
stretch
>Continue</UiButton>
</UiStack>;
}<script>
import { UiButton, UiStack } from "@threadlabs/looma";
</script>
<UiStack
gap="s"
style="max-inline-size: 22rem"
>
<UiButton
variant="ghost"
align="start"
stretch
>New page at the project root</UiButton>
<UiButton
variant="solid"
stretch
>Continue</UiButton>
</UiStack>import { Component } from "@angular/core";
import { UiButton, UiStack } from "@threadlabs/looma";
@Component({
selector: "example-view",
standalone: true,
imports: [UiStack, UiButton],
template: `
<div
ui-stack
[gap]="'s'"
style="max-inline-size: 22rem"
>
<ng-template
ui-button
[variant]="'ghost'"
[align]="'start'"
[stretch]="true"
>New page at the project root</ng-template>
<ng-template
ui-button
[variant]="'solid'"
[stretch]="true"
>Continue</ng-template>
</div>
`,
})
export default class Example {}as a link
Supplying href automatically renders a real link that looks and responds exactly like the button, in every variant. target and rel pass to the link. A disabled link drops its href and states aria-disabled, so it cannot be followed.
Code
<link
rel="component"
href="@threadlabs/looma/components/ui-cluster/ui-cluster.html"
>
<link
rel="component"
href="@threadlabs/looma/components/ui-button/ui-button.html"
>
<ui-cluster
gap="s"
>
<ui-button
href="#get-started"
variant="solid"
>Get started</ui-button>
<ui-button
href="https://example.com/"
target="_blank"
rel="noreferrer"
>Read the guide</ui-button>
<ui-button
href="#get-started"
disabled
>Unavailable</ui-button>
</ui-cluster><script setup>
import { UiButton, UiCluster } from "@threadlabs/looma";
</script>
<template>
<UiCluster
gap="s"
>
<UiButton
href="#get-started"
variant="solid"
>Get started</UiButton>
<UiButton
href="https://example.com/"
target="_blank"
rel="noreferrer"
>Read the guide</UiButton>
<UiButton
href="#get-started"
:disabled="true"
>Unavailable</UiButton>
</UiCluster>
</template>import { UiButton, UiCluster } from "@threadlabs/looma";
export default function Example() {
return <UiCluster
gap="s"
>
<UiButton
href="#get-started"
variant="solid"
>Get started</UiButton>
<UiButton
href="https://example.com/"
target="_blank"
rel="noreferrer"
>Read the guide</UiButton>
<UiButton
href="#get-started"
disabled
>Unavailable</UiButton>
</UiCluster>;
}/** @jsxImportSource preact */
import { UiButton, UiCluster } from "@threadlabs/looma";
export default function Example() {
return <UiCluster
gap="s"
>
<UiButton
href="#get-started"
variant="solid"
>Get started</UiButton>
<UiButton
href="https://example.com/"
target="_blank"
rel="noreferrer"
>Read the guide</UiButton>
<UiButton
href="#get-started"
disabled
>Unavailable</UiButton>
</UiCluster>;
}<script>
import { UiButton, UiCluster } from "@threadlabs/looma";
</script>
<UiCluster
gap="s"
>
<UiButton
href="#get-started"
variant="solid"
>Get started</UiButton>
<UiButton
href="https://example.com/"
target="_blank"
rel="noreferrer"
>Read the guide</UiButton>
<UiButton
href="#get-started"
disabled
>Unavailable</UiButton>
</UiCluster>import { Component } from "@angular/core";
import { UiButton, UiCluster } from "@threadlabs/looma";
@Component({
selector: "example-view",
standalone: true,
imports: [UiCluster, UiButton],
template: `
<div
ui-cluster
[gap]="'s'"
>
<ng-template
ui-button
[href]="'#get-started'"
[variant]="'solid'"
>Get started</ng-template>
<ng-template
ui-button
[href]="'https://example.com/'"
[target]="'_blank'"
[rel]="'noreferrer'"
>Read the guide</ng-template>
<ng-template
ui-button
[href]="'#get-started'"
[disabled]="true"
>Unavailable</ng-template>
</div>
`,
})
export default class Example {}Loading action
Press Save changes to see the loading state. Its spinner appears beside the label, and the action stays focusable while another press is blocked.
Code
<script
type="module"
>
import "@threadlabs/looma";
import { componentRegistry } from "@nextwebwg/html-next/runtime";
const button = document.querySelector("#docs-save-changes");
button.addEventListener("click", async () => {
componentRegistry.update(button, { loading: true });
try {
await new Promise((resolve) => setTimeout(resolve, 1500));
} finally {
componentRegistry.update(button, { loading: false });
}
});
</script>
<ui-button
id="docs-save-changes"
variant="solid"
>Save changes</ui-button>
<script setup lang="ts">
import { ref } from "vue";
import { UiButton as Button } from "@threadlabs/looma";
const loading = ref(false);
async function saveChanges() {
loading.value = true;
try {
await new Promise((resolve) => setTimeout(resolve, 1500));
} finally {
loading.value = false;
}
}
</script>
<template>
<Button variant="solid" :loading="loading" @click="saveChanges">Save changes</Button>
</template>
import { UiButton } from "@threadlabs/looma";
export default function Example() {
return <UiButton
id="docs-save-changes"
data-example-id="docs-save-changes"
variant="solid"
>Save changes</UiButton>;
}/** @jsxImportSource preact */
import { UiButton } from "@threadlabs/looma";
export default function Example() {
return <UiButton
id="docs-save-changes"
data-example-id="docs-save-changes"
variant="solid"
>Save changes</UiButton>;
}<script>
import { UiButton } from "@threadlabs/looma";
</script>
<UiButton
id="docs-save-changes"
data-example-id="docs-save-changes"
variant="solid"
>Save changes</UiButton>import { Component } from "@angular/core";
import { UiButton } from "@threadlabs/looma";
@Component({
selector: "example-view",
standalone: true,
imports: [UiButton],
template: `
<ng-template
ui-button
[variant]="'solid'"
[hnAttributes]="{ id: 'docs-save-changes', 'data-example-id': 'docs-save-changes' }"
>Save changes</ng-template>
`,
})
export default class Example {}Pill
shape="pill" rounds the ends fully. A small ghost pill suits a compact choice in a line of text, such as a status or a person, and opens its menu like any button.
Code
<link
rel="component"
href="@threadlabs/looma/components/ui-cluster/ui-cluster.html"
>
<link
rel="component"
href="@threadlabs/looma/components/ui-button/ui-button.html"
>
<link
rel="component"
href="@threadlabs/looma/components/ui-menu/ui-menu.html"
>
<link
rel="component"
href="@threadlabs/looma/components/ui-menu-item/ui-menu-item.html"
>
<ui-cluster
gap="s"
align="center"
>
<ui-button
id="pill-stage"
variant="ghost"
tone="neutral"
size="xs"
shape="pill"
>On track</ui-button>
<ui-menu
for="pill-stage"
size="sm"
aria-label="Stage"
>
<ui-menu-item
type="radio"
value="early"
>Early</ui-menu-item>
<ui-menu-item
type="radio"
value="on-track"
checked
>On track</ui-menu-item>
<ui-menu-item
type="radio"
value="stable"
>Stable</ui-menu-item>
</ui-menu>
<ui-button
shape="pill"
>Pill</ui-button>
</ui-cluster><script setup>
import { UiButton, UiCluster, UiMenu, UiMenuItem } from "@threadlabs/looma";
</script>
<template>
<UiCluster
gap="s"
align="center"
>
<UiButton
id="pill-stage"
variant="ghost"
tone="neutral"
size="xs"
shape="pill"
>On track</UiButton>
<UiMenu
for="pill-stage"
size="sm"
aria-label="Stage"
>
<UiMenuItem
type="radio"
value="early"
>Early</UiMenuItem>
<UiMenuItem
type="radio"
value="on-track"
:checked="true"
>On track</UiMenuItem>
<UiMenuItem
type="radio"
value="stable"
>Stable</UiMenuItem>
</UiMenu>
<UiButton
shape="pill"
>Pill</UiButton>
</UiCluster>
</template>import { UiButton, UiCluster, UiMenu, UiMenuItem } from "@threadlabs/looma";
export default function Example() {
return <UiCluster
gap="s"
align="center"
>
<UiButton
id="pill-stage"
variant="ghost"
tone="neutral"
size="xs"
shape="pill"
>On track</UiButton>
<UiMenu
htmlFor="pill-stage"
size="sm"
aria-label="Stage"
>
<UiMenuItem
type="radio"
value="early"
>Early</UiMenuItem>
<UiMenuItem
type="radio"
value="on-track"
checked
>On track</UiMenuItem>
<UiMenuItem
type="radio"
value="stable"
>Stable</UiMenuItem>
</UiMenu>
<UiButton
shape="pill"
>Pill</UiButton>
</UiCluster>;
}/** @jsxImportSource preact */
import { UiButton, UiCluster, UiMenu, UiMenuItem } from "@threadlabs/looma";
export default function Example() {
return <UiCluster
gap="s"
align="center"
>
<UiButton
id="pill-stage"
variant="ghost"
tone="neutral"
size="xs"
shape="pill"
>On track</UiButton>
<UiMenu
htmlFor="pill-stage"
size="sm"
aria-label="Stage"
>
<UiMenuItem
type="radio"
value="early"
>Early</UiMenuItem>
<UiMenuItem
type="radio"
value="on-track"
checked
>On track</UiMenuItem>
<UiMenuItem
type="radio"
value="stable"
>Stable</UiMenuItem>
</UiMenu>
<UiButton
shape="pill"
>Pill</UiButton>
</UiCluster>;
}<script>
import { UiButton, UiCluster, UiMenu, UiMenuItem } from "@threadlabs/looma";
</script>
<UiCluster
gap="s"
align="center"
>
<UiButton
id="pill-stage"
variant="ghost"
tone="neutral"
size="xs"
shape="pill"
>On track</UiButton>
<UiMenu
for="pill-stage"
size="sm"
aria-label="Stage"
>
<UiMenuItem
type="radio"
value="early"
>Early</UiMenuItem>
<UiMenuItem
type="radio"
value="on-track"
checked
>On track</UiMenuItem>
<UiMenuItem
type="radio"
value="stable"
>Stable</UiMenuItem>
</UiMenu>
<UiButton
shape="pill"
>Pill</UiButton>
</UiCluster>import { Component } from "@angular/core";
import { UiButton, UiCluster, UiMenu, UiMenuItem } from "@threadlabs/looma";
@Component({
selector: "example-view",
standalone: true,
imports: [UiCluster, UiButton, UiMenu, UiMenuItem],
template: `
<div
ui-cluster
[gap]="'s'"
[align]="'center'"
>
<ng-template
ui-button
[variant]="'ghost'"
[tone]="'neutral'"
[size]="'xs'"
[shape]="'pill'"
[hnAttributes]="{ id: 'pill-stage' }"
>On track</ng-template>
<div
ui-menu
[for]="'pill-stage'"
[size]="'sm'"
aria-label="Stage"
>
<ng-template
ui-menu-item
[type]="'radio'"
[value]="'early'"
>Early</ng-template>
<ng-template
ui-menu-item
[type]="'radio'"
[value]="'on-track'"
[checked]="true"
>On track</ng-template>
<ng-template
ui-menu-item
[type]="'radio'"
[value]="'stable'"
>Stable</ng-template>
</div>
<ng-template
ui-button
[shape]="'pill'"
>Pill</ng-template>
</div>
`,
})
export default class Example {}Square minimum size
Short numeric and icon actions share the control's minimum height and width. Longer labels grow naturally; the ordinary Button default stays content-sized.
Code
<link
rel="component"
href="@threadlabs/looma/components/ui-cluster/ui-cluster.html"
>
<link
rel="component"
href="@threadlabs/looma/components/ui-button/ui-button.html"
>
<link
rel="component"
href="@threadlabs/looma/components/ui-icon/ui-icon.html"
>
<ui-cluster
gap="xs"
>
<ui-button
square
size="sm"
variant="ghost"
tone="neutral"
aria-label="Previous"
>
<ui-icon
name="chevron-left"
></ui-icon>
</ui-button>
<ui-button
square
size="sm"
variant="ghost"
tone="neutral"
>1</ui-button>
<ui-button
square
size="sm"
variant="solid"
>2</ui-button>
<ui-button
square
size="sm"
variant="ghost"
tone="neutral"
>10</ui-button>
<ui-button
square
size="sm"
variant="ghost"
tone="neutral"
aria-label="Next"
>
<ui-icon
name="chevron-right"
></ui-icon>
</ui-button>
</ui-cluster><script setup>
import { UiButton, UiCluster, UiIcon } from "@threadlabs/looma";
</script>
<template>
<UiCluster
gap="xs"
>
<UiButton
:square="true"
size="sm"
variant="ghost"
tone="neutral"
aria-label="Previous"
>
<UiIcon
name="chevron-left"
/>
</UiButton>
<UiButton
:square="true"
size="sm"
variant="ghost"
tone="neutral"
>1</UiButton>
<UiButton
:square="true"
size="sm"
variant="solid"
>2</UiButton>
<UiButton
:square="true"
size="sm"
variant="ghost"
tone="neutral"
>10</UiButton>
<UiButton
:square="true"
size="sm"
variant="ghost"
tone="neutral"
aria-label="Next"
>
<UiIcon
name="chevron-right"
/>
</UiButton>
</UiCluster>
</template>import { UiButton, UiCluster, UiIcon } from "@threadlabs/looma";
export default function Example() {
return <UiCluster
gap="xs"
>
<UiButton
square
size="sm"
variant="ghost"
tone="neutral"
aria-label="Previous"
>
<UiIcon
name="chevron-left"
/>
</UiButton>
<UiButton
square
size="sm"
variant="ghost"
tone="neutral"
>1</UiButton>
<UiButton
square
size="sm"
variant="solid"
>2</UiButton>
<UiButton
square
size="sm"
variant="ghost"
tone="neutral"
>10</UiButton>
<UiButton
square
size="sm"
variant="ghost"
tone="neutral"
aria-label="Next"
>
<UiIcon
name="chevron-right"
/>
</UiButton>
</UiCluster>;
}/** @jsxImportSource preact */
import { UiButton, UiCluster, UiIcon } from "@threadlabs/looma";
export default function Example() {
return <UiCluster
gap="xs"
>
<UiButton
square
size="sm"
variant="ghost"
tone="neutral"
aria-label="Previous"
>
<UiIcon
name="chevron-left"
/>
</UiButton>
<UiButton
square
size="sm"
variant="ghost"
tone="neutral"
>1</UiButton>
<UiButton
square
size="sm"
variant="solid"
>2</UiButton>
<UiButton
square
size="sm"
variant="ghost"
tone="neutral"
>10</UiButton>
<UiButton
square
size="sm"
variant="ghost"
tone="neutral"
aria-label="Next"
>
<UiIcon
name="chevron-right"
/>
</UiButton>
</UiCluster>;
}<script>
import { UiButton, UiCluster, UiIcon } from "@threadlabs/looma";
</script>
<UiCluster
gap="xs"
>
<UiButton
square
size="sm"
variant="ghost"
tone="neutral"
aria-label="Previous"
>
<UiIcon
name="chevron-left"
/>
</UiButton>
<UiButton
square
size="sm"
variant="ghost"
tone="neutral"
>1</UiButton>
<UiButton
square
size="sm"
variant="solid"
>2</UiButton>
<UiButton
square
size="sm"
variant="ghost"
tone="neutral"
>10</UiButton>
<UiButton
square
size="sm"
variant="ghost"
tone="neutral"
aria-label="Next"
>
<UiIcon
name="chevron-right"
/>
</UiButton>
</UiCluster>import { Component } from "@angular/core";
import { UiButton, UiCluster, UiIcon } from "@threadlabs/looma";
@Component({
selector: "example-view",
standalone: true,
imports: [UiCluster, UiButton, UiIcon],
template: `
<div
ui-cluster
[gap]="'xs'"
>
<ng-template
ui-button
[square]="true"
[size]="'sm'"
[variant]="'ghost'"
[tone]="'neutral'"
[hnAttributes]="{ 'aria-label': 'Previous' }"
>
<span
ui-icon
name="chevron-left"
></span>
</ng-template>
<ng-template
ui-button
[square]="true"
[size]="'sm'"
[variant]="'ghost'"
[tone]="'neutral'"
>1</ng-template>
<ng-template
ui-button
[square]="true"
[size]="'sm'"
[variant]="'solid'"
>2</ng-template>
<ng-template
ui-button
[square]="true"
[size]="'sm'"
[variant]="'ghost'"
[tone]="'neutral'"
>10</ng-template>
<ng-template
ui-button
[square]="true"
[size]="'sm'"
[variant]="'ghost'"
[tone]="'neutral'"
[hnAttributes]="{ 'aria-label': 'Next' }"
>
<span
ui-icon
name="chevron-right"
></span>
</ng-template>
</div>
`,
})
export default class Example {}card action
Button's card variant keeps its tone palette and places top-aligned icon and content beside a centered action. The action slot defaults to a caret.
Code
<link
rel="component"
href="@threadlabs/looma/components/ui-stack/ui-stack.html"
>
<link
rel="component"
href="@threadlabs/looma/components/ui-button/ui-button.html"
>
<link
rel="component"
href="@threadlabs/looma/components/ui-icon/ui-icon.html"
>
<ui-stack
gap="s"
>
<ui-button
variant="card"
tone="accent"
>
<ui-icon
slot="icon"
name="book-user"
aria-hidden="true"
></ui-icon>
Read the latest project notes and decisions
</ui-button>
<ui-button
variant="card"
tone="neutral"
>Open document history</ui-button>
<ui-button
variant="card"
tone="warning"
>
<ui-icon
slot="icon"
name="triangle-alert"
aria-hidden="true"
></ui-icon>
Inspect items that need attention
<ui-icon
slot="action"
name="chevron-down"
aria-hidden="true"
></ui-icon>
</ui-button>
</ui-stack><script setup>
import { UiButton, UiIcon, UiStack } from "@threadlabs/looma";
</script>
<template>
<UiStack
gap="s"
>
<UiButton
variant="card"
tone="accent"
><template #icon>
<UiIcon
name="book-user"
aria-hidden="true"
/>
</template>Read the latest project notes and decisions</UiButton>
<UiButton
variant="card"
tone="neutral"
>Open document history</UiButton>
<UiButton
variant="card"
tone="warning"
><template #icon>
<UiIcon
name="triangle-alert"
aria-hidden="true"
/>
</template>Inspect items that need attention<template #action>
<UiIcon
name="chevron-down"
aria-hidden="true"
/>
</template></UiButton>
</UiStack>
</template>import { UiButton, UiIcon, UiStack } from "@threadlabs/looma";
export default function Example() {
return <UiStack
gap="s"
>
<UiButton
variant="card"
tone="accent"
slots={{
icon: <UiIcon
name="book-user"
aria-hidden="true"
/>,
}}
>{"Read the latest project notes and decisions"}</UiButton>
<UiButton
variant="card"
tone="neutral"
>Open document history</UiButton>
<UiButton
variant="card"
tone="warning"
slots={{
icon: <UiIcon
name="triangle-alert"
aria-hidden="true"
/>,
action: <UiIcon
name="chevron-down"
aria-hidden="true"
/>,
}}
>Inspect items that need attention</UiButton>
</UiStack>;
}/** @jsxImportSource preact */
import { UiButton, UiIcon, UiStack } from "@threadlabs/looma";
export default function Example() {
return <UiStack
gap="s"
>
<UiButton
variant="card"
tone="accent"
slots={{
icon: <UiIcon
name="book-user"
aria-hidden="true"
/>,
}}
>{"Read the latest project notes and decisions"}</UiButton>
<UiButton
variant="card"
tone="neutral"
>Open document history</UiButton>
<UiButton
variant="card"
tone="warning"
slots={{
icon: <UiIcon
name="triangle-alert"
aria-hidden="true"
/>,
action: <UiIcon
name="chevron-down"
aria-hidden="true"
/>,
}}
>Inspect items that need attention</UiButton>
</UiStack>;
}<script>
import { UiButton, UiIcon, UiStack } from "@threadlabs/looma";
</script>
{#snippet icon()}
<UiIcon
name="book-user"
aria-hidden="true"
/>
{/snippet}
{#snippet buttonIcon()}
<UiIcon
name="triangle-alert"
aria-hidden="true"
/>
{/snippet}
{#snippet action()}
<UiIcon
name="chevron-down"
aria-hidden="true"
/>
{/snippet}
<UiStack
gap="s"
>
<UiButton
variant="card"
tone="accent"
slots={{ icon }}
>Read the latest project notes and decisions</UiButton>
<UiButton
variant="card"
tone="neutral"
>Open document history</UiButton>
<UiButton
variant="card"
tone="warning"
slots={{ icon: buttonIcon, action }}
>Inspect items that need attention</UiButton>
</UiStack>import { Component } from "@angular/core";
import { UiButton, UiIcon, UiStack } from "@threadlabs/looma";
@Component({
selector: "example-view",
standalone: true,
imports: [UiStack, UiButton, UiIcon],
template: `
<div
ui-stack
[gap]="'s'"
>
<ng-template #icon>
<span
ui-icon
name="book-user"
aria-hidden="true"
></span>
</ng-template>
<ng-template
ui-button
[variant]="'card'"
[tone]="'accent'"
[slots]="{ icon: icon }"
>Read the latest project notes and decisions</ng-template>
<ng-template
ui-button
[variant]="'card'"
[tone]="'neutral'"
>Open document history</ng-template>
<ng-template #buttonIcon>
<span
ui-icon
name="triangle-alert"
aria-hidden="true"
></span>
</ng-template>
<ng-template #action>
<span
ui-icon
name="chevron-down"
aria-hidden="true"
></span>
</ng-template>
<ng-template
ui-button
[variant]="'card'"
[tone]="'warning'"
[slots]="{ icon: buttonIcon, action: action }"
>Inspect items that need attention</ng-template>
</div>
`,
})
export default class Example {}Value picker
A custom value picker shares Input and Select's quiet edge and height, with a slight resting lift.
Code
<link
rel="component"
href="@threadlabs/looma/components/ui-cluster/ui-cluster.html"
>
<link
rel="component"
href="@threadlabs/looma/components/ui-input/ui-input.html"
>
<link
rel="component"
href="@threadlabs/looma/components/ui-select/ui-select.html"
>
<link
rel="component"
href="@threadlabs/looma/components/ui-button/ui-button.html"
>
<link
rel="component"
href="@threadlabs/looma/components/ui-icon/ui-icon.html"
>
<ui-cluster>
<ui-input
aria-label="Name"
value="General"
></ui-input>
<ui-select
aria-label="Category"
>
<option>General</option>
</ui-select>
<ui-button
variant="field"
aria-label="Choose a color"
aria-expanded="false"
>Choose color <ui-icon
name="chevron-down"
></ui-icon></ui-button>
</ui-cluster><script setup>
import { UiButton, UiCluster, UiIcon, UiInput, UiSelect } from "@threadlabs/looma";
</script>
<template>
<UiCluster>
<UiInput
aria-label="Name"
value="General"
/>
<UiSelect
aria-label="Category"
>
<option>General</option>
</UiSelect>
<UiButton
variant="field"
aria-label="Choose a color"
aria-expanded="false"
>Choose color <UiIcon
name="chevron-down"
/></UiButton>
</UiCluster>
</template>import { UiButton, UiCluster, UiIcon, UiInput, UiSelect } from "@threadlabs/looma";
export default function Example() {
return <UiCluster>
<UiInput
aria-label="Name"
value="General"
/>
<UiSelect
aria-label="Category"
>
<option>General</option>
</UiSelect>
<UiButton
variant="field"
aria-label="Choose a color"
aria-expanded="false"
>Choose color <UiIcon
name="chevron-down"
/></UiButton>
</UiCluster>;
}/** @jsxImportSource preact */
import { UiButton, UiCluster, UiIcon, UiInput, UiSelect } from "@threadlabs/looma";
export default function Example() {
return <UiCluster>
<UiInput
aria-label="Name"
value="General"
/>
<UiSelect
aria-label="Category"
>
<option>General</option>
</UiSelect>
<UiButton
variant="field"
aria-label="Choose a color"
aria-expanded="false"
>Choose color <UiIcon
name="chevron-down"
/></UiButton>
</UiCluster>;
}<script>
import { UiButton, UiCluster, UiIcon, UiInput, UiSelect } from "@threadlabs/looma";
</script>
<UiCluster>
<UiInput
aria-label="Name"
value="General"
/>
<UiSelect
aria-label="Category"
>
<option>General</option>
</UiSelect>
<UiButton
variant="field"
aria-label="Choose a color"
aria-expanded="false"
>Choose color <UiIcon
name="chevron-down"
/></UiButton>
</UiCluster>import { Component } from "@angular/core";
import { UiButton, UiCluster, UiIcon, UiInput, UiSelect } from "@threadlabs/looma";
@Component({
selector: "example-view",
standalone: true,
imports: [UiCluster, UiInput, UiSelect, UiButton, UiIcon],
template: `
<div
ui-cluster
>
<input
ui-input
aria-label="Name"
[value]="'General'"
>
<select
ui-select
aria-label="Category"
>
<option>General</option>
</select>
<ng-template
ui-button
[variant]="'field'"
[hnAttributes]="{ 'aria-label': 'Choose a color', 'aria-expanded': 'false' }"
>Choose color <span
ui-icon
name="chevron-down"
></span></ng-template>
</div>
`,
})
export default class Example {}Appearance and tone
Appearance controls emphasis; tone expresses intent. Semantic and optional supporting brand tones work as solid, outline and quiet actions, including solid neutral. Icon actions use the same palette.
Code
<link
rel="component"
href="@threadlabs/looma/components/ui-stack/ui-stack.html"
>
<link
rel="component"
href="@threadlabs/looma/components/ui-cluster/ui-cluster.html"
>
<link
rel="component"
href="@threadlabs/looma/components/ui-button/ui-button.html"
>
<link
rel="component"
href="@threadlabs/looma/components/ui-icon-button/ui-icon-button.html"
>
<link
rel="component"
href="@threadlabs/looma/components/ui-icon/ui-icon.html"
>
<ui-stack>
<ui-cluster>
<ui-button
variant="solid"
tone="accent"
>Send memo</ui-button>
<ui-button
variant="solid"
tone="neutral"
>File notes</ui-button>
<ui-button
variant="solid"
tone="danger"
>Delete draft</ui-button>
<ui-button
variant="solid"
tone="success"
>Approve leave</ui-button>
<ui-button
variant="solid"
tone="warning"
>Review route</ui-button>
<ui-button
variant="solid"
tone="info"
>See briefing</ui-button>
</ui-cluster>
<ui-cluster>
<ui-button
variant="outline"
tone="accent"
>Send memo</ui-button>
<ui-button
variant="outline"
tone="neutral"
>File notes</ui-button>
<ui-button
variant="outline"
tone="danger"
>Delete draft</ui-button>
<ui-button
variant="outline"
tone="success"
>Approve leave</ui-button>
<ui-button
variant="outline"
tone="warning"
>Review route</ui-button>
<ui-button
variant="outline"
tone="info"
>See briefing</ui-button>
</ui-cluster>
<ui-cluster>
<ui-button
variant="ghost"
tone="accent"
>Send memo</ui-button>
<ui-button
variant="ghost"
tone="neutral"
>File notes</ui-button>
<ui-button
variant="ghost"
tone="danger"
>Delete draft</ui-button>
<ui-button
variant="ghost"
tone="success"
>Approve leave</ui-button>
<ui-button
variant="ghost"
tone="warning"
>Review route</ui-button>
<ui-button
variant="ghost"
tone="info"
>See briefing</ui-button>
</ui-cluster>
<ui-cluster>
<ui-icon-button
preset="primary"
match-button
label="Send memo"
>
<ui-icon
name="check"
></ui-icon>
</ui-icon-button>
<ui-icon-button
preset="standard"
match-button
label="File notes"
>
<ui-icon
name="check"
></ui-icon>
</ui-icon-button>
<ui-icon-button
preset="destructive"
match-button
label="Delete draft"
>
<ui-icon
name="check"
></ui-icon>
</ui-icon-button>
<ui-icon-button
variant="solid"
tone="success"
match-button
label="Approve leave"
>
<ui-icon
name="check"
></ui-icon>
</ui-icon-button>
<ui-icon-button
variant="solid"
tone="warning"
match-button
label="Review route"
>
<ui-icon
name="check"
></ui-icon>
</ui-icon-button>
<ui-icon-button
variant="solid"
tone="info"
match-button
label="See briefing"
>
<ui-icon
name="check"
></ui-icon>
</ui-icon-button>
</ui-cluster>
<ui-cluster>
<ui-button
variant="outline"
tone="accent-secondary"
>Explore category</ui-button>
<ui-button
variant="ghost"
tone="accent-tertiary"
>Related collection</ui-button>
</ui-cluster>
</ui-stack><script setup>
import { UiButton, UiCluster, UiIcon, UiIconButton, UiStack } from "@threadlabs/looma";
</script>
<template>
<UiStack>
<UiCluster>
<UiButton
variant="solid"
tone="accent"
>Send memo</UiButton>
<UiButton
variant="solid"
tone="neutral"
>File notes</UiButton>
<UiButton
variant="solid"
tone="danger"
>Delete draft</UiButton>
<UiButton
variant="solid"
tone="success"
>Approve leave</UiButton>
<UiButton
variant="solid"
tone="warning"
>Review route</UiButton>
<UiButton
variant="solid"
tone="info"
>See briefing</UiButton>
</UiCluster>
<UiCluster>
<UiButton
variant="outline"
tone="accent"
>Send memo</UiButton>
<UiButton
variant="outline"
tone="neutral"
>File notes</UiButton>
<UiButton
variant="outline"
tone="danger"
>Delete draft</UiButton>
<UiButton
variant="outline"
tone="success"
>Approve leave</UiButton>
<UiButton
variant="outline"
tone="warning"
>Review route</UiButton>
<UiButton
variant="outline"
tone="info"
>See briefing</UiButton>
</UiCluster>
<UiCluster>
<UiButton
variant="ghost"
tone="accent"
>Send memo</UiButton>
<UiButton
variant="ghost"
tone="neutral"
>File notes</UiButton>
<UiButton
variant="ghost"
tone="danger"
>Delete draft</UiButton>
<UiButton
variant="ghost"
tone="success"
>Approve leave</UiButton>
<UiButton
variant="ghost"
tone="warning"
>Review route</UiButton>
<UiButton
variant="ghost"
tone="info"
>See briefing</UiButton>
</UiCluster>
<UiCluster>
<UiIconButton
preset="primary"
:match-button="true"
label="Send memo"
>
<UiIcon
name="check"
/>
</UiIconButton>
<UiIconButton
preset="standard"
:match-button="true"
label="File notes"
>
<UiIcon
name="check"
/>
</UiIconButton>
<UiIconButton
preset="destructive"
:match-button="true"
label="Delete draft"
>
<UiIcon
name="check"
/>
</UiIconButton>
<UiIconButton
variant="solid"
tone="success"
:match-button="true"
label="Approve leave"
>
<UiIcon
name="check"
/>
</UiIconButton>
<UiIconButton
variant="solid"
tone="warning"
:match-button="true"
label="Review route"
>
<UiIcon
name="check"
/>
</UiIconButton>
<UiIconButton
variant="solid"
tone="info"
:match-button="true"
label="See briefing"
>
<UiIcon
name="check"
/>
</UiIconButton>
</UiCluster>
<UiCluster>
<UiButton
variant="outline"
tone="accent-secondary"
>Explore category</UiButton>
<UiButton
variant="ghost"
tone="accent-tertiary"
>Related collection</UiButton>
</UiCluster>
</UiStack>
</template>import { UiButton, UiCluster, UiIcon, UiIconButton, UiStack } from "@threadlabs/looma";
export default function Example() {
return <UiStack>
<UiCluster>
<UiButton
variant="solid"
tone="accent"
>Send memo</UiButton>
<UiButton
variant="solid"
tone="neutral"
>File notes</UiButton>
<UiButton
variant="solid"
tone="danger"
>Delete draft</UiButton>
<UiButton
variant="solid"
tone="success"
>Approve leave</UiButton>
<UiButton
variant="solid"
tone="warning"
>Review route</UiButton>
<UiButton
variant="solid"
tone="info"
>See briefing</UiButton>
</UiCluster>
<UiCluster>
<UiButton
variant="outline"
tone="accent"
>Send memo</UiButton>
<UiButton
variant="outline"
tone="neutral"
>File notes</UiButton>
<UiButton
variant="outline"
tone="danger"
>Delete draft</UiButton>
<UiButton
variant="outline"
tone="success"
>Approve leave</UiButton>
<UiButton
variant="outline"
tone="warning"
>Review route</UiButton>
<UiButton
variant="outline"
tone="info"
>See briefing</UiButton>
</UiCluster>
<UiCluster>
<UiButton
variant="ghost"
tone="accent"
>Send memo</UiButton>
<UiButton
variant="ghost"
tone="neutral"
>File notes</UiButton>
<UiButton
variant="ghost"
tone="danger"
>Delete draft</UiButton>
<UiButton
variant="ghost"
tone="success"
>Approve leave</UiButton>
<UiButton
variant="ghost"
tone="warning"
>Review route</UiButton>
<UiButton
variant="ghost"
tone="info"
>See briefing</UiButton>
</UiCluster>
<UiCluster>
<UiIconButton
preset="primary"
matchButton
label="Send memo"
>
<UiIcon
name="check"
/>
</UiIconButton>
<UiIconButton
preset="standard"
matchButton
label="File notes"
>
<UiIcon
name="check"
/>
</UiIconButton>
<UiIconButton
preset="destructive"
matchButton
label="Delete draft"
>
<UiIcon
name="check"
/>
</UiIconButton>
<UiIconButton
variant="solid"
tone="success"
matchButton
label="Approve leave"
>
<UiIcon
name="check"
/>
</UiIconButton>
<UiIconButton
variant="solid"
tone="warning"
matchButton
label="Review route"
>
<UiIcon
name="check"
/>
</UiIconButton>
<UiIconButton
variant="solid"
tone="info"
matchButton
label="See briefing"
>
<UiIcon
name="check"
/>
</UiIconButton>
</UiCluster>
<UiCluster>
<UiButton
variant="outline"
tone="accent-secondary"
>Explore category</UiButton>
<UiButton
variant="ghost"
tone="accent-tertiary"
>Related collection</UiButton>
</UiCluster>
</UiStack>;
}/** @jsxImportSource preact */
import { UiButton, UiCluster, UiIcon, UiIconButton, UiStack } from "@threadlabs/looma";
export default function Example() {
return <UiStack>
<UiCluster>
<UiButton
variant="solid"
tone="accent"
>Send memo</UiButton>
<UiButton
variant="solid"
tone="neutral"
>File notes</UiButton>
<UiButton
variant="solid"
tone="danger"
>Delete draft</UiButton>
<UiButton
variant="solid"
tone="success"
>Approve leave</UiButton>
<UiButton
variant="solid"
tone="warning"
>Review route</UiButton>
<UiButton
variant="solid"
tone="info"
>See briefing</UiButton>
</UiCluster>
<UiCluster>
<UiButton
variant="outline"
tone="accent"
>Send memo</UiButton>
<UiButton
variant="outline"
tone="neutral"
>File notes</UiButton>
<UiButton
variant="outline"
tone="danger"
>Delete draft</UiButton>
<UiButton
variant="outline"
tone="success"
>Approve leave</UiButton>
<UiButton
variant="outline"
tone="warning"
>Review route</UiButton>
<UiButton
variant="outline"
tone="info"
>See briefing</UiButton>
</UiCluster>
<UiCluster>
<UiButton
variant="ghost"
tone="accent"
>Send memo</UiButton>
<UiButton
variant="ghost"
tone="neutral"
>File notes</UiButton>
<UiButton
variant="ghost"
tone="danger"
>Delete draft</UiButton>
<UiButton
variant="ghost"
tone="success"
>Approve leave</UiButton>
<UiButton
variant="ghost"
tone="warning"
>Review route</UiButton>
<UiButton
variant="ghost"
tone="info"
>See briefing</UiButton>
</UiCluster>
<UiCluster>
<UiIconButton
preset="primary"
matchButton
label="Send memo"
>
<UiIcon
name="check"
/>
</UiIconButton>
<UiIconButton
preset="standard"
matchButton
label="File notes"
>
<UiIcon
name="check"
/>
</UiIconButton>
<UiIconButton
preset="destructive"
matchButton
label="Delete draft"
>
<UiIcon
name="check"
/>
</UiIconButton>
<UiIconButton
variant="solid"
tone="success"
matchButton
label="Approve leave"
>
<UiIcon
name="check"
/>
</UiIconButton>
<UiIconButton
variant="solid"
tone="warning"
matchButton
label="Review route"
>
<UiIcon
name="check"
/>
</UiIconButton>
<UiIconButton
variant="solid"
tone="info"
matchButton
label="See briefing"
>
<UiIcon
name="check"
/>
</UiIconButton>
</UiCluster>
<UiCluster>
<UiButton
variant="outline"
tone="accent-secondary"
>Explore category</UiButton>
<UiButton
variant="ghost"
tone="accent-tertiary"
>Related collection</UiButton>
</UiCluster>
</UiStack>;
}<script>
import { UiButton, UiCluster, UiIcon, UiIconButton, UiStack } from "@threadlabs/looma";
</script>
<UiStack>
<UiCluster>
<UiButton
variant="solid"
tone="accent"
>Send memo</UiButton>
<UiButton
variant="solid"
tone="neutral"
>File notes</UiButton>
<UiButton
variant="solid"
tone="danger"
>Delete draft</UiButton>
<UiButton
variant="solid"
tone="success"
>Approve leave</UiButton>
<UiButton
variant="solid"
tone="warning"
>Review route</UiButton>
<UiButton
variant="solid"
tone="info"
>See briefing</UiButton>
</UiCluster>
<UiCluster>
<UiButton
variant="outline"
tone="accent"
>Send memo</UiButton>
<UiButton
variant="outline"
tone="neutral"
>File notes</UiButton>
<UiButton
variant="outline"
tone="danger"
>Delete draft</UiButton>
<UiButton
variant="outline"
tone="success"
>Approve leave</UiButton>
<UiButton
variant="outline"
tone="warning"
>Review route</UiButton>
<UiButton
variant="outline"
tone="info"
>See briefing</UiButton>
</UiCluster>
<UiCluster>
<UiButton
variant="ghost"
tone="accent"
>Send memo</UiButton>
<UiButton
variant="ghost"
tone="neutral"
>File notes</UiButton>
<UiButton
variant="ghost"
tone="danger"
>Delete draft</UiButton>
<UiButton
variant="ghost"
tone="success"
>Approve leave</UiButton>
<UiButton
variant="ghost"
tone="warning"
>Review route</UiButton>
<UiButton
variant="ghost"
tone="info"
>See briefing</UiButton>
</UiCluster>
<UiCluster>
<UiIconButton
preset="primary"
matchButton
label="Send memo"
>
<UiIcon
name="check"
/>
</UiIconButton>
<UiIconButton
preset="standard"
matchButton
label="File notes"
>
<UiIcon
name="check"
/>
</UiIconButton>
<UiIconButton
preset="destructive"
matchButton
label="Delete draft"
>
<UiIcon
name="check"
/>
</UiIconButton>
<UiIconButton
variant="solid"
tone="success"
matchButton
label="Approve leave"
>
<UiIcon
name="check"
/>
</UiIconButton>
<UiIconButton
variant="solid"
tone="warning"
matchButton
label="Review route"
>
<UiIcon
name="check"
/>
</UiIconButton>
<UiIconButton
variant="solid"
tone="info"
matchButton
label="See briefing"
>
<UiIcon
name="check"
/>
</UiIconButton>
</UiCluster>
<UiCluster>
<UiButton
variant="outline"
tone="accent-secondary"
>Explore category</UiButton>
<UiButton
variant="ghost"
tone="accent-tertiary"
>Related collection</UiButton>
</UiCluster>
</UiStack>import { Component } from "@angular/core";
import { UiButton, UiCluster, UiIcon, UiIconButton, UiStack } from "@threadlabs/looma";
@Component({
selector: "example-view",
standalone: true,
imports: [UiStack, UiCluster, UiButton, UiIconButton, UiIcon],
template: `
<div
ui-stack
>
<div
ui-cluster
>
<ng-template
ui-button
[variant]="'solid'"
[tone]="'accent'"
>Send memo</ng-template>
<ng-template
ui-button
[variant]="'solid'"
[tone]="'neutral'"
>File notes</ng-template>
<ng-template
ui-button
[variant]="'solid'"
[tone]="'danger'"
>Delete draft</ng-template>
<ng-template
ui-button
[variant]="'solid'"
[tone]="'success'"
>Approve leave</ng-template>
<ng-template
ui-button
[variant]="'solid'"
[tone]="'warning'"
>Review route</ng-template>
<ng-template
ui-button
[variant]="'solid'"
[tone]="'info'"
>See briefing</ng-template>
</div>
<div
ui-cluster
>
<ng-template
ui-button
[variant]="'outline'"
[tone]="'accent'"
>Send memo</ng-template>
<ng-template
ui-button
[variant]="'outline'"
[tone]="'neutral'"
>File notes</ng-template>
<ng-template
ui-button
[variant]="'outline'"
[tone]="'danger'"
>Delete draft</ng-template>
<ng-template
ui-button
[variant]="'outline'"
[tone]="'success'"
>Approve leave</ng-template>
<ng-template
ui-button
[variant]="'outline'"
[tone]="'warning'"
>Review route</ng-template>
<ng-template
ui-button
[variant]="'outline'"
[tone]="'info'"
>See briefing</ng-template>
</div>
<div
ui-cluster
>
<ng-template
ui-button
[variant]="'ghost'"
[tone]="'accent'"
>Send memo</ng-template>
<ng-template
ui-button
[variant]="'ghost'"
[tone]="'neutral'"
>File notes</ng-template>
<ng-template
ui-button
[variant]="'ghost'"
[tone]="'danger'"
>Delete draft</ng-template>
<ng-template
ui-button
[variant]="'ghost'"
[tone]="'success'"
>Approve leave</ng-template>
<ng-template
ui-button
[variant]="'ghost'"
[tone]="'warning'"
>Review route</ng-template>
<ng-template
ui-button
[variant]="'ghost'"
[tone]="'info'"
>See briefing</ng-template>
</div>
<div
ui-cluster
>
<button
ui-icon-button
[preset]="'primary'"
[matchButton]="true"
[label]="'Send memo'"
>
<span
ui-icon
name="check"
></span>
</button>
<button
ui-icon-button
[preset]="'standard'"
[matchButton]="true"
[label]="'File notes'"
>
<span
ui-icon
name="check"
></span>
</button>
<button
ui-icon-button
[preset]="'destructive'"
[matchButton]="true"
[label]="'Delete draft'"
>
<span
ui-icon
name="check"
></span>
</button>
<button
ui-icon-button
[variant]="'solid'"
[tone]="'success'"
[matchButton]="true"
[label]="'Approve leave'"
>
<span
ui-icon
name="check"
></span>
</button>
<button
ui-icon-button
[variant]="'solid'"
[tone]="'warning'"
[matchButton]="true"
[label]="'Review route'"
>
<span
ui-icon
name="check"
></span>
</button>
<button
ui-icon-button
[variant]="'solid'"
[tone]="'info'"
[matchButton]="true"
[label]="'See briefing'"
>
<span
ui-icon
name="check"
></span>
</button>
</div>
<div
ui-cluster
>
<ng-template
ui-button
[variant]="'outline'"
[tone]="'accent-secondary'"
>Explore category</ng-template>
<ng-template
ui-button
[variant]="'ghost'"
[tone]="'accent-tertiary'"
>Related collection</ng-template>
</div>
</div>
`,
})
export default class Example {}Interaction emphasis
Keep a choice neutral at rest, then use accent on hover and press. Interaction tone and variant inherit the resting settings unless supplied; pressed feedback remains stronger than hover.
Code
<link
rel="component"
href="@threadlabs/looma/components/ui-stack/ui-stack.html"
>
<link
rel="component"
href="@threadlabs/looma/components/ui-button/ui-button.html"
>
<ui-stack
gap="s"
>
<ui-button
tone="neutral"
variant="outline"
interaction-tone="accent"
align="start"
stretch
> Choose a project </ui-button>
<ui-button
tone="neutral"
variant="ghost"
interaction-tone="accent"
interaction-variant="outline"
> Browse projects </ui-button>
</ui-stack><script setup>
import { UiButton, UiStack } from "@threadlabs/looma";
</script>
<template>
<UiStack
gap="s"
>
<UiButton
tone="neutral"
variant="outline"
interaction-tone="accent"
align="start"
:stretch="true"
> Choose a project </UiButton>
<UiButton
tone="neutral"
variant="ghost"
interaction-tone="accent"
interaction-variant="outline"
> Browse projects </UiButton>
</UiStack>
</template>import { UiButton, UiStack } from "@threadlabs/looma";
export default function Example() {
return <UiStack
gap="s"
>
<UiButton
tone="neutral"
variant="outline"
interactionTone="accent"
align="start"
stretch
>{" Choose a project "}</UiButton>
<UiButton
tone="neutral"
variant="ghost"
interactionTone="accent"
interactionVariant="outline"
>{" Browse projects "}</UiButton>
</UiStack>;
}/** @jsxImportSource preact */
import { UiButton, UiStack } from "@threadlabs/looma";
export default function Example() {
return <UiStack
gap="s"
>
<UiButton
tone="neutral"
variant="outline"
interactionTone="accent"
align="start"
stretch
>{" Choose a project "}</UiButton>
<UiButton
tone="neutral"
variant="ghost"
interactionTone="accent"
interactionVariant="outline"
>{" Browse projects "}</UiButton>
</UiStack>;
}<script>
import { UiButton, UiStack } from "@threadlabs/looma";
</script>
<UiStack
gap="s"
>
<UiButton
tone="neutral"
variant="outline"
interactionTone="accent"
align="start"
stretch
> Choose a project </UiButton>
<UiButton
tone="neutral"
variant="ghost"
interactionTone="accent"
interactionVariant="outline"
> Browse projects </UiButton>
</UiStack>import { Component } from "@angular/core";
import { UiButton, UiStack } from "@threadlabs/looma";
@Component({
selector: "example-view",
standalone: true,
imports: [UiStack, UiButton],
template: `
<div
ui-stack
[gap]="'s'"
>
<ng-template
ui-button
[tone]="'neutral'"
[variant]="'outline'"
[interactionTone]="'accent'"
[align]="'start'"
[stretch]="true"
> Choose a project </ng-template>
<ng-template
ui-button
[tone]="'neutral'"
[variant]="'ghost'"
[interactionTone]="'accent'"
[interactionVariant]="'outline'"
> Browse projects </ng-template>
</div>
`,
})
export default class Example {}API
Package: @threadlabs/looma · Native root: button
Attributes
| Name | Description | Property | Type | Default | Allowed values |
|---|---|---|---|---|---|
align | Content alignment. start lays the content out like a list option: from the start edge, with start-aligned text. | align | keyword | center | center, start |
disabled | Makes the button unavailable: it cannot be pressed, uses muted neutral colors, and loses its raised look. An unselected disabled ghost keeps its transparent surface; a selected ghost retains a muted selection wash. A disabled link (with href) drops its href and states aria-disabled="true" instead, because a link has no native disabled state. | disabled | boolean | false | — |
href | The link's destination. Supplying href automatically renders a native link instead of a button, including an empty href for the current document. A disabled link drops its href and states aria-disabled="true", so it cannot be followed. | href | string | — | — |
interaction-tone | The action palette while hovered or pressed. inherit follows tone and preset. Choose a different tone for transient emphasis, such as a neutral choice that uses accent feedback. Hover and pressed keep their distinct shared treatments; disabled and loading actions keep their resting treatment. | interactionTone | keyword | inherit | inherit, accent, accent-secondary, accent-tertiary, neutral, danger, success, warning, info |
interaction-variant | The paint while hovered or pressed. inherit follows variant and preset. outline, solid and ghost change emphasis without changing the control's layout, size or content. The shared hover and pressed treatments remain distinct. | interactionVariant | keyword | inherit | inherit, outline, solid, ghost |
loading | Keeps the action focusable and its label visible while work is in progress. It shows a decorative spinner, states aria-disabled and aria-busy, and prevents activation or form submission until cleared. | loading | boolean | false | — |
pending | Deprecated alias for loading. | pending | boolean | false | — |
preset | A shortcut that sets appearance and tone together: primary is solid accent, standard is solid neutral, quiet is ghost neutral, and destructive is solid danger. A named preset takes precedence over variant and tone. Leave it at none to choose variant and tone independently. | preset | keyword | none | none, primary, standard, quiet, destructive |
rel | The link's relationship to its destination, as on a native link. Only meaningful with href. | rel | string | — | — |
selected | Keeps a ghost choice highlighted with the shared selection surface and text colors, matching selected menu choices independently of its action tone. Composite controls own the appropriate selection semantics, such as aria-selected on a grid cell; this visual state does not make the button a toggle. | selected | boolean | false | — |
shape | rounded uses the theme's action radius; pill rounds the ends fully, for a compact choice such as a status or a person. | shape | keyword | rounded | rounded, pill |
size | Height, padding, and type size. xs is 1.5rem with the smallest text, for a control inside a line of small text; sm is the small control height (2rem by default) with tighter padding and smaller text, md is the standard control height (2.5rem), and lg is taller (3rem) with roomier padding. Visible sizes stay the same on touch. Inline xs and link actions can gain an adjustable invisible hit area. | size | keyword | md | xs, sm, md, lg |
square | Gives short labels and icons the same square minimum footprint at each size. Longer labels grow naturally. Applies to boxed actions; link and card variants keep their normal layout. | square | boolean | false | — |
stretch | Fills the inline size of its container. | stretch | boolean | false | — |
target | Where a link opens, as on a native link. Only meaningful with href. | target | string | — | — |
tone | Which colour the button speaks in. It applies to every variant, so an outline, a ghost, and a solid in the same tone are the same action at three volumes: tone="danger" variant="outline" is a destructive secondary action. neutral is the quiet one, for a button that should not claim a colour. The field variant always uses neutral field colors. Supporting brand families use accent-secondary and accent-tertiary; their usable colors derive from the theme, and unset families follow the primary accent. | tone | keyword | neutral | accent, accent-secondary, accent-tertiary, neutral, danger, success, warning, info |
type | The button's type, as on a native button. button by default, so it never submits a form by accident. A link has no type. | type | keyword | button | button, submit, reset |
variant | Emphasis: how loudly the button asks. solid fills with its tone, outline draws its tone at the edge over a wash of it, ghost carries only text until it is hovered or selected, and link is an inline text action that reads as a link. danger is solid in the danger tone, kept for the call sites that name it. card uses the same tone on a full-width action with an icon slot, wrapping content, and a centered action slot. field opens a custom value picker: it shares Select's quiet outline, neutral text and slightly raised surface, independently of action tone. | variant | keyword | outline | outline, solid, danger, ghost, link, card, field |
Framework props
| Name | Type | Default | Allowed values |
|---|---|---|---|
align | "center" | "start" | center | center, start |
disabled | boolean | false | — |
href | string | — | — |
interactionTone | "inherit" | "accent" | "accent-secondary" | "accent-tertiary" | "neutral" | "danger" | "success" | "warning" | "info" | inherit | inherit, accent, accent-secondary, accent-tertiary, neutral, danger, success, warning, info |
interactionVariant | "inherit" | "outline" | "solid" | "ghost" | inherit | inherit, outline, solid, ghost |
loading | boolean | false | — |
pending | boolean | false | — |
preset | "none" | "primary" | "standard" | "quiet" | "destructive" | none | none, primary, standard, quiet, destructive |
rel | string | — | — |
selected | boolean | false | — |
shape | "rounded" | "pill" | rounded | rounded, pill |
size | "xs" | "sm" | "md" | "lg" | md | xs, sm, md, lg |
square | boolean | false | — |
stretch | boolean | false | — |
target | string | — | — |
tone | "accent" | "accent-secondary" | "accent-tertiary" | "neutral" | "danger" | "success" | "warning" | "info" | neutral | accent, accent-secondary, accent-tertiary, neutral, danger, success, warning, info |
type | "button" | "submit" | "reset" | button | button, submit, reset |
variant | "outline" | "solid" | "danger" | "ghost" | "link" | "card" | "field" | outline | outline, solid, danger, ghost, link, card, field |
Events
No events.
Slots
| Name | Purpose |
|---|---|
icon | Named content for the icon region. |
default | Default child content. |
action | Named content for the action region. |
badge | Named content for the badge region. |
Design tokens
Set shared theme properties on a theme boundary. Component hooks apply only to their owning component.
Component tokens
| Token | Declared values | Fallback |
|---|---|---|
--_tone-outline-border | var(--ui-accent-outline-border, var(--ui-accent-subtle-text)) | var(--ui-accent-secondary-outline-border, var(--ui-accent-secondary-subtle-text)) | var(--ui-accent-tertiary-outline-border, var(--ui-accent-tertiary-subtle-text)) | var(--ui-control-border) | var(--ui-danger-outline-border, var(--ui-danger-subtle-text)) | var(--ui-success-outline-border, var(--ui-success-subtle-text)) | var(--ui-warning-outline-border, var(--ui-warning-subtle-text)) | var(--ui-info-outline-border, var(--ui-info-subtle-text)) | var(--_hue-text) | — |
--ui-action-shadow | var(--_ui-action-edge), 0 1px 2px light-dark(rgb(0 0 0 / 0.10), rgb(0 0 0 / 0.20)) | — |
--ui-button-active-surface | oklch(from var(--_tone) l c h / calc(18% * var(--ui-tonal-opacity, 1))) | var(--ui-neutral-active) | var(--_tone-active) | var(--ui-neutral-active) | oklch(from var(--_tone) l c h / calc(18% * var(--ui-tonal-opacity, 1))) | var(--ui-neutral-active) |
--ui-button-border | var(--_hue-text) | var(--ui-accent-border, var(--ui-accent)) | var(--ui-accent-secondary-border, var(--ui-accent-secondary)) | var(--ui-accent-tertiary-border, var(--ui-accent-tertiary)) | var(--ui-control-border, var(--ui-neutral-surface)) | var(--ui-danger-border, var(--ui-danger)) | var(--ui-success-border, var(--ui-success)) | var(--ui-warning-border, var(--ui-warning)) | var(--ui-info-border, var(--ui-info)) | var(--_tone-outline-border, var(--_tone-text)) | var(--ui-border) | var(--ui-control-border) | var(--ui-control-border, var(--ui-border-strong)) |
--ui-button-disabled-filter | — | var(--ui-disabled-filter) |
--ui-button-disabled-opacity | — | 1 |
--ui-button-ghost-active-surface | — | oklch(from var(--_tone) l c h / 18%) | var(--ui-selection-surface) |
--ui-button-ghost-hover-surface | var(--ui-accent-ghost-hover) | var(--ui-accent-secondary-ghost-hover) | var(--ui-accent-tertiary-ghost-hover) | var(--ui-neutral-ghost-hover) | var(--ui-danger-ghost-hover) | var(--ui-success-ghost-hover) | var(--ui-warning-ghost-hover) | var(--ui-info-ghost-hover) | — |
--ui-button-ghost-text | var(--_hue-text) | var(--ui-selection-text) |
--ui-button-hover-border | var(--ui-accent-outline-border, var(--ui-accent-subtle-text)) | var(--ui-accent-secondary-outline-border, var(--ui-accent-secondary-subtle-text)) | var(--ui-accent-tertiary-outline-border, var(--ui-accent-tertiary-subtle-text)) | var(--ui-control-border) | var(--ui-danger-outline-border, var(--ui-danger-subtle-text)) | var(--ui-success-outline-border, var(--ui-success-subtle-text)) | var(--ui-warning-outline-border, var(--ui-warning-subtle-text)) | var(--ui-info-outline-border, var(--ui-info-subtle-text)) | var(--_hue-text) | var(--ui-accent-hover-border, var(--ui-accent-hover)) | var(--ui-accent-secondary-hover-border, var(--ui-accent-secondary-hover)) | var(--ui-accent-tertiary-hover-border, var(--ui-accent-tertiary-hover)) | var(--ui-control-border-hover, var(--ui-neutral-hover)) | var(--ui-danger-hover-border, var(--ui-danger-hover)) | var(--ui-success-hover-border, var(--ui-success-hover)) | var(--ui-warning-hover-border, var(--ui-warning-hover)) | var(--ui-info-hover-border, var(--ui-info-hover)) | var(--_tone-outline-border) | var(--ui-control-border-hover) | var(--_tone-text) | var(--ui-border-strong) | var(--ui-border-strong) | var(--ui-control-border-hover) | var(--ui-control-border-hover, var(--ui-text-secondary)) |
--ui-button-hover-surface | var(--_tone-hover) | var(--ui-neutral-hover) | transparent | oklch(from var(--_tone-text) l c h / calc(12% * var(--ui-tonal-opacity, 1))) | var(--ui-neutral-hover) | var(--ui-control-surface, var(--ui-surface-elevated)) |
--ui-button-link-hover-text | var(--_hue-text) | var(--ui-text-primary) |
--ui-button-link-text | — | var(--ui-text-secondary) |
--ui-button-min-block-size | — | var(--ui-control-size-md) |
--ui-button-radius | — | var(--ui-action-radius, var(--ui-radius-md)) | var(--ui-radius-round) | var(--ui-field-radius, var(--ui-radius-md)) |
--ui-button-shadow | var(--ui-shadow-sm) | var(--ui-pressed) | var(--ui-action-shadow, var(--_ui-action-shadow)) | var(--ui-neutral-shadow) |
--ui-button-solid-shadow | — | var(--ui-action-shadow, var(--_ui-action-shadow)) | var(--ui-button-shadow, var(--ui-neutral-shadow)) |
--ui-button-surface | — | oklch(from var(--_tone) l c h / calc(5% * var(--ui-tonal-opacity, 1))) | transparent | var(--ui-neutral-surface) | var(--ui-control-surface, var(--ui-surface-elevated)) |
--ui-button-text | var(--_hue-text) | var(--ui-text) | var(--ui-text-primary) |
--ui-button-white-space | — | inherit |
--ui-neutral-hover-highlight | var(--ui-accent-highlight, none) | var(--ui-accent-secondary-highlight, none) | var(--ui-accent-tertiary-highlight, none) | var(--ui-neutral-highlight, none) | var(--ui-danger-highlight, none) | var(--ui-success-highlight, none) | var(--ui-warning-highlight, none) | var(--ui-info-highlight, none) | — |
Shared tokens
| Token | Fallback |
|---|---|
--ui-accent | — |
--ui-accent-active | — |
--ui-accent-active-border | var(--ui-accent-active) |
--ui-accent-border | var(--ui-accent) |
--ui-accent-ghost-hover | — |
--ui-accent-glow | 0 0 transparent |
--ui-accent-highlight | none |
--ui-accent-hover | — |
--ui-accent-hover-border | var(--ui-accent-hover) |
--ui-accent-hover-highlight | none |
--ui-accent-outline-border | var(--ui-accent-subtle-text) |
--ui-accent-secondary | — |
--ui-accent-secondary-active | — |
--ui-accent-secondary-active-border | var(--ui-accent-secondary-active) |
--ui-accent-secondary-border | var(--ui-accent-secondary) |
--ui-accent-secondary-ghost-hover | — |
--ui-accent-secondary-glow | 0 0 transparent |
--ui-accent-secondary-highlight | none |
--ui-accent-secondary-hover | — |
--ui-accent-secondary-hover-border | var(--ui-accent-secondary-hover) |
--ui-accent-secondary-hover-highlight | none |
--ui-accent-secondary-on-strong | — |
--ui-accent-secondary-outline-border | var(--ui-accent-secondary-subtle-text) |
--ui-accent-secondary-subtle-text | — |
--ui-accent-secondary-wash | — |
--ui-accent-secondary-wash-hover | — |
--ui-accent-solid | — |
--ui-accent-subtle-text | — |
--ui-accent-tertiary | — |
--ui-accent-tertiary-active | — |
--ui-accent-tertiary-active-border | var(--ui-accent-tertiary-active) |
--ui-accent-tertiary-border | var(--ui-accent-tertiary) |
--ui-accent-tertiary-ghost-hover | — |
--ui-accent-tertiary-glow | 0 0 transparent |
--ui-accent-tertiary-highlight | none |
--ui-accent-tertiary-hover | — |
--ui-accent-tertiary-hover-border | var(--ui-accent-tertiary-hover) |
--ui-accent-tertiary-hover-highlight | none |
--ui-accent-tertiary-on-strong | — |
--ui-accent-tertiary-outline-border | var(--ui-accent-tertiary-subtle-text) |
--ui-accent-tertiary-subtle-text | — |
--ui-accent-tertiary-wash | — |
--ui-accent-tertiary-wash-hover | — |
--ui-accent-wash | — |
--ui-accent-wash-hover | — |
--ui-action-edge | inset var(--_ui-action-start) 1px 0 light-dark(rgb(255 255 255 / 0.08), rgb(255 255 255 / 0.06)),
inset calc(-1 * var(--_ui-action-start)) -1px 0 light-dark(rgb(0 0 0 / 0.08), rgb(0 0 0 / 0.08)) |
--ui-action-inset-lg | var(--ui-space-4) |
--ui-action-inset-md | var(--ui-space-3) |
--ui-action-inset-sm | var(--ui-space-2) |
--ui-action-radius | var(--ui-radius-md) |
--ui-border | — |
--ui-border-strong | — |
--ui-border-width | — |
--ui-control-border | var(--ui-neutral-surface) | var(--ui-border-strong) |
--ui-control-border-hover | var(--ui-neutral-hover) | var(--ui-neutral-active) | var(--ui-text-secondary) |
--ui-control-focus | var(--ui-accent-solid) |
--ui-control-focus-halo-shadow | — |
--ui-control-inset-block-lg | var(--ui-space-3) |
--ui-control-inset-block-md | var(--ui-space-2) |
--ui-control-inset-block-sm | var(--ui-space-1) |
--ui-control-min-block-size | — |
--ui-control-size-lg | — |
--ui-control-size-md | — |
--ui-control-size-sm | — |
--ui-control-size-xs | — |
--ui-control-surface | var(--ui-surface-elevated) |
--ui-danger | — |
--ui-danger-active | var(--ui-danger-hover) |
--ui-danger-active-border | var(--ui-danger-active) |
--ui-danger-border | var(--ui-danger) |
--ui-danger-ghost-hover | — |
--ui-danger-glow | 0 0 transparent |
--ui-danger-highlight | none |
--ui-danger-hover | — |
--ui-danger-hover-border | var(--ui-danger-hover) |
--ui-danger-hover-highlight | none |
--ui-danger-outline-border | var(--ui-danger-subtle-text) |
--ui-danger-subtle-text | — |
--ui-danger-wash | — |
--ui-danger-wash-hover | — |
--ui-disabled-border | — |
--ui-disabled-filter | — |
--ui-disabled-surface | — |
--ui-disabled-text | — |
--ui-field-radius | var(--ui-radius-md) |
--ui-focus-halo | — |
--ui-focus-ring | — |
--ui-focus-width | — |
--ui-font-medium | — |
--ui-font-normal | — |
--ui-font-size-md | — |
--ui-font-size-sm | — |
--ui-font-size-xs | — |
--ui-info | — |
--ui-info-active | — |
--ui-info-active-border | var(--ui-info-active) |
--ui-info-border | var(--ui-info) |
--ui-info-ghost-hover | — |
--ui-info-glow | 0 0 transparent |
--ui-info-highlight | none |
--ui-info-hover | — |
--ui-info-hover-border | var(--ui-info-hover) |
--ui-info-hover-highlight | none |
--ui-info-on-strong | — |
--ui-info-outline-border | var(--ui-info-subtle-text) |
--ui-info-subtle-text | — |
--ui-info-wash | — |
--ui-info-wash-hover | — |
--ui-line-height-tight | — |
--ui-motion-base | — |
--ui-motion-ease | — |
--ui-motion-fast | — |
--ui-motion-press | var(--ui-motion-fast) |
--ui-neutral-active | — |
--ui-neutral-ghost-hover | — |
--ui-neutral-glow | 0 0 transparent |
--ui-neutral-highlight | none |
--ui-neutral-hover | — |
--ui-neutral-shadow | — |
--ui-neutral-surface | — |
--ui-neutral-wash-hover | — |
--ui-on-accent | — |
--ui-on-danger | — |
--ui-press-scale | 1 |
--ui-pressed | — |
--ui-radius-md | — |
--ui-radius-round | — |
--ui-radius-sm | — |
--ui-selection-border | — |
--ui-selection-surface | — |
--ui-selection-text | — |
--ui-shadow-sm | — |
--ui-space-0-5 | — |
--ui-space-1 | — |
--ui-space-2 | — |
--ui-space-3 | — |
--ui-space-4 | — |
--ui-success | — |
--ui-success-active | — |
--ui-success-active-border | var(--ui-success-active) |
--ui-success-border | var(--ui-success) |
--ui-success-ghost-hover | — |
--ui-success-glow | 0 0 transparent |
--ui-success-highlight | none |
--ui-success-hover | — |
--ui-success-hover-border | var(--ui-success-hover) |
--ui-success-hover-highlight | none |
--ui-success-on-strong | — |
--ui-success-outline-border | var(--ui-success-subtle-text) |
--ui-success-subtle-text | — |
--ui-success-wash | — |
--ui-success-wash-hover | — |
--ui-surface | — |
--ui-surface-elevated | — |
--ui-surface-highlight | none |
--ui-text | — |
--ui-text-primary | — |
--ui-text-secondary | — |
--ui-tonal-opacity | 1 |
--ui-warning | — |
--ui-warning-active | — |
--ui-warning-active-border | var(--ui-warning-active) |
--ui-warning-border | var(--ui-warning) |
--ui-warning-ghost-hover | — |
--ui-warning-glow | 0 0 transparent |
--ui-warning-highlight | none |
--ui-warning-hover | — |
--ui-warning-hover-border | var(--ui-warning-hover) |
--ui-warning-hover-highlight | none |
--ui-warning-on-strong | — |
--ui-warning-outline-border | var(--ui-warning-subtle-text) |
--ui-warning-subtle-text | — |
--ui-warning-wash | — |
--ui-warning-wash-hover | — |