-
Pl
chevron_right
Alice Mikhaylenko: Libadwaita 1.9
news.movim.eu / PlanetGnome • 1 day ago • 6 minutes
Another slow cycle, same as last time. Still, a few new things to showcase.
Sidebars
The most visible addition is the new sidebar widget. This is a bit confusing, because we already had widgets for creating windows with sidebars -
AdwNavigationSplitView
and
AdwOverlaySplitView
, but nothing to actually put into the sidebar pane. The usual recommendation is to build your own sidebar using
GtkListBox
or
GtkListView
, combined with the
.navigation-sidebar
style class.
This isn't too difficult, but the result is zero consistency between different apps, not unlike what we had with
GtkNotebook
-based tabs
in the past:
It's even worse on mobile. In the best scenario it will just be a strangely styled flat list. Sometimes it will also have selection, and depending on how it's implemented it may be impossible to activate the selected row, like in libadwaita demo.
So we have a pre-built one now. It doesn't aim to support every single use case (sidebars can get very complex, see e.g. GNOME Builder ), but just to be good enough for the basic situations.
How basic is basic? Well, it has selection, sections (with or without titles), tooltips, context menus, a drop target, suffix widgets at the end of each item's row, auto-activation when hovered during drag-n-drop.
A more advanced feature is built-in search filter - via providing a
GtkFilter
and a placeholder page.
And that's about it. There will likely be more features in future, like collapsible sections and drag source on items, rather than just a drop target, but this should already be enough for quite a lot of apps. Not everything, but that's not the goal here.
Internally, it's using
GtkListBox
. This means that it doesn't scale to thousands of items the way
GtkListView
would, but we can have much tighter API and mobile integration.
Now, let's talk about mobile. Ideally sidebars on mobile wouldn't really be sidebars at all. This pattern inherently requires a second pane, and falls apart otherwise.
AdwNavigationSplitView
already presents the sidebar pane as a regular page, so let's go further and turn sidebars into boxed lists. We're already using
GtkListBox
, after all.
So -
AdwSidebar
has the
mode
property. When set to
ADW_SIDEBAR_MODE_PAGE
, it becomes a page of boxed lists - indistinguishable from any others. It hides item selection, but it's still tracked internally. It can still be changed programmatically, and changes when an item is activated. Once the sidebar mode is set back to
ADW_SIDEBAR_MODE_SIDEBAR
, it will reappear.
Internally it's nothing special, as it just presents the same data using different widgets.
The adaptive layouts page has a detailed example for how to create UIs like this, as well as the newly added section about overlay sidebars that don't change as drastically.
View switcher sidebar
Once we have a sidebar, a rather obvious thing to do is to provide a
GtkStackSidebar
replacement. So
AdwViewSwitcherSidebar
is exactly that.
It works with
AdwViewStack
rather than
GtkStack
, and has all the same features as existing view switcher, as well as an extra one - sections.
To support that,
AdwViewStackPage
has new API for defining sections - the
:starts-section
and
:section-title
properties, while the
AdwViewStack:pages
) model is now a section model.
Like regular sidebars, it supports the boxed list mode and search filtering.
Unlike other view switchers or
GtkStackSidebar
, it also exposes
AdwSidebar
's item activation signal. This is required to make it work on mobile.
Demo improvements
The lack of sidebar was the main blocker for improving libadwaita demo in the past. Now that it's solved, the demo is at last, fully adaptive. The sidebar has been reorganized into sections, and has icons and search now.
This also unblocks other potential improvements, such as having a more scalable preferences dialog .
Reduced motion
While there isn't any new API, most widgets with animations have been updated to respect the new reduced motion preference - mostly by replacing sliding/scaling animations with crossfades, or otherwise toning down animations when it's impossible:
-
AdwDialogopen/close transitions are crossfades except for the swipe-to-close gesture -
AdwBottomSheettransition is a crossfade when there's no bottom bar, and a slide without overshooting if there is -
AdwNavigationViewtransition is a crossfade except when using the swipe gestures -
AdwTabOverviewtransition is a crossfade
AdwOverlaySplitView
is unaffected for now. Same for toasts, those are likely small enough to not cause motion sickness. If it turns out to be a problem, it can be changed later.
I also didn't update any of the deprecated widgets, like
AdwLeaflet
. Applications still using those should switch to the modern alternatives.
The
prefers-reduced-motion
media feature is available for use from app CSS as well, following the GTK addition.
Other changes
-
AdwAboutDialogrows that contain links have a context menu now. Link rows may become a public widget in future if there's interest.
-
GTK_DEBUG=builderdiagnostics are now supported for all libadwaita widgets. This can be used to find places where<child>tags are used in UI when equivalent properties exist. -
Following GTK, all
GListModelimplementations now come with:item-typeand:n-itemproperties, to make it easier to use them from expressions. -
The
AdwTabView:pagesmodel implements sections now: one for pinned pages and one for everything else. -
AdwTogglehas a new:descriptionproperty that can be used to set accessible description for individual toggles separately from tooltips. -
Adrien Plazas improved accessibility in a bunch of widgets. The majority of this work has been backported to 1.8.x as well. For example,
AdwViewSwitcherandAdwInlineViewSwithernow read out number badges and needs attention status. -
AdwNoneAnimationTargetnow exists for situations where animations are used as frame clock-based timers, as an alternative to usingAdwCallbackAnimationTargetwith empty callback. -
AdwPreferencesPagewill refuse to add children of types other thanAdwPreferencesGroup, instead of overlaying them over the page and then leaking them after the page is destroyed. This change was backported to 1.8.2 and subsequently reverted in 1.8.3 as it turned out multiple apps were relying on the broken behavior. -
Maximiliano made non-nullable string setter functions automatically replace
NULLparameters with empty strings, since allowingNULLbreaks Rust bindings, while rejecting them means apps using expressions get unexpected criticals - for example, when accessing a non-nullable string property on an object, and that object itself isNULL. -
As mentioned in the 1.8 blog post,
style-dark.css,style-hc.cssandstyle-hc-dark.cssresources are now deprecated and apps using them will get warnings on startup. Apps are encouraged to switch to a singlestyle.cssand conditionally load styles using media queries instead. -
While not a user-visible change (hopefully!), the internal stylesheet has been refactored to use
prefers-contrastmedia queries for high contrast styles instead of 2 conditionally loaded variants - further reducing the need on SCSS, even if not entirely replacing it just yet. (the main blocker is@extend, as well nesting and a few mixins, such as focus ring)
Future
A big change in works is a revamp of icon API. GTK has a new icon format that supports stateful icons with animated transitions, variable stroke weight, and many other capabilities. Currently, libadwaita doesn't make use of this, but it will in future.
In fact, a few smaller changes are already in 1.9: all of the internal icons in libadwaita itself, as well as in the demo and docs, have been updated to use the new format.
Thanks to the GNOME STF Team for providing the funding for this work. Also thanks to the GNOME Foundation for their support and thanks to all the contributors who made this release possible.
Because 2026 is such an interesting period of time to live in, I feel I should explicitly say that libadwaita does not contain any AI slop, nor does allow such contributions , nor do I have any plans to change that. Same goes for all of my other projects, including this website.