Skip to content

View Switching

When your window has several peer pages and shows one at a time, put the pages in a view stack and give the user a switcher to pick between them. Five switchers are on this page, and all of them adapt to the window: a wide desktop gets the full switcher and a narrow phone gets a collapsed one.

What the preview does not show

The previews run the browser port, so gestures Libadwaita drives natively (drag-to-reorder tabs, the tab bar’s auto-hide, cross-fade transitions) can be simplified here. Click a switcher button, a tab or a carousel dot to move between pages. The carousel’s own gestures are not simplified — see below.

The standard switcher: one segmented control whose buttons each carry a page’s icon and label, driving a paired view stack. Its policy decides the button layout. wide puts the icon and label side by side; narrow stacks the icon above the label so the bar fits a slim window. An adaptive layout normally swaps between the two on a breakpoint.

Blueprint
Code
using Gtk 4.0;
using Adw 1;
Adw.ToolbarView {
[top]
Adw.HeaderBar {
title-widget: Adw.ViewSwitcher {
policy: wide;
stack: stack;
};
}
content: Adw.ViewStack stack {
Adw.ViewStackPage {
name: "inbox";
title: _("Inbox");
icon-name: "mail-unread-symbolic";
child: Adw.StatusPage {
icon-name: "mail-unread-symbolic";
title: _("Inbox");
description: _("You have three unread conversations.");
};
}
Adw.ViewStackPage {
name: "starred";
title: _("Starred");
icon-name: "starred-symbolic";
child: Adw.StatusPage {
icon-name: "starred-symbolic";
title: _("Starred");
description: _("Messages you have marked as important.");
};
}
Adw.ViewStackPage {
name: "archive";
title: _("Archive");
icon-name: "folder-symbolic";
child: Adw.StatusPage {
icon-name: "folder-symbolic";
title: _("Archive");
description: _("Older conversations kept for reference.");
};
}
};
}
TypeScript
TypeScript
import Adw from 'gi://Adw?version=1';
import Gtk from 'gi://Gtk?version=4.0';
// The view stack holds the pages; each is added with a name, title and icon.
const stack = new Adw.ViewStack({ vexpand: true });
stack.add_titled_with_icon(
new Adw.StatusPage({ iconName: 'mail-unread-symbolic', title: 'Inbox', description: 'You have three unread conversations.' }),
'inbox', 'Inbox', 'mail-unread-symbolic',
);
stack.add_titled_with_icon(
new Adw.StatusPage({ iconName: 'starred-symbolic', title: 'Starred', description: 'Messages you have marked as important.' }),
'starred', 'Starred', 'starred-symbolic',
);
stack.add_titled_with_icon(
new Adw.StatusPage({ iconName: 'folder-symbolic', title: 'Archive', description: 'Older conversations kept for reference.' }),
'archive', 'Archive', 'folder-symbolic',
);
// The switcher drives the stack; policy is Adw.ViewSwitcherPolicy.WIDE | NARROW.
const switcher = new Adw.ViewSwitcher({
stack,
policy: Adw.ViewSwitcherPolicy.WIDE,
halign: Gtk.Align.CENTER,
});
const box = new Gtk.Box({ orientation: Gtk.Orientation.VERTICAL, spacing: 12 });
box.append(switcher);
box.append(stack);
Web Components
HTML
<adw-view-switcher policy="wide" style="flex: 1; width: 100%;">
<adw-view-switcher-page name="inbox" title="Inbox" icon-name="mail-unread">
<!-- description: The description markup to be displayed below the title. -->
<adw-status-page icon="mail-unread" title="Inbox" description="You have three unread conversations."></adw-status-page>
</adw-view-switcher-page>
<adw-view-switcher-page name="starred" title="Starred" icon-name="starred">
<!-- description: The description markup to be displayed below the title. -->
<adw-status-page icon="starred" title="Starred" description="Messages you have marked as important."></adw-status-page>
</adw-view-switcher-page>
<adw-view-switcher-page name="archive" title="Archive" icon-name="folder">
<!-- description: The description markup to be displayed below the title. -->
<adw-status-page icon="folder" title="Archive" description="Older conversations kept for reference."></adw-status-page>
</adw-view-switcher-page>
</adw-view-switcher>

The narrow-window half of the same pattern. When the window is too slim for a switcher in the header bar, put one at the bottom edge instead — that is a view switcher bar, pinned into a toolbar view’s bottom slot and bound to the same stack.

`reveal` is a request, not a state

A stack with fewer than two pages stays collapsed however loudly it is asked, so a bar over a one-page stack simply does not appear.

Blueprint
Code
using Gtk 4.0;
using Adw 1;
Adw.ToolbarView {
content: Adw.ViewStack stack {
Adw.ViewStackPage {
name: "inbox";
title: _("Inbox");
icon-name: "mail-unread-symbolic";
child: Adw.StatusPage {
icon-name: "mail-unread-symbolic";
title: _("Inbox");
description: _("The inbox page.");
};
}
Adw.ViewStackPage {
name: "starred";
title: _("Starred");
icon-name: "starred-symbolic";
child: Adw.StatusPage {
icon-name: "starred-symbolic";
title: _("Starred");
description: _("The starred page.");
};
}
Adw.ViewStackPage {
name: "archive";
title: _("Archive");
icon-name: "folder-symbolic";
child: Adw.StatusPage {
icon-name: "folder-symbolic";
title: _("Archive");
description: _("The archive page.");
};
}
};
[bottom]
Adw.ViewSwitcherBar {
stack: stack;
reveal: true;
}
}
TypeScript
TypeScript
import { build } from './view-switcher-bar.blp';
const { stack } = build();
stack.visibleChildName = 'starred';
Web Components
index.html
HTML
<adw-toolbar-view>
<adw-view-stack id="stack" slot="content">
<adw-view-stack-page
name="inbox"
title="Inbox"
icon-name="mail-unread-symbolic"
>
<adw-status-page
icon-name="mail-unread-symbolic"
title="Inbox"
description="The inbox page."
slot="child"
></adw-status-page>
</adw-view-stack-page>
<adw-view-stack-page
name="starred"
title="Starred"
icon-name="starred-symbolic"
>
<adw-status-page
icon-name="starred-symbolic"
title="Starred"
description="The starred page."
slot="child"
></adw-status-page>
</adw-view-stack-page>
<adw-view-stack-page
name="archive"
title="Archive"
icon-name="folder-symbolic"
>
<adw-status-page
icon-name="folder-symbolic"
title="Archive"
description="The archive page."
slot="child"
></adw-status-page>
</adw-view-stack-page>
</adw-view-stack>
<adw-view-switcher-bar
stack="stack"
reveal
slot="bottom"
></adw-view-switcher-bar>
</adw-toolbar-view>
<script type="module">
import '@gjsify/adwaita-web';
const stack = document.querySelector('#stack');
stack.visibleChildName = 'starred';
</script>
main.js (Blueprint)
JavaScript
import { mountSharedTree } from '@gjsify/adwaita-web';
import tree from './view-switcher-bar.blp?shared-tree';
mountSharedTree(tree);
const stack = document.querySelector('#stack');
stack.visibleChildName = 'starred';
NativeScript
views/view-switcher-bar.xml
XML
<adw:ToolbarView
xmlns="http://schemas.nativescript.org/tns.xsd"
xmlns:adw="~/adw"
>
<adw:ToolbarView.content>
<adw:ViewStack id="stack">
<adw:ViewStackPage
name="inbox"
title="Inbox"
iconName="mail-unread-symbolic"
>
<adw:ViewStackPage.child>
<adw:StatusPage
iconName="mail-unread-symbolic"
title="Inbox"
description="The inbox page."
/>
</adw:ViewStackPage.child>
</adw:ViewStackPage>
<adw:ViewStackPage
name="starred"
title="Starred"
iconName="starred-symbolic"
>
<adw:ViewStackPage.child>
<adw:StatusPage
iconName="starred-symbolic"
title="Starred"
description="The starred page."
/>
</adw:ViewStackPage.child>
</adw:ViewStackPage>
<adw:ViewStackPage
name="archive"
title="Archive"
iconName="folder-symbolic"
>
<adw:ViewStackPage.child>
<adw:StatusPage
iconName="folder-symbolic"
title="Archive"
description="The archive page."
/>
</adw:ViewStackPage.child>
</adw:ViewStackPage>
</adw:ViewStack>
</adw:ToolbarView.content>
<adw:ToolbarView.bottom>
<adw:ViewSwitcherBar stack="stack" reveal="true" />
</adw:ToolbarView.bottom>
</adw:ToolbarView>
app.ts
TypeScript
import { type Adw } from '@gjsify/adwaita-nativescript';
import { Builder } from '@nativescript/core';
const view = Builder.load({ path: '~/views', name: 'view-switcher-bar' }) as Adw.ToolbarView;
const stack = view.getViewById<Adw.ViewStack>('stack')!;
stack.visibleChildName = 'starred';
app.ts (Blueprint)
TypeScript
import { type Adw } from '@gjsify/adwaita-nativescript';
import { build } from '@gjsify/adwaita-nativescript/builder';
import tree from './view-switcher-bar.blp?shared-tree';
const view = build(tree) as Adw.ToolbarView;
const stack = view.getViewById<Adw.ViewStack>('stack')!;
stack.visibleChildName = 'starred';

Reach for a tab view when the pages are not fixed. Unlike a view switcher, tabs are meant to be added, closed and reordered while the app runs. The tab bar draws one chip per page, each with a title and a close button, and raises the selected chip onto the view background.

Autohide

Turn on autohide and the bar disappears once a single page is left, so a one-tab document looks chrome-free.

Blueprint
Code
using Gtk 4.0;
using Adw 1;
Gtk.Box {
orientation: vertical;
Adw.TabBar {
view: tabs;
}
Adw.TabView tabs {
vexpand: true;
}
}
TypeScript
TypeScript
import Adw from 'gi://Adw?version=1';
import Gtk from 'gi://Gtk?version=4.0';
const tabView = new Adw.TabView({ vexpand: true });
for (const [title, body] of [
['Overview', 'A summary of everything at a glance.'],
['Details', 'The specifics, broken down line by line.'],
['History', 'A log of every change made so far.'],
] as const) {
const page = tabView.append(new Adw.StatusPage({ iconName: 'view-paged-symbolic', title, description: body }));
page.title = title;
}
// The tab bar renders the chips; autohide collapses it down to a single tab.
const tabBar = new Adw.TabBar({ view: tabView, autohide: false });
const box = new Gtk.Box({ orientation: Gtk.Orientation.VERTICAL });
box.append(tabBar);
box.append(tabView);
Web Components
HTML
<adw-tab-view style="flex: 1; width: 100%;">
<adw-tab-page title="Overview">
<!-- description: The description markup to be displayed below the title. -->
<adw-status-page icon="view-paged" title="Overview" description="A summary of everything at a glance."></adw-status-page>
</adw-tab-page>
<adw-tab-page title="Details">
<!-- description: The description markup to be displayed below the title. -->
<adw-status-page icon="view-paged" title="Details" description="The specifics, broken down line by line."></adw-status-page>
</adw-tab-page>
<adw-tab-page title="History">
<!-- description: The description markup to be displayed below the title. -->
<adw-status-page icon="view-paged" title="History" description="A log of every change made so far."></adw-status-page>
</adw-tab-page>
</adw-tab-view>

A button that stands in for a tab bar when there is no room for one. It shows how many pages its view holds, and lights a dot when a page you are not looking at needs attention. The number gets smaller from ten pages and gives way to a glyph at a hundred. Pair it with an action that opens a tab overview, and listen to clicked to do so.

Blueprint
Code
using Gtk 4.0;
using Adw 1;
Gtk.Box {
Adw.TabButton {
view: tabs;
}
Adw.TabView tabs {}
}
TypeScript
TypeScript
import Adw from 'gi://Adw?version=1';
import Gtk from 'gi://Gtk?version=4.0';
const view = new Adw.TabView();
for (const title of ['One', 'Two', 'Three']) {
view.append(new Gtk.Box()).title = title;
}
// Counts the pages; `needs-attention` on a page that is not selected lights the dot.
const button = new Adw.TabButton({ view });
button.connect('clicked', () => console.log('Open the tab overview'));
Web Components
HTML
<adw-tab-view id="tabs" style="display:none;">
<adw-tab-page title="One"></adw-tab-page>
<adw-tab-page title="Two"></adw-tab-page>
<adw-tab-page title="Three"></adw-tab-page>
</adw-tab-view>
<adw-tab-button view="tabs"></adw-tab-button>

The tab bar on its own. libadwaita keeps it a separate widget from the view it drives, bound through its view property, which is what lets one bar sit over a view it does not own — a header bar of its own, or a strip that belongs to the window rather than to the pages. Adw.TabView carries a merged bar of its own, so reach for this one when the bar and the view are two things in your layout.

Each tab is a chip with the page’s title, its icon and its close button. Two action widgets may sit either side of the chips, and inverted swaps the order inside every chip: the close button moves to the leading edge and the indicator to the trailing one.

Autohide and expand-tabs

Autohide is the bar’s default upstream, and it hides the strip once a single page is left — a pinned page keeps it up. Expand-tabs makes the chips fill the strip instead of sitting at their smallest size. Both default TRUE in libadwaita, and an HTML boolean attribute can only spell “present”, so both are opt-in in the markup: write the attribute to get the behaviour, leave it off for the other one.

Blueprint
Code
using Gtk 4.0;
using Adw 1;
Gtk.Box {
orientation: vertical;
Adw.TabBar {
view: tabs;
autohide: false;
start-action-widget: Gtk.Button {
icon-name: "list-add-symbolic";
styles ["flat"]
};
}
Adw.TabView tabs {
vexpand: true;
}
}
TypeScript
TypeScript
import Adw from 'gi://Adw?version=1';
import Gtk from 'gi://Gtk?version=4.0';
const tabView = new Adw.TabView({ vexpand: true });
for (const [title, body] of [
['Overview', 'A summary of everything at a glance.'],
['Details', 'The specifics, broken down line by line.'],
['History', 'A log of every change made so far.'],
] as const) {
const page = tabView.append(new Adw.StatusPage({ iconName: 'view-paged-symbolic', title, description: body }));
page.title = title;
}
// The bar is a widget of its own over the view; `autohide` and `expand-tabs` both
// default TRUE here, so the strip would start collapsed without the first.
const tabBar = new Adw.TabBar({ view: tabView, autohide: false });
tabBar.startActionWidget = new Gtk.Button({ iconName: 'list-add-symbolic', cssClasses: ['flat'] });
tabBar.endActionWidget = new Gtk.Button({ iconName: 'view-more-symbolic', cssClasses: ['flat'] });
const box = new Gtk.Box({ orientation: Gtk.Orientation.VERTICAL });
box.append(tabBar);
box.append(tabView);
Web Components
HTML
<!-- view: The tab view the tab bar controls. -->
<adw-tab-bar view="tabs" style="flex: 0 0 auto;">
<button slot="start-action-widget" class="adw-button flat image-button" title="New page">
<gtk-image icon="list-add"></gtk-image>
</button>
<button slot="end-action-widget" class="adw-button flat image-button" title="Menu">
<gtk-image icon="view-more"></gtk-image>
</button>
</adw-tab-bar>
<adw-tab-view id="tabs" style="flex: 1;">
<adw-tab-page title="Overview">
<!-- description: The description markup to be displayed below the title. -->
<adw-status-page icon="view-paged" title="Overview" description="A summary of everything at a glance."></adw-status-page>
</adw-tab-page>
<adw-tab-page title="Details">
<!-- description: The description markup to be displayed below the title. -->
<adw-status-page icon="view-paged" title="Details" description="The specifics, broken down line by line."></adw-status-page>
</adw-tab-page>
<adw-tab-page title="History">
<!-- description: The description markup to be displayed below the title. -->
<adw-status-page icon="view-paged" title="History" description="A log of every change made so far."></adw-status-page>
</adw-tab-page>
</adw-tab-view>

The overview is every page at once: a grid of thumbnails over the tab view, with the page title under each one and its own close button on it. It is meant to be the direct child of the window, with the tab view as its child — opening it covers that view and closing it gives it back.

The header bar counts the open pages (3 Tabs, 1 Tab for a single page) and carries the search button; the search matches titles, tooltips and each page’s keyword, so a browser can make its URLs findable. Turn enable-search off and the button goes, leaving a bar that shows nothing worth showing — which is also what happens when the secondary menu is unset and both sides’ title buttons are off.

Pinned pages

A pinned page gets its own grid above the ordinary one, and its thumbnail carries an unpin mark instead of a close button — that is the arrangement the tab bar’s narrow chips come from. Inverted puts each thumbnail’s close button at the leading edge and its indicator at the trailing one, for a right-to-left layout.

What the thumbnails are not

GTK paints each page into a texture and shows that picture. A browser cannot paint a widget into a texture, so the portrait area shows the page’s own title instead. Everything around it — the card, the close button, the unpin mark, the attention dot, the indicator — is the real thing. Thumbnails are not dragged to reorder here either: reordering goes through the tab view’s own API, the way the tab bar does it.

Blueprint
Code
using Gtk 4.0;
using Adw 1;
Adw.TabOverview {
child: Adw.TabView tabs {};
view: tabs;
}
TypeScript
TypeScript
import Adw from 'gi://Adw?version=1';
import Gtk from 'gi://Gtk?version=4.0';
const view = new Adw.TabView();
for (const title of ['One', 'Two', 'Three']) {
view.append(new Gtk.Box()).title = title;
}
// The view goes in twice, deliberately: once as the overview's `child` (the thing it
// covers) and once as its `view` (the thing whose pages it lists).
const overview = new Adw.TabOverview({ view, child: view, enableNewTab: true });
// `overview.open` / `overview.close` are the two actions an Adw.TabButton pairs with.
const button = new Adw.TabButton({ view });
button.connect('clicked', () => overview.activate_overview_open());
Web Components
HTML
<adw-tab-overview open enable-new-tab>
<adw-tab-view>
<adw-tab-page title="One"></adw-tab-page>
<adw-tab-page title="Two"></adw-tab-page>
<adw-tab-page title="Three" pinned></adw-tab-page>
</adw-tab-view>
</adw-tab-overview>

When a full switcher is too wide for the space, use the inline one. It is built from a linked toggle group and drives the same kind of view stack, but its display mode lets each toggle show labels, icons or both. That makes it fit a header bar or a tight toolbar.

Blueprint
Code
using Gtk 4.0;
using Adw 1;
Gtk.Box {
orientation: vertical;
spacing: 12;
Adw.InlineViewSwitcher {
display-mode: both;
stack: stack;
halign: center;
}
Adw.ViewStack stack {
vexpand: true;
Adw.ViewStackPage {
title: _("Overview");
icon-name: "view-grid-symbolic";
child: Adw.StatusPage {
icon-name: "view-grid-symbolic";
title: _("Overview");
description: _("A quick summary of your project.");
};
}
Adw.ViewStackPage {
title: _("Activity");
icon-name: "document-edit-symbolic";
child: Adw.StatusPage {
icon-name: "document-edit-symbolic";
title: _("Activity");
description: _("Recent edits and changes.");
};
}
Adw.ViewStackPage {
title: _("Settings");
icon-name: "emblem-system-symbolic";
child: Adw.StatusPage {
icon-name: "emblem-system-symbolic";
title: _("Settings");
description: _("Configure how things behave.");
};
}
}
}
TypeScript
TypeScript
import Adw from 'gi://Adw?version=1';
import Gtk from 'gi://Gtk?version=4.0';
const stack = new Adw.ViewStack({ vexpand: true });
stack.add_titled_with_icon(
new Adw.StatusPage({ iconName: 'view-grid-symbolic', title: 'Overview', description: 'A quick summary of your project.' }),
'overview', 'Overview', 'view-grid-symbolic',
);
stack.add_titled_with_icon(
new Adw.StatusPage({ iconName: 'document-edit-symbolic', title: 'Activity', description: 'Recent edits and changes.' }),
'activity', 'Activity', 'document-edit-symbolic',
);
stack.add_titled_with_icon(
new Adw.StatusPage({ iconName: 'emblem-system-symbolic', title: 'Settings', description: 'Configure how things behave.' }),
'settings', 'Settings', 'emblem-system-symbolic',
);
// displayMode is LABELS | ICONS | BOTH.
const switcher = new Adw.InlineViewSwitcher({
stack,
displayMode: Adw.InlineViewSwitcherDisplayMode.BOTH,
halign: Gtk.Align.CENTER,
});
const box = new Gtk.Box({ orientation: Gtk.Orientation.VERTICAL, spacing: 12 });
box.append(switcher);
box.append(stack);
Web Components
HTML
<adw-inline-view-switcher display-mode="both" style="flex: 1; width: 100%;">
<adw-view-stack-page title="Overview" icon-name="view-grid">
<!-- description: The description markup to be displayed below the title. -->
<adw-status-page id="overview" icon="view-grid" title="Overview" description="A quick summary of your project."></adw-status-page>
</adw-view-stack-page>
<adw-view-stack-page title="Activity" icon-name="document-edit">
<!-- description: The description markup to be displayed below the title. -->
<adw-status-page id="activity" icon="document-edit" title="Activity" description="Recent edits and changes."></adw-status-page>
</adw-view-stack-page>
<adw-view-stack-page title="Settings" icon-name="emblem-system">
<!-- description: The description markup to be displayed below the title. -->
<adw-status-page id="settings" icon="emblem-system" title="Settings" description="Configure how things behave."></adw-status-page>
</adw-view-stack-page>
</adw-inline-view-switcher>

The one Adw switcher built out of a sidebar, and the one whose rows can be grouped into sections. Point it at a view stack and each page becomes a row with its icon, its title and — when it asks — an unread dot or a badge count; starts-section on a page opens a new group, headed by that page’s section-title.

It is adaptive in the sidebar’s sense: mode=“page” turns it into a page of boxed lists, which is what a NavigationSplitView wants for its sidebar pane once the window is too narrow for a sidebar. Keep it in sidebar mode with an OverlaySplitView, where the pane is still a sidebar when collapsed.

Ordering of `activated`

Activating a row selects the stack page first and only then emits activated — that is the signal a split view reveals its content pane on, so a handler that read the stack inside it would otherwise reveal the page you were leaving.

Blueprint
Code
using Gtk 4.0;
using Adw 1;
Adw.NavigationSplitView {
sidebar: Adw.NavigationPage {
child: Adw.ViewSwitcherSidebar {
stack: pages;
};
};
content: Adw.NavigationPage {
child: Adw.ViewStack pages {};
};
}
TypeScript
TypeScript
import Adw from 'gi://Adw?version=1';
import Gtk from 'gi://Gtk?version=4.0';
const stack = new Adw.ViewStack();
const inbox = stack.add(new Gtk.Box(), 'inbox');
inbox.title = 'Inbox';
// `starts_section` opens the group; `section_title` names it.
inbox.starts_section = true;
inbox.section_title = 'Mail';
inbox.badge_number = 3;
// Each page becomes a row; the stack's visible page marks its row.
const sidebar = new Adw.ViewSwitcherSidebar({ stack });
sidebar.connect('activated', () => console.log('Reveal the content pane'));
Web Components
HTML
<adw-view-switcher-sidebar>
<!-- description: The description markup to be displayed below the title. -->
<adw-status-page slot="placeholder" title="No Results" description="Try a different search"></adw-status-page>
</adw-view-switcher-sidebar>
<adw-view-stack>
<adw-view-stack-page name="inbox" title="Inbox" starts-section section-title="Mail" badge-number="3"></adw-view-stack-page>
<adw-view-stack-page name="drafts" title="Drafts"></adw-view-stack-page>
<!-- needs-attention: Whether the page requires the user attention. -->
<adw-view-stack-page name="archive" title="Archive" starts-section section-title="Older" needs-attention></adw-view-stack-page>
</adw-view-stack>

For onboarding screens and galleries, use a carousel: pages sit side by side and the user flicks, scrolls or clicks a page indicator to move between them. Two indicator widgets bind to a carousel, dots (shown here) and lines. Both track the fractional scroll position and grow the marker nearest the current page.

The three gestures

Touch and a touchpad scroll the carousel natively — the browser owns those, momentum and snapping included. A mouse drag is the one the browser has no gesture for, so it is implemented: press inside the carousel and pull, and the pages follow the cursor. Where it lands is Adw.SwipeTracker’s decision, not the browser’s — the drag’s velocity is projected and the nearest reachable page wins, so a short flick pages and a slow half-drag settles back.

The three knobs

The scroll wheel pages the carousel by default; set allow-scroll-wheel="false" to leave wheel events to the page instead. Mouse drag is on by default; allow-mouse-drag="false" leaves dragging to touch, as it does upstream. Long swipes are off by default; turn them on to let one flick skip several pages — with the caveat that a touchpad flick can already cross more than one page here. The setting is applied (each page gets scroll-snap-stop: always when long swipes are off), but the browser does not honour it for that gesture; GTK, which runs the same input through its own tracker, does.

  • Navigation: pages, split views and the navigation stack the switchers sit above.
  • Layout: the Clamp and boxes that size a switched view.
  • Adwaita Storybook: the same widgets in a live component browser you can poke at.