Layout & flexbox
Compose Canvas with Row, Column, Container and Grid. Their semantic props express direction, spacing, alignment and bounds using the same React Native layout on iOS, Android and the web.
The parent provides the bounds.
Fields and cards fill the space their parent gives them. Buttons and badges hug their content. A Container measure caps a group without fixing its width.
Direction
Row arranges siblings horizontally; Column stacks them vertically. Choose a gap with flush, tight, snug, cozy, relaxed or loose.
A
B
C
iOS
A
B
C
Android
A
B
C
Web
tsx
Row
Column
Alignment
center, between and the other distribution props act along the layout's main axis. alignCenter, alignStart, alignEnd and baseline act across it. The example fills its parent, so space-between has real bounds to distribute.
A
B
C
iOS
A
B
C
Android
A
B
C
Web
tsx
Space between
Centered
Sizing
A fill component beside a hugging sibling takes the remaining room. Use Container for a shared measure and span on a Row's direct children for proportional columns; the Row includes its gaps in the calculation.
Search
Connected
iOS
Search
Connected
Android
Search
Connected
Web
tsx
Fill and hug
Measure
Spans
A named measure centers by default. Add start to pin it to the leading edge. Input and other measure-aware controls accept these same step booleans directly.
Responsive layout
Start with the desktop composition. Grid measures its own container to choose how many tiles fit. Row stacks changes direction at its own container breakpoint, preserving mounted controls, field values and focus.
Overview
Activity
Members
iOS
Overview
Activity
Members
Android
Overview
Activity
Members
Web
tsx
Wrapping grid
Stacking row
Choose the smallest mechanism that works.
Intrinsic fill, hug and wrap need no layout state. Container measurement handles component reflow. Viewport hooks are reserved for window-level chrome: a responsive Sidebar or FilterPanel drawer, Popover's sheet on a phone, and app shells.
Viewport tier
Window-level chrome reads the viewport tier: the window's width placed in a breakpoint bucket. A bucket applies at its width and below, and a width wider than every breakpoint, or one not known yet (a server render, the frame before layout), is base, the desktop variant. Consumers re-render only when the bucket changes, never per resize pixel. useFormFactor collapses the buckets into three tiers.
The tier is the window width.
It is the same on every platform: a narrow or zoomed desktop browser window is the phone or tablet tier, and a landscape phone is usually the tablet tier. There is no separate desktop-OS tier; a macOS or desktop web window is placed by its width like any other.
tsx
A server cannot measure a window, so it renders base. An app that knows it is serving a narrow client passes ThemeProvider's ssrBreakpoint (sm for a phone): the server and the hydration render use that bucket, and the real window's bucket applies right after.
Simulating a tier
BreakpointOverride pins the viewport bucket for a subtree, so a preview stage or a test can show the phone or tablet branch inside a desktop window. The form-factor switcher in each example's stage header on the web uses it. It renders nothing of its own.
tsx
- It pins the bucket for every useBreakpoint, useResponsive and useFormFactor reading under it, the Sidebar and FilterPanel drawer modes and Popover's phone sheet included. Menus, dialogs and toasts opened from inside it resolve it too, wherever their overlay layer sits.
- Components that measure their own container (DataTable, Grid, Row stacks, Tabs, Navbar) follow their real width. Constrain the subtree to the tier's width beside the override; their first frame, before they measure, already takes the simulated tier.
- It pins the tier, not the geometry. A drawer or a phone sheet opened under it takes its phone presentation but lays out against the real window, so a simulated phone in a desktop window opens its sheet across the desktop window.
- It is for previews and tests: a real app takes the tier from its window, never from an override.
Accessibility
BreakpointOverride adds nothing to the accessibility tree, and the names, roles and states its consumers put there survive it. Keyboard, screen reader and touch behavior is each consumer's, the same under a simulated tier as under a real one. The tier follows the window's width in CSS pixels, so zooming a desktop browser in reflows the page into the tablet or phone tier.