Framework expansion will proceed in this order. All three packages build on the
framework-agnostic tokens and themes provided by @gnome-ui/core.
Priority
Status
Package
Description
1
🚧
@gnome-ui/web-components
Framework-agnostic Custom Elements for GNOME widgets. Foundation: gnome-button, gnome-dialog, gnome-menu, gnome-toast, and gnome-popover; uses semantic HTML and light DOM, exposes standard DOM events, preserves accessibility, and remains compatible with htmx and server-rendered fragments.
2
⬜
@gnome-ui/angular
Angular package built after the Web Components foundation. Provide standalone components, Angular Forms integration where applicable, and reuse @gnome-ui/core tokens plus Web Components rather than duplicating styling and behavior. Blocked on Priority 1.
3
🚧
@gnome-ui/react-native
React Native package targeting iOS/Android/GNOME-mobile shells. No DOM to reuse from Web Components, so components are rebuilt with native primitives (View, Text, Pressable) and StyleSheet; consumes @gnome-ui/core tokens via a generated RN-compatible theme object (JS values, not CSS custom properties) and mirrors the @gnome-ui/react component API/props where the platforms overlap. Independent of Priority 1/2 — can start in parallel since it does not depend on the Web Components foundation.
Breadcrumb path bar for hierarchical navigation; ancestor segments are interactive buttons, current segment is bold non-interactive label; optional per-segment icons — issue #17
Plays the CSS animation embedded in an animated icon from @gnome-ui/icons (Syncing, Recording, Downloading, Connecting); always honors prefers-reduced-motion. Pragmatic web analog to GTK 4.22's GtkSvg native animated-SVG renderer — see @gnome-ui/icons — Icon Library below
GnomeProvider supplies locale, dir, numberFormat, and dateTimeFormat; useNumberFormatter and useDateTimeFormatter apply those defaults across @gnome-ui/react, @gnome-ui/layout, and @gnome-ui/charts
Lightweight components and props derived from the libadwaita 1.9 style-class reference.
These fill gaps between what we already ship and what the full Adwaita toolkit offers.
.spacer separator: invisible flex: 1 filler for Toolbar/HeaderBar to push trailing items to the end — mirrors GtkSeparator.spacer
✅
LinkedGroup
.linked box: children rendered as a single connected unit with no gap and merged borders — canonical GNOME pattern for button groups and segmented inputs
Primary action button with an attached dropdown arrow — mirrors AdwSplitButton; supports suggested and destructive variants
✅
IconButton
Accessible icon-only action button composed from Button, Icon, and optional Tooltip; supports variants, sizes, disabled state, refs, and HTML button attributes — issue #102
✅
Buttonraised variant
Add variant="raised" to Button: explicit raised look for buttons inside flat/toolbar contexts — mirrors .raised style class
✅
Buttonosd modifier
Add osd prop to Button: dark semi-transparent style for controls overlaid on media/images — mirrors .osd style class
✅
CopyButton
Icon button that copies a value to the clipboard via navigator.clipboard, swapping to a checkmark and "Copied!" tooltip/live-region announcement as confirmation; composed from IconButton — no @gnome-ui/platform dependency required
Full-page composition stories that demonstrate real-world use of the component library.
Status
Story
Description
✅
Layout/Dashboard
Full-page app layout: Toolbar with logo + inline SearchBar + action buttons + avatar Popover, collapsible sidebar with SidebarItem + Badge, content area with Card, BoxedList, ExpanderRow, InlineViewSwitcher, StatusPage, and footer Toolbar
✅
Layout/FileManager
GNOME Files (Nautilus)–style file browser: PathBar breadcrumb navigation in toolbar, collapsible Sidebar with Places + Network sections, InlineViewSwitcher for grid/list toggle, folder drill-down, and mobile overlay sidebar — issue #16
✅
Layout/Settings
GNOME Settings–style preferences app: dual-headerbar pattern, 14-category sidebar with per-category icons, sub-page drill-down (Accessibility → Seeing), SwitchRow toggle rows, ActionRow for value navigation, PreferencesGroup sections
Tier 10 — Sidebar Enhancements (identified via Dashboard story)¶
Gaps discovered while building the Dashboard composition story.
Status
Component
Description
✅
Sidebarcollapsed prop
Built-in icon-only (mini/rail) mode: collapsed prop animates width (240 px → 56 px), hides labels/suffixes/section titles, and auto-shows tooltips on hover. SidebarCollapsedContext and useSidebarCollapsed hook exported for custom consumers. Dashboard story updated to use the real Sidebar component.
Framework-agnostic Adwaita symbolic icon definitions. Each icon is a plain IconDefinition object (SVG path data) consumed by the <Icon> component in @gnome-ui/react.
Dedicated npm package that ships the full-page application shell as a first-class primitive.
Consumers can compose any GNOME application layout without pulling in the full @gnome-ui/react bundle.
Status
Component
Description
✅
Layout
Full-page shell with four named zones: topBar (pinned header), sidebar (fixed-width navigation), children (scrollable content), and bottomBar (pinned footer). All zones are optional. Mirrors the composition pattern demonstrated in Layout/Dashboard. Ships as @gnome-ui/layout with its own CSS output, Vitest unit tests, and Storybook story (Layout/Layout).
Pure TypeScript package. Communicates with GNOME via the WebKitGTK window.webkit.messageHandlers bridge or XDG Desktop Portals. Falls back to no-op stubs in standard browsers / test environments.
Status
Module
Description
✅
settings
getSetting/setSetting/onSettingChanged — WebKitGTK via the bridge (request/response correlation for the async Gio.Settings.get_value() round-trip, plus a changed-signal subscription filtered by key). No browser fallback — there is no web equivalent of an app-schema-scoped GSettings store.
✅
notifications
sendNotification/withdrawNotification/onNotificationAction — WebKitGTK via the bridge (Gio.Notification, action buttons), with a real browser Notification fallback (permission flow, single click routed through the same action-event shape as a synthetic 'default' action).
✅
fileChooser
openFile/saveFile/selectFolder — WebKitGTK via the bridge (GtkFileChooserDialog / XDG portal), request/response correlated. No browser fallback — the File System Access API only hands back opaque handles, never real filesystem paths.
✅
colorScheme
getColorScheme/setColorScheme/onColorSchemeChanged — WebKitGTK via the bridge (maps to Adw.StyleManager; set only ever overrides this app's own rendering, never the desktop-wide preference), with a real matchMedia('(prefers-color-scheme: dark)') fallback for get/subscribe in browsers/PWAs. set has no browser fallback — there is no JS API to force the browser's own rendering into a scheme.
✅
window
getWindowState/setMaximized/setFullscreen/minimizeWindow/closeWindow/onWindowStateChanged — WebKitGTK via the bridge (Gtk.Window's maximized/fullscreened/is-active). Browser/PWA fallback for fullscreen (real Fullscreen API), focused (real document.hasFocus()), and close (real window.close(), subject to the browser's own script-only restriction); maximized/minimize have no browser equivalent and either report false or reject.
✅
clipboard
readText/writeText/readImage/writeImage/readFiles/writeFiles — WebKitGTK via the bridge (request/response correlation for the async Gdk.Clipboard reads; images cross the bridge as base64 data: URLs). Real navigator.clipboard fallback for text and images in browsers/PWAs (Blob⇄data: URL conversion keeps both paths returning the same shape). Files have no browser fallback — same constraint as fileChooser: browsers never expose real filesystem paths to page scripts.
✅
portals
callPortal/onPortalSignal — the generic escape hatch behind the other portal-backed modules: an arbitrary { interface, method, args } D-Bus call (request/response correlated, bridging the real portal Request/Response two-step) plus signal subscription filtered by interface+signal. WebKitGTK only — portals are meaningless without a sandboxed host.
React hooks that surface every @gnome-ui/platform module as idiomatic React state.
Status
Hook
Description
✅
useRuntime
Full runtime snapshot: shell, engine, browser, OS
✅
usePlatform
Convenience booleans for the current shell context (isGnomeWebView, isPWA…)
✅
useNativeEvent
Subscribe to an event dispatched by the GJS host via gnome: prefix
✅
useBreakpoint
Reactive isMobile, isTablet, isDesktop flags based on GNOME HIG breakpoints
✅
useSettings
Read and write a GSettings key; re-renders on external changes, optimistic writes, exposes loading/error
✅
useNotification
Returns send/dismiss, scoped to the component's lifetime — notifications sent through it are auto-withdrawn and onAction listeners auto-unsubscribed on unmount
✅
useColorScheme
Returns the resolved "light"/"dark" scheme and a "light"/"dark"/"system" setter, reactive to external changes — talks to Adw.StyleManager via the bridge, distinct from @gnome-ui/react's GnomeProvider-based hook of the same name
✅
useFileChooser
Returns open()/save()/selectFolder() triggers and the resolved path/paths as reactive state, plus loading/error
✅
useClipboard
Returns { value, copy, paste } with reactive clipboard state, plus loading/error — text only; use @gnome-ui/platform's clipboard module directly for images/files
✅
useWindowState
Returns { maximized, fullscreen, focused } and matching actions (setMaximized, setFullscreen, minimize, close), plus loading/error
✅
useHapticFeedback
Trigger haptic feedback via feedbackd (native) or Vibration API (browser) — issue #81
Widgets from the GTK4/libadwaita catalog (or well-established HIG-adjacent
patterns) not yet covered by the ~96 components already shipped in
@gnome-ui/react. Scoped to atoms and simple molecules only — no new
organism/page-level compositions. Verified against the current component
tree to avoid duplicating existing functionality (e.g. ColorPicker
already covers Adwaita accent-color swatches via GNOME_PALETTE, so it is
intentionally excluded here).
Discrete level indicator with colour-coded low/high/full offset zones — mirrors GtkLevelBar; distinct from ProgressBar (determinate task progress) and SegmentedBar (proportional category breakdown)
✅
Expander
Standalone disclosure triangle + collapsible content — mirrors GtkExpander; complements ExpanderRow, which only works nested inside a BoxedList row
✅
PasswordField
Standalone masked TextField with a built-in reveal/conceal toggle, for login forms and dialogs outside a settings-row context — reuses the reveal-icon pattern from PasswordEntryRow without requiring ActionRow
✅
Divider
Horizontal rule with an optional centred label (e.g. "OR") — common auth/login-form pattern; distinct from the plain Separator line
✅
RatingStars
Star rating display and interactive input, keyboard-navigable — common HIG-adjacent pattern for review/quality widgets, pairs with Icon's Star/StarOutline
✅
FileTypeIcon
Small icon (optionally with a thumbnail) resolved from a file's MIME type or extension — useful for file-manager-style listings, complementing the existing Layout/FileManager story
✅
Callout
Inline, dismissible admonition box (info/warning/tip variants) for contextual help text within forms and cards — distinct from Banner (persistent, view-level) and Toast (temporary, notification-level)
✅
StepIndicator
Numbered "Step X of Y" progress indicator for onboarding/wizard flows — complements the existing CarouselIndicatorDots/CarouselIndicatorLines with a labelled, linear alternative
✅
RangeSlider
Dual-thumb slider for selecting a min/max range — Slider is single-thumb only; needed for range filters (price, date range, etc.)
✅
TextTruncate
Single/multi-line text truncation with an automatic tooltip revealing the full content on overflow — mirrors GtkLabel's ellipsize property
✅
Kbd
Standalone single key-cap (e.g. Enter, Esc) for inline instructional text ("press Enter to continue") — complements ShortcutLabel, which only renders full +-delimited combos and doesn't expose its key-cap rendering separately
✅
Highlight
Inline <mark>-based text highlighting for matched search terms — pairs with SearchBar's suggestion list and any filterable list/table
✅
VisuallyHidden
Reusable "sr-only" utility — visually hides content while keeping it in the accessibility tree; extracts the recipe currently duplicated inline inside CopyButton's live-region announcement
✅
Overlay
Standalone backdrop/scrim layer with fade transition and click-to-dismiss — extracts the near-identical backdrop implementation currently duplicated across Modal, Dialog, and BottomSheet
Month-grid date display with keyboard navigation — mirrors GtkCalendar; usable standalone or as the panel inside DatePicker
✅
DatePicker
TextField trigger + Popover-anchored Calendar — mirrors the GtkCalendar + GtkPopover composition pattern used for date entry across GNOME apps. showTime adds TimePicker's hour/minute columns under the calendar, turning the emitted Date into a point in time: the day click then keeps the popover open and a Done button finishes the selection
✅
TimePicker
Hour/minute selection built from paired SpinButtons in a Popover, with 12/24-hour format support. The columns live in an internal TimeFields, shared with DatePicker/DateRangePicker's showTime footer
✅
CalendarRange
Start/end date-range selection sharing Calendar's grid engine (roving tabindex, month/year drill-down, min/max). Emits through onChangeonly once both ends have a value — a first click sets the anchor and paints a live preview band up to the hovered (or keyboard-focused) day, and the second click commits the range; picking backwards reorders the pair instead of failing. visibleMonths (default 1) renders N side-by-side month panels paged as one unit, so a range spanning months is picked without navigating. Adds minRange/maxRange day limits on top of min/max, aria-selected on every in-range cell plus start/in-range/end suffixes in the day labels, and Esc to cancel an in-progress range (after leaving the drill-down)
✅
DateRangePicker
Popover-anchored CalendarRange behind a DatePicker-style trigger reading "1 Aug – 15 Aug 2026". Defaults to visibleMonths={2}, closes only on a complete range, and offers an optional preset sidebar (last 7 days, this month, last quarter) — the composition counterpart of DatePicker, mirroring GtkCalendar + GtkPopover. showTime gives each end its own hour/minute columns plus a Done button, keeping start ≤ end when both land on the same day
✅
FontPicker
Button that opens a family/size/weight chooser — mirrors GtkFontDialogButton
✅
EmojiPicker
Searchable emoji grid in a Popover — mirrors GtkEmojiChooser
✅
TagInput
Type-to-add multi-value input rendering entries as removable Chips in a WrapBox — WrapBox/Chip currently only support static/pre-populated display, not interactive entry
✅
OtpInput
Segmented PIN/verification-code input (one cell per digit, auto-advance, paste support) — common auth pattern, pairs naturally with PasswordEntryRow/PasswordField
✅
CopyField
Read-only TextField/EntryRow with a built-in trailing CopyButton — for displaying copyable values (API keys, tokens, IDs) outside the CveIdentifier/CweIdentifier-style specialised components
✅
ChoiceCardGroup
Card-based single-choice selector (large selectable cards instead of radio buttons) — mirrors the pattern used in GNOME Initial Setup / welcome flows
✅
FileDropZone
Drag-and-drop file upload target with hover/active states, falling back to a GtkFileDialog-style click-to-browse trigger
✅
MultiSelectDropdown
Checkbox-list variant of Dropdown for selecting multiple values from a single trigger — Dropdown/ComboRow are currently single-select only
✅
CodeBlock
Static monospace code/config snippet display with optional line numbers and a CopyButton trailing action — distinct from TerminalView (live scrolling terminal output)
✅
WidgetManager
Card that manages a controlled collection of widgets picked from a catalog, each rendering its own content via render(); edit-mode trigger opens a staged add/remove picker (Modal/BottomSheet/Drawer, configurable) applied only on confirm
✅
FieldGroup
Generic form-field grouping with a shared label, help text, and error message, for arbitrary fields outside a BoxedList — PreferencesGroup is scoped specifically to wrapping settings rows
✅
Portal
Reusable createPortal wrapper (mount target, SSR-safe no-op) — extracts the ad-hoc portal logic currently duplicated independently across 13 components (Dialog, Modal, Popover, Tooltip, BottomSheet, etc.)
✅
CoachMark
Onboarding feature-discovery pattern: spotlights a target element and anchors a callout bubble (title, description, actions) beside it, with a CoachMarkTour orchestrator for sequential steps (Next/Back/Skip/Done + "X of N"). Pragmatic web-app pattern beyond GNOME HIG, built on Button/Portal and a viewport-aware flip positioner