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
gap: Numeric scale value representing spacing (gap={1}is--spacing-1,gap={4}is--spacing-4).hAlign: Horizontal alignment ("start","center","end","between").vAlign: Vertical alignment ("start","center","end","between").wrap: Flex wrapping mode ("wrap","nowrap").
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:
LayoutHeader: The top bar. AddhasDividerto draw a separator under it, andpaddingto control inset spacing.LayoutContent: The scrollable body. Itsrefis forwarded to the underlying DOM node — we will use that in lesson 11 for drag-and-drop hit-testing.Layouttakesheaderandcontentas render props (or JSX children).
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:
'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:
Section height="100dvh"locks the app to the viewport height.Layout height="fill"makes the frame fill that section.LayoutHeaderholds the title bar;hasDividerdraws the separator line.LayoutContent padding={4}is the scrollable body — when real columns overflow, this is what scrolls.- Inside, an
HStack gap={4}lays the four placeholder columns side by side. Each is a mutedCardat a fixedwidth={300}withflexShrink: 0so columns never squish. hAlign="between"on the header stack pushes the title left and the supporting text right.
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
- The board’s permanent frame:
Section→Layout→LayoutHeader+LayoutContent. - A
HStackcolumn strip with Astryx’s gap scale and alignment props. - The placeholder columns we will style in lesson 4 and fill with real data in lesson 6.
In the next lesson, we will localize the board and add a language switcher.