Theme
← Examples
Layout Systems
A real page showing layout, navigation, and composition primitives working together in one place.
apps/docs/src/lib/demos/LayoutDemo.svelte
Preview
Open in new tabLayout & Navigation
Container
sm (640px max)
md (768px max)
lg (1024px max)
Stack
Vertical (default)
Item 1
Item 2
Item 3
Horizontal
A
B
C
Grid
1
2
3
4
5
6
Flex
Flex 1
Flex 2
Flex 3
Flex 4
Separator
Content above
Content below
Left Right
Spacer
Before
xs spacer
lg spacer
After
AspectRatio
16:9
16:9
1:1
1:1
4:3
4:3
Tabs
Account settings and profile information.
Breadcrumb
Pagination
Page: 3
Stepper
- Details
- Payment
- Confirm
Step 2 of 3
Toolbar
ScrollArea
Splitter
Panel 1 (50%)
Panel 2 (50%)
Source
This page is rendered from the real demo file shown below.
svelte
<script lang="ts">
import {
Container,
Stack,
Grid,
Flex,
Separator,
Spacer,
AspectRatio,
Tabs,
Breadcrumb,
Pagination,
Stepper,
Toolbar,
ScrollArea,
Splitter,
Button,
} from '@dryui/ui';
let activeTab = $state('tab1');
let currentPage = $state(3);
let activeStep = $state(1);
let splitterSizes = $state([50, 50]);
</script>
<h2>Layout & Navigation</h2>
<!-- Container -->
<section>
<h3>Container</h3>
<div class="demo-bg">
<Container size="sm">
<div class="demo-box">sm (640px max)</div>
</Container>
<Container size="md">
<div class="demo-box">md (768px max)</div>
</Container>
<Container size="lg">
<div class="demo-box">lg (1024px max)</div>
</Container>
</div>
</section>
<!-- Stack -->
<section>
<h3>Stack</h3>
<div class="row-gap">
<div>
<p class="sublabel">Vertical (default)</p>
<Stack gap="sm">
<div class="demo-box">Item 1</div>
<div class="demo-box">Item 2</div>
<div class="demo-box">Item 3</div>
</Stack>
</div>
<div>
<p class="sublabel">Horizontal</p>
<Stack direction="horizontal" gap="md" align="center">
<div class="demo-box">A</div>
<div class="demo-box">B</div>
<div class="demo-box">C</div>
</Stack>
</div>
</div>
</section>
<!-- Grid -->
<section>
<h3>Grid</h3>
<Grid columns={3} gap="sm">
<div class="demo-box">1</div>
<div class="demo-box">2</div>
<div class="demo-box">3</div>
<div class="demo-box">4</div>
<div class="demo-box">5</div>
<div class="demo-box">6</div>
</Grid>
</section>
<!-- Flex -->
<section>
<h3>Flex</h3>
<Flex gap="sm" justify="between" align="center" wrap="wrap">
<div class="demo-box">Flex 1</div>
<div class="demo-box">Flex 2</div>
<div class="demo-box">Flex 3</div>
<div class="demo-box">Flex 4</div>
</Flex>
</section>
<!-- Separator -->
<section>
<h3>Separator</h3>
<div>
<p>Content above</p>
<Separator />
<p>Content below</p>
</div>
<div class="row separator-demo">
<span>Left</span>
<Separator orientation="vertical" />
<span>Right</span>
</div>
</section>
<!-- Spacer -->
<section>
<h3>Spacer</h3>
<div class="demo-bg demo-bg--padded">
<div class="demo-box">Before</div>
<Spacer size="xs" />
<p class="sublabel">xs spacer</p>
<Spacer size="lg" />
<p class="sublabel">lg spacer</p>
<div class="demo-box">After</div>
</div>
</section>
<!-- AspectRatio -->
<section>
<h3>AspectRatio</h3>
<div class="row-gap">
<div class="aspect-shell aspect-shell--wide">
<p class="sublabel">16:9</p>
<AspectRatio ratio={16 / 9}>
<div class="demo-box demo-box--fill-center">16:9</div>
</AspectRatio>
</div>
<div class="aspect-shell aspect-shell--square">
<p class="sublabel">1:1</p>
<AspectRatio ratio={1}>
<div class="demo-box demo-box--fill-center">1:1</div>
</AspectRatio>
</div>
<div class="aspect-shell aspect-shell--portrait">
<p class="sublabel">4:3</p>
<AspectRatio ratio={4 / 3}>
<div class="demo-box demo-box--fill-center">4:3</div>
</AspectRatio>
</div>
</div>
</section>
<!-- Tabs -->
<section>
<h3>Tabs</h3>
<Tabs.Root bind:value={activeTab}>
<Tabs.List>
<Tabs.Trigger value="tab1">Account</Tabs.Trigger>
<Tabs.Trigger value="tab2">Settings</Tabs.Trigger>
<Tabs.Trigger value="tab3" disabled>Billing</Tabs.Trigger>
</Tabs.List>
<Tabs.Content value="tab1">
<p>Account settings and profile information.</p>
</Tabs.Content>
<Tabs.Content value="tab2">
<p>Application preferences and configuration.</p>
</Tabs.Content>
<Tabs.Content value="tab3">
<p>Billing and subscription details.</p>
</Tabs.Content>
</Tabs.Root>
</section>
<!-- Breadcrumb -->
<section>
<h3>Breadcrumb</h3>
<Breadcrumb.Root>
<Breadcrumb.List>
<Breadcrumb.Item>
<Breadcrumb.Link href="#">Home</Breadcrumb.Link>
</Breadcrumb.Item>
<Breadcrumb.Separator />
<Breadcrumb.Item>
<Breadcrumb.Link href="#">Products</Breadcrumb.Link>
</Breadcrumb.Item>
<Breadcrumb.Separator />
<Breadcrumb.Item>
<Breadcrumb.Link current>Headphones</Breadcrumb.Link>
</Breadcrumb.Item>
</Breadcrumb.List>
</Breadcrumb.Root>
</section>
<!-- Pagination -->
<section>
<h3>Pagination</h3>
<Pagination.Root bind:page={currentPage} totalPages={10}>
<Pagination.Content>
<Pagination.Item>
<Pagination.Previous>Prev</Pagination.Previous>
</Pagination.Item>
<Pagination.Item>
<Pagination.Link page={1}>1</Pagination.Link>
</Pagination.Item>
<Pagination.Item>
<Pagination.Link page={2}>2</Pagination.Link>
</Pagination.Item>
<Pagination.Item>
<Pagination.Link page={3}>3</Pagination.Link>
</Pagination.Item>
<Pagination.Item>
<Pagination.Ellipsis />
</Pagination.Item>
<Pagination.Item>
<Pagination.Link page={10}>10</Pagination.Link>
</Pagination.Item>
<Pagination.Item>
<Pagination.Next>Next</Pagination.Next>
</Pagination.Item>
</Pagination.Content>
</Pagination.Root>
<p class="preview">Page: {currentPage}</p>
</section>
<!-- Stepper -->
<section>
<h3>Stepper</h3>
<Stepper.Root bind:activeStep>
<Stepper.List>
<Stepper.Step step={0}>Details</Stepper.Step>
<Stepper.Separator step={0} />
<Stepper.Step step={1}>Payment</Stepper.Step>
<Stepper.Separator step={1} />
<Stepper.Step step={2}>Confirm</Stepper.Step>
</Stepper.List>
</Stepper.Root>
<div class="row stepper-actions">
<Button size="sm" variant="outline" onclick={() => activeStep = Math.max(0, activeStep - 1)} disabled={activeStep === 0}>Back</Button>
<Button size="sm" onclick={() => activeStep = Math.min(2, activeStep + 1)} disabled={activeStep === 2}>Next</Button>
<span class="preview">Step {activeStep + 1} of 3</span>
</div>
</section>
<!-- Toolbar -->
<section>
<h3>Toolbar</h3>
<Toolbar.Root>
<Toolbar.Button onclick={() => {}}>Bold</Toolbar.Button>
<Toolbar.Button onclick={() => {}}>Italic</Toolbar.Button>
<Toolbar.Button onclick={() => {}}>Underline</Toolbar.Button>
<Toolbar.Separator />
<Toolbar.Button onclick={() => {}}>Align Left</Toolbar.Button>
<Toolbar.Button onclick={() => {}}>Align Center</Toolbar.Button>
<Toolbar.Separator />
<Toolbar.Link href="#">Help</Toolbar.Link>
</Toolbar.Root>
</section>
<!-- ScrollArea -->
<section>
<h3>ScrollArea</h3>
<div class="scroll-shell">
<ScrollArea class="scroll-area-frame">
{#each Array.from({ length: 20 }) as _, i (i)}
<p>Scrollable item {i + 1}</p>
{/each}
</ScrollArea>
</div>
</section>
<!-- Splitter -->
<section>
<h3>Splitter</h3>
<div class="splitter-shell">
<Splitter.Root bind:sizes={splitterSizes}>
<Splitter.Panel index={0}>
<div class="demo-box demo-box--fill-center">
Panel 1 ({Math.round(splitterSizes[0] ?? 0)}%)
</div>
</Splitter.Panel>
<Splitter.Handle index={0} />
<Splitter.Panel index={1}>
<div class="demo-box demo-box--fill-center">
Panel 2 ({Math.round(splitterSizes[1] ?? 0)}%)
</div>
</Splitter.Panel>
</Splitter.Root>
</div>
</section>
<style>
section { margin-bottom: 2rem; }
h3 { margin: 1.5rem 0 0.75rem; }
.row {
display: flex;
flex-wrap: wrap;
gap: 0.75rem;
align-items: center;
}
.separator-demo {
height: 40px;
}
.stepper-actions {
margin-top: var(--dry-space-4);
}
.row-gap {
display: flex;
flex-wrap: wrap;
gap: 2rem;
align-items: flex-start;
}
.demo-bg {
background: var(--dry-color-surface);
border-radius: var(--dry-radius-md);
padding: 0.5rem;
}
.demo-bg--padded {
padding: 1rem;
}
.demo-box {
background: color-mix(in srgb, var(--dry-color-primary) 10%, transparent);
border: 1px dashed color-mix(in srgb, var(--dry-color-primary) 30%, transparent);
border-radius: var(--dry-radius-sm);
padding: 0.5rem 1rem;
font-size: var(--dry-text-sm-size);
color: var(--dry-color-text-secondary);
text-align: center;
}
.demo-box--fill-center {
width: 100%;
height: 100%;
display: grid;
place-items: center;
}
.aspect-shell {
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.aspect-shell--wide {
width: 200px;
}
.aspect-shell--square {
width: 150px;
}
.aspect-shell--portrait {
width: 120px;
}
.scroll-shell {
height: 150px;
border: 1px solid var(--dry-color-border);
border-radius: var(--dry-radius-md);
}
:global(.scroll-area-frame) {
height: 100%;
padding: 1rem;
}
.splitter-shell {
height: 200px;
border: 1px solid var(--dry-color-border);
border-radius: var(--dry-radius-md);
overflow: hidden;
}
.preview {
color: var(--dry-color-muted);
font-size: var(--dry-text-sm-size);
margin: 0.25rem 0;
}
.sublabel {
font-size: var(--dry-text-xs-size);
color: var(--dry-color-text-secondary);
margin: 0 0 0.5rem;
text-transform: uppercase;
letter-spacing: 0.05em;
}
</style>