Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

ListItem

Layer: cell · Path: src/cells/list_item.rs · Exports: list_item::ListItem

A selectable list row built from an optional leading icon, a title, and an optional subtitle. Modelled on the shadcn Item. Selection is a stateless input (selected: bool) and a click yields a plain [Response] — the consumer owns the selected index and reacts to .clicked().

Design

  • Purpose / when to use — Vertically stacked, single-line-or-two rows in a list/panel where one item can be highlighted (file lists, asset pickers, project entries).

  • Anatomy — A Surface (interactive, padded) wrapping a horizontal layout: optional Icon (muted) + a vertical stack of Text (title) and an optional muted caption Text (subtitle).

  • Variants / states

    StateEffect
    defaultSurface::fill_none().border_none() (transparent)
    selected (selected(true))Surface::muted() fill
    hover/clickSurface::interactive() provides hover feedback + sense; the returned Response carries .clicked()
  • Tokens / layout consumedcore::SPACE_2 (8px outer pad + icon→text gap), core::RADIUS_SM (4px). See tokens.

  • Accessibility — Inherits the Surface’s interactive sense; selection state is purely visual (muted fill), so pair with a real selection model in the consumer.

API

MethodSignatureEffect
newnew(title: impl Into<String>) -> SelfConstruct with a title; icon/subtitle/selected default off.
iconicon(self, glyph: &'static str) -> SelfLeading muted icon (a phosphor glyph).
subtitlesubtitle(self, subtitle: impl Into<String>) -> SelfSecond line, rendered caption + muted.
selectedselected(self, selected: bool) -> SelfToggle the muted selected fill.
id_sourceid_source(self, id: impl std::hash::Hash) -> SelfStable id for the underlying Surface (needed when rows share otherwise-equal layout).
showshow(self, ui: &mut Ui) -> ResponseRender; returns the Surface response (.clicked(), .hovered()).

Usage

#![allow(unused)]
fn main() {
use ouroboros_ui::cells::ListItem;
use ouroboros_ui::egui_phosphor::light;

ListItem::new("Cube").icon(light::CUBE).subtitle("Mesh").show(ui);
}
#![allow(unused)]
fn main() {
// realistic — a selectable list owning the selected index
let mut sel: usize = /* persisted state */ 0;
for (i, (icon, title, sub)) in [
    (light::CUBE, "Cube", "Mesh"),
    (light::STAR, "Light", "Point"),
    (light::GEAR, "Settings", "Project"),
].iter().enumerate() {
    if ListItem::new(*title)
        .icon(icon)
        .subtitle(*sub)
        .selected(sel == i)
        .id_source(("li", i))
        .show(ui)
        .clicked()
    {
        sel = i;
    }
}
}

Composition

Composes the Surface, Icon, and Text atoms only. It performs no painting — all visuals come from Surface (fill/border/interaction) and the atoms. Enforced by tests/no_painter_in_molecules.rs.

Notes

  • Selection is input, not state: ListItem never remembers it. Drive it from a usize/HashSet in the parent and feed .selected(...).
  • Give each row a distinct id_source (e.g. ("li", i)) so the interactive surfaces don’t collide.