Skip to content

Mastering Astryx / lesson 2 of 13

Layout & Spatial Composition

Shape the Kanban board stub into a full application shell using Section, Layout, LayoutHeader, LayoutContent, HStack, and VStack.

Play

Layout management in Astryx relies on composable flex primitives that eliminate manual layout CSS. In this lesson, we turn the stub from lesson 1 into the real board shell — an app-frame with a fixed header and a scrollable body holding a row of placeholder columns.

Files this lesson: src/app/components/KanbanBoard.tsx (rewritten). page.tsx stays untouched.

Spatial Stacks: HStack and VStack

Rather than applying display: flex and flex-direction across custom classes, Astryx provides HStack (horizontal stack) and VStack (vertical stack).

Key Props

Application Shell Containers

Astryx provides Section and Layout for establishing top-level viewport bounds and scrollable regions.

Section

The <Section> component defines top-level section boundaries. For full-screen tools like our Kanban board, set height="100dvh" so the app always fills the viewport:

<Section height="100dvh">
{/* Application content */}
</Section>

Layout, LayoutHeader, and LayoutContent

Layout partitions an application into a fixed header and a scrollable content body:

Building the Shell: KanbanBoard.tsx

Rewrite src/app/components/KanbanBoard.tsx as a full app frame: a header with the board title, and a content area holding four placeholder columns in a horizontal strip:

src/app/components/KanbanBoard.tsx
'use client';
import { Section } from '@astryxdesign/core/Section';
import {
Layout,
LayoutHeader,
LayoutContent,
HStack,
} from '@astryxdesign/core/Layout';
import { Heading, Text } from '@astryxdesign/core/Text';
import { Card } from '@astryxdesign/core/Card';
export default function KanbanBoard() {
return (
<Card padding={4}>
<Heading level={2}>Sprint Board</Heading>
<Text color="secondary">
The Kanban board is under construction — we will build it together
over the coming lessons.
</Text>
</Card>
<Section height="100dvh">
<Layout
height="fill"
header={
<LayoutHeader hasDivider padding={4}>
<HStack hAlign="between" vAlign="center">
<Heading level={3}>Sprint Board</Heading>
<Text type="supporting" color="secondary">
Layout shell — real columns arrive in lesson 6
</Text>
</HStack>
</LayoutHeader>
}
content={
<LayoutContent padding={4}>
<HStack gap={4}>
{[0, 1, 2, 3].map(i => (
<Card
key={i}
variant="muted"
padding={3}
width={300}
style={{ flexShrink: 0 }}
>
<Heading level={4}>Column {i + 1}</Heading>
<Text type="supporting" color="secondary">
Placeholder — data arrives in lesson 6.
</Text>
</Card>
))}
</HStack>
</LayoutContent>
}
/>
</Section>
);
}

Read the structure top-down:

See It in Action

Run npm run dev and open http://localhost:3000. You now have a full-height application frame: a fixed header with a divider, and a scrollable content area with four muted placeholder columns. Resize the window — the header stays put and the columns are side by side. If the strip overflows, the content body scrolls.

What You Built

In the next lesson, we will localize the board and add a language switcher.


Share this post on:

Previous
Introduction, Setup & Architecture
Next
Internationalization & Localization (i18n)