Skip to content

Buttons

The buttons on this page belong to GTK. Gtk.Button is the plain button every other one is built on; the rest are the ones that add a state or a target to it — Gtk.ToggleButton stays pressed, Gtk.LinkButton follows a URI, Gtk.ScaleButton opens a scale, and the two dialog buttons open a colour or a font chooser. Gtk.MenuButton is the one whose press opens a menu. Libadwaita ships none of them. The buttons it does ship are on Adwaita Buttons.

What the preview does not show

The previews run the browser port, so behaviour the toolkits drive natively can be simplified here. The menu button diverges: NativeScript has no popover, so its menu opens as the platform action sheet. Four of the buttons below have no NativeScript widget yet — the toggle button, the link button and the two dialog buttons — so their XML template tabs say so.

Add a style class to restyle a plain button. .pill makes it rounded and prominent, .circular suits an icon-only button, .suggested-action and .destructive-action colour an affirmative or a dangerous action, and .flat drops the visible background. They compose, and they mean the same thing everywhere in the toolkit.

Gtk.Button
Blueprint
Code
using Gtk 4.0;
using Adw 1;
Adw.WrapBox button_box {
child-spacing: 12;
line-spacing: 12;
Gtk.Button pill_button {
label: _("Pill");
styles ["pill"]
}
Gtk.Button add_button {
icon-name: "list-add-symbolic";
styles ["circular"]
}
Gtk.Button suggested_button {
label: _("Suggested");
styles ["suggested-action"]
}
Gtk.Button delete_button {
label: _("Delete");
styles ["destructive-action"]
}
Gtk.Button flat_button {
label: _("Flat");
styles ["flat"]
}
}
TypeScript
TypeScript
import { build } from './button.blp';
const { delete_button } = build();
delete_button.connect('clicked', () => console.log('Delete pressed'));
Web Components
index.html
HTML
<adw-wrap-box id="button_box" child-spacing="12" line-spacing="12">
<gtk-button id="pill_button" label="Pill" class="pill"></gtk-button>
<gtk-button
id="add_button"
icon-name="list-add-symbolic"
class="circular"
></gtk-button>
<gtk-button
id="suggested_button"
label="Suggested"
class="suggested-action"
></gtk-button>
<gtk-button
id="delete_button"
label="Delete"
class="destructive-action"
></gtk-button>
<gtk-button id="flat_button" label="Flat" class="flat"></gtk-button>
</adw-wrap-box>
<script type="module">
import '@gjsify/adwaita-web';
const deleteButton = document.querySelector('#delete_button');
deleteButton.addEventListener('click', () => console.log('Delete pressed'));
</script>
main.js (Blueprint)
JavaScript
import { mountSharedTree } from '@gjsify/adwaita-web';
import tree from './button.blp?shared-tree';
mountSharedTree(tree);
const deleteButton = document.querySelector('#delete_button');
deleteButton.addEventListener('click', () => console.log('Delete pressed'));
NativeScript
views/button.xml
XML
<adw:WrapBox
xmlns="http://schemas.nativescript.org/tns.xsd"
xmlns:adw="~/adw"
xmlns:gtk="~/gtk"
id="button_box"
childSpacing="12"
lineSpacing="12"
>
<gtk:Button id="pill_button" label="Pill" styleClasses="pill" />
<gtk:Button
id="add_button"
iconName="list-add-symbolic"
styleClasses="circular"
/>
<gtk:Button
id="suggested_button"
label="Suggested"
styleClasses="suggested-action"
/>
<gtk:Button
id="delete_button"
label="Delete"
styleClasses="destructive-action"
/>
<gtk:Button id="flat_button" label="Flat" styleClasses="flat" />
</adw:WrapBox>
app.ts
TypeScript
import { type Adw, type Gtk } from '@gjsify/adwaita-nativescript';
import { Builder } from '@nativescript/core';
const box = Builder.load({ path: '~/views', name: 'button' }) as Adw.WrapBox;
const deleteButton = box.getViewById<Gtk.Button>('delete_button')!;
deleteButton.connect('clicked', () => console.log('Delete pressed'));
app.ts (Blueprint)
TypeScript
import { type Adw, type Gtk } from '@gjsify/adwaita-nativescript';
import { build } from '@gjsify/adwaita-nativescript/builder';
import tree from './button.blp?shared-tree';
const box = build(tree) as Adw.WrapBox;
const deleteButton = box.getViewById<Gtk.Button>('delete_button')!;
deleteButton.connect('clicked', () => console.log('Delete pressed'));
Solid
TypeScript
// mount(() => <GtkButton />, container) — from '@gjsify/gtk-host/solid'
const GtkButton = () => (
<gtk-box
orientation="horizontal"
spacing={12}
halign="center"
>
<gtk-button
label="Pill"
cssClasses={['pill']}
/>
<gtk-button
iconName="list-add-symbolic"
cssClasses={['circular']}
/>
<gtk-button
label="Suggested"
cssClasses={['suggested-action']}
/>
<gtk-button
label="Delete"
cssClasses={['destructive-action']}
/>
<gtk-button
label="Flat"
cssClasses={['flat']}
/>
</gtk-box>
);
Vue
Vue
<!-- GtkButton.vue — mount(GtkButton, container) from '@gjsify/gtk-host/vue' -->
<template>
<gtk-box
orientation="horizontal"
:spacing="12"
halign="center"
>
<gtk-button
label="Pill"
:css-classes="['pill']"
/>
<gtk-button
icon-name="list-add-symbolic"
:css-classes="['circular']"
/>
<gtk-button
label="Suggested"
:css-classes="['suggested-action']"
/>
<gtk-button
label="Delete"
:css-classes="['destructive-action']"
/>
<gtk-button
label="Flat"
:css-classes="['flat']"
/>
</gtk-box>
</template>
React
TypeScript
// createRoot(container).render(<GtkButton />) — from '@gjsify/gtk-host/react'
const GtkButton = () => (
<gtk-box
orientation="horizontal"
spacing={12}
halign="center"
>
<gtk-button
label="Pill"
cssClasses={['pill']}
/>
<gtk-button
iconName="list-add-symbolic"
cssClasses={['circular']}
/>
<gtk-button
label="Suggested"
cssClasses={['suggested-action']}
/>
<gtk-button
label="Delete"
cssClasses={['destructive-action']}
/>
<gtk-button
label="Flat"
cssClasses={['flat']}
/>
</gtk-box>
);

A button that stays pressed. It is a Gtk.Button with one more property, active, so the label, the icon and every style class of the plain button work on it unchanged. Listen for toggled (or notify::active) to follow the state.

group makes two or more of them mutually exclusive: setting one active releases the others, and the member you linked cannot be clicked back off, so a group always keeps exactly one press. Link the later button to the earlier one — loop.group = mute puts loop into mute’s group, which is the half that stops being clickable-off. To pick exactly one of several style classes instead, use the toggle group.

Gtk.ToggleButton
Blueprint
Code
using Gtk 4.0;
Gtk.Box {
spacing: 12;
halign: center;
Gtk.ToggleButton {
label: _("Mute");
active: true;
}
Gtk.ToggleButton loop_button {
label: _("Loop");
}
Gtk.ToggleButton {
label: _("Follow");
// `group` takes another Gtk.ToggleButton, so it is set from code.
}
}
TypeScript
TypeScript
import Gtk from 'gi://Gtk?version=4.0';
const mute = new Gtk.ToggleButton({ label: 'Mute', active: true });
mute.connect('toggled', () => console.log(`Mute is ${mute.active ? 'on' : 'off'}`));
// A group is mutually exclusive, and the member that GAINED the link (here `follow`)
// cannot be clicked off — so the group always keeps exactly one button pressed.
const loop = new Gtk.ToggleButton({ label: 'Loop' });
const follow = new Gtk.ToggleButton({ label: 'Follow' });
follow.group = loop;
Web Components
HTML
<div style="display:flex;flex-wrap:wrap;gap:12px;justify-content:center;align-items:center;">
<!-- active: If the toggle button should be pressed in. -->
<gtk-toggle-button label="Mute" active></gtk-toggle-button>
<gtk-toggle-button id="loop-group-target" label="Loop"></gtk-toggle-button>
<!-- group: The toggle button whose group this widget belongs to. -->
<gtk-toggle-button label="Follow" group="loop-group-target"></gtk-toggle-button>
</div>
Solid
TypeScript
// mount(() => <GtkToggleButton />, container) — from '@gjsify/gtk-host/solid'
const GtkToggleButton = () => (
<gtk-box
orientation="horizontal"
spacing={12}
halign="center"
>
<gtk-toggle-button
label="Mute"
active
/>
<gtk-toggle-button label="Loop" />
</gtk-box>
);
Vue
Vue
<!-- GtkToggleButton.vue — mount(GtkToggleButton, container) from '@gjsify/gtk-host/vue' -->
<template>
<gtk-box
orientation="horizontal"
:spacing="12"
halign="center"
>
<gtk-toggle-button
label="Mute"
:active="true"
/>
<gtk-toggle-button label="Loop" />
</gtk-box>
</template>
React
TypeScript
// createRoot(container).render(<GtkToggleButton />) — from '@gjsify/gtk-host/react'
const GtkToggleButton = () => (
<gtk-box
orientation="horizontal"
spacing={12}
halign="center"
>
<gtk-toggle-button
label="Mute"
active
/>
<gtk-toggle-button label="Loop" />
</gtk-box>
);

A button that follows a URI — a uri, and a visited state saying it has been followed. Clicking launches the URI and marks the link visited; pointing the button somewhere new un-visits it, because the new target has not been seen. Listen for activate-link to handle the click yourself: cancel the event and neither the launch nor the visit happens.

The context menu of the native widget (copy the URL, on Shift+F10) is the platform’s own here — a browser already owns that menu on a button.

Gtk.LinkButton
Blueprint
Code
using Gtk 4.0;
Gtk.Box {
spacing: 12;
halign: center;
Gtk.LinkButton {
label: _("GNOME");
uri: "https://gnome.org";
}
Gtk.LinkButton {
label: _("GTK");
uri: "https://docs.gtk.org/gtk4/";
visited: true;
}
}
TypeScript
TypeScript
import Gtk from 'gi://Gtk?version=4.0';
const link = new Gtk.LinkButton({ uri: 'https://gnome.org', label: 'GNOME' });
// Returning TRUE from `activate-link` stops the default handler, so neither the
// launcher nor the visited state runs.
link.connect('activate-link', () => {
console.log('Would open', link.uri);
return true;
});
Web Components
HTML
<div style="display:flex;flex-wrap:wrap;gap:12px;justify-content:center;align-items:center;">
<!-- uri: The URI bound to this button. -->
<gtk-link-button label="GNOME" uri="https://gnome.org"></gtk-link-button>
<!-- uri: The URI bound to this button. -->
<!-- visited: The 'visited' state of this button. -->
<gtk-link-button label="GTK" uri="https://docs.gtk.org/gtk4/" visited></gtk-link-button>
</div>
Solid
TypeScript
// mount(() => <GtkLinkButton />, container) — from '@gjsify/gtk-host/solid'
const GtkLinkButton = () => (
<gtk-box
orientation="vertical"
spacing={6}
halign="center"
>
<gtk-link-button
uri="https://gnome.org"
label="GNOME"
/>
<gtk-link-button
uri="https://docs.gtk.org/gtk4/"
visited
/>
</gtk-box>
);
Vue
Vue
<!-- GtkLinkButton.vue — mount(GtkLinkButton, container) from '@gjsify/gtk-host/vue' -->
<template>
<gtk-box
orientation="vertical"
:spacing="6"
halign="center"
>
<gtk-link-button
uri="https://gnome.org"
label="GNOME"
/>
<gtk-link-button
uri="https://docs.gtk.org/gtk4/"
:visited="true"
/>
</gtk-box>
</template>
React
TypeScript
// createRoot(container).render(<GtkLinkButton />) — from '@gjsify/gtk-host/react'
const GtkLinkButton = () => (
<gtk-box
orientation="vertical"
spacing={6}
halign="center"
>
<gtk-link-button
uri="https://gnome.org"
label="GNOME"
/>
<gtk-link-button
uri="https://docs.gtk.org/gtk4/"
visited
/>
</gtk-box>
);
Why the NativeScript tab says so

@gjsify/adwaita-nativescript has no Gtk.LinkButton: GtkButton takes a label and an icon, and nothing that follows a URI. The block’s XML template tab says that instead of showing one.

A button whose press opens a scale — the volume control of a media player, the brightness slider of a toolbar. It is a toggle button with an icon plus a popover holding a minus stepper, the scale and a plus one.

The icon follows the value, and how depends on how many names the icons list holds: none draws image-missing; one name is used throughout; two split the range in half; three or more put the first at the bottom and the second at the top, and spread what is left evenly over the values between. The steppers move by the range’s page increment and go insensitive at their end of it. Listen for value-changed to follow the value.

has-frame draws the icon button with a frame (it has none by default, so it is flat), and the orientation axis is vertical unless you say otherwise — which is why a scale button grows upwards.

Gtk.ScaleButton
Blueprint
Code
using Gtk 4.0;
Gtk.Box {
spacing: 12;
halign: center;
Gtk.ScaleButton scale_button {
value: 70;
// `icons` is a G_TYPE_STRV, and a Blueprint list is not a spelling this
// compiler holds for it, so the icon names are set from code.
}
}
TypeScript
TypeScript
import Gtk from 'gi://Gtk?version=4.0';
const volume = new Gtk.ScaleButton({
icons: ['audio-volume-muted-symbolic', 'audio-volume-low-symbolic', 'audio-volume-high-symbolic'],
value: 70,
});
volume.connect('value-changed', () => console.log(`Volume is ${volume.value}`));
// A wider range with its own step, as the portable adjustment spells it.
volume.adjustment = new Gtk.Adjustment({
lower: 0,
upper: 200,
stepIncrement: 5,
pageIncrement: 20,
});
Web Components
HTML
<div style="display:flex;flex-wrap:wrap;gap:12px;justify-content:center;align-items:center;">
<gtk-scale-button icons='["audio-volume-muted-symbolic","audio-volume-low-symbolic","audio-volume-high-symbolic"]' value="70"></gtk-scale-button>
</div>
Solid
TypeScript
// mount(() => <GtkScaleButton />, container) — from '@gjsify/gtk-host/solid'
const GtkScaleButton = () => (
<gtk-scale-button
icons={['audio-volume-muted-symbolic', 'audio-volume-low-symbolic', 'audio-volume-high-symbolic']}
value={70}
/>
);
Vue
Vue
<!-- GtkScaleButton.vue — mount(GtkScaleButton, container) from '@gjsify/gtk-host/vue' -->
<template>
<gtk-scale-button
:icons="['audio-volume-muted-symbolic', 'audio-volume-low-symbolic', 'audio-volume-high-symbolic']"
:value="70"
/>
</template>
React
TypeScript
// createRoot(container).render(<GtkScaleButton />) — from '@gjsify/gtk-host/react'
const GtkScaleButton = () => (
<gtk-scale-button
icons={['audio-volume-muted-symbolic', 'audio-volume-low-symbolic', 'audio-volume-high-symbolic']}
value={70}
/>
);
What the preview shows instead of the dock

The dock is a popover the element builds itself, so a static tree has no slot for it — press the icon in the preview to open it. The NativeScript port has no Gtk.ScaleButton either: GtkButton has no popover child to put the slider in.

A button that shows a colour and opens a chooser for it — the swatch in a preferences dialog. rgba is the colour, in any spelling the browser knows, and the swatch announces its channel percentages (“Red 75%, Green 25%, Blue 25%”), with the alpha clause appearing only while the colour is translucent.

The button is insensitive until a dialog is set, which is GTK’s own rule, so markup needs the dialog attribute and code needs the dialog property. The chooser itself is the platform’s colour picker here, which has no alpha channel: a colour chosen in it keeps the alpha the button already had.

Gtk.ColorDialogButton
Blueprint
Code
using Gtk 4.0;
Gtk.Box {
spacing: 12;
halign: center;
Gtk.ColorDialogButton {
// `dialog` is a GtkColorDialog, so it is set from code.
halign: center;
}
}
TypeScript
TypeScript
import Gdk from 'gi://Gdk?version=4.0';
import Gtk from 'gi://Gtk?version=4.0';
const button = new Gtk.ColorDialogButton({ dialog: new Gtk.ColorDialog() });
const rgba = Gdk.RGBA.parse('#3584e4');
if (rgba !== null) button.rgba = rgba;
button.connect('notify::rgba', () => {
const chosen = button.rgba;
console.log(`${chosen.red}, ${chosen.green}, ${chosen.blue}`);
});
Web Components
HTML
<div style="display:flex;flex-wrap:wrap;gap:12px;justify-content:center;align-items:center;">
<!-- dialog: The `GtkColorDialog` that contains parameters for the color chooser dialog. -->
<gtk-color-dialog-button dialog></gtk-color-dialog-button>
<!-- dialog: The `GtkColorDialog` that contains parameters for the color chooser dialog. -->
<gtk-color-dialog-button dialog rgba="#3584e4"></gtk-color-dialog-button>
<!-- dialog: The `GtkColorDialog` that contains parameters for the color chooser dialog. -->
<gtk-color-dialog-button dialog rgba="rgba(53, 132, 228, 0.5)"></gtk-color-dialog-button>
</div>
Solid
TypeScript
// mount(() => <GtkColorDialogButton />, container) — from '@gjsify/gtk-host/solid'
const GtkColorDialogButton = () => (
<gtk-color-dialog-button />
);
Vue
Vue
<!-- GtkColorDialogButton.vue — mount(GtkColorDialogButton, container) from '@gjsify/gtk-host/vue' -->
<template>
<gtk-color-dialog-button />
</template>
React
TypeScript
// createRoot(container).render(<GtkColorDialogButton />) — from '@gjsify/gtk-host/react'
const GtkColorDialogButton = () => (
<gtk-color-dialog-button />
);
Why the NativeScript tab says so

@gjsify/adwaita-nativescript has no Gtk.ColorDialogButton, and @nativescript/core exports no colour-picker view for it to host.

A button that shows a font and opens a chooser for it. The font-desc is a Pango font description — "Sans Bold 12", the spelling Pango itself reads and writes — and the label is its family, with its size beside it.

The level decides how much of the font the chooser offers, and what the label shows: at family the label is the family name alone and no size is drawn; at face the style words join it; from font up the size appears beside it. use-font draws the family label in the selected font, and use-size decides whether the size is drawn in it too. font-features and language ride along with them.

As with the colour button, the button is insensitive until a dialog is set.

Gtk.FontDialogButton
Blueprint
Code
using Gtk 4.0;
Gtk.Box {
spacing: 12;
halign: center;
Gtk.FontDialogButton {
// `dialog` is a GtkFontDialog and `font-desc` a PangoFontDescription, so both
// are set from code; the flags are attributes.
use-font: true;
use-size: true;
}
}
TypeScript
TypeScript
import Gtk from 'gi://Gtk?version=4.0';
import Pango from 'gi://Pango?version=1.0';
const font = new Gtk.FontDialogButton({ dialog: new Gtk.FontDialog() });
font.fontDesc = Pango.FontDescription.from_string('Sans Bold 12');
font.level = Gtk.FontLevel.FONT;
// The family label is drawn in the chosen font, at the chosen size.
font.useFont = true;
font.useSize = true;
Web Components
HTML
<div style="display:flex;flex-wrap:wrap;gap:12px;justify-content:center;align-items:center;">
<!-- dialog: The `GtkFontDialog` that contains parameters for the font chooser dialog. -->
<gtk-font-dialog-button dialog font-desc="Sans Bold 12"></gtk-font-dialog-button>
<!-- dialog: The `GtkFontDialog` that contains parameters for the font chooser dialog. -->
<!-- use-font: Whether the buttons label will be drawn in the selected font. -->
<gtk-font-dialog-button dialog font-desc="Sans Bold 24" use-font use-size></gtk-font-dialog-button>
</div>
Solid
TypeScript
// mount(() => <GtkFontDialogButton />, container) — from '@gjsify/gtk-host/solid'
const GtkFontDialogButton = () => (
<gtk-font-dialog-button />
);
Vue
Vue
<!-- GtkFontDialogButton.vue — mount(GtkFontDialogButton, container) from '@gjsify/gtk-host/vue' -->
<template>
<gtk-font-dialog-button />
</template>
React
TypeScript
// createRoot(container).render(<GtkFontDialogButton />) — from '@gjsify/gtk-host/react'
const GtkFontDialogButton = () => (
<gtk-font-dialog-button />
);
Where the chooser lists its families

The native font chooser walks Pango’s font map. A page has no font map, so this one lists the families the DOCUMENT declares and the (weight, slant) faces document.fonts can render for each — which is the browser’s answer to the same question Pango’s walk answers.

When a button’s only job is to open a menu, use a menu button: the hamburger at the end of a header bar, with no action of its own and every choice in the popover it opens.

Why the Blueprint holds only the button

Libadwaita ships no menu button, so this is Gtk.MenuButton, and the Adwaita stylesheet gives it the flat, rounded-square shape. The .blp below declares the button alone — the subset the gallery builds it with has no menu block — so each tab sets the menu from code.

Gtk.MenuButton
Blueprint
Code
using Gtk 4.0;
Gtk.MenuButton menu_button {
icon-name: "open-menu-symbolic";
styles ["flat"]
}
TypeScript
TypeScript
import Gio from 'gi://Gio?version=2.0';
import { build } from './menu-button.blp';
const { menu_button } = build();
menu_button.primary = true; // opens on F10, the way an app menu should
const menu = new Gio.Menu();
menu.append('Save as…', 'app.save-as');
menu.append('Export', 'app.export');
menu.append('Print', 'app.print');
menu_button.menuModel = menu;
Web Components
index.html
HTML
<gtk-menu-button
id="menu_button"
icon-name="open-menu-symbolic"
class="flat"
></gtk-menu-button>
<script type="module">
import '@gjsify/adwaita-web';
const menuButton = document.querySelector('#menu_button');
menuButton.menuTitle = 'Document';
menuButton.menuModel = [
{ label: 'Save as…', action: 'app.save-as' },
{ label: 'Export', action: 'app.export' },
{ label: 'Print', action: 'app.print' },
];
</script>
main.js (Blueprint)
JavaScript
import { mountSharedTree } from '@gjsify/adwaita-web';
import tree from './menu-button.blp?shared-tree';
mountSharedTree(tree);
const menuButton = document.querySelector('#menu_button');
menuButton.menuTitle = 'Document';
menuButton.menuModel = [
{ label: 'Save as…', action: 'app.save-as' },
{ label: 'Export', action: 'app.export' },
{ label: 'Print', action: 'app.print' },
];
NativeScript
views/menu-button.xml
XML
<gtk:MenuButton
xmlns="http://schemas.nativescript.org/tns.xsd"
xmlns:gtk="~/gtk"
id="menu_button"
iconName="open-menu-symbolic"
styleClasses="flat"
/>
app.ts
TypeScript
import { type Gtk } from '@gjsify/adwaita-nativescript';
import { Builder } from '@nativescript/core';
const menuButton = Builder.load({ path: '~/views', name: 'menu-button' }) as Gtk.MenuButton;
menuButton.menuTitle = 'Document'; // the action sheet's heading: there is no popover to open
menuButton.menuModel = [
{ label: 'Save as…', action: 'app.save-as' },
{ label: 'Export', action: 'app.export' },
{ label: 'Print', action: 'app.print' },
];
app.ts (Blueprint)
TypeScript
import { type Gtk } from '@gjsify/adwaita-nativescript';
import { build } from '@gjsify/adwaita-nativescript/builder';
import tree from './menu-button.blp?shared-tree';
const menuButton = build(tree) as Gtk.MenuButton;
menuButton.menuTitle = 'Document'; // the action sheet's heading: there is no popover to open
menuButton.menuModel = [
{ label: 'Save as…', action: 'app.save-as' },
{ label: 'Export', action: 'app.export' },
{ label: 'Print', action: 'app.print' },
];
Solid
TypeScript
// mount(() => <GtkMenuButton />, container) — from '@gjsify/gtk-host/solid'
const GtkMenuButton = () => (
<gtk-menu-button
iconName="open-menu-symbolic"
cssClasses={['flat']}
menuModel={[
{ label: 'Preferences', action: 'app.preferences' },
{ label: 'Keyboard Shortcuts', action: 'win.show-help-overlay' },
{ label: 'About', action: 'app.about' },
]}
/>
);
Vue
Vue
<!-- GtkMenuButton.vue — mount(GtkMenuButton, container) from '@gjsify/gtk-host/vue' -->
<template>
<gtk-menu-button
icon-name="open-menu-symbolic"
:css-classes="['flat']"
:menu-model="[
{ label: 'Preferences', action: 'app.preferences' },
{ label: 'Keyboard Shortcuts', action: 'win.show-help-overlay' },
{ label: 'About', action: 'app.about' },
]"
/>
</template>
React
TypeScript
// createRoot(container).render(<GtkMenuButton />) — from '@gjsify/gtk-host/react'
const GtkMenuButton = () => (
<gtk-menu-button
iconName="open-menu-symbolic"
cssClasses={['flat']}
menuModel={[
{ label: 'Preferences', action: 'app.preferences' },
{ label: 'Keyboard Shortcuts', action: 'win.show-help-overlay' },
{ label: 'About', action: 'app.about' },
]}
/>
);
  • Controls: the entry and the drop down, the other two GTK widgets the Adwaita stylesheet paints.
  • Layout: the separator, the first of the GTK layout widgets.
  • Adwaita Buttons: button content, the split button and the toggle group.
  • Adwaita Storybook: the same widgets in a live component browser you can poke at.