Layout
These four containers give an Adwaita window its shape. Use a clamp to hold content at a readable width, a header bar for the top chrome, a toolbar view to frame content between fixed bars, and a wrap box to let a run of children flow onto new lines. None of them hold data: they position what you put inside and adapt as the space around them changes.
Each block below is a stack of windows. The first one RUNS the widget: the preview
is the live browser port, so it follows the light and dark toggle the way a real
window would, and the HTML tab beside it holds the very markup that paints it —
one import '@gjsify/adwaita-web' registers every element in it. Then comes
one window per kind of implementation, for every kind that can express this widget.
Two of them name a file pair — Native TypeScript, the @girs program that
runs unchanged on GJS, Node, Bun and Deno, with the matching Blueprint declaration
beside it, and NativeScript, the port that runs on a phone, which splits the same
way: an XML template holds the tree and the TypeScript beside it is the loader.
A NativeScript template reaches these widgets through its xmlns, and the namespace
is a MODULE: NativeScript loads it and reads the element name off its exports, so
xmlns:adw="~/adwaita" needs an app-local app/adwaita.ts that re-exports what the
markup names. A bare package specifier there does not resolve. Every XML tab in this
gallery was inflated on an Android device before it was written down —
adwaita-gallery-nativescript
loads each template through NativeScript’s own Builder and asserts the view tree it
built, which is the only way to tell a template that renders from one that renders
something else: an attribute arrives as a string, and a child a widget has no slot for
is added to the layout anyway.
The third, UI frameworks, is on all four as well: each shows the same widget
written in Solid, Vue and React through
@gjsify/gtk-host,
with a @gjsify/react-native tab beside them. The
wrap box only recently joined them. @gjsify/gtk-host had no child policy for
AdwWrapBox, so a child placed in one was refused by name — deliberately, because a
renderer that guessed the policy would call add, append or set_child and be
wrong at exit 0. The policy is now curated against libadwaita, so the block has a tree
like the other three. That window renders a GTK window, not a phone screen — which is
why it is not the NativeScript one, and the React Native
page says what does and does not
exist there.
Two of those three style with className, and both configure their token scales
on the way in. That line is not decoration: the values behind a class name come
from the project, the layer’s default scales are deliberately small (spacing holds
0 and px alone), and a class naming an undeclared token throws out of the
render — leaving an empty window at exit 0 with nothing in the log. The header
bar’s snippet names no class and needs no such line.
Libadwaita is the reference here, typed by
@girs/adw-1.
@gjsify/adwaita-web
and @gjsify/adwaita-nativescript
follow its naming, and where one of them differs, its own window says so.
Wrap long-form content in a clamp so it stops growing at a maximum width and stays centred in anything wider. As the window shrinks, the clamp starts tightening the child once it passes the tightening threshold. That keeps text at a comfortable measure on a large display without wasting room on a small one.
Header Bar
Section titled “Header Bar”The standard top chrome of an Adwaita window. Put a title widget in the centre, usually a window title with a subtitle, and pack controls to the start and end edges: navigation on the leading side, menu and action buttons on the trailing one.
Toolbar View
Section titled “Toolbar View”Frame your content between a top bar and a bottom bar, typically a header bar above and an action bar below. Each set of bars reveals and hides independently, and the content scrolls underneath, so the chrome stays put while the view moves.
Wrap Box
Section titled “Wrap Box”Lay children out in a horizontal line and let them wrap onto new lines when they run out of room. This is what you want for a variable-length run of tags, chips or filter pills. Child spacing sets the gap between items on a line, line spacing the gap between the lines.
Related
Section titled “Related”- Boxed Lists: the rows a
Clampkeeps at a readable width. - Navigation: split views and pages that pair with a
HeaderBar. - Native Adwaita Apps: assemble these into a running app.
- Adwaita Storybook: the same widgets in a live component browser you can poke at.