Buttons
Libadwaita adds three button widgets to GTK’s own: button content for an icon
plus a label, a split button pairing an action with alternatives, and a
toggle group for a single-choice selector. Gtk.Button and Gtk.MenuButton
are GTK’s, under Gtk Buttons.
What the preview does not show
The previews run the browser port, so behaviour Libadwaita drives natively (a split button’s popover) can be simplified here. A toggle group’s keyboard navigation is not: see below.
Button Content
Section titled “Button Content”To put an icon and text on a button, make an Adw.ButtonContent its child.
Set can-shrink if the label may ellipsize when horizontal space runs short.
using Gtk 4.0;using Adw 1;
Gtk.Button download_button { child: Adw.ButtonContent content { label: _("Download"); icon-name: "folder-download-symbolic"; };
styles ["suggested-action", "pill"]}import { build } from './button-content.blp';
const { download_button, content } = build();download_button.connect('clicked', () => { content.label = 'Downloading…';});<gtk-button id="download_button" class="suggested-action pill"> <adw-button-content id="content" label="Download" icon-name="folder-download-symbolic" slot="child" ></adw-button-content></gtk-button><script type="module"> import '@gjsify/adwaita-web';
const button = document.querySelector('#download_button'); const content = document.querySelector('#content'); button.addEventListener('click', () => { content.setAttribute('label', 'Downloading…'); });</script>import { mountSharedTree } from '@gjsify/adwaita-web';import tree from './button-content.blp?shared-tree';
mountSharedTree(tree);
const button = document.querySelector('#download_button');const content = document.querySelector('#content');button.addEventListener('click', () => { content.setAttribute('label', 'Downloading…');});<gtk:Button xmlns="http://schemas.nativescript.org/tns.xsd" xmlns:adw="~/adw" xmlns:gtk="~/gtk" id="download_button" styleClasses="suggested-action pill"> <gtk:Button.child> <adw:ButtonContent id="content" label="Download" iconName="folder-download-symbolic" /> </gtk:Button.child></gtk:Button>import { type Adw, type Gtk } from '@gjsify/adwaita-nativescript';import { Builder } from '@nativescript/core';
const button = Builder.load({ path: '~/views', name: 'button-content' }) as Gtk.Button;const content = button.getViewById<Adw.ButtonContent>('content')!;// The bitmap is pre-coloured, so a suggested button's white icon is pinned here// rather than inherited from the stylesheet the way GTK inherits `color`.content.iconColor = '#ffffff';button.connect('clicked', () => { content.label = 'Downloading…';});import { type Adw, type Gtk } from '@gjsify/adwaita-nativescript';import { build } from '@gjsify/adwaita-nativescript/builder';import tree from './button-content.blp?shared-tree';
const button = build(tree) as Gtk.Button;const content = button.getViewById<Adw.ButtonContent>('content')!;// The bitmap is pre-coloured, so a suggested button's white icon is pinned here// rather than inherited from the stylesheet the way GTK inherits `color`.content.iconColor = '#ffffff';button.connect('clicked', () => { content.label = 'Downloading…';});// mount(() => <AdwButtonContent />, container) — from '@gjsify/gtk-host/solid'const AdwButtonContent = () => ( <gtk-button cssClasses={['suggested-action', 'pill']}> <adw-button-content label="Download" iconName="folder-download-symbolic" /> </gtk-button>);<!-- AdwButtonContent.vue — mount(AdwButtonContent, container) from '@gjsify/gtk-host/vue' --><template> <gtk-button :css-classes="['suggested-action', 'pill']"> <adw-button-content label="Download" icon-name="folder-download-symbolic" /> </gtk-button></template>// createRoot(container).render(<AdwButtonContent />) — from '@gjsify/gtk-host/react'const AdwButtonContent = () => ( <gtk-button cssClasses={['suggested-action', 'pill']}> <adw-button-content label="Download" iconName="folder-download-symbolic" /> </gtk-button>);Split Button
Section titled “Split Button”Use a split button when one action is the obvious default and the rest are variations on it. Clicking the main half runs the default; the attached arrow opens a menu with the alternatives.
using Gtk 4.0;using Adw 1;
Adw.SplitButton split_button { label: _("Save"); icon-name: "document-save-symbolic";}import Gio from 'gi://Gio?version=2.0';import { build } from './split-button.blp';
const { split_button } = build();// split_button.add_css_class('flat'); // the header-bar / toolbar variant
const menu = new Gio.Menu();menu.append('Save as…', 'app.save-as');menu.append('Export', 'app.export');menu.append('Print', 'app.print');split_button.menuModel = menu;<adw-split-button id="split_button" label="Save" icon-name="document-save-symbolic"></adw-split-button><script type="module"> import '@gjsify/adwaita-web';
const button = document.querySelector('#split_button'); // button.classList.add('flat'); // the header-bar / toolbar variant
button.menuModel = [ { label: 'Save as…', action: 'app.save-as' }, { label: 'Export', action: 'app.export' }, { label: 'Print', action: 'app.print' }, ];</script>import { mountSharedTree } from '@gjsify/adwaita-web';import tree from './split-button.blp?shared-tree';
mountSharedTree(tree);
const button = document.querySelector('#split_button');// button.classList.add('flat'); // the header-bar / toolbar variant
button.menuModel = [ { label: 'Save as…', action: 'app.save-as' }, { label: 'Export', action: 'app.export' }, { label: 'Print', action: 'app.print' },];<adw:SplitButton xmlns="http://schemas.nativescript.org/tns.xsd" xmlns:adw="~/adw" id="split_button" label="Save" iconName="document-save-symbolic"/>import { type Adw } from '@gjsify/adwaita-nativescript';import { Builder } from '@nativescript/core';
const button = Builder.load({ path: '~/views', name: 'split-button' }) as Adw.SplitButton;// button.className = 'adw-split-button flat'; // the header-bar / toolbar variant
button.menuModel = [ { label: 'Save as…', action: 'app.save-as' }, { label: 'Export', action: 'app.export' }, { label: 'Print', action: 'app.print' },];import { type Adw } from '@gjsify/adwaita-nativescript';import { build } from '@gjsify/adwaita-nativescript/builder';import tree from './split-button.blp?shared-tree';
const button = build(tree) as Adw.SplitButton;// button.className = 'adw-split-button flat'; // the header-bar / toolbar variant
button.menuModel = [ { label: 'Save as…', action: 'app.save-as' }, { label: 'Export', action: 'app.export' }, { label: 'Print', action: 'app.print' },];// mount(() => <AdwSplitButton />, container) — from '@gjsify/gtk-host/solid'const AdwSplitButton = () => ( <adw-split-button label="Save" menuModel={[ { label: 'Save as…', action: 'app.save-as' }, { label: 'Export', action: 'app.export' }, { label: 'Print', action: 'app.print' }, ]} />);<!-- AdwSplitButton.vue — mount(AdwSplitButton, container) from '@gjsify/gtk-host/vue' --><template> <adw-split-button label="Save" :menu-model="[ { label: 'Save as…', action: 'app.save-as' }, { label: 'Export', action: 'app.export' }, { label: 'Print', action: 'app.print' }, ]" /></template>// createRoot(container).render(<AdwSplitButton />) — from '@gjsify/gtk-host/react'const AdwSplitButton = () => ( <adw-split-button label="Save" menuModel={[ { label: 'Save as…', action: 'app.save-as' }, { label: 'Export', action: 'app.export' }, { label: 'Print', action: 'app.print' }, ]} />);Toggle Group
Section titled “Toggle Group”For a small set of mutually exclusive options, such as a view mode, use a toggle
group: a linked row where exactly one toggle is active at a time. Each toggle takes an
icon, a label, or both, and the style classes .flat and .round adapt the group for a
toolbar or give it a pill shape.
Each toggle carries a name, and the group’s active-name picks the active one by it,
so code that switches the view mode says 'grid' instead of counting toggles.
Keyboard and accessibility
A toggle group is a single tab stop, the way Adw.ToggleGroup routes focus:
Tab enters on the active toggle and the next Tab leaves the group, while Left and
Right move between toggles. Up and Down stay the page’s, as they are upstream.
Home and End jump to the ends — that pair is the WAI-ARIA pattern rather than
anything GTK does, since GTK’s focus directions have no Home or End.
It announces itself as a radio group with one checked toggle —
GTK_ACCESSIBLE_ROLE_RADIO_GROUP upstream — unless the element already carries a
role when it connects, which it then keeps; role="tablist" additionally
switches the toggles to tabs, the way Adw.InlineViewSwitcher does. Set it in
markup or before the element is inserted: it is read once, which is all GTK allows
too — GtkAccessible:accessible-role is documented “cannot be changed once set”,
and the only setter is class-level.
using Gtk 4.0;using Adw 1;
Adw.ToggleGroup toggle_group { active-name: "list";
Adw.Toggle { name: "list"; label: _("List"); icon-name: "view-list-symbolic"; }
Adw.Toggle { name: "grid"; label: _("Grid"); icon-name: "view-grid-symbolic"; }
Adw.Toggle { name: "pages"; label: _("Pages"); icon-name: "view-paged-symbolic"; }}import { build } from './toggle-group.blp';
const { toggle_group } = build();toggle_group.activeName = 'grid';<adw-toggle-group id="toggle_group" active-name="list"> <adw-toggle name="list" label="List" icon-name="view-list-symbolic" ></adw-toggle> <adw-toggle name="grid" label="Grid" icon-name="view-grid-symbolic" ></adw-toggle> <adw-toggle name="pages" label="Pages" icon-name="view-paged-symbolic" ></adw-toggle></adw-toggle-group><script type="module"> import '@gjsify/adwaita-web';
const group = document.querySelector('#toggle_group'); group.activeName = 'grid';</script>import { mountSharedTree } from '@gjsify/adwaita-web';import tree from './toggle-group.blp?shared-tree';
mountSharedTree(tree);
const group = document.querySelector('#toggle_group');group.activeName = 'grid';<adw:ToggleGroup xmlns="http://schemas.nativescript.org/tns.xsd" xmlns:adw="~/adw" id="toggle_group" activeName="list"> <adw:Toggle name="list" label="List" iconName="view-list-symbolic" /> <adw:Toggle name="grid" label="Grid" iconName="view-grid-symbolic" /> <adw:Toggle name="pages" label="Pages" iconName="view-paged-symbolic" /></adw:ToggleGroup>import { type Adw } from '@gjsify/adwaita-nativescript';import { Builder } from '@nativescript/core';
const group = Builder.load({ path: '~/views', name: 'toggle-group' }) as Adw.ToggleGroup;group.activeName = 'grid';import { type Adw } from '@gjsify/adwaita-nativescript';import { build } from '@gjsify/adwaita-nativescript/builder';import tree from './toggle-group.blp?shared-tree';
const group = build(tree) as Adw.ToggleGroup;group.activeName = 'grid';Related
Section titled “Related”- Gtk Buttons: the plain button, its style classes and the menu button.
- Boxed Lists: rows that embed these buttons and reuse the same style classes.
- Layout: the containers that arrange buttons within a window.
- Adwaita Storybook: the same widgets in a live component browser you can poke at.