pub fn Button(props: ButtonProps) -> impl IntoViewExpand description
Runs a single command when activated — form submits, dialog confirmations, toolbar actions, and inline commands.
Pick ButtonAppearance::Primary for the one main action on a surface. Wire async work with loading and on_click. For navigation, use Link instead.
§When to use
- Submitting forms, confirming dialogs, or firing one-off commands - Toolbar and card actions where a single clear primary action is needed - Icon-only affordances when space is tight (pair with
aria-labelon a wrapper)
§Usage
- Pick an
ButtonAppearance—Primaryfor the main action,Secondaryfor alternatives. 2. Wireon_clickwithCallbackwhen the button should run logic (not submit a native form). 3. Setloadingwhile async work runs; disable the control when input is invalid or work is in-flight. 4. For E2E hooks, wrap the button in a native element withdata-testid(see project UI rules).
§Best Practices
§Do’s
- Use
appearance=ButtonAppearance::Primaryfor the main action on a surface * Showloadingduring async handlers so users see in-progress state * Disable while the form is invalid or a request is outstanding * Useiconfor recognizable actions (save, search, add)
§Don’ts
- Do not stack multiple primary buttons in one row * Do not use
data-testidon the component itself — wrap with a native element * Do not use icon-only buttons without an accessible name on the wrapper
§Button family
Orbital ships several command controls. When Button is not the right fit:
- Single command on click —
Button(this component). UseLinkfor navigation. - Primary command plus related alternates —ActionMenuButton(Save + Save as / Export). - Menu of options, no primary segment —MenuButton, orMenufor custom triggers. - Primary label plus supporting line —CompoundButton. - One action pinned to the viewport —FloatingButton. - Primary float plus fan-out secondaries —FloatingActionsMenu. - Merge adjacent buttons visually —ButtonGroup(layout only; style each child explicitly). - Toolbar on/off pressed state —ToggleButton. PreferSwitchfor immediate settings.
§Examples
§Primary button
Default call-to-action on a form or dialog footer.
view! {
<div data-testid="button-preview">
<Button appearance=ButtonAppearance::Primary>
"Save"
</Button>
</div>
}§Secondary outline
Secondary actions beside the primary—cancel, back, or low-commit choices. Outline styling keeps emphasis below Primary without blending into the surface.
view! {
<div data-testid="button-secondary">
<Button appearance=ButtonAppearance::Secondary>
"Cancel"
</Button>
</div>
}§Subtle and transparent
Low-emphasis actions that blend into the surface until hovered.
view! {
<div data-testid="button-subtle">
<Button appearance=ButtonAppearance::Subtle>"More"</Button>
<Button appearance=ButtonAppearance::Transparent>"Dismiss"</Button>
</div>
}§With icon
Leading icon reinforces the action (save, add, search) while the text label keeps meaning clear for sighted users and screen readers.
view! {
<div data-testid="button-icon">
<Button appearance=ButtonAppearance::Primary icon=icondata::AiSaveOutlined>
"Save"
</Button>
</div>
}§Icon-only
Compact affordance when toolbar space is tight. Wrap with aria-label in app code—the button has no visible text for assistive technologies.
view! {
<div data-testid="button-icon-only">
<Button icon=icondata::AiSearchOutlined appearance=ButtonAppearance::Subtle />
</div>
}§Sizes
Small fits toolbars and dense rows; medium is the default; large suits prominent mobile CTAs or hero actions. Set each with size=ButtonSize::….
use crate::{Button, ButtonSize};
view! {
<div data-testid="button-sizes">
<Button size=ButtonSize::Small>"Small"</Button>
<Button size=ButtonSize::Medium>"Medium"</Button>
<Button size=ButtonSize::Large>"Large"</Button>
</div>
}§Block (full width)
Stretches to the full container width—common for mobile form footers, stacked dialog actions, and narrow layouts.
view! {
<div data-testid="button-block">
<Button block=true appearance=ButtonAppearance::Primary>
"Continue"
</Button>
</div>
}§Loading state
Spinner replaces the icon slot and blocks clicks while async work runs. Pair with disabled form controls to prevent double submission.
view! {
<div data-testid="button-loading">
<Button appearance=ButtonAppearance::Primary loading=true>
"Saving…"
</Button>
</div>
}§Click handler
use leptos::prelude::*;
view! {
<Button
appearance=ButtonAppearance::Primary
on_click=|_| {}
>
"Run action"
</Button>
}§Shapes
Rounded is the default for labeled buttons. Circular and square fit icon-only controls in toolbars, floating actions, and compact settings grids.
use crate::{Button, ButtonShape};
view! {
<div data-testid="button-shapes">
<Button shape=ButtonShape::Rounded>"Rounded"</Button>
<Button shape=ButtonShape::Circular icon=icondata::AiPlusOutlined />
<Button shape=ButtonShape::Square icon=icondata::AiSettingOutlined />
</div>
}§Disabled
Unavailable actions stay visibly disabled and ignore clicks. disabled_focusable keeps the button in tab order for tooltips or custom disabled messaging.
view! {
<div data-testid="button-disabled">
<Button appearance=ButtonAppearance::Primary disabled=true>
"Unavailable"
</Button>
<Button appearance=ButtonAppearance::Secondary disabled_focusable=true>
"Focusable when disabled"
</Button>
</div>
}§Theme: primary uses brand token
Wrap in OrbitalThemeProvider with a custom brand palette so primary buttons use the theme’s brand color token.
use leptos::prelude::*;
use orbital_theme::{BrandPalette, OrbitalThemeProvider, Theme, ThemeMode};
view! {
<div data-testid="button-theme-brand">
<OrbitalThemeProvider theme=RwSignal::new(Theme::with_brand(
ThemeMode::Light,
BrandPalette { primary: "#E3008C".to_string() },
))>
<Button appearance=ButtonAppearance::Primary>"Brand action"</Button>
</OrbitalThemeProvider>
</div>
}§Imperative handle
// Focus or programmatically click via ButtonRef after mount.
use crate::{Button, ButtonRef};
use orbital_base_components::ComponentRef;
let btn_ref = ComponentRef::<ButtonRef>::default();
view! {
<Button comp_ref=btn_ref appearance=ButtonAppearance::Primary>"Focus me"</Button>
}§Optional Props
- class:
impl Into<MaybeProp<String>>- Extra CSS class names merged onto the root
<button>element.
- Extra CSS class names merged onto the root
- appearance:
impl Into<Signal<ButtonAppearance>>- Visual emphasis: primary, secondary, subtle, or transparent.
- shape:
impl Into<Signal<ButtonShape>>- Border shape: rounded (default), circular, or square.
- size:
impl Into<Signal<ButtonSize>>- Control size.
- button_type:
impl Into<MaybeProp<ButtonType>>- Native button
typeattribute (submit,reset, orbutton).
- Native button
- block:
impl Into<Signal<bool>>- When true, the button stretches to the full width of its container.
- icon:
impl Into<MaybeProp<IconData>>- Leading icon from the icondata catalog; omit
childrenfor icon-only buttons.
- Leading icon from the icondata catalog; omit
- disabled:
impl Into<Signal<bool>>- When true, the button does not respond to clicks or submit actions.
- disabled_focusable:
impl Into<Signal<bool>>- When true, the button stays focusable while disabled (for tooltips or custom UX).
- loading:
impl Into<Signal<bool>>- When true, shows a spinner and blocks click handling until cleared.
- aria_pressed:
impl Into<MaybeProp<String>>- Optional
aria-pressedfor toggle buttons.
- Optional
- on_click:
Callback<leptos::ev::MouseEvent>- Handler invoked on click when not disabled or loading.
- children:
Children- Button label text; optional when
iconalone is sufficient.
- Button label text; optional when
- comp_ref:
ComponentRef<ButtonRef>- Imperative handle for
focusandclickon the underlying DOM button.
- Imperative handle for