Stack
Vertical layout primitive that owns spacing between children.
Default
With no properties supplied, Stack uses its default gap, alignment, and distribution.
Frodo
Sam
Sméagol
Code
<link
rel="component"
href="@threadlabs/looma/components/ui-stack/ui-stack.html"
>
<link
rel="component"
href="@threadlabs/looma/components/ui-card/ui-card.html"
>
<ui-stack>
<ui-card
padding="sm"
>Frodo</ui-card>
<ui-card
padding="sm"
>Sam</ui-card>
<ui-card
padding="sm"
>Sméagol</ui-card>
</ui-stack><script setup>
import { UiCard, UiStack } from "@threadlabs/looma";
</script>
<template>
<UiStack>
<UiCard
padding="sm"
>Frodo</UiCard>
<UiCard
padding="sm"
>Sam</UiCard>
<UiCard
padding="sm"
>Sméagol</UiCard>
</UiStack>
</template>import { UiCard, UiStack } from "@threadlabs/looma";
export default function Example() {
return <UiStack>
<UiCard
padding="sm"
>Frodo</UiCard>
<UiCard
padding="sm"
>Sam</UiCard>
<UiCard
padding="sm"
>Sméagol</UiCard>
</UiStack>;
}/** @jsxImportSource preact */
import { UiCard, UiStack } from "@threadlabs/looma";
export default function Example() {
return <UiStack>
<UiCard
padding="sm"
>Frodo</UiCard>
<UiCard
padding="sm"
>Sam</UiCard>
<UiCard
padding="sm"
>Sméagol</UiCard>
</UiStack>;
}<script>
import { UiCard, UiStack } from "@threadlabs/looma";
</script>
<UiStack>
<UiCard
padding="sm"
>Frodo</UiCard>
<UiCard
padding="sm"
>Sam</UiCard>
<UiCard
padding="sm"
>Sméagol</UiCard>
</UiStack>import { Component } from "@angular/core";
import { UiCard, UiStack } from "@threadlabs/looma";
@Component({
selector: "example-view",
standalone: true,
imports: [UiStack, UiCard],
template: `
<div
ui-stack
>
<ng-template
ui-card
[padding]="'sm'"
>Frodo</ng-template>
<ng-template
ui-card
[padding]="'sm'"
>Sam</ng-template>
<ng-template
ui-card
[padding]="'sm'"
>Sméagol</ng-template>
</div>
`,
})
export default class Example {}gap="xl" and align="center"
The extra-large gap visibly increases vertical space; center alignment returns the bounded children to their intrinsic widths.
Frodo
Sam
Sméagol
Code
<link
rel="component"
href="@threadlabs/looma/components/ui-stack/ui-stack.html"
>
<link
rel="component"
href="@threadlabs/looma/components/ui-card/ui-card.html"
>
<ui-stack
gap="xl"
align="center"
>
<ui-card
padding="sm"
>Frodo</ui-card>
<ui-card
padding="sm"
>Sam</ui-card>
<ui-card
padding="sm"
>Sméagol</ui-card>
</ui-stack><script setup>
import { UiCard, UiStack } from "@threadlabs/looma";
</script>
<template>
<UiStack
gap="xl"
align="center"
>
<UiCard
padding="sm"
>Frodo</UiCard>
<UiCard
padding="sm"
>Sam</UiCard>
<UiCard
padding="sm"
>Sméagol</UiCard>
</UiStack>
</template>import { UiCard, UiStack } from "@threadlabs/looma";
export default function Example() {
return <UiStack
gap="xl"
align="center"
>
<UiCard
padding="sm"
>Frodo</UiCard>
<UiCard
padding="sm"
>Sam</UiCard>
<UiCard
padding="sm"
>Sméagol</UiCard>
</UiStack>;
}/** @jsxImportSource preact */
import { UiCard, UiStack } from "@threadlabs/looma";
export default function Example() {
return <UiStack
gap="xl"
align="center"
>
<UiCard
padding="sm"
>Frodo</UiCard>
<UiCard
padding="sm"
>Sam</UiCard>
<UiCard
padding="sm"
>Sméagol</UiCard>
</UiStack>;
}<script>
import { UiCard, UiStack } from "@threadlabs/looma";
</script>
<UiStack
gap="xl"
align="center"
>
<UiCard
padding="sm"
>Frodo</UiCard>
<UiCard
padding="sm"
>Sam</UiCard>
<UiCard
padding="sm"
>Sméagol</UiCard>
</UiStack>import { Component } from "@angular/core";
import { UiCard, UiStack } from "@threadlabs/looma";
@Component({
selector: "example-view",
standalone: true,
imports: [UiStack, UiCard],
template: `
<div
ui-stack
[gap]="'xl'"
[align]="'center'"
>
<ng-template
ui-card
[padding]="'sm'"
>Frodo</ng-template>
<ng-template
ui-card
[padding]="'sm'"
>Sam</ng-template>
<ng-template
ui-card
[padding]="'sm'"
>Sméagol</ng-template>
</div>
`,
})
export default class Example {}justify="between"
Justify distributes children along the stack's height when it is taller than its content; between pushes the first and last to the ends.
Top
Bottom
Code
<link
rel="component"
href="@threadlabs/looma/components/ui-stack/ui-stack.html"
>
<ui-stack
justify="between"
style="height: 12rem"
>
<div>Top</div>
<div>Bottom</div>
</ui-stack><script setup>
import { UiStack } from "@threadlabs/looma";
</script>
<template>
<UiStack
justify="between"
style="height: 12rem"
>
<div>Top</div>
<div>Bottom</div>
</UiStack>
</template>import { UiStack } from "@threadlabs/looma";
export default function Example() {
return <UiStack
justify="between"
style={{"height":"12rem"}}
>
<div>Top</div>
<div>Bottom</div>
</UiStack>;
}/** @jsxImportSource preact */
import { UiStack } from "@threadlabs/looma";
export default function Example() {
return <UiStack
justify="between"
style={{"height":"12rem"}}
>
<div>Top</div>
<div>Bottom</div>
</UiStack>;
}<script>
import { UiStack } from "@threadlabs/looma";
</script>
<UiStack
justify="between"
style="height: 12rem"
>
<div>Top</div>
<div>Bottom</div>
</UiStack>import { Component } from "@angular/core";
import { UiStack } from "@threadlabs/looma";
@Component({
selector: "example-view",
standalone: true,
imports: [UiStack],
template: `
<div
ui-stack
[justify]="'between'"
style="height: 12rem"
>
<div>Top</div>
<div>Bottom</div>
</div>
`,
})
export default class Example {}API
Package: @threadlabs/looma · Native root: div
Attributes
| Name | Description | Property | Type | Default | Allowed values |
|---|---|---|---|---|---|
align | How items sit across the stack: stretch (the default) makes each fill the stack's width; start, center, and end keep each at its own width, against the start, in the middle, or against the end. | align | keyword | — | start, center, end, stretch |
fill | Grows into the remaining space of a flex layout and allows its scrolling children to shrink. | fill | boolean | false | — |
gap | Space between items, on the spacing scale: none is zero, xs is 0.5rem, s 0.75rem, m 1rem (also the default), l 1.5rem, and xl 2rem. The --ui-stack-gap custom property, set on :root, an ancestor, or the component itself, overrides it. Theme rhythm scales these vertical gaps, while an explicit gap override stays exact. | gap | keyword | — | none, xs, s, m, l, xl |
height | An optional measured height in CSS pixels, for a viewport-bounded composition. Omit it to retain intrinsic sizing. | height | number | — | — |
justify | Where items sit along a stack that is taller than its content: start (the default), center, end, or between, which spreads the spare space between items. It has no effect unless the stack is given a height or stretched to one. | justify | keyword | — | start, center, end, between |
Framework props
| Name | Type | Default | Allowed values |
|---|---|---|---|
align | "start" | "center" | "end" | "stretch" | — | start, center, end, stretch |
fill | boolean | false | — |
gap | "none" | "xs" | "s" | "m" | "l" | "xl" | — | none, xs, s, m, l, xl |
height | number | — | — |
justify | "start" | "center" | "end" | "between" | — | start, center, end, between |
Events
No events.
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-stack-gap | — | calc(var(--_layout-gap) * clamp(0.75, var(--ui-rhythm, 1), 1.5)) |
Shared tokens
| Token | Fallback |
|---|---|
--ui-rhythm | 1 |
--ui-space-2 | — |
--ui-space-3 | — |
--ui-space-4 | — |
--ui-space-5 | — |
--ui-space-6 | — |