Knit UI
GitHub

Layout

Everything in the kit is a Box underneath. The layout components are thin, named intentions on top of it — which is worth more than it sounds, because <Group> says "these sit side by side with a gap" and a bare flexDirection does not.

The decision tree

You wantUse
A generic styled containerBox
Explicit flex controlFlex
Vertical rhythmStack
Horizontal row with gapGroup
A real grid with spansGrid
Equal columns, responsiveSimpleGrid
Centred, max-width page bodyContainer
One thing dead centreCenter
Fixed aspect boxAspectRatio
A surface with padding and elevationPaper
Deliberate empty spaceSpacer

Flex defaults differ from the web

<Box>            {/* column */}
<Group>          {/* row, gap, wraps */}
<Stack gap="$md">{/* column, gap */}

Gap, not margins

Prefer gap on the parent to margins on children. It composes, it collapses correctly when a child is conditional, and it is a token.

<Stack gap="$md">
  <TextInput label="Email" />
  {showPassword ? <PasswordInput label="Password" /> : null}
  <Button>Continue</Button>
</Stack>

Scrolling

Use ScrollArea, not a bare ScrollView — it carries the kit's scrollbar chrome, keyboard scrolling, and the reach callbacks (onReachEnd, onReachTop) that pagination hangs off.

For long lists, VirtualList windows rows and keeps a mounted pool, which is what you want past a few hundred items.

Responsive layout

Every style prop takes breakpoint objects, and useMedia() gives you the same information in JS:

<SimpleGrid cols={{ xxs: 1, sm: 2, lg: 3 }} gap="$md" />

See Responsive.

Safe areas and the keyboard

KeyboardAvoidingView and KeyboardAwareScrollView are in the kit and handle the native keyboard through the platform Keyboard API — no third-party controller is needed or used.