Layout
Arrange things on the page: stacks, grids, containers and page chrome.
Stack #
Flex stack; gap maps to --a-stack-gap.
First
Second
Third
<Stack gap="0.5rem">
<Text>First</Text>
<Text>Second</Text>
<Text>Third</Text>
</Stack>| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
children | content | Items to stack. | ||
direction | "column" | "row" | "column" | Stack vertically (column) or horizontally (row). | |
gap | string | Space between children (any CSS length). |
Also accepts the shared props: pass-through attributes, class, style, classes, styles, unstyled.
Group #
Horizontal flex group (Mantine Group / Bootstrap btn-group row).
<Group gap="0.5rem">
<Button variant="ghost" onClick={() => {}}>
Cancel
</Button>
<Button onClick={() => {}}>Save</Button>
</Group>| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
align | "start" | "center" | "end" | "stretch" | Vertical alignment of the items. | ||
children | content | Items in a row. | ||
gap | string | Space between items (any CSS length). | ||
grow | boolean | Items share the row's width equally. | ||
justify | "start" | "center" | "end" | "between" | "around" | Horizontal distribution of the items. | ||
wrap | boolean | Let items wrap onto new lines. |
Also accepts the shared props: pass-through attributes, class, style, classes, styles, unstyled.
Flex #
Flexbox layout primitive (direction, gap, align, justify, wrap).
Invoices
<Flex justify="space-between" align="center">
<Text>Invoices</Text>
<Button size="sm" onClick={() => {}}>
Export
</Button>
</Flex>| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
align | string | CSS align-items. | ||
children | content | Flex items. | ||
direction | "column" | "row" | Main axis. | ||
gap | string | Space between items (any CSS length). | ||
justify | string | CSS justify-content. | ||
wrap | boolean | Let items wrap. |
Also accepts the shared props: pass-through attributes, class, style, classes, styles, unstyled.
Grid #
CSS grid layout (Bulma-style 2D grid).
<Grid cols={3} gap="0.75rem">
<Box>1</Box>
<Box>2</Box>
<Box>3</Box>
<Box>4</Box>
<Box>5</Box>
<Box>6</Box>
</Grid>| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
children | content | Grid cells (plain elements or GridItems). | ||
cols | number | 12 | Column count (CSS grid). Default 12. | |
gap | string | Space between cells (any CSS length). | ||
min | string | Min track width for auto-fit dense grids, e.g. 12rem. Overrides cols when set. |
Also accepts the shared props: pass-through attributes, class, style, classes, styles, unstyled.
Parts
GridItem #
Item of a CSS grid, placed with span / start.
<Grid cols={3} gap="0.75rem">
<GridItem span={2}>
<Box>Spans two columns</Box>
</GridItem>
<Box>One</Box>
</Grid>| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
children | content | Cell content. | ||
span | number | Number of columns the cell covers. | ||
start | number | Column the cell starts at (1-based). |
Columns #
Flexbox columns container (Bulma columns).
<Columns gap="1rem">
<Column>
<Box>Auto</Box>
</Column>
<Column size={6}>
<Box>Half</Box>
</Column>
<Column>
<Box>Auto</Box>
</Column>
</Columns>| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
centered | boolean | Centre the columns horizontally. | ||
children | content | Columns. | ||
gap | string | Space between columns (any CSS length). | ||
mobile | boolean | Keep columns side-by-side on mobile (default stacks under 768px). | ||
multiline | boolean | Wrap columns onto new rows when they don't fit. | ||
vcentered | boolean | Centre the columns vertically. |
Also accepts the shared props: pass-through attributes, class, style, classes, styles, unstyled.
Parts
Column #
Single column (Bulma column).
<Columns>
<Column size={4}>
<Box>One third</Box>
</Column>
<Column>
<Box>Rest</Box>
</Column>
</Columns>| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
children | content | Column content. | ||
narrow | boolean | Only as wide as its content. | ||
offset | ColumnSize | Empty space before the column, in the same units as size. | ||
size | ColumnSize | Width in twelfths (1–12) or a named fraction (half, one-third, …); auto when unset. |
ColumnSize
type ColumnSize = | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | "full" | "four-fifths" | "three-quarters" | "two-thirds" | "three-fifths" | "half" | "two-fifths" | "one-third" | "one-quarter" | "one-fifth" | "narrow" | "auto";Container #
Horizontally centred content container with a max width.
<Container size="sm">
<Box>Content constrained to the small container width.</Box>
</Container>| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
children | content | Centred, width-constrained content. | ||
size | "full" | "sm" | "md" | "lg" | Maximum width. |
Also accepts the shared props: pass-through attributes, class, style, classes, styles, unstyled.
Section #
Vertical page section with rhythm spacing.
Pricing
Sections add vertical rhythm between page regions.
<Section size="sm">
<Title order={3}>Pricing</Title>
<Text>Sections add vertical rhythm between page regions.</Text>
</Section>| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
children | content | Section content. | ||
size | "sm" | "md" | "lg" | Vertical padding. |
Also accepts the shared props: pass-through attributes, class, style, classes, styles, unstyled.
Level #
Horizontal level bar (Bulma level).
<Level>
<LevelLeft>
<LevelItem>
<strong>128 deploys</strong>
</LevelItem>
</LevelLeft>
<LevelRight>
<LevelItem>
<Button size="sm" onClick={() => {}}>
New deploy
</Button>
</LevelItem>
</LevelRight>
</Level>| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
children | content | LevelLeft, LevelRight and/or LevelItems. | ||
mobile | boolean | Keep the row horizontal on small screens (it stacks by default). |
Also accepts the shared props: pass-through attributes, class, style, classes, styles, unstyled.
Parts
LevelLeft #
Left-aligned group of a level bar.
<Level>
<LevelLeft>
<LevelItem>Left side</LevelItem>
</LevelLeft>
</Level>| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
children | content | Items on this side of the row. |
LevelRight #
Right-aligned group of a level bar.
<Level>
<LevelRight>
<LevelItem>Right side</LevelItem>
</LevelRight>
</Level>| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
children | content | Items on this side of the row. |
LevelItem #
One centred item of a level bar.
Deploys
<Level>
<LevelItem>
<Text>Deploys</Text>
</LevelItem>
<LevelItem>
<strong>128</strong>
</LevelItem>
</Level>| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
children | content | Items on this side of the row. |
Media #
Media object (Bulma / UIkit comment / Bootstrap media).
opened #421
2h
<Media>
<MediaLeft>
<Avatar name="Ada Lovelace" />
</MediaLeft>
<MediaContent>
<strong>Ada Lovelace</strong> <Text muted>opened #421</Text>
</MediaContent>
<MediaRight>
<Text muted>2h</Text>
</MediaRight>
</Media>| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
children | content | MediaLeft, MediaContent and MediaRight. |
Also accepts the shared props: pass-through attributes, class, style, classes, styles, unstyled.
Parts
MediaLeft #
Leading figure of a media object (avatar, thumbnail).
<Media>
<MediaLeft>
<Avatar name="Grace Hopper" />
</MediaLeft>
<MediaContent>Left slot holds the avatar or thumbnail.</MediaContent>
</Media>| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
children | content | Content of this part. |
MediaContent #
Main content of a media object.
<Media>
<MediaLeft>
<Avatar name="Grace Hopper" />
</MediaLeft>
<MediaContent>The content column grows to fill the row.</MediaContent>
</Media>| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
children | content | Content of this part. |
MediaRight #
Trailing content of a media object (actions).
<Media>
<MediaContent>Row content</MediaContent>
<MediaRight>
<Button size="sm" variant="ghost" onClick={() => {}}>
Reply
</Button>
</MediaRight>
</Media>| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
children | content | Content of this part. |
Center & space #
Centre content or add fixed space.
Center #
Centres its content horizontally and vertically.
Centered on both axes
<Center style={{ "min-height": "6rem" }}>
<Text muted>Centered on both axes</Text>
</Center>| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
children | content | Content to centre horizontally and vertically. | ||
inline | boolean | Shrink to the content (inline-flex) instead of filling the width. |
Space #
Fixed spacer; h / w accept numbers (px) or CSS lengths.
Above
Below, 1.5rem later
<div>
<Text>Above</Text>
<Space h="1.5rem" />
<Text>Below, 1.5rem later</Text>
</div>| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
h | string | number | Vertical space (pixels or any CSS length). | ||
w | string | number | Horizontal space (pixels or any CSS length). |
Divider #
Horizontal rule.
Account
Billing
<Stack gap="0.75rem">
<Text>Account</Text>
<Divider />
<Text>Billing</Text>
</Stack>Also accepts the shared props: pass-through attributes, class, style, classes, styles, unstyled.
AspectRatio #
Fixed-ratio box (--a-aspect).
<AspectRatio style={{ "max-width": "20rem" }} ratio={16 / 9}>
<img src="/images/16-9.jpg" alt="16 by 9 placeholder" />
</AspectRatio>Slots: root inner
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
children | content | Content that fills the box (images and video are cropped to fit). | ||
ratio | number | 16 / 9 | Width divided by height, e.g. 16 / 9. |
Also accepts the shared props: pass-through attributes, class, style, classes, styles, unstyled.
ScrollArea #
Scrollable region with a max height.
Deploy #128
Deploy #127
Deploy #126
Deploy #125
Deploy #124
Deploy #123
<ScrollArea maxHeight="6rem">
<Stack gap="0.35rem">
<Text>Deploy #128</Text>
<Text>Deploy #127</Text>
<Text>Deploy #126</Text>
<Text>Deploy #125</Text>
<Text>Deploy #124</Text>
<Text>Deploy #123</Text>
</Stack>
</ScrollArea>| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
children | content | Scrollable content. | ||
maxHeight | string | Height after which the content scrolls (any CSS length). |
Also accepts the shared props: pass-through attributes, class, style, classes, styles, unstyled.
Splitter #
Two resizable panes (pointer + ← → Home End).
Files
Editor
<Splitter
style={{ height: "8rem" }}
label="Resize panes"
initial={40}
left={<Text>Files</Text>}
right={<Text>Editor</Text>}
/>Slots: root handle pane
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
initial | number | 0.4 | Left pane ratio 0–1, default 0.4 (read once, at mount). | |
label | string | "Resize panes" | Accessible name for the handle (default "Resize panes"). | |
left | content | First (left) pane content. | ||
max | number | 0.8 | Largest size of the first pane, in percent. | |
min | number | 0.2 | Smallest size of the first pane, in percent. | |
right | content | Second (right) pane content. |
Also accepts the shared props: pass-through attributes, class, style, classes, styles, unstyled.
Masonry #
Masonry layout of variable-height items in columns.
Dark theme, a component reference and interactive examples.
Ship the tree search.
Tighten the button group borders, fix the burger icon, make quote backgrounds optional and give the tree folder icons.
PIN input needed two Backspaces.
Masonry packs cards of different heights into columns without gaps.
WAI-ARIA tree pattern.
function Example() {
const notes = [
{ title: "Release 2.4", body: "Dark theme, a component reference and interactive examples." },
{ title: "Standup", body: "Ship the tree search." },
{
title: "Design review",
body: "Tighten the button group borders, fix the burger icon, make quote backgrounds optional and give the tree folder icons.",
},
{ title: "Bug", body: "PIN input needed two Backspaces." },
{ title: "Idea", body: "Masonry packs cards of different heights into columns without gaps." },
{ title: "Reading", body: "WAI-ARIA tree pattern." },
];
return (
<Masonry columns={3}>
<For each={notes}>
{(note) => (
<Paper withBorder padding="md">
<strong>{note.title}</strong>
<Text muted>{note.body}</Text>
</Paper>
)}
</For>
</Masonry>
);
}| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
children | content | Items to pack; each keeps its own height. | ||
columns | 2 | 3 | 4 | 3 | Number of columns. |
Also accepts the shared props: pass-through attributes, class, style, classes, styles, unstyled.
Reel #
Horizontal scroll reel.
<Reel>
<img src="/images/1.jpg" alt="Slide 1" width="240" height="160" />
<img src="/images/2.jpg" alt="Slide 2" width="240" height="160" />
<img src="/images/3.jpg" alt="Slide 3" width="240" height="160" />
<img src="/images/4.jpg" alt="Slide 4" width="240" height="160" />
</Reel>| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
children | content | Items in a horizontally scrolling row. |
Also accepts the shared props: pass-through attributes, class, style, classes, styles, unstyled.
Bleed #
Negative horizontal margin to break out of padding.
Full-width strip that ignores its container's padding.
<Bleed x="1rem">
<Text>Full-width strip that ignores its container's padding.</Text>
</Bleed>| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
children | content | Content to extend. | ||
x | string | "-1rem" | How far to extend past the container on each side (any CSS length). |
Also accepts the shared props: pass-through attributes, class, style, classes, styles, unstyled.
AppShell #
Application chrome: optional sidebar + header around main content.
Deploys page
const sections = [
{ id: "overview", label: "Overview" },
{ id: "deploys", label: "Deploys" },
{ id: "settings", label: "Settings" },
];
function Example() {
const page = signal("deploys");
return (
<AppShell
contentAs="div"
header={<strong>Acme Console</strong>}
sidebar={<SidebarNav label="Main" items={sections} value={page()} onChange={page.set} />}
>
<Text>{sections.find((s) => s.id === page())?.label} page</Text>
</AppShell>
);
}Slots: root content header main sidebar
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
children | content | Main content. | ||
contentAs | "main" | "div" | Element for the content area (default "main"). Use "div" when the shell is nested in a page that already has a <main> landmark. | ||
header | content | Content of the top bar. | ||
sidebar | content | Content of the side column, e.g. a SidebarNav. |
Also accepts the shared props: pass-through attributes, class, style, classes, styles, unstyled.
PageHeader #
Page title block with breadcrumb, description and actions.
Deploys
Every push to a branch creates a deploy.
<PageHeader
title="Deploys"
description="Every push to a branch creates a deploy."
actions={<Button onClick={() => {}}>New deploy</Button>}
/>Slots: root actions crumb description row text title
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
title | string | yes | Page title (rendered as <h1>). | |
actions | content | Buttons aligned to the end of the header. | ||
breadcrumb | content | Breadcrumb above the title. | ||
description | content | Text under the title. |
Also accepts the shared props: pass-through attributes, class, style, classes, styles, unstyled.
Hero #
Full-bleed page hero (Bulma / Bootstrap jumbotron).
Ship faster with Arachne
Signals, SSR and 330+ accessible components.
<Hero tone="accent" size="sm">
<HeroBody>
<Title order={2} size={3}>
Ship faster with Arachne
</Title>
<Text>Signals, SSR and 330+ accessible components.</Text>
</HeroBody>
</Hero>| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
children | content | HeroHead, HeroBody and HeroFoot, or plain content. | ||
size | HeroSize | Height: sm / md / lg, half screen or full screen. | ||
tone | HeroTone | Background colour scheme. |
HeroSize
type HeroSize = "sm" | "md" | "lg" | "half" | "full";HeroTone
type HeroTone = "default" | "accent" | "dark" | "light";Also accepts the shared props: pass-through attributes, class, style, classes, styles, unstyled.
Parts
HeroHead #
Top area of a hero (e.g. navigation).
<Hero tone="dark" size="sm">
<HeroHead>
<strong>Arachne</strong>
</HeroHead>
<HeroBody>Hero head sits at the top, for a navbar or brand.</HeroBody>
</Hero>| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
children | content | Content of this part. |
HeroBody #
Main content area of a hero.
<Hero size="sm">
<HeroBody>The body grows to fill the hero and centres its content.</HeroBody>
</Hero>| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
children | content | Content of this part. |
HeroFoot #
Bottom area of a hero (e.g. tabs).
Trusted by 2,000 teams
<Hero tone="light" size="sm">
<HeroBody>Hero with a footer row.</HeroBody>
<HeroFoot>
<Text muted>Trusted by 2,000 teams</Text>
</HeroFoot>
</Hero>| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
children | content | Content of this part. |
Footer #
Page and site footers.
Footer #
Page footer region.
<Footer>
<Text muted>© 2026 Acme Inc. · Privacy · Terms</Text>
</Footer>| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
children | content | Footer content. |
SiteFooter #
Marketing footer.
<SiteFooter
brand="Arachne"
columns={[
{
title: "Product",
links: [
{ label: "Pricing", href: "#pricing" },
{ label: "Changelog", href: "#changelog" },
],
},
{
title: "Company",
links: [
{ label: "About", href: "#about" },
{ label: "Careers", href: "#careers" },
],
},
]}
meta="© 2026 Arachne"
/>Slots: root brand column columnTitle grid link meta
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
brand | content | Logo or name. | ||
columns | { title: string; links: SiteFooterLink[]; }[] | Link columns: each a title and its links. | ||
meta | content | Bottom line, e.g. copyright. |
SiteFooterLink
| Field | Type | Required | Description |
|---|---|---|---|
label | string | yes | Link text. |
href | string | Renders a real link when set. | |
onClick | () => void | Click handler (renders a button when there is no href). |
Also accepts the shared props: pass-through attributes, class, style, classes, styles, unstyled.
Sticky & affix #
Keep content in view while scrolling.
Sticky #
Sticks its content to an edge of the scroll container.
<Sticky offset={8}>
<Paper withBorder>Sticks 8px from the top while its container scrolls.</Paper>
</Sticky>| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
children | content | Content to keep in view. | ||
offset | number | 0 | Distance in pixels from the edge it sticks to. | |
position | "top" | "bottom" | "top" | Edge to stick to while scrolling. |
StickyBar #
Bar pinned to the top/bottom of its scroll container.
<StickyBar position="bottom">
<Text>You have unsaved changes.</Text>
<Button size="sm" onClick={() => {}}>
Save
</Button>
</StickyBar>| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
children | content | Bar content, e.g. a message and a Save button. | ||
position | "top" | "bottom" | "bottom" | Edge the bar sticks to. |
Affix #
Viewport-pinned container.
<Affix position="bottom-right" offset="1rem">
<Button size="sm" onClick={() => {}}>
Feedback
</Button>
</Affix>| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
children | content | Pinned content, e.g. a feedback button. | ||
offset | string | Distance from the corner (any CSS length). | ||
position | "top-left" | "top-right" | "bottom-left" | "bottom-right" | "bottom-right" | Viewport corner to pin to. |
Also accepts the shared props: pass-through attributes, class, style, classes, styles, unstyled.