Documentation

Layout Components

Build responsive layouts with Column, Row, Box, and Scaffold components.

Column

Stack children vertically:

<Column gap={16} p={20}>
  <Text>First</Text>
  <Text>Second</Text>
  <Text>Third</Text>
</Column>

Common Props

PropEffectExample
gapSpacing between itemsgap={16}
horizontalAlignmentAlign items horizontallyhorizontalAlignment="center"
verticalArrangementDistribute items verticallyverticalArrangement="spaceBetween"
scrollableEnable vertical scrollingscrollable

Alignment Values

  • "start" - Align to start (left for LTR)
  • "center" - Center items
  • "end" - Align to end (right for LTR)

Arrangement Values

  • "start" - Items at top
  • "center" - Items centered
  • "end" - Items at bottom
  • "spaceBetween" - Equal space between items
  • "spaceAround" - Equal space around items
  • "spaceEvenly" - Equal space including edges

Row

Arrange children horizontally:

<Row gap={8} verticalAlignment="center">
  <Icon name="ic:baseline-star" />
  <Text>4.5</Text>
  <Text color="secondary">(120 reviews)</Text>
</Row>

Common Props

PropEffectExample
gapSpacing between itemsgap={8}
verticalAlignmentAlign items verticallyverticalAlignment="center"
horizontalArrangementDistribute items horizontallyhorizontalArrangement="spaceBetween"
scrollableEnable horizontal scrollingscrollable

See it happen

Row and Column take the same alignment and gap classes, but which axis each one governs depends on which component it lands on. Switch between these to see the mapping flip.

Rating.wh
<Row class="items-center gap-8">
  <Icon name="ic:baseline-star" />
  <Text>4.5</Text>
</Row>
Kotlin waiting
Scroll into view to compile.

On a Row, items-center is the cross axis — vertical — so it becomes verticalAlignment, and gap-8 is the main axis, so it becomes horizontalArrangement.

Box

Stack children on top of each other or create containers:

<Box w={200} h={200} background="primary">
  <Image src={url} />
  <Text color="#FFF" p={16}>Caption</Text>
</Box>

Common Use Cases

Background Container

<Box fillMaxWidth background="#F5F5F5" p={16} cornerRadius={8}>
  <Text>Content</Text>
</Box>

Overlay

<Box>
  <Image src={photo} />
  <Box background="v-gradient(transparent 60%, #000)" fillMaxSize />
  <Text color="#FFF" p={16}>Overlay Text</Text>
</Box>

Centered Content

<Box fillMaxSize contentAlignment="center">
  <CircularProgressIndicator />
</Box>

Scaffold

Standard Material Design layout structure with top bar, bottom bar, and FAB:

<Scaffold
  topBar={<TopAppBar title="My App" />}
  bottomBar={<BottomNavigation />}
  floatingActionButton={<Button onClick={add}>Add</Button>}
>
  <Column>
    <Text>Main Content</Text>
  </Column>
</Scaffold>

Scaffold in Layouts

Use Scaffold in +layout.wh files for consistent screen structure:

// +layout.wh
<Scaffold>
  <TopAppBar title="App" />
  <slot />  // Screen content goes here
  <BottomNavigation>
    <NavigationBarItem icon="home" label="Home" />
    <NavigationBarItem icon="search" label="Search" />
  </BottomNavigation>
</Scaffold>

Common Patterns

Header/Content/Footer

<Column fillMaxSize>
  <Row safeTop px={16} py={12} background="primary">
    <Text color="#FFF" fontSize={20}>Header</Text>
  </Row>

  <Column weight={1} scrollable p={16}>
    <Text>Scrollable content</Text>
  </Column>

  <Row safeBottom p={16} background="#F5F5F5">
    <Button text="Cancel" />
    <Spacer weight={1} />
    <Button text="Save" />
  </Row>
</Column>

Side-by-Side

<Row gap={16} p={16}>
  <Column weight={1}>
    <Text>Left Column</Text>
  </Column>

  <Column weight={1}>
    <Text>Right Column</Text>
  </Column>
</Row>

Card Grid

<Column scrollable p={16} gap={16}>
  <Row gap={16}>
    <Card weight={1}>Item 1</Card>
    <Card weight={1}>Item 2</Card>
  </Row>
  <Row gap={16}>
    <Card weight={1}>Item 3</Card>
    <Card weight={1}>Item 4</Card>
  </Row>
</Column>

Centering

// Center in available space
<Column fillMaxSize horizontalAlignment="center" verticalArrangement="center">
  <Text>Centered</Text>
</Column>

// Center with Box
<Box fillMaxSize contentAlignment="center">
  <Text>Centered</Text>
</Box>

Padding and Spacing

Individual Sides

<Column pt={16} pb={8} pl={20} pr={20}>
  <Text>Content</Text>
</Column>

Horizontal/Vertical

<Row px={16} py={12}>
  <Text>Content</Text>
</Row>

All Sides

<Column p={20}>
  <Text>Content</Text>
</Column>

Safe Area Insets

Automatically pad for system UI:

<Column safeTop>
  <Text>Below status bar</Text>
</Column>

<Row safeBottom>
  <Text>Above navigation bar</Text>
</Row>

Tailwind-Style Classes

Use utility classes for rapid prototyping:

<Column class="p-16 gap-8 items-center bg-primary rounded-lg">
  <Text class="text-lg font-bold">Title</Text>
  <Text class="text-sm">Description</Text>
</Column>

Common classes:

  • Padding: p-16, px-8, py-12, pt-8
  • Layout: gap-8, items-center, justify-between
  • Size: w-full, h-full, w-48
  • Background: bg-primary, bg-surface
  • Shape: rounded-lg, rounded-full

When both class and prop are specified, the prop takes precedence. class="p-16" p={20} results in 20dp padding.

See Also