Summary#
A list pane 440px wide on a 1440px screen is narrow, and the screen is not. Ask the question you mean:
[Route("/inbox")] [AllowAnonymous]
component InboxPage() {
render {
Row(gap: 4) {
Box(w: "440px") { InboxList(); }
Box(grow: 1) { Text("Reading pane"); }
}
}
}
[Composable]
component InboxList() {
render {
Stack(gap: 2) {
// The ROOM: this pane is never wide enough for columns, so it lays out as cards.
if (Layout.AtLeast(Tablet)) { Text("Subject · From · Received"); }
// The DEVICE: on a desk-sized window, say which keys move through the list.
if (Viewport.AtLeast(Laptop)) { Text("J and K move between messages"); }
Text("Your messages");
}
}
}Signature#
Viewport.AtLeast(<breakpoint>) // is the browser window at least this wide?
Layout.AtLeast(<breakpoint>) // is THIS component's container at least this wide?Description#
Which one do I want?#
| You are deciding | Ask |
|---|---|
| whether a table fits, how many columns, cards or rows | Layout.AtLeast — the room the component was given |
| something about the DEVICE — key hints, a desk-only shortcut bar, a phone-only bottom bar | Viewport.AtLeast — the window |
A component placed in a narrow column should lay itself out narrow however wide the window is, which is why
Layout.AtLeast measures the container. But a narrow column on a wide window is still a desk with a keyboard in front
of it, and asking the container would hide a desk's key hints in exactly the pane where they help.
Which names can I pass?#
A declared Breakpoints token, written bare — the kit declares Phone (480), Tablet (768), Laptop (1100),
Desktop (1440) and Widescreen (1680), and a theme may add its own (theme tokens). The same names a variants
block's Tablet { … } override uses, so the two agree about where a layout changes.
Where can I use them?#
In a render block. An action or function body may run on the server, where there is no window and nothing on
screen, so both are refused there with a message naming render; decide in render and pass the answer on.
What does the server answer?#
false for both — mobile-first, the narrow arm. The browser corrects it on its first render, and from then on each
follows its own width: resizing the window re-renders a Viewport.AtLeast branch with nothing wired by the app.
How do I test it?#
Ui.Viewport(1440) sets the window's width, before or after a visit: Ui.Viewport(390) mid-test makes the page
re-flow on the spot (Ui — drive the app's UI from a test).
See also#
- theme tokens — declaring breakpoints, and styling at them
- style props — style props, which take a breakpoint override instead of a branch
- keys — key bindings and the hints that show them
- Device.HasKeyboard — whether to show key hints —
Device.HasKeyboard: whether there are keys to hint at, which a window's width cannot tell