Skip to main content

Crate g3_ui

Crate g3_ui 

Source
Expand description

§g3-ui

CI Playground image Crates.io docs.rs License

Mobile-first Dioxus components inspired by Ionic.

Four mobile g3-ui screens showing a feed, a booking form, a sheet, and a profile

g3-ui is a component library for Dioxus web and desktop/android/ios using web view. It may be expanded to work with Dioxus Native (blitz) in the future. Components try to be compatible with desktop and mobile sizing as much as possible. Every component has iOS and Material Design (MD) styling, CSS-variable theming, and WAI-ARIA semantics. The Rust crate name is g3_ui.

§Install

[dependencies]
dioxus = { version = "0.7.9", features = ["router"] }
g3-ui = "0.4"

Enable the optional route-transition integration when your app also uses g3-route-transitions:

[dependencies]
g3-ui = { version = "0.4", features = ["transitions"] }
g3-route-transitions = "0.4"

The minimum supported Rust version is 1.88.

§Quick Start

AppWrapper loads the stylesheet, resolves the platform mode, applies the theme, and hosts the toasts, alerts, and action sheets opened from code. Everything else nests inside it.

use dioxus::prelude::*;
use g3_ui::prelude::*;

#[component]
fn App() -> Element {
    rsx! {
        AppWrapper { theme: Theme::system(),
            Header { title: "Games" }
            Content {
                Card { title: "Pending game",
                    "Invite players and choose a format."
                }
                Button { onclick: |_| {}, "Create game" }
            }
        }
    }
}

g3_ui::prelude exports the components and theme items only. Import dioxus::prelude yourself. Component names are unprefixed. If one collides with a local name, import it under an alias (use g3_ui::Button as UiButton;) or write the path (g3_ui::Button { .. }).

§Components

CategoryComponents
App shellAppWrapper, Header, BackButton, Content, TabLayout, ThemeProvider
NavigationAdaptiveNav, NavBar, NavRail, NavItem, NavigationDrawer, Tabs, TabList, Tab, TabPanel, SegmentGroup, SegmentButton
ActionsButton, Fab, FabButton, FabList, FabMenu, InfoButton, Popover, Menu, MenuItem
FormsInput, TextArea, Select, Checkbox, Toggle, RadioGroup, Radio, Range, Stepper, Searchbar, DatePicker, TimePicker, Calendar
ContentCard, List, ListHeader, Item, SwipeItem, SwipeAction, Text, Img, Tooltip, Avatar, Badge, Chip, Divider
LayoutStack, Grid
DisclosureAccordionGroup, AccordionItem
OverlaysBottomSheet, SideSheet, Modal, Alert, ConfirmModal, ActionSheet, Toast
FeedbackProgress, Skeleton, Spinner, Refresher, InfiniteScroll

docs.rs/g3-ui has the full prop reference. The playground shows every component live.

§Component State

A component with a value takes an optional Signal<T> and reads and writes it directly. Leave the signal out and the component keeps its own state. An optional onchange or on_* callback reports changes when you need a side effect as well:

let checked = use_signal(|| false);
let name = use_signal(String::new);
let format = use_signal(|| None::<Format>);

rsx! {
    Toggle { checked, label: "Notifications" }
    Input { label: "Name", value: name, onchange: move |name| save(name) }
    RadioGroup { value: format, label: "Format",
        Radio { value: Format::Stroke, label: "Stroke play" }
        Radio { value: Format::Match, label: "Match play" }
    }
}

Select, RadioGroup, SegmentGroup, Tabs, and AccordionGroup are generic over the value type, so options can be your own enums instead of strings or indexes.

§Dates and Times

DatePicker and TimePicker are form fields that open a picker. They are the way in: Input has no date or time kind, because the browser’s own picker ignores the mode and the theme. Their values are CalendarDate and TimeOfDay, which parse from and print as ISO 8601 (2026-09-19, 14:05), so nothing has to agree on a string format:

let tee_day = use_signal(|| None::<CalendarDate>);
let tee_time = use_signal(|| None::<TimeOfDay>);

rsx! {
    DatePicker { label: "Tee day", value: tee_day, min: CalendarDate::today() }
    TimePicker { label: "Tee time", value: tee_time, minute_step: 10 }
}

style decides how one opens. By default it follows the mode:

PickerStyleDateTime
Autowheels on iOS, dialog on MDwheels on iOS, dialog on MD
Wheelsmonth, day, and year columns in a bottom sheethour, minute, and AM/PM columns
Dialoga calendar with Cancel and OKa clock face, with a typing mode
Popovera calendar anchored to the fieldwheels anchored to the field

A Popover picker becomes a bottom sheet on a phone. Calendar is also available on its own, for a month grid inside a page.

Both are usable without a pointer. The calendar’s arrow keys move a day at a time, Home and End reach the ends of the week, and Page Up and Page Down change month or year. A wheel column is a spin button, and the clock face is a radio group; Material’s dialog can also be typed into.

§Pull to Refresh

Give Content an on_refresh handler and it refreshes when pulled down from the top. Keep refreshing true while the work runs:

let mut refreshing = use_signal(|| false);

rsx! {
    Content {
        refreshing: refreshing(),
        on_refresh: move |_| async move {
            refreshing.set(true);
            reload().await;
            refreshing.set(false);
        },
        RoundList {}
    }
}

§Overlays From Code

Toasts, alerts, and action sheets can be opened from an event handler without declaring them in markup. AppWrapper renders them one at a time. Alerts and action sheets return a future with the user’s answer:

let toast = use_toast();
let alerts = use_alert();

let delete = move |_: MouseEvent| async move {
    if alerts.confirm("Delete round?", "This cannot be undone.").await {
        remove_round();
        toast.success("Round deleted");
    }
};

use_action_sheet() works the same way and resolves to the chosen button’s index. Each overlay is also a component (Toast, Alert, ActionSheet) that takes an open signal, for cases where the markup should own it.

§Modes and Themes

Components have Ionic-style Ios and Md modes. A component takes the first mode it finds: its own mode prop, the nearest AppWrapper or ThemeProvider, then the global default set by set_mode or init_auto_mode. Changing the provider’s mode prop updates the subtree.

fn main() {
    g3_ui::init_auto_mode(); // iOS look on Apple platforms, MD elsewhere
    dioxus::launch(App);
}

Colors are CSS custom properties (--g3-color-*) generated from a Theme. The presets are Theme::default_light(), Theme::default_dark(), and Theme::system(), which follows the operating system through CSS light-dark(). Every field is public:

let brand = Theme::system().with_accent("#1f7a4d");

let custom = Theme {
    bg: "#0b1020".into(),
    card: "#151b2e".into(),
    ..Theme::default_dark()
};

let paired = Theme::adaptive(light_brand, dark_brand);

The theme is written as inline custom properties on the wrapper, so passing a different Theme re-themes the tree in place. use_theme() returns the theme in effect for code that needs the values.

Built-in component text such as “Close” and “Cancel” comes from Strings. Pass translated strings to AppWrapper { strings, .. }.

§Responsive App Shell

AppWrapper measures its own width with a CSS container query rather than the browser viewport, so an app embedded in a narrow frame keeps its phone layout. At 48rem and wider:

  • AdaptiveNav inside a TabLayout moves from the bottom edge to a rail beside the page. NavBar and NavRail are the fixed forms, for apps that decide the layout themselves.
  • Bottom sheets become floating panels, Select and Popover open as anchored menus instead of sheets, and modals widen.
  • Toasts become a centred snackbar.

At 64rem the Header toolbar moves inline with the title.

Grid takes wide_columns and wide_gap for the same breakpoint, and Content { width: ContentWidth::Readable } keeps text at a comfortable width on a wide shell while its scrollbar stays at the page edge.

rsx! {
    TabLayout {
        Header { title: "Rounds" }
        Content { /* page */ }
        AdaptiveNav {
            NavItem { label: "Rounds", icon: rsx! { Flag {} }, to: Route::Rounds {}, selected: true }
            NavItem { label: "Profile", icon: rsx! { User {} }, to: Route::Profile {},
                group: NavItemGroup::Secondary }
        }
    }
}

NavItemGroup::Secondary moves an item to the bottom of the rail; the phone tab bar keeps the declared order. AdaptiveNav { compact: AdaptiveNavCompact::Hidden } shows only the rail and hides the phone tab bar, for full-screen routes. Set --g3-nav-rail-width to widen the rail.

§Sheets and Drawers

BottomSheet rises from the bottom edge. It can rest at several heights, given as fractions of the app’s height. With backdrop_detent, the page stays usable while the sheet is low:

BottomSheet { open: results_open, detents: vec![0.2, 0.5, 1.0], backdrop_detent: 2,
    /* content */
}

SideSheet slides in from the start or end edge. SideSheetBehavior::Overlay covers the page, Push moves the page aside, and Reveal moves the page to uncover a sheet that stays still. Both edges are logical, so SheetEdge::Start is on the right in a right-to-left document.

NavigationDrawer is persistent navigation beside the page, like Ionic’s split pane. It is not a dialog: the page narrows to make room, and nothing is dimmed or trapped. For Push, Reveal, and NavigationDrawer, render the sheet and one page element as direct children of AppWrapper.

A sheet normally opens over a scrim that closes it when tapped. backdrop: SheetBackdrop::None leaves the page behind visible and interactive, for something like comments beside a video. The sheet is then no longer modal, and a bottom sheet closes only when dragged down.

Android Back should still close a sheet with no scrim. Every open dismissible sheet renders a hidden [data-g3-sheet-dismiss] control, and open_sheet_count() reports how many are open. Claim Back while the count is above zero, then click the topmost sheet’s control:

const dismiss = [
    ...document.querySelectorAll('.g3-sheet[data-state="open"] [data-g3-sheet-dismiss]'),
].pop();
if (dismiss) {
    event.preventDefault();
    dismiss.click();
}

§Route Transition Integration

With the transitions feature enabled, g3-ui components provide the g3-route-transitions snapshot regions for you:

ComponentRegionEffect
AppWrapperoverlay (plus the stylesheet)Rises and falls for routed sheets
TabLayoutbaseStays put during navigation and dims under a sheet
ContentsegmentSlides for ordered peer routes such as segmented tabs
AdaptiveNav or NavRail as a railpersistentStays in place above a rising sheet (the phone tab bar stays part of the base)

Add RouteTransitionPage yourself, around each page’s header and content, to get stack push and pop motion:

ⓘ
use g3_route_transitions::RouteTransitionPage;

rsx! {
    TabLayout {
        RouteTransitionPage {
            Header { title: "Rounds" }
            Content { /* page content */ }
        }
        AdaptiveNav { /* persistent tabs stay still */ }
    }
}

Layout rules:

  • Sheet routes: a route declared with layer = sheet must render TabLayout { route_transition_base: false, .. } (or no tab layout) and no RouteTransitionPage. Otherwise its content is captured outside the rising overlay. To keep the desktop rail beside the sheet, render the same tabs with AdaptiveNav { compact: AdaptiveNavCompact::Hidden, .. }. Phones hide them, so the sheet still covers the bottom tabs.
  • Segmented screens: leave RouteTransitionPage out of screens whose Content should slide by itself. Inside a page, the whole page moves instead.
  • Nested wrappers: AppWrapper is the overlay region by default. If a documentation shell or other non-navigating wrapper contains a second app wrapper, set route_transition_overlay: false on the outer one. A document may only have one overlay region.

See the g3-route-transitions README for the route metadata that decides which transition runs.

Without the feature, g3-ui does not depend on g3-route-transitions and does not emit route-transition marker classes.

§Styling

All rules live in the g3 cascade layer, so any unlayered rule in your stylesheet overrides them without extra specificity or !important. Components accept a class prop. Button, FabButton, and Input also pass any other HTML attribute through, such as aria_haspopup or data-*. Component state is exposed as data-state and ARIA attributes ([data-state="open"], [aria-checked="true"]) rather than modifier classes.

§Upgrading From 0.3

0.4 renames most of the API. CHANGELOG.md lists every change; the common ones are:

0.30.4
G3-prefixed aliasesunprefixed names only
G3BodyContent
G3Navbar, G3NavbarTabBar, G3NavbarTabTabLayout, AdaptiveNav, NavItem
G3Sheet with SheetPlacementBottomSheet, SideSheet, NavigationDrawer
G3FieldInput, TextArea
G3Line, G3ItemDividerDivider, ListHeader
G3SheetButtonInfoButton { sheet, .. }
G3FabContainerFabMenu
ButtonStyle / style:ButtonFill / fill:
Card { inset }Card { variant: CardVariant::Filled }
List { inset }List { variant: ListVariant::Raised }
SwipeItem { behavior }start_behavior, end_behavior
is_open, active propsopen, value
--color-* variables--g3-color-*
Theme::with_focused, focusedTheme::with_accent, accent

§Playground

The deployed interactive component gallery is built from playground/ inside this repository. It renders every component with live controls. Switch between MD and iOS, and between Mobile and Desktop frames, to see the same tree in a compact and a wide shell. Every demo has a stable URL such as /components/button.

The deployed /transitions showcase composes the real app shell, header, content, navigation, cards, lists, buttons, and segmented controls with g3-route-transitions, including a routed sheet.

When developing g3-ui and g3-route-transitions side by side, uncomment the adjacent [patch.crates-io] block in .cargo/config.toml. Cargo then redirects every g3-route-transitions dependency in the library and playground to the sibling checkout. Comment the block again before committing; normal builds and published packages continue using the version from crates.io.

cd playground
dx serve

To type-check the playground without launching a dev server:

cargo check --manifest-path playground/Cargo.toml

To regenerate the transition showcase media while the playground is running on port 8080, install the optional capture dependency and run the recording recipe. The tour pauses for more than a second between animations so each transition is readable.

npm ci --prefix playground
just record-transitions

Production images are published to the GitHub Container Registry. See deploy/README.md for Portainer and Docker Compose instructions.

§License

Licensed under either of MIT or Apache-2.0 at your option.

Re-exports§

pub use theme::ThemeProvider;
pub use theme::ThemeProvider;
pub use accordion::AccordionGroup;
pub use accordion::AccordionGroup;
pub use accordion::AccordionItem;
pub use accordion::AccordionItem;
pub use action_sheet::ActionSheet;
pub use action_sheet::ActionSheet;
pub use alert::Alert;
pub use alert::Alert;
pub use app_wrapper::AppWrapper;
pub use app_wrapper::AppWrapper;
pub use avatar::Avatar;
pub use avatar::Avatar;
pub use back_button::BackButton;
pub use back_button::BackButton;
pub use badge::Badge;
pub use badge::Badge;
pub use bottom_sheet::BottomSheet;
pub use bottom_sheet::BottomSheet;
pub use button::Button;
pub use button::Button;
pub use calendar::Calendar;
pub use calendar::Calendar;
pub use card::Card;
pub use card::Card;
pub use checkbox::Checkbox;
pub use checkbox::Checkbox;
pub use chip::Chip;
pub use chip::Chip;
pub use confirm_modal::ConfirmModal;
pub use confirm_modal::ConfirmModal;
pub use content::Content;
pub use content::Content;
pub use date_picker::DatePicker;
pub use date_picker::DatePicker;
pub use divider::Divider;
pub use divider::Divider;
pub use empty_state::EmptyState;
pub use empty_state::EmptyState;
pub use fab::Fab;
pub use fab::Fab;
pub use fab::FabButton;
pub use fab::FabButton;
pub use fab::FabList;
pub use fab::FabList;
pub use fab::FabMenu;
pub use fab::FabMenu;
pub use field::Input;
pub use field::Input;
pub use field::TextArea;
pub use field::TextArea;
pub use header::Header;
pub use header::Header;
pub use infinite_scroll::InfiniteScroll;
pub use infinite_scroll::InfiniteScroll;
pub use info_button::InfoButton;
pub use info_button::InfoButton;
pub use layout::Grid;
pub use layout::Grid;
pub use layout::Stack;
pub use layout::Stack;
pub use list::Item;
pub use list::Item;
pub use list::List;
pub use list::List;
pub use list::ListHeader;
pub use list::ListHeader;
pub use media::Img;
pub use media::Img;
pub use media::Tooltip;
pub use media::Tooltip;
pub use modal::Modal;
pub use modal::Modal;
pub use nav::AdaptiveNav;
pub use nav::AdaptiveNav;
pub use nav::NavBar;
pub use nav::NavBar;
pub use nav::NavItem;
pub use nav::NavItem;
pub use nav::NavRail;
pub use nav::NavRail;
pub use navigation_drawer::NavigationDrawer;
pub use navigation_drawer::NavigationDrawer;
pub use popover::Menu;
pub use popover::Menu;
pub use popover::MenuItem;
pub use popover::MenuItem;
pub use popover::Popover;
pub use popover::Popover;
pub use progress::Progress;
pub use progress::Progress;
pub use radio::Radio;
pub use radio::Radio;
pub use radio::RadioGroup;
pub use radio::RadioGroup;
pub use range::Range;
pub use range::Range;
pub use range::Stepper;
pub use range::Stepper;
pub use rating::Rating;
pub use rating::Rating;
pub use refresher::Refresher;
pub use refresher::Refresher;
pub use reorder::ReorderHandle;
pub use reorder::ReorderHandle;
pub use reorder::ReorderItem;
pub use reorder::ReorderItem;
pub use reorder::ReorderList;
pub use reorder::ReorderList;
pub use searchbar::Searchbar;
pub use searchbar::Searchbar;
pub use segment::SegmentButton;
pub use segment::SegmentButton;
pub use segment::SegmentGroup;
pub use segment::SegmentGroup;
pub use select::Select;
pub use select::Select;
pub use shelf::Shelf;
pub use shelf::Shelf;
pub use side_sheet::SideSheet;
pub use side_sheet::SideSheet;
pub use skeleton::Skeleton;
pub use skeleton::Skeleton;
pub use spinner::Spinner;
pub use spinner::Spinner;
pub use swipe::SwipeAction;
pub use swipe::SwipeAction;
pub use swipe::SwipeItem;
pub use swipe::SwipeItem;
pub use tab_layout::TabLayout;
pub use tab_layout::TabLayout;
pub use table::Table;
pub use table::Table;
pub use tabs::Tab;
pub use tabs::Tab;
pub use tabs::TabList;
pub use tabs::TabList;
pub use tabs::TabPanel;
pub use tabs::TabPanel;
pub use tabs::Tabs;
pub use tabs::Tabs;
pub use text::Text;
pub use text::Text;
pub use time_picker::TimePicker;
pub use time_picker::TimePicker;
pub use toast::Toast;
pub use toast::Toast;
pub use toggle::Toggle;
pub use toggle::Toggle;

Modules§

prelude
Every component, enum, and hook in one import.

Structs§

ActionSheetButton
One choice in an ActionSheet.
ActionSheetOptions
An action sheet to show with ActionSheets::show.
ActionSheets
Shows action sheets from code and waits for the choice. Get one with use_action_sheet.
AlertButton
One button of an Alert.
AlertInput
A text field inside an Alert, for a prompt.
AlertOptions
An alert to show with Alerts::show.
AlertResult
What the user did with an Alert.
Alerts
Shows alerts from code and waits for the answer. Get one with use_alert.
CalendarDate
A day in the proleptic Gregorian calendar, with no time or time zone.
ComponentDescriptor
Name and one-line summary for a component, used by the playground and by generated documentation.
Destination
Where a tappable component navigates, built from a route, a path, or a URL.
ParseDateTimeError
Why a date or time string did not parse.
SelectOption
One choice in a Select.
Strings
Text that components render on their own: accessible names, button labels, status messages. English by default; provide a translated set through AppWrapper or ThemeProvider.
SwipeState
The live state of a swipe, passed to SwipeItem’s callbacks.
Theme
Color tokens for g3-ui components.
TimeOfDay
A time of day to the minute, with no date or time zone.
ToastId
Identifies a toast shown with Toaster::show.
ToastOptions
A toast to show with Toaster::show.
Toaster
Shows toasts from code. Get one with use_toast.

Enums§

AdaptiveNavCompact
What an AdaptiveNav does on a compact shell (narrower than 48rem). On wide shells it is always a rail.
AlertButtonRole
What an AlertButton does, which decides its look and position.
AvatarSize
Avatar size.
ButtonExpand
How a Button fills the width of its container.
ButtonFill
How a Button is filled.
ButtonSize
Button size.
ButtonType
HTML type of a <button>.
CardVariant
How a Card separates itself from the page.
Color
A semantic color for buttons, badges, chips, toasts, and swipe actions.
ComponentMode
Platform styling mode, like Ionic’s mode attribute.
ContentWidth
How wide Content lets its children grow.
ControlLabelPlacement
Where a checkbox, toggle, or radio sits relative to its label.
DividerOrientation
Direction of a Divider.
FabHorizontal
Horizontal position of a Fab, in reading direction.
FabListSide
Which way a FabList opens from its button.
FabSize
FabButton size.
FabVertical
Vertical position of a Fab.
GridColumns
How a Grid sizes its columns.
HourCycle
Whether times show on a 12-hour clock with AM and PM, or a 24-hour one.
ImgFit
How an Img fills its box.
InputType
The kind of value an Input takes. Each maps to an HTML input type, which picks the on-screen keyboard.
ItemDetail
Whether an Item shows a trailing chevron.
ListLines
How separators are drawn between list rows.
ListVariant
How a List sits on the page. Apart from EdgeToEdge, these match CardVariant: the rows sit in a rounded group, like an iOS settings screen, drawn the way a card with that variant is.
ModalRole
The ARIA role of a Modal.
ModalSize
Width of a Modal.
NavItemGroup
Where a NavItem sits in a rail. Bottom bars keep declaration order.
PickerStyle
How a DatePicker or TimePicker opens.
PopoverPlacement
Where a Popover or Menu opens relative to its trigger.
ReorderHandlePosition
Which edge of a row holds a ReorderHandle.
ReorderLayout
How the items of a ReorderList are laid out, which decides where a dragged item lands and how the others make room.
SelectWidth
How wide a Select is.
SheetBackdrop
What sits behind an open sheet.
SheetEdge
A side of the screen, in reading direction.
ShellSize
How wide the app shell is, in the two sizes the stylesheet lays out for.
SideSheetBehavior
How a SideSheet moves the page beside it.
SkeletonShape
The shape of a Skeleton.
Space
A spacing step, shared by Stack and Grid.
SpinnerSize
Spinner size.
StackAlign
Cross-axis alignment in a Stack.
StackJustify
Main-axis distribution in a Stack.
SwipeBehavior
What swiping toward one edge does once it passes its threshold.
SwipeSide
Which edge of a row a swipe uncovers.
TableVariant
How a Table sits on its page.
TextTone
How strongly Text stands out.
TextVariant
The typographic role of Text, which also picks its HTML element.
ToastDuration
How long a toast stays up.
ToastPosition
Where a toast appears.
ToggleSize
Size of a Toggle.
TooltipPlacement
Where a Tooltip appears.

Statics§

UI_CSS
The component stylesheet.

Functions§

AccordionGroup
A group of expandable sections. Like Ionic’s ion-accordion-group.
AccordionItem
One expandable section of an AccordionGroup.
ActionSheet
A sheet of choices with a separate cancel button. Like Ionic’s ion-action-sheet.
AdaptiveNav
Navigation that is a bottom bar on compact shells and a side rail on wide ones. Put it last inside a TabLayout.
Alert
A short dialog with a title, message, buttons, and an optional text field. Like Ionic’s ion-alert.
AppWrapper
The root of a g3-ui app: loads the stylesheet, applies the mode, theme, and strings, and lays out a full-height, responsive app shell.
Avatar
A round image of a person or team, with initials when there is no image. Like Ionic’s ion-avatar.
BackButton
A back button for a Header’s start slot. Like Ionic’s ion-back-button.
Badge
A small pill for a count or a status. Like Ionic’s ion-badge.
BottomSheet
A sheet that rises from the bottom of the screen. Like Ionic’s sheet modal. On wide shells it floats as a centred card.
Button
A button, or a link that looks like one. Like Ionic’s ion-button.
Calendar
A month calendar for picking a date. Like the calendar in iOS’s inline date picker and Material’s date picker.
Card
A content container with an optional title, subtitle, leading and trailing content, and media. Like Ionic’s ion-card.
Checkbox
A checkbox row: the box, a label, and optional helper and error text. The whole row is the control. Like Ionic’s ion-checkbox.
Chip
A compact pill for a filter, tag, or choice. Like Ionic’s ion-chip.
ConfirmModal
A confirmation dialog with cancel and confirm buttons.
Content
The scrollable content area of a page, below its Header. Like Ionic’s ion-content.
DatePicker
A form field that picks a date, with iOS wheels or a Material calendar dialog. Like Ionic’s ion-datetime in a modal.
Divider
A thin rule that separates content. Set --g3-divider-color to recolor it.
EmptyState
What fills a screen, or a part of one, when there is nothing to show: an icon, a headline, a line of explanation, and usually a way forward.
Fab
Positions floating action buttons over the page. Like Ionic’s ion-fab. Pass it to Content’s fab slot so it stays put while the content scrolls.
FabButton
A round floating action button. Like Ionic’s ion-fab-button.
FabList
Secondary buttons that open from a FabButton. Like Ionic’s ion-fab-list. FabMenu wires one up for you.
FabMenu
A floating action button that opens a list of secondary actions, with the open state and close icon handled for you. A speed dial.
Grid
Lays children out in a grid of equal columns.
Header
The top bar of a page: a title between start and end slots, with an optional toolbar row below. Like Ionic’s ion-header with an ion-toolbar.
Img
An image that loads lazily, holds its space with a placeholder while it loads, and shows fallback if it fails. Like Ionic’s ion-img.
InfiniteScroll
Calls on_load when the user scrolls near its position. Put it after the last item of a list. Like Ionic’s ion-infinite-scroll.
InfoButton
A round “i” button. Give it sheet content and it opens that content in a BottomSheet; otherwise handle onclick yourself.
Input
A single-line text field with a label. Like Ionic’s ion-input.
Item
A list row with leading content, text lines, metadata, and trailing content. Like Ionic’s ion-item.
List
A vertical list of Items. Like Ionic’s ion-list.
ListHeader
A section heading inside a List.
Menu
A menu of actions anchored to a trigger. Like a desktop dropdown menu.
MenuItem
One action in a Menu.
Modal
A centred dialog over a dimmed page.
NavBar
A bottom tab bar at every shell width. Put it last inside a TabLayout.
NavItem
One destination in a NavBar, NavRail, or AdaptiveNav.
NavRail
A side navigation rail at every shell width. Put it inside a TabLayout.
NavigationDrawer
Navigation that stays open beside the page, like Ionic’s split pane. The page narrows to make room instead of being covered.
Popover
A panel of content floating beside a trigger, such as a filter form or a profile card. Like Ionic’s ion-popover.
Progress
A horizontal progress bar. Like Ionic’s ion-progress-bar.
Radio
One choice in a RadioGroup.
RadioGroup
A set of Radio choices where one may be selected. Like Ionic’s ion-radio-group.
Range
A slider for a number in a range. Like Ionic’s ion-range.
Rating
A row of stars. Like a slider, it can be pressed, dragged across, or moved with the arrow keys; readonly turns it into a display, which can show any fraction, such as an average of 3.7.
Refresher
Pull-to-refresh around scrollable content. Like Ionic’s ion-refresher.
ReorderHandle
The grip that moves a row of a ReorderList. Drag it, or focus it and press the up and down arrows; in a ReorderLayout::Grid, left and right move it back and on too.
ReorderItem
One row of a ReorderList, at position index.
ReorderList
A list whose rows can be put in a new order. Like Ionic’s ion-reorder-group.
Searchbar
A search field with an icon and a clear button. Like Ionic’s ion-searchbar.
SegmentButton
One choice in a SegmentGroup.
SegmentGroup
A row of mutually exclusive buttons, like Ionic’s ion-segment: a sliding pill on iOS and an underlined tab strip on Material Design.
Select
A field that picks one value from a list. Like Ionic’s ion-select.
Shelf
A titled row of items that scrolls sideways, like a streaming app’s rows of posters or a store’s “New this week”. Items keep their own width, so the row overflows and is scrolled rather than squeezed.
SideSheet
A sheet that slides in from a side, for filters, inspectors, and temporary navigation. Like Ionic’s ion-menu.
Skeleton
A pulsing placeholder shown while content loads. Like Ionic’s ion-skeleton-text. Hidden from screen readers; announce loading with a Spinner or text instead.
Spinner
A spinning loading indicator, announced to screen readers as a status.
Stack
Lays children out in a column or row with even spacing.
Stepper
A number with decrease and increase buttons, for small counts such as players or holes.
SwipeAction
A button uncovered by swiping a SwipeItem.
SwipeItem
A list row with actions behind it, uncovered by swiping. Like Ionic’s ion-item-sliding.
Tab
One tab in a TabList.
TabLayout
A page with persistent navigation: a Header, its Content, and a navigation component side by side. Like Ionic’s ion-tabs.
TabList
The row of Tabs inside Tabs.
TabPanel
The content shown while its Tab is selected.
Table
A table of data, such as a scorecard, a leaderboard or a price list.
Tabs
Tabs that show one panel at a time, with full tab semantics: arrow keys move between tabs, and each tab controls its panel.
Text
Text in the theme’s type scale and colors.
TextArea
A multi-line text field with a label.
ThemeProvider
Apply a mode, theme, and strings to everything inside, without the app layout that AppWrapper adds.
TimePicker
A form field that picks a time, with iOS wheels or a Material clock dialog. Like Ionic’s ion-datetime with presentation="time".
Toast
A brief message that does not block the page. Like Ionic’s ion-toast.
Toggle
An on/off switch row. Like Ionic’s ion-toggle.
Tooltip
A short label shown while the trigger is hovered or focused.
component_descriptors
Every component in the library, with its description.
detect_platform_mode
The platform’s native mode: iOS on iPhone and iPad (including their web browsers), Material Design everywhere else.
get_mode
The global mode: whatever set_mode set, or else detect_platform_mode.
init_auto_mode
Set the global mode to detect_platform_mode.
merge_classes
Join a component’s own classes with a caller’s class prop.
open_sheet_count
How many dismissible sheets are open in the app.
set_mode
Set the mode used by components with no mode prop and no provider.
use_action_sheet
Show action sheets from event handlers and await the choice.
use_alert
Show alerts from event handlers and await the answer.
use_component_mode
Resolve a component’s mode: its own mode prop, then the nearest provider, then the global mode. Subscribes the calling component to mode changes.
use_shell_size
The width class of the enclosing AppWrapper’s shell.
use_strings
The strings in effect here, or Strings::default outside any provider. Subscribes the calling component to changes.
use_theme
The theme in effect here, or Theme::default outside any provider. Subscribes the calling component to theme changes.
use_toast
Show toasts from event handlers.