limn
    ↑↓ ChooseEnter OpenEsc Close
    GitHub

    Components/Layout

    PreferencesGroup

    A card of settings rows separated by hairlines, under a small muted label. Its rows are ActionRow: a title, a subtitle, an icon and a control at the end.

    Native componentGuide source

    Preview

    CodeSource
    fn view(state: &State, palette: ComponentPalette) -> Element {
        PreferencesGroup::new(
            "Plugins",
            vec![
                ActionRow::new("agent-skills", palette)
                    .subtitle("25 skills")
                    .trailing(Switch::new("agent-skills", state.agent_skills, palette).render())
                    .render(),
                ActionRow::new("Installed skills", palette)
                    .value("0 active")
                    .render(),
            ],
            palette,
        )
        .description("Instructions installed for the agent.")
        .render()
    }
    
    fn update(state: &mut State, action: &UiAction) {
        if let UiAction::Clicked { id } = action {
            if id == "agent-skills" {
                state.agent_skills = !state.agent_skills;
            }
        }
    }

    Examples

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

    PreferencesGroup
    CodeSource

    Read the source of this example.

    PreferencesGroup
    CodeSource

    Read the source of this example.

    PreferencesGroup
    CodeSource

    Read the source of this example.

    PreferencesGroup

    A card of settings rows separated by hairlines, under a small muted label. Its rows are ActionRow: a title, a subtitle, an icon and a control at the end.

    Import

    use limn::{ActionRow, ActionRowSizing, Component, PreferencesGroup};

    Usage

    A group takes a title, its rows as elements and the palette. The group is passive; a control in a row reports its own action.

    fn view(state: &State, palette: ComponentPalette) -> Element {
        PreferencesGroup::new(
            "Plugins",
            vec![
                ActionRow::new("agent-skills", palette)
                    .subtitle("25 skills")
                    .trailing(Switch::new("agent-skills", state.agent_skills, palette).render())
                    .render(),
                ActionRow::new("Installed skills", palette)
                    .value("0 active")
                    .render(),
            ],
            palette,
        )
        .description("Instructions installed for the agent.")
        .render()
    }
    
    fn update(state: &mut State, action: &UiAction) {
        if let UiAction::Clicked { id } = action {
            if id == "agent-skills" {
                state.agent_skills = !state.agent_skills;
            }
        }
    }

    description adds a second muted line under the title. With an empty title and no description the group is just its card.

    Rows

    ActionRow::new(title, palette) is one row. The title is cut to one line.

    ActionRow::new("Account", palette)
        .icon(Icon::Users)
        .subtitle("Session, plan and billing.")
        .render()

    icon puts an icon before the copy, and icon_muted(true) paints it in the muted color, for a note rather than a setting. subtitle is supporting copy under the title, in the muted color; it wraps.

    Trailing and value

    ActionRow::new("Explore", palette)
        .trailing(Button::new("marketplace", "Open Marketplace", palette).render())
        .render()
    
    ActionRow::new("Context", palette).value("82% left").render()

    trailing puts an element the host owns at the end of the row, centered on it: a Switch, a Button, a chevron. value is a read-only value there, as plain muted text so it is not mistaken for a control; it replaces any trailing element.

    A row that is an action

    ActionRow::new("Keyboard shortcuts", palette)
        .icon(Icon::Keyboard)
        .trailing(Element::icon(Icon::ChevronRight).foreground(palette.muted))
        .action("open-shortcuts")
        .render()

    action(id) makes the whole row a button that reports UiAction::Clicked with that ID.

    Disabled

    ActionRow::new("Keyboard shortcuts", palette).action("open-shortcuts").enabled(false).render()

    A disabled row is drawn muted and is not a button: it takes no pointer or focus and reports nothing. A control in trailing is the host’s to disable.

    Long copy and narrow panes

    ActionRow::new("Working folder of background agents", palette)
        .subtitle("Where an agent started in the background runs.")
        .wrap_title(true)
        .align_top(true)
        .trailing(Button::new("folder", "Choose folder", palette).render())
        .stacked(true)
        .render()
    • wrap_title(true) wraps a long title over several lines instead of cutting it.
    • align_top(true) starts the icon and the copy at the top of the row instead of centering them. The trailing element stays centered.
    • trailing_top(true) keeps the trailing element on the row’s first line instead of centering it, for a keycap beside copy that may wrap.
    • stacked(true) places the trailing element under the copy, for a narrow pane. A trailing element with a fixed width of 64 or less, such as a switch, stays beside the copy.

    Sizing

    const NOTE: ActionRowSizing = ActionRowSizing {
        icon_column: 16.0,
        min_height: 0.0,
        min_height_with_subtitle: 0.0,
        ..ActionRowSizing::DEFAULT
    };
    
    ActionRow::new("Only CLIs started from the app", palette).sizing(NOTE).render()

    An ActionRowSizing holds a row’s density in logical pixels. The row’s padding is not part of it: every row in a card shares one inset.

    FieldSetsDEFAULT
    gapSpace between the icon, the copy and the trailing element10
    copy_gapSpace between the title and the subtitle4
    icon_columnWidth of the column the icon sits in20
    min_heightLeast height of a row with a title only36
    min_height_with_subtitleLeast height of a row with a subtitle54

    Actions

    ActionWhen
    UiAction::Clicked { id }A row with action(id) is clicked.

    Accessibility

    An ActionRow with an action is a button named by its title and described by its subtitle, and stays there as disabled when it is disabled. A row without an action is copy: a control in trailing is named by the host.

    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/preferences.rs.