limn
    ↑↓ ChooseEnter OpenEsc Close
    GitHub

    Components/Actions

    Button

    A labelled action. Eleven variants and seven sizes, optional icons before and after the label, a hint, and disabled, loading and active states.

    Native componentGuide source

    Preview

    CodeSource
    fn view(palette: ComponentPalette) -> Element {
        Button::new("save", "Save changes", palette).render()
    }
    
    fn update(state: &mut State, action: &UiAction) {
        if let UiAction::Clicked { id } = action {
            if id == "save" {
                state.save();
            }
        }
    }

    Examples

    Each one is the library drawing it. Press, type and hover.

    Disabled
    CodeSource
    variants("button-disabled", Button::disabled)
    Loading
    CodeSource
    variants("button-loading", |button| button.loading(true))
    Sizes
    CodeSource
    row(vec![
                Button::new("button-mini", "More", palette)
                    .variant(ButtonVariant::Ghost)
                    .button_size(ButtonSize::Mini)
                    .render(),
                Button::new("button-small", "Small", palette).button_size(ButtonSize::Small).render(),
                Button::new("button-default", "Default", palette).button_size(ButtonSize::Default).render(),
                Button::new("button-large", "Large", palette).button_size(ButtonSize::Large).render(),
                IconButton::new("button-large-icon", Icon::Add, palette)
                    .button_size(ButtonSize::Large)
                    .render(),
            ])
    Application sizing
    CodeSource
    row(vec![
        Button::new("button-sizing", "Panel", palette)
            .variant(ButtonVariant::Subtle)
            .icon(Icon::PanelRightOpen)
            .sizing(NAVIGATION)
            .radius(RadiusRole::Card)
            .render(),
        Button::new("button-sizing-disabled", "Panel", palette)
            .variant(ButtonVariant::Subtle)
            .icon(Icon::PanelRightOpen)
            .sizing(NAVIGATION)
            .radius(RadiusRole::Card)
            .disabled()
            .render(),
        IconButton::new("button-sizing-close", Icon::Close, palette)
            .variant(ButtonVariant::Ghost)
            .sizing(TAB_CLOSE)
            .render(),
    ])
    With icon
    CodeSource
    row(vec![
                Button::new("button-icon", "New", palette).icon(Icon::Add).render(),
                Button::new("button-trailing", "Branch", palette)
                    .variant(ButtonVariant::Outline)
                    .icon(Icon::GitBranch)
                    .trailing_icon(Icon::ChevronDown)
                    .render(),
                IconButton::new("button-settings", Icon::Settings, palette).tooltip("Settings").render(),
                IconButton::new("button-trash", Icon::Trash, palette)
                    .variant(ButtonVariant::Destructive)
                    .tooltip("Delete")
                    .render(),
            ])
    Toolbar
    CodeSource
    row(vec![
        IconButton::new("button-tool-dense", Icon::Add, palette)
            .variant(ButtonVariant::Ghost)
            .size(ControlSize::Dense)
            .tooltip_with(
                TooltipSpec::new("New")
                    .description("Creates a file in the open folder.")
                    .shortcut("Ctrl+N")
                    .placement(TooltipPlacement::Below),
            )
            .render(),
        IconButton::new("button-tool-minus", Icon::Minus, palette)
            .variant(ButtonVariant::Ghost)
            .size(ControlSize::Compact)
            .dispatch_as("button-tool-dense")
            .tooltip_with(TooltipSpec::new("Remove").placement(TooltipPlacement::Below))
            .render(),
        IconButton::new("button-tool-disabled", Icon::Trash, palette)
            .variant(ButtonVariant::Ghost)
            .size(ControlSize::Regular)
            .disabled()
            .tooltip_with(
                TooltipSpec::new("Nothing to delete").placement(TooltipPlacement::Below),
            )
            .render(),
        IconButton::new("button-tool-lift", Icon::PanelLeft.filled(), palette)
            .variant(ButtonVariant::Ghost)
            .size(ControlSize::Regular)
            .active(true)
            .tooltip("Active: Lift")
            .render(),
        IconButton::new("button-tool-palette", Icon::PanelRight.filled(), palette)
            .variant(ButtonVariant::Ghost)
            .size(ControlSize::Regular)
            .active(true)
            .active_hover(ActiveHover::Palette)
            .tooltip("Active: Palette")
            .render(),
    ])
    Ink, spacing and radius1 / 2
    CodeSource
    row(vec![
        Button::new("button-ink", "Discard", palette)
            .variant(ButtonVariant::Ghost)
            .ink(DANGER)
            .render(),
        Button::new("button-ink-disabled", "Discard", palette)
            .variant(ButtonVariant::Ghost)
            .ink(DANGER)
            .disabled()
            .render(),
        Button::new("button-gap", "Connect", palette)
            .variant(ButtonVariant::Outline)
            .icon(Icon::Github)
            .gap(12.0)
            .render(),
        Button::new("button-radius", "Card", palette)
            .variant(ButtonVariant::Outline)
            .radius(RadiusRole::Card)
            .render(),
        IconButton::new("button-radius-square", Icon::Add, palette)
            .variant(ButtonVariant::Outline)
            .radius(RadiusRole::Square)
            .tooltip("Radius: Square")
            .render(),
    ])
    Ink, spacing and radius2 / 2
    CodeSource
    row(vec![
        IconButton::new("button-round-send", Icon::ArrowUp, palette)
            .round()
            .tooltip("round: send")
            .render(),
        IconButton::new("button-round-stop", Icon::StopFill, palette)
            .round()
            .tooltip("round: stop")
            .render(),
        Button::new("button-round-pill", "Pill", palette)
            .variant(ButtonVariant::Secondary)
            .round()
            .render(),
    ])
    Active
    CodeSource
    row(vec![Button::new("button-toggle", "Toggle", palette)
        .variant(ButtonVariant::Ghost)
        .active(cx.state.flag("button-toggle"))
        .render()])

    Button

    A labelled action. Eleven variants and seven sizes, optional icons before and after the label, a hint, and disabled, loading and active states.

    Import

    use limn::{Button, ButtonSize, ButtonVariant, Component, Icon};

    Component gives every component its render.

    Usage

    A button needs an ID, a label and the palette. It reports UiAction::Clicked with its ID.

    fn view(palette: ComponentPalette) -> Element {
        Button::new("save", "Save changes", palette).render()
    }
    
    fn update(state: &mut State, action: &UiAction) {
        if let UiAction::Clicked { id } = action {
            if id == "save" {
                state.save();
            }
        }
    }

    Variants

    Default is the primary action. Secondary, Outline, Ghost, Subtle, Raised and Solid are quieter; Success, Warning and Destructive say what the action does; Link is a text action.

    Button::new("delete", "Delete", palette)
        .variant(ButtonVariant::Destructive)
        .render()

    Subtle is the navigation row and keeps its label at the left; the filled variants center it.

    Sizes

    Button::new("more", "More", palette)
        .button_size(ButtonSize::Small)
        .render()

    Default, Small and Large are for labelled buttons; Icon, IconSmall and IconExtraSmall are square; Mini is a 22 px action inside a dense row. A host with a density of its own passes a ButtonSizing to sizing instead.

    Icons

    Button::new("open", "Open", palette)
        .icon(Icon::Folder)
        .trailing_icon(Icon::Search)
        .render()

    IconButton is the button whose icon is mandatory; without a label it is square.

    Loading and disabled

    Button::new("install", "Installing…", palette).loading(true).render()
    Button::new("install", "Install", palette).enabled(can_install).render()

    A loading button replaces its leading icon with a spinner and keeps its height and label. Neither a loading nor a disabled button can be focused or activated; a disabled one keeps its hint.

    Active

    Button::new("view=list", "List", palette)
        .variant(ButtonVariant::Ghost)
        .active(view == "list")
        .render()

    active marks the chosen one of several. active_hover chooses how it hovers: ActiveHover::Lift lightens the selected fill.

    Hint

    Button::new("search", "Search", palette)
        .tooltip("Search the project")
        .tooltip_shortcut("Ctrl+K")
        .render()

    tooltip_with takes a whole TooltipSpec: description, placement, width.

    Ink, gap and radius

    ink, hover_ink and pressed_ink draw the label and icons in a color of the host’s, such as its destructive ink. gap sets the space between icons and label, radius takes another radius token, and round makes a pill or a circle.

    Actions

    ActionWhen
    UiAction::Clicked { id }The button is activated by pointer, Enter or Space.

    dispatch_as(action_id) reports another ID while the button keeps its own for focus, hover and its hint.

    Accessibility

    The platform is told a button named by its label, and described by its hint’s title when it has one. A button of an icon alone is named by that title instead, or by accessibility_label, which goes over both. Disabled or loading, the button is still there and says it cannot be used.

    IconButton::new("close", Icon::Close, palette).accessibility_label("Close")

    API reference

    The guide covers composition, options and actions. Generate the complete Rust type and builder reference from the checkout:

    cargo doc -p limn --open

    Component API overview · State and actions

    The example is drawn by crates/limn-gallery/src/pages/buttons.rs.