Kanzo UI
Layout

Section

Content scaffolding — a heading with optional icon, supporting text and actions, over a body and a footer.

The board

Everything the Amber Hall has posted, at a glance.

12 contracts

Usage

import {
  SectionRoot, SectionHeader, SectionIcon, SectionTitleGroup,
  SectionTitle, SectionDescription, SectionActions, SectionBody, SectionFooter,
} from "@kanzo-tech/ui";
<SectionRoot>
  <SectionHeader>
    <SectionIcon><ScrollTextIcon /></SectionIcon>
    <SectionTitleGroup>
      <SectionTitle>Open contracts</SectionTitle>
      <SectionDescription>Posted to the board. Anyone chartered may claim them.</SectionDescription>
    </SectionTitleGroup>
    <SectionActions><Button>Edit</Button></SectionActions>
  </SectionHeader>

  <SectionBody>{/* … */}</SectionBody>
</SectionRoot>

Section vs Shell

Different axis, so they never compete. Shell positions the window — regions, asides, what scrolls. Section positions the content inside one of those regions, and nests within ShellMain.

The one header vocabulary

Section is where a heading with an optional icon, supporting text and end-aligned controls is described, once, for every screen that needs one.

CardHeader and DialogHeader have this same shape and are not part of it — a header wired to a machine stays with its machine, and DialogHeader wires Ark's aria-labelledby. That is the header rule.

Scale

scale is what actually differed between the three. It changes breathing room and the title's weight, nothing else.

  • section (default) — a block within a screen. No padding of its own, so it sits in whatever container you put it in.
  • page — the top of a screen. Adds the page padding and a heavier title.
<SectionHeader scale="page">
  <SectionTitleGroup>
    <SectionTitle level={1} scale="page">The board</SectionTitle>
  </SectionTitleGroup>
</SectionHeader>

level and scale are deliberately separate. How big a title looks and where it sits in the document outline are different questions — tying them would force a visual choice to change your heading semantics. Set level={1} on a page title because it is the page's heading, not because it is large.

Layout

SectionHeader is a flex row, not a grid: SectionTitleGroup plus ms-auto on the actions aligns them without a second code path under RTL, and handles the optional icon a two-column grid could not.

SectionTitleGroup carries min-w-0, which is what lets a long title truncate instead of pushing the actions off the row.

Open contracts

Posted to the board. Anyone chartered may claim them.

Bordered

bordered draws a separator under the header, for when the body below it is dense enough that the heading would otherwise float.

Party rules

Checked when a party signs, and again when it comes back.

SectionBody renders <section>, never <main> — it nests inside a shell that already owns the page's single <main> landmark.

SectionFooter carries a surface and a top border, unlike the header: it sits against the bottom of a scrolling body and has to separate itself from the content sliding under it.

API Reference

SectionHeader

PropTypeDefault
scale"page" | "section""section"
borderedbooleanfalse

Extends ComponentProps<typeof ark.header>, so asChild, ref and every native prop pass through.

SectionTitle

PropTypeDefault
level1 | 2 | 3 | 4 | 5 | 62
scale"page" | "section""section"

Renders h{level} directly rather than through the ark factory, so it extends ComponentProps<"h2"> with ref omitted — and there is no asChild, because level already covers what you would reach for it.

SectionBody

PropTypeDefault
scale"page" | "section""section"

Renders <section>, never <main>. Extends ComponentProps<typeof ark.section>.

Other parts

SectionRoot, SectionIcon, SectionTitleGroup and SectionActions have no props of their own and extend ComponentProps<typeof ark.div>; SectionDescription is ark.p and SectionFooter is ark.footer. All of them take asChild, ref and their element's native props.

Every part's props are exported as an interface — SectionBodyProps, SectionHeaderProps, SectionRootProps and SectionTitleProps — so a wrapper can take the same props without restating them.

On this page