Skip to content

Navigation

Navigation widgets move between the top-level places of an app and adapt that movement to the window size. On a wide window a sidebar and its content sit side by side; as the window narrows the same structure folds into a stack you push and pop, or a panel that overlays the content. Each widget below is described independently of any one toolkit, then shown three ways.

Native GJS (real Libadwaita through @girs/adw-1) is the primary implementation; the Web (@gjsify/adwaita-web) and NativeScript (@gjsify/adwaita-nativescript) ports mirror it.

A resizable sidebar beside a content pane. On a wide window the two panes sit side by side; when the window is narrow the view collapses into a single navigation stack, where selecting a sidebar row pushes the content page and a back button returns to the list. The sidebar and content are each a navigation page with its own header bar.

Adw.NavigationSplitView
TypeScript
import Adw from '@girs/adw-1';
// Sidebar: an Adw.Sidebar, NOT a boxed list. A boxed list is a card of
// settings and draws itself as one — rounded, bordered, edge to edge in a
// pane that gives it no margin. A navigation sidebar is a flat selectable
// list, and the widget that already knows how to be one is this.
const section = new Adw.SidebarSection();
for (const [title, subtitle, icon] of [
['All Mail', '128 messages', 'mail-unread-symbolic'],
['Starred', '6 messages', 'starred-symbolic'],
] as const) {
section.append(new Adw.SidebarItem({ title, subtitle, iconName: icon }));
}
const sidebarList = new Adw.Sidebar({ mode: Adw.SidebarMode.SIDEBAR, selected: 0 });
sidebarList.append(section);
const sidebarToolbar = new Adw.ToolbarView();
sidebarToolbar.add_top_bar(new Adw.HeaderBar());
sidebarToolbar.content = sidebarList;
const sidebar = new Adw.NavigationPage({ title: 'Mailboxes', child: sidebarToolbar });
// Content: a status page inside a toolbar view.
const status = new Adw.StatusPage({
iconName: 'mail-unread-symbolic',
title: 'All Mail',
description: 'Select a conversation from the list to read it here.',
vexpand: true,
});
const contentToolbar = new Adw.ToolbarView();
contentToolbar.add_top_bar(new Adw.HeaderBar());
contentToolbar.content = status;
const content = new Adw.NavigationPage({ title: 'All Mail', child: contentToolbar });
const view = new Adw.NavigationSplitView({ sidebar, content, showContent: true });
Code
using Gtk 4.0;
using Adw 1;
Adw.NavigationSplitView {
sidebar: Adw.NavigationPage {
title: _("Mailboxes");
child: Adw.ToolbarView {
[top]
Adw.HeaderBar {}
content: Adw.Sidebar {
mode: sidebar;
selected: 0;
Adw.SidebarSection {
Adw.SidebarItem {
title: _("All Mail");
subtitle: _("128 messages");
icon-name: "mail-unread-symbolic";
}
Adw.SidebarItem {
title: _("Starred");
subtitle: _("6 messages");
icon-name: "starred-symbolic";
}
Adw.SidebarItem {
title: _("Drafts");
subtitle: _("2 messages");
icon-name: "document-edit-symbolic";
}
Adw.SidebarItem {
title: _("Archive");
subtitle: _("512 messages");
icon-name: "folder-symbolic";
}
}
};
};
};
content: Adw.NavigationPage {
title: _("All Mail");
child: Adw.ToolbarView {
[top]
Adw.HeaderBar {}
content: Adw.StatusPage {
icon-name: "mail-unread-symbolic";
title: _("All Mail");
description: _("Select a conversation from the list to read it here.");
};
};
};
}
HTML
<!-- import '@gjsify/adwaita-web' once to register the elements -->
<div style="height: 340px; width: 100%; display: flex; overflow: hidden;">
<adw-navigation-split-view show-content style="flex: 1;">
<adw-toolbar-view slot="sidebar">
<adw-header-bar slot="top">
<adw-window-title slot="center" title="Mailboxes"></adw-window-title>
</adw-header-bar>
<adw-sidebar mode="sidebar" selected="0">
<adw-sidebar-section>
<adw-sidebar-item title="All Mail" subtitle="128 messages" icon-name="mail-unread-symbolic"></adw-sidebar-item>
<adw-sidebar-item title="Starred" subtitle="6 messages" icon-name="starred-symbolic"></adw-sidebar-item>
<adw-sidebar-item title="Drafts" subtitle="2 messages" icon-name="document-edit-symbolic"></adw-sidebar-item>
<adw-sidebar-item title="Archive" subtitle="512 messages" icon-name="folder-symbolic"></adw-sidebar-item>
</adw-sidebar-section>
</adw-sidebar>
</adw-toolbar-view>
<adw-toolbar-view slot="content">
<adw-header-bar slot="top">
<adw-window-title slot="center" title="All Mail"></adw-window-title>
</adw-header-bar>
<adw-status-page icon="mail-unread-symbolic" title="All Mail" description="Select a conversation from the list to read it here."></adw-status-page>
</adw-toolbar-view>
</adw-navigation-split-view>
</div>
TypeScript
import {
AdwHeaderBar,
AdwNavigationSplitView,
AdwSidebar,
AdwStatusPage,
AdwToolbarView,
} from '@gjsify/adwaita-nativescript';
import { mailUnreadSymbolic } from '@gjsify/adwaita-icons/status';
// Sidebar: the navigation list, not a boxed list. The NS surface takes a
// flat label list (no per-item subtitle/icon slot).
const sidebarList = new AdwSidebar();
sidebarList.setItems(['All Mail', 'Starred', 'Drafts', 'Archive']);
sidebarList.selected = 0;
const sidebarHeader = new AdwHeaderBar();
sidebarHeader.title = 'Mailboxes';
const sidebar = new AdwToolbarView();
sidebar.addTopBar(sidebarHeader);
sidebar.setContent(sidebarList);
// Content: a status page inside a toolbar view.
const status = new AdwStatusPage();
status.icon = mailUnreadSymbolic;
status.title = 'All Mail';
status.description = 'Select a conversation from the list to read it here.';
const contentHeader = new AdwHeaderBar();
contentHeader.title = 'All Mail';
const content = new AdwToolbarView();
content.addTopBar(contentHeader);
content.setContent(status);
const view = new AdwNavigationSplitView();
view.setSidebar(sidebar);
view.setContent(content);
view.showSidebar = true;

A sidebar shown beside the content, or laid over the top of it when collapsed. Unlike the navigation split view, the collapsed sidebar overlays the content as a temporary panel — sliding in over a dimming scrim — rather than replacing it. This suits a utility, filter or navigation pane that should not push the primary content aside on a narrow window.

Adw.OverlaySplitView
TypeScript
import Adw from '@girs/adw-1';
// Sidebar: a flat, title-less toolbar view over an Adw.Sidebar. The pane
// needs no style class of its own — Adw.OverlaySplitView puts `.sidebar-pane`
// on it while docked and `.overlay-pane` while collapsed, which is what
// gives it its colour. (The old `.sidebar` class libadwaita deprecates in
// favour of `.navigation-sidebar`; Adw.Sidebar carries that look itself.)
const section = new Adw.SidebarSection();
for (const [title, icon] of [
['Home', 'go-home-symbolic'],
['Discover', 'system-search-symbolic'],
['Library', 'folder-music-symbolic'],
['Settings', 'emblem-system-symbolic'],
] as const) {
section.append(new Adw.SidebarItem({ title, iconName: icon }));
}
const sidebarList = new Adw.Sidebar({ mode: Adw.SidebarMode.SIDEBAR, selected: 0 });
sidebarList.append(section);
const sidebar = new Adw.ToolbarView();
sidebar.add_top_bar(new Adw.HeaderBar({ showTitle: false }));
sidebar.content = sidebarList;
const status = new Adw.StatusPage({
iconName: 'folder-music-symbolic',
title: 'Your Library',
description: 'Toggle the sidebar to browse sections. Collapse it to overlay the content.',
vexpand: true,
});
const content = new Adw.ToolbarView();
content.add_top_bar(new Adw.HeaderBar());
content.content = status;
const view = new Adw.OverlaySplitView({ sidebar, content, showSidebar: true, collapsed: false });
Code
using Gtk 4.0;
using Adw 1;
Adw.OverlaySplitView {
show-sidebar: true;
sidebar: Adw.ToolbarView {
[top]
Adw.HeaderBar {}
content: Adw.Sidebar {
mode: sidebar;
selected: 0;
Adw.SidebarSection {
Adw.SidebarItem {
title: _("Home");
icon-name: "go-home-symbolic";
}
Adw.SidebarItem {
title: _("Discover");
icon-name: "system-search-symbolic";
}
Adw.SidebarItem {
title: _("Library");
icon-name: "folder-music-symbolic";
}
Adw.SidebarItem {
title: _("Settings");
icon-name: "emblem-system-symbolic";
}
}
};
};
content: Adw.ToolbarView {
[top]
Adw.HeaderBar {}
content: Adw.StatusPage {
icon-name: "folder-music-symbolic";
title: _("Your Library");
description: _("Toggle the sidebar to browse sections. Collapse it to overlay the content.");
};
};
}
HTML
<div style="height: 340px; width: 100%; display: flex; overflow: hidden;">
<adw-overlay-split-view show-sidebar style="flex: 1;">
<adw-toolbar-view slot="sidebar">
<adw-header-bar slot="top"></adw-header-bar>
<adw-sidebar mode="sidebar" selected="0">
<adw-sidebar-section>
<adw-sidebar-item title="Home" icon-name="go-home-symbolic"></adw-sidebar-item>
<adw-sidebar-item title="Discover" icon-name="system-search-symbolic"></adw-sidebar-item>
<adw-sidebar-item title="Library" icon-name="folder-music-symbolic"></adw-sidebar-item>
<adw-sidebar-item title="Settings" icon-name="emblem-system-symbolic"></adw-sidebar-item>
</adw-sidebar-section>
</adw-sidebar>
</adw-toolbar-view>
<adw-toolbar-view slot="content">
<adw-header-bar slot="top"></adw-header-bar>
<adw-status-page icon="folder-music" title="Your Library" description="Toggle the sidebar to browse sections. Collapse it to overlay the content."></adw-status-page>
</adw-toolbar-view>
</adw-overlay-split-view>
</div>
TypeScript
import {
AdwHeaderBar,
AdwOverlaySplitView,
AdwSidebar,
AdwStatusPage,
AdwToolbarView,
} from '@gjsify/adwaita-nativescript';
import { folderMusicSymbolic } from '@gjsify/adwaita-icons/places';
const sidebarList = new AdwSidebar();
sidebarList.setItems(['Home', 'Discover', 'Library', 'Settings']);
sidebarList.selected = 0;
const header = new AdwHeaderBar();
header.flat = true;
const sidebar = new AdwToolbarView();
sidebar.addTopBar(header);
sidebar.setContent(sidebarList);
const status = new AdwStatusPage();
status.icon = folderMusicSymbolic;
status.title = 'Your Library';
status.description = 'Toggle the sidebar to browse sections. Collapse it to overlay the content.';
const content = new AdwToolbarView();
content.addTopBar(new AdwHeaderBar());
content.setContent(status);
const view = new AdwOverlaySplitView();
view.setSidebar(sidebar);
view.setContent(content);
view.showSidebar = true;
view.collapsed = false;

A navigation stack of pages with push/pop semantics and an automatic back button. The root page is shown first; pushing a page slides it in from the trailing edge (when transitions are animated) and adds a back button that pops it, while a back-swipe gesture returns to the previous page. In the preview below the root page’s Open contact button pushes the detail page — the push is interactive, so click it to see the transition and back button.

Adw.NavigationView
TypeScript
import Adw from '@girs/adw-1';
import Gtk from '@girs/gtk-4.0';
const page = (title: string, body: Gtk.Widget) => {
const toolbar = new Adw.ToolbarView();
toolbar.add_top_bar(new Adw.HeaderBar());
toolbar.content = body;
return new Adw.NavigationPage({ title, child: toolbar });
};
const view = new Adw.NavigationView({ animateTransitions: true });
const detail = page('Ada Lovelace', new Adw.StatusPage({
iconName: 'avatar-default-symbolic',
title: 'Ada Lovelace',
description: 'Mathematician and writer, the first computer programmer.',
vexpand: true,
}));
const open = new Gtk.Button({
label: 'Open contact',
halign: Gtk.Align.CENTER,
valign: Gtk.Align.CENTER,
vexpand: true,
});
open.add_css_class('pill');
open.add_css_class('suggested-action');
open.connect('clicked', () => view.push(detail));
view.add(page('Contacts', open));
view.add(detail);
Code
using Gtk 4.0;
using Adw 1;
Adw.NavigationView {
Adw.NavigationPage {
tag: "root";
title: _("Contacts");
child: Adw.ToolbarView {
[top]
Adw.HeaderBar {}
content: Gtk.Button {
label: _("Open contact");
halign: center;
valign: center;
action-name: "navigation.push";
action-target: "'detail'";
styles ["pill", "suggested-action"]
};
};
}
Adw.NavigationPage {
tag: "detail";
title: _("Ada Lovelace");
child: Adw.ToolbarView {
[top]
Adw.HeaderBar {}
content: Adw.StatusPage {
icon-name: "avatar-default-symbolic";
title: _("Ada Lovelace");
description: _("Mathematician and writer, the first computer programmer.");
};
};
}
}
HTML
<div style="height: 340px; width: 100%; display: flex; overflow: hidden;">
<adw-navigation-view animate-transitions="true" style="flex: 1;">
<adw-navigation-page tag="root" title="Contacts">
<adw-toolbar-view>
<adw-header-bar slot="top">
<adw-window-title slot="center" title="Contacts"></adw-window-title>
</adw-header-bar>
<adw-button label="Open contact" pill suggested class="adw-navigation-view-root-action"></adw-button>
</adw-toolbar-view>
</adw-navigation-page>
<adw-navigation-page tag="detail" title="Ada Lovelace">
<adw-toolbar-view>
<adw-header-bar slot="top">
<adw-window-title slot="center" title="Ada Lovelace"></adw-window-title>
</adw-header-bar>
<adw-status-page icon="avatar-default" title="Ada Lovelace" description="Mathematician and writer, the first computer programmer."></adw-status-page>
</adw-toolbar-view>
</adw-navigation-page>
</adw-navigation-view>
</div>
TypeScript
import { AdwButton, AdwHeaderBar, AdwNavigationView, AdwStatusPage, AdwToolbarView } from '@gjsify/adwaita-nativescript';
import { avatarDefaultSymbolic } from '@gjsify/adwaita-icons/status';
const view = new AdwNavigationView();
// Detail page.
const detailHeader = new AdwHeaderBar();
detailHeader.title = 'Ada Lovelace';
const detailStatus = new AdwStatusPage();
detailStatus.icon = avatarDefaultSymbolic;
detailStatus.title = 'Ada Lovelace';
detailStatus.description = 'Mathematician and writer, the first computer programmer.';
const detail = new AdwToolbarView();
detail.addTopBar(detailHeader);
detail.setContent(detailStatus);
// Root page: a pill button that pushes the detail page by tag.
const rootHeader = new AdwHeaderBar();
rootHeader.title = 'Contacts';
const open = new AdwButton();
open.text = 'Open contact';
open.variant = 'pill';
open.addEventListener('tap', () => view.push('detail'));
const root = new AdwToolbarView();
root.addTopBar(rootHeader);
root.setContent(open);
view.add(root, 'root');
view.add(detail, 'detail');

A selectable list of items grouped into titled sections. Selecting an item is the navigation gesture that drives the content shown beside it. Each item carries a title, an optional subtitle and a leading icon, and the sidebar supports two modes — a persistent sidebar and a full-width page — so it can adapt between wide and narrow layouts.

Adw.Sidebar
TypeScript
import Adw from '@girs/adw-1';
import Gtk from '@girs/gtk-4.0';
const items = [
{ title: 'Inbox', subtitle: '3 unread', icon: 'mail-unread-symbolic' },
{ title: 'Starred', subtitle: 'Favourites', icon: 'starred-symbolic' },
{ title: 'Sent', subtitle: 'Outgoing mail', icon: 'mail-send-symbolic' },
{ title: 'Archive', subtitle: 'Older mail', icon: 'folder-symbolic' },
];
const section = new Adw.SidebarSection({ title: 'Mailboxes' });
for (const it of items) {
section.append(new Adw.SidebarItem({ title: it.title, subtitle: it.subtitle, iconName: it.icon }));
}
const sidebar = new Adw.Sidebar({ mode: Adw.SidebarMode.SIDEBAR, selected: 0, widthRequest: 220 });
sidebar.append(section);
const status = new Adw.StatusPage({ hexpand: true, vexpand: true });
const syncContent = () => {
const it = items[sidebar.selected] ?? items[0];
status.title = it.title;
status.iconName = it.icon;
status.description = it.subtitle;
};
sidebar.connect('notify::selected', syncContent);
syncContent();
const box = new Gtk.Box({ orientation: Gtk.Orientation.HORIZONTAL });
box.append(sidebar);
box.append(new Gtk.Separator({ orientation: Gtk.Orientation.VERTICAL }));
box.append(status);
Code
using Gtk 4.0;
using Adw 1;
Adw.Sidebar {
mode: sidebar;
selected: 0;
Adw.SidebarSection {
title: _("Mailboxes");
Adw.SidebarItem {
title: _("Inbox");
subtitle: _("3 unread");
icon-name: "mail-unread-symbolic";
}
Adw.SidebarItem {
title: _("Starred");
subtitle: _("Favourites");
icon-name: "starred-symbolic";
}
Adw.SidebarItem {
title: _("Sent");
subtitle: _("Outgoing mail");
icon-name: "mail-send-symbolic";
}
Adw.SidebarItem {
title: _("Archive");
subtitle: _("Older mail");
icon-name: "folder-symbolic";
}
}
}
HTML
<div style="height: 340px; width: 100%; display: flex; overflow: hidden; border: 1px solid var(--card-shade-color); border-radius: var(--card-radius, 12px);">
<adw-sidebar mode="sidebar" selected="0" style="width: 220px;">
<adw-sidebar-section title="Mailboxes">
<adw-sidebar-item title="Inbox" subtitle="3 unread" icon-name="mail-unread-symbolic"></adw-sidebar-item>
<adw-sidebar-item title="Starred" subtitle="Favourites" icon-name="starred-symbolic"></adw-sidebar-item>
<adw-sidebar-item title="Sent" subtitle="Outgoing mail" icon-name="mail-send-symbolic"></adw-sidebar-item>
<adw-sidebar-item title="Archive" subtitle="Older mail" icon-name="folder-symbolic"></adw-sidebar-item>
</adw-sidebar-section>
</adw-sidebar>
<div style="width: 1px; align-self: stretch; background-color: var(--separator-color, var(--card-shade-color));"></div>
<adw-status-page title="Inbox" icon="mail-unread" description="3 unread" style="flex: 1 1 auto;"></adw-status-page>
</div>
TypeScript
import { AdwSidebar, AdwStatusPage, NOTIFY_SIDEBAR_SELECTED } from '@gjsify/adwaita-nativescript';
import { mailUnreadSymbolic, starredSymbolic } from '@gjsify/adwaita-icons/status';
import { mailSendSymbolic } from '@gjsify/adwaita-icons/actions';
import { folderSymbolic } from '@gjsify/adwaita-icons/places';
import { GridLayout, ItemSpec } from '@nativescript/core';
const items = [
{ title: 'Inbox', subtitle: '3 unread', icon: mailUnreadSymbolic },
{ title: 'Starred', subtitle: 'Favourites', icon: starredSymbolic },
{ title: 'Sent', subtitle: 'Outgoing mail', icon: mailSendSymbolic },
{ title: 'Archive', subtitle: 'Older mail', icon: folderSymbolic },
];
// The NS surface takes a flat label list (no per-item subtitle/icon slot).
const sidebar = new AdwSidebar();
sidebar.setItems(items.map((it) => it.title));
sidebar.selected = 0;
sidebar.width = 220;
const status = new AdwStatusPage();
const syncContent = () => {
const it = items[sidebar.selected] ?? items[0];
status.icon = it.icon;
status.title = it.title;
status.description = it.subtitle;
};
sidebar.addEventListener(NOTIFY_SIDEBAR_SELECTED, syncContent);
syncContent();
const box = new GridLayout();
box.addColumn(new ItemSpec(1, 'auto'));
box.addColumn(new ItemSpec(1, 'star'));
GridLayout.setColumn(sidebar, 0);
box.addChild(sidebar);
GridLayout.setColumn(status, 1);
box.addChild(status);

A sheet that slides up from the bottom edge over the content it belongs to. It suits contextual actions and secondary content, especially on narrow windows. It can be modal — dimming the content behind it — and optionally dismissed by dragging it down. The preview shows the sheet in its open state; toggling it is interactive in a real window.

Adw.BottomSheet
TypeScript
import Adw from '@girs/adw-1';
import Gtk from '@girs/gtk-4.0';
const sheet = new Adw.BottomSheet({ open: true, modal: true, canClose: true });
// Persistent content: a centered pill button that toggles the sheet.
const toggle = new Gtk.Button({
label: 'Toggle sheet',
halign: Gtk.Align.CENTER,
valign: Gtk.Align.CENTER,
vexpand: true,
});
toggle.add_css_class('pill');
toggle.add_css_class('suggested-action');
toggle.connect('clicked', () => { sheet.open = !sheet.open; });
sheet.content = toggle;
// The sheet: a title above a boxed list of share actions.
const box = new Gtk.Box({
orientation: Gtk.Orientation.VERTICAL,
spacing: 12,
marginTop: 18,
marginBottom: 24,
marginStart: 18,
marginEnd: 18,
});
box.append(new Gtk.Label({ label: 'Share track', halign: Gtk.Align.START, cssClasses: ['title-2'] }));
const group = new Adw.PreferencesGroup();
for (const [title, icon] of [
['Copy link', 'edit-copy-symbolic'],
['Send to a friend', 'mail-send-symbolic'],
['Add to playlist', 'list-add-symbolic'],
] as const) {
const row = new Adw.ActionRow({ title });
row.add_prefix(new Gtk.Image({ iconName: icon }));
row.activatable = true;
group.add(row);
}
box.append(group);
sheet.sheet = box;
Code
using Gtk 4.0;
using Adw 1;
Adw.BottomSheet {
open: true;
modal: true;
can-close: true;
content: Gtk.Button {
label: _("Toggle sheet");
halign: center;
valign: center;
styles ["pill", "suggested-action"]
};
sheet: Gtk.Box {
orientation: vertical;
spacing: 12;
margin-start: 18;
margin-end: 18;
margin-top: 18;
margin-bottom: 24;
Gtk.Label {
label: _("Share track");
xalign: 0;
styles ["title-2"]
}
Adw.PreferencesGroup {
Adw.ActionRow {
title: _("Copy link");
activatable: true;
[prefix]
Gtk.Image {
icon-name: "edit-copy-symbolic";
}
}
Adw.ActionRow {
title: _("Send to a friend");
activatable: true;
[prefix]
Gtk.Image {
icon-name: "mail-send-symbolic";
}
}
Adw.ActionRow {
title: _("Add to playlist");
activatable: true;
[prefix]
Gtk.Image {
icon-name: "list-add-symbolic";
}
}
}
};
}
HTML
<div style="height: 340px; width: 100%; display: flex; overflow: hidden; position: relative;">
<adw-bottom-sheet open modal can-close style="flex: 1;">
<adw-bottom-sheet-content>
<div style="display: flex; align-items: center; justify-content: center; width: 100%; height: 100%;">
<adw-button pill suggested>Toggle sheet</adw-button>
</div>
</adw-bottom-sheet-content>
<adw-bottom-sheet-sheet>
<div style="display: flex; flex-direction: column; gap: 12px; margin: 18px 18px 24px;">
<span style="font-size: 15pt; font-weight: 800;">Share track</span>
<adw-preferences-group>
<adw-action-row title="Copy link" activatable>
<span slot="prefix" class="adw-icon adw-icon--edit-copy"></span>
</adw-action-row>
<adw-action-row title="Send to a friend" activatable>
<span slot="prefix" class="adw-icon adw-icon--mail-send"></span>
</adw-action-row>
<adw-action-row title="Add to playlist" activatable>
<span slot="prefix" class="adw-icon adw-icon--list-add"></span>
</adw-action-row>
</adw-preferences-group>
</div>
</adw-bottom-sheet-sheet>
</adw-bottom-sheet>
</div>
TypeScript
import { AdwActionRow, AdwBottomSheet, AdwButton, AdwPreferencesGroup } from '@gjsify/adwaita-nativescript';
import { Label, StackLayout } from '@nativescript/core';
const sheet = new AdwBottomSheet();
// Persistent content: a centered pill button that toggles the sheet.
const center = new StackLayout();
center.horizontalAlignment = 'center';
center.verticalAlignment = 'middle';
const toggle = new AdwButton();
toggle.text = 'Toggle sheet';
toggle.variant = 'pill';
toggle.addEventListener('tap', () => { sheet.openState = !sheet.openState; });
center.addChild(toggle);
sheet.setContent(center);
// The sheet: a title above a boxed list of share actions.
const box = new StackLayout();
box.orientation = 'vertical';
const title = new Label();
title.text = 'Share track';
title.className = 'title-2';
box.addChild(title);
const group = new AdwPreferencesGroup();
for (const rowTitle of ['Copy link', 'Send to a friend', 'Add to playlist']) {
const row = new AdwActionRow();
row.title = rowTitle;
group.addRow(row);
}
box.addChild(group);
sheet.setSheet(box);
sheet.openState = true;
  • View Switching — switch between peer views (view stacks, view switchers, tab views) rather than moving through a stack.
  • Layout — the Clamp, ToolbarView and breakpoints these navigation surfaces are built on.
  • Adwaita Storybook — the same widgets in a live, interactive component browser.