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

StandardListItem

StandardListItem preview

Canonical row layout for ListView / TreeView delegates.

Public types

KindName
structStandardListItem — Canonical single-line or two-line row layout for use in a ListView
structStandardTreeItem — Canonical row layout for a TreeView — StandardListItem plus a depth-driven indent column and an always-reserved chevron column

Public functions

StandardListItem

ReturnsFunction
Constructors
Selfnew(label: impl Into<LocalizedString>)
Builder methods
Selfstyle(style: impl teksilo_core::styles::StandardItemStyle)
Selfsubtitle(text: impl Into<LocalizedString>)
Selfleading_slot(widget: impl Widget + 'static)
Selfleading_slot_boxed(widget: Box<dyn Widget>)
Selfcenter_slot(widget: impl Widget + 'static)
Selfcenter_slot_boxed(widget: Box<dyn Widget>)
Selftrailing_slot(widget: impl Widget + 'static)
Selftrailing_slot_boxed(widget: Box<dyn Widget>)
Selfsubtitle_leading_slot(widget: impl Widget + 'static)
Selfsubtitle_leading_slot_boxed(widget: Box<dyn Widget>)
Selfsubtitle_trailing_slot(widget: impl Widget + 'static)
Selfsubtitle_trailing_slot_boxed(widget: Box<dyn Widget>)
Selfcheckbox(checked: Signal<bool>)
Selftristate_checkbox(state: Signal<CheckState>)
Selfon_checkbox_toggle(f: impl Fn(bool, &mut teksilo_core::widget::EventContext) + 'static)
Selfselected(selected: impl Into<Prop<bool>>)
Selfenabled(enabled: impl Into<Prop<bool>>)
Selflabel_style(style: impl Into<teksilo_core::color_prop::TextStyleProp>)
Selfsubtitle_style(style: impl Into<teksilo_core::color_prop::TextStyleProp>)
Selflabel_color(color: impl Into<teksilo_core::color_prop::ColorProp>)
Selfsubtitle_color(color: impl Into<teksilo_core::color_prop::ColorProp>)
Selfinteraction_signal(signal: Signal<InteractionState>)
Selfreveal_signal(signal: Signal<bool>)
Selflabel_slot(widget: impl Widget + 'static)
Selflabel_overflow(overflow: TextOverflow)
Selfsubtitle_overflow(overflow: TextOverflow)
Selftooltip(text: impl Into<LocalizedString>)
Selfrich_tooltip(key: impl Into<String>)
Selfrich_tooltip_content(content: crate::tooltip::TooltipContent)
Selfcomposite_tooltip(content: impl Widget + 'static)

StandardTreeItem

ReturnsFunction
Constructors
Selfnew(label: impl Into<LocalizedString>)
Builder methods
Selfinteraction_signal(signal: Signal<InteractionState>)
Selfreveal_signal(signal: Signal<bool>)
Selflabel_slot(widget: impl Widget + 'static)
Selfsubtitle(text: impl Into<LocalizedString>)
Selfleading_slot(widget: impl Widget + 'static)
Selfleading_slot_boxed(widget: Box<dyn Widget>)
Selfcenter_slot(widget: impl Widget + 'static)
Selfcenter_slot_boxed(widget: Box<dyn Widget>)
Selftrailing_slot(widget: impl Widget + 'static)
Selftrailing_slot_boxed(widget: Box<dyn Widget>)
Selfsubtitle_leading_slot(widget: impl Widget + 'static)
Selfsubtitle_leading_slot_boxed(widget: Box<dyn Widget>)
Selfsubtitle_trailing_slot(widget: impl Widget + 'static)
Selfsubtitle_trailing_slot_boxed(widget: Box<dyn Widget>)
Selfcheckbox(checked: Signal<bool>)
Selfon_checkbox_toggle(f: impl Fn(bool, &mut teksilo_core::widget::EventContext) + 'static)
Selftristate_checkbox(state: Signal<CheckState>)
Selfselected(selected: impl Into<Prop<bool>>)
Selfenabled(enabled: impl Into<Prop<bool>>)
Selflabel_style(style: impl Into<teksilo_core::color_prop::TextStyleProp>)
Selfsubtitle_style(style: impl Into<teksilo_core::color_prop::TextStyleProp>)
Selflabel_color(color: impl Into<teksilo_core::color_prop::ColorProp>)
Selfsubtitle_color(color: impl Into<teksilo_core::color_prop::ColorProp>)
Selflabel_overflow(overflow: TextOverflow)
Selfsubtitle_overflow(overflow: TextOverflow)
Selfstyle(style: impl teksilo_core::styles::StandardItemStyle)
Selftooltip(text: impl Into<LocalizedString>)
Selfrich_tooltip(key: impl Into<String>)
Selfrich_tooltip_content(content: crate::tooltip::TooltipContent)
Selfcomposite_tooltip(content: impl Widget + 'static)
Selfdepth(depth: usize)
Selfhas_children(has: bool)
Selfis_expanded(expanded: impl Into<Prop<bool>>)
Selffrom_entry(entry: &FlatEntry)
Selfon_chevron_toggle(f: impl Fn(&mut teksilo_core::widget::EventContext) + 'static)
Selfon_chevron_toggle_rc(f: Rc<dyn Fn(&mut teksilo_core::widget::EventContext)>)

Detailed description

Two widgets:

  • StandardListItem — primary line [checkbox?] [leading_slot?] [center_slot?] [label] [Spacer] [trailing_slot?] with optional subtitle line [subtitle_leading_slot?] [subtitle] [Spacer] [subtitle_trailing_slot?].
  • StandardTreeItem — same plus depth-driven indent + chevron column (always reserved, even for leaves, so labels at the same depth align).

Selection / hover / pressed background mirrors MenuItem / ComboBox: rounded RectWidget (item_corner_radius: 8.0), horizontally inset so corners are visible, theme-driven via SurfaceRole so light/dark/custom themes propagate without rebuild.

Canonical TreeView wiring

use teksilo::data::{TreeCheckedModel, TreeModel};
use teksilo::widgets::{StandardTreeItem, TreeView};

let tree: TreeModel<Item> = ...;
let checks = TreeCheckedModel::new(tree.clone());

TreeView::new_with_context(tree, move |item, entry, selected, ctx| {
    let mut row = StandardTreeItem::new(lit!(item.title.clone()))
        .from_entry(entry)
        .selected(selected)
        .leading_slot(IconWidget::from_svg(FOLDER_ICON).icon_size(16.0))
        .on_chevron_toggle_rc(ctx.toggle_callback());
    if entry.has_children {
        row = row.tristate_checkbox(checks.signal_for(entry.node_id));
    } else {
        row = row.checkbox(checks.bool_signal_for(entry.node_id));
    }
    Box::new(row)
})
.row_click_expands(false)   // chevron is the only toggle target

Wiring rules:

  • TreeView::new_with_context exposes a TreeRowContext that yields toggle_callback() for chevron clicks. Pair with .row_click_expands(false) so body clicks don't also toggle.
  • For tristate parent rows, bind to signal_for(node). For leaves, prefer bool_signal_for(node) — the model's bool ↔ tristate bridge runs ancestor recompute on writes either way.
  • from_entry(&FlatEntry) is shorthand for .depth(entry.depth).has_children(entry.has_children) .is_expanded(entry.is_expanded).

Accessibility

StandardListItem.accessibility() sets the row's name (label only) and description (subtitle, if any) — structural role + position/level/expanded/selected come from the parent's ListItemWrapper / TreeItemWrapper wrapper. The embedded Checkbox receives an access_label* override carrying the row label so screen readers announce "checkbox, checked, [label]" rather than a nameless Role::CheckBox. The chevron's TwistArrow is decorative (set_hidden); the row's expanded state is owned by the wrapper.

Touch and pen

A row's height is a target floor and follows the density ladder. The row asks the style it was built with for that floor, through StandardItemStyle::min_height_single_line and its two-line twin. The shipped recipe answers 28 / 44 dp at Compact, and a preset that writes its own (macOS 24, Fluent 40) gets that height.

A row's press is not the row's. Inside a ListView or a TreeView the body pane owns the tap, the double tap and the reorder drag, and resolves which row they mean by coordinate; the framework press belongs to the node whose gesture arena took it, so a row's own pressed_signal is structurally always false. The Pressed chrome the recipe paints is therefore reachable only through a caller-supplied interaction_signal. Changing that means ruling on which node owns a press when a data view is wrapped in something tappable, which is an open design question rather than a widget change.

Hover is decoration plus the reveal policy: at a density that reveals every affordance the row pins its reveal signal on, so trailing actions do not depend on a hover a contact never produces.

Density

The picture above is the widget at TargetDensity::Compact, the mouse-and-keyboard ladder. Below is the same subject on the same canvas with only the ladder changed, so what moves is the density and nothing else — where the subject no longer fits, that is what the denser targets cost it at that size. See docs/density-and-targets.md.

Touch

StandardListItem at Touch density

API reference

📖 Full rustdoc API for this module

pub struct StandardListItem

Import: use teksilo::widgets::StandardListItem;

Canonical single-line or two-line row layout for use in a ListView.

See the module-level documentation for the full slot layout and wiring rules.

#![allow(unused)]
fn main() {
pub struct StandardListItem { /* fields */ }
}

Methods

pub fn new(label: impl Into<LocalizedString>) -> Self

Create a list item with the given primary label.

pub fn style(mut self, style: impl teksilo_core::styles::StandardItemStyle) -> Self

Per-call style override. Replaces the theme-wide default StandardItemStyle for just this row instance.

pub fn subtitle(mut self, text: impl Into<LocalizedString>) -> Self

Set an optional secondary line below the primary label.

pub fn leading_slot(mut self, widget: impl Widget + 'static) -> Self

Leading slot — placed AFTER the optional checkbox, BEFORE the center slot. Typical: IconWidget, avatar, color swatch.

pub fn leading_slot_boxed(mut self, widget: Box<dyn Widget>) -> Self

Box<dyn Widget> variant of leading_slot.

pub fn center_slot(mut self, widget: impl Widget + 'static) -> Self

Center slot — placed BETWEEN the leading slot and the label. Typical: status dot, colored category bar, drag-handle gripper, key-binding chip. Distinct from leading_slot: leading is the row's icon identity, center is label-adjacent decoration.

pub fn center_slot_boxed(mut self, widget: Box<dyn Widget>) -> Self

Box<dyn Widget> variant of center_slot.

pub fn trailing_slot(mut self, widget: impl Widget + 'static) -> Self

Trailing slot — placed AFTER the flex Spacer on the primary line. Typical: badge, count, status pill, secondary IconButton.

pub fn trailing_slot_boxed(mut self, widget: Box<dyn Widget>) -> Self

Box<dyn Widget> variant of trailing_slot.

pub fn subtitle_leading_slot(mut self, widget: impl Widget + 'static) -> Self

Leading slot for the subtitle line. No-op without subtitle(...).

pub fn subtitle_leading_slot_boxed(mut self, widget: Box<dyn Widget>) -> Self

Box<dyn Widget> variant of subtitle_leading_slot.

pub fn subtitle_trailing_slot(mut self, widget: impl Widget + 'static) -> Self

Trailing slot for the subtitle line. No-op without subtitle(...).

pub fn subtitle_trailing_slot_boxed(mut self, widget: Box<dyn Widget>) -> Self

Box<dyn Widget> variant of subtitle_trailing_slot.

pub fn checkbox(mut self, checked: Signal<bool>) -> Self

Optional two-state checkbox at the start of the row. Mutually exclusive with tristate_checkbox — last call wins.

pub fn tristate_checkbox(mut self, state: Signal<CheckState>) -> Self

Optional tri-state checkbox bound to Signal<CheckState>. User clicks toggle Checked ↔ Unchecked (clicking from Indeterminate checks the whole); Indeterminate is reserved for external sources such as TreeCheckedModel aggregation. Mutually exclusive with checkbox — last call wins.

pub fn on_checkbox_toggle( mut self, f: impl Fn(bool, &mut teksilo_core::widget::EventContext) + 'static, ) -> Self

Run f when the user flips this row's checkbox, forwarded to the embedded Checkbox::on_change: same contract, same four paths, including Space on the focused row.

Reach for it only when flipping the box has to touch the ambient context (ctx.send_intent(..), opening a dialog). To read or react to check state, bind the row's box to a CheckedModel and use that: is_checked / checked_indices / checked_count, or checked_signal() for the reactive view. The model is the source of truth and it survives the row being recycled by virtualization, which a per-row callback does not.

pub fn selected(mut self, selected: impl Into<Prop<bool>>) -> Self

Set the selection state, statically or reactively via a bound Signal<bool>.

pub fn enabled(mut self, enabled: impl Into<Prop<bool>>) -> Self

Set the enabled state, statically or reactively via a bound Signal<bool> / Prop<bool>.

pub fn label_style( mut self, style: impl Into<teksilo_core::color_prop::TextStyleProp>, ) -> Self

Override the label's text style (font, size, weight). Accepts a TextStyleRole, a TextStyle, or a Signal of either. Default is TextStyleRole::Body.

pub fn subtitle_style( mut self, style: impl Into<teksilo_core::color_prop::TextStyleProp>, ) -> Self

Override the subtitle's text style. Default is TextStyleRole::Small.

pub fn label_color(mut self, color: impl Into<teksilo_core::color_prop::ColorProp>) -> Self

Override the label's text color. Accepts Color, a role, or a Signal of either. Default (unset) is enabled-derived (Primary / Disabled); setting this replaces that cascade.

pub fn subtitle_color(mut self, color: impl Into<teksilo_core::color_prop::ColorProp>) -> Self

Override the subtitle's text color. Default (unset) is TextRole::Secondary.

pub fn interaction_signal(mut self, signal: Signal<InteractionState>) -> Self

Share the row's interaction state — idle, hovered, pressed.

A row that shows its actions only while the pointer is over it is a standard pattern — a search result offering replace and dismiss, a list offering remove — and it cannot be built from outside without knowing when the row is hovered. The row already tracks that; this is the handle on it.

The signal is written by the row, not read: pass one in and watch it.

To gate revealed controls, use reveal_signal instead. This one reports hover, and hover is a mouse's alone — a trailing slot gated on Hovered is a slot a finger can never reach.

pub fn reveal_signal(mut self, signal: Signal<bool>) -> Self

Whether this row's revealed controls should be reachable, which is not the same question as whether the row is hovered.

interaction_signal reports the row's interaction state, and a caller gating a trailing slot on Hovered has built something a finger can never reach: a contact produces no hover, ever, so the controls never appear. This signal is the same intent stated as intent, and the row answers it per density — hover while the density reveals on hover, and permanently true at a density whose RevealPolicy is Always, where nothing is going to hover.

Gate the slot on this, not on the interaction state, and reserve the space the controls take — the row reflows otherwise, under the pointer trying to hit them.

pub fn label_slot(mut self, widget: impl Widget + 'static) -> Self

Draw this instead of the label's text, keeping the label as the row's accessible name.

For a row whose label is not plain text: a search result with the matched run picked out of its excerpt, a diff line, anything built from runs rather than from a string. The label passed to new is still what accessibility reports, so the row keeps a name a screen reader can read — which is the whole reason this is a replacement for the drawing and not a replacement for the label.

The widget is laid out where the text would have been, so it inherits the row's spacing and its place beside the leading and trailing slots. label_style, label_color and label_overflow do not reach it: it draws itself.

pub fn label_overflow(mut self, overflow: TextOverflow) -> Self

pub fn subtitle_overflow(mut self, overflow: TextOverflow) -> Self

Truncate the subtitle instead of wrapping it. Default (unset) is TextOverflow::Wrap.

Same rationale as label_overflow — and the usual culprit, since subtitles carry long secondary text (file paths, URLs). TextOverflow::Ellipsis(EllipsisMode::Middle) suits a path: it keeps both the root and the file name legible.

pub fn tooltip(mut self, text: impl Into<LocalizedString>) -> Self

Attach a plain tooltip shown after the standard hover delay.

Mutually exclusive with rich_tooltip, rich_tooltip_content, and composite_tooltip — the last setter called wins and clears the other slots.

pub fn rich_tooltip(mut self, key: impl Into<String>) -> Self

Attach a rich tooltip looked up from the global tooltip registry by key.

Mutually exclusive with tooltip, rich_tooltip_content, and composite_tooltip — the last setter called wins and clears the other slots.

pub fn rich_tooltip_content(mut self, content: crate::tooltip::TooltipContent) -> Self

Attach a rich tooltip from an inline TooltipContent value (no registry lookup required).

Mutually exclusive with tooltip, rich_tooltip, and composite_tooltip — the last setter called wins and clears the other slots.

pub fn composite_tooltip(mut self, content: impl Widget + 'static) -> Self

Attach a composite tooltip whose body is an arbitrary widget tree.

Mutually exclusive with tooltip, rich_tooltip, and rich_tooltip_content — the last setter called wins and clears the other slots.

pub struct StandardTreeItem

Import: use teksilo::widgets::StandardTreeItem;

Canonical row layout for a TreeView — StandardListItem plus a depth-driven indent column and an always-reserved chevron column.

See the module-level documentation for the canonical TreeView wiring pattern and wiring rules.

#![allow(unused)]
fn main() {
pub struct StandardTreeItem { /* fields */ }
}

Methods

pub fn new(label: impl Into<LocalizedString>) -> Self

Create a tree item with the given primary label.

pub fn interaction_signal(mut self, signal: Signal<InteractionState>) -> Self

See StandardListItem::interaction_signal: the row's own hover/press state. To gate revealed controls use reveal_signal.

pub fn reveal_signal(mut self, signal: Signal<bool>) -> Self

See StandardListItem::reveal_signal: whether this row's revealed controls should be reachable, answered per density.

pub fn label_slot(mut self, widget: impl Widget + 'static) -> Self

See StandardListItem::label_slot: draw this instead of the label's text, keeping the label as the row's accessible name.

pub fn subtitle(mut self, text: impl Into<LocalizedString>) -> Self

pub fn leading_slot(mut self, widget: impl Widget + 'static) -> Self

Forwarded to the inner StandardListItem — see its leading_slot.

pub fn leading_slot_boxed(mut self, widget: Box<dyn Widget>) -> Self

Box<dyn Widget> variant of leading_slot.

pub fn center_slot(mut self, widget: impl Widget + 'static) -> Self

Forwarded to the inner StandardListItem — see its center_slot.

pub fn center_slot_boxed(mut self, widget: Box<dyn Widget>) -> Self

Box<dyn Widget> variant of center_slot.

pub fn trailing_slot(mut self, widget: impl Widget + 'static) -> Self

Forwarded to the inner StandardListItem — see its trailing_slot.

pub fn trailing_slot_boxed(mut self, widget: Box<dyn Widget>) -> Self

Box<dyn Widget> variant of trailing_slot.

pub fn subtitle_leading_slot(mut self, widget: impl Widget + 'static) -> Self

Forwarded to the inner StandardListItem — see its subtitle_leading_slot.

pub fn subtitle_leading_slot_boxed(mut self, widget: Box<dyn Widget>) -> Self

Box<dyn Widget> variant of subtitle_leading_slot.

pub fn subtitle_trailing_slot(mut self, widget: impl Widget + 'static) -> Self

Forwarded to the inner StandardListItem — see its subtitle_trailing_slot.

pub fn subtitle_trailing_slot_boxed(mut self, widget: Box<dyn Widget>) -> Self

Box<dyn Widget> variant of subtitle_trailing_slot.

pub fn checkbox(mut self, checked: Signal<bool>) -> Self

Forwarded to the inner StandardListItem — see its checkbox.

pub fn on_checkbox_toggle( mut self, f: impl Fn(bool, &mut teksilo_core::widget::EventContext) + 'static, ) -> Self

Forwarded to the inner StandardListItem — see its on_checkbox_toggle. Distinct from on_chevron_toggle, which is the expand / collapse control.

pub fn tristate_checkbox(mut self, state: Signal<CheckState>) -> Self

Forwarded to the inner StandardListItem — see its tristate_checkbox.

pub fn selected(mut self, selected: impl Into<Prop<bool>>) -> Self

Set the selection state, statically or reactively via a bound Signal<bool>. Forwarded to the inner StandardListItem — see its selected.

pub fn enabled(mut self, enabled: impl Into<Prop<bool>>) -> Self

Set the enabled state, statically or reactively via a bound Signal<bool> / Prop<bool>. Forwarded to the inner StandardListItem.

pub fn label_style( mut self, style: impl Into<teksilo_core::color_prop::TextStyleProp>, ) -> Self

Override the label's text style. Forwarded to the inner StandardListItem — see its label_style.

pub fn subtitle_style( mut self, style: impl Into<teksilo_core::color_prop::TextStyleProp>, ) -> Self

Override the subtitle's text style. Forwarded to the inner StandardListItem — see its subtitle_style.

pub fn label_color(mut self, color: impl Into<teksilo_core::color_prop::ColorProp>) -> Self

Override the label's text color. Forwarded to the inner StandardListItem — see its label_color(...).

pub fn subtitle_color(mut self, color: impl Into<teksilo_core::color_prop::ColorProp>) -> Self

Override the subtitle's text color. Forwarded to the inner StandardListItem — see its subtitle_color(...).

pub fn label_overflow(mut self, overflow: TextOverflow) -> Self

Truncate the primary label instead of wrapping it. Forwarded to the inner StandardListItem — see its label_overflow.

pub fn subtitle_overflow(mut self, overflow: TextOverflow) -> Self

Truncate the subtitle instead of wrapping it. Forwarded to the inner StandardListItem — see its subtitle_overflow.

pub fn style(mut self, style: impl teksilo_core::styles::StandardItemStyle) -> Self

Per-call style override for the row chrome. Forwarded to the inner StandardListItem — see its style(...) for the precedence rules (per-call > theme.style_slots.standard_item > RecipeStandardItemStyle).

pub fn tooltip(mut self, text: impl Into<LocalizedString>) -> Self

Attach a plain tooltip shown after the standard hover delay. Forwarded to the inner StandardListItem — see its tooltip.

pub fn rich_tooltip(mut self, key: impl Into<String>) -> Self

Attach a rich tooltip looked up from the global tooltip registry by key. Forwarded to the inner StandardListItem — see its rich_tooltip.

pub fn rich_tooltip_content(mut self, content: crate::tooltip::TooltipContent) -> Self

Attach a rich tooltip from an inline TooltipContent value. Forwarded to the inner StandardListItem — see its rich_tooltip_content.

pub fn composite_tooltip(mut self, content: impl Widget + 'static) -> Self

Attach a composite tooltip whose body is an arbitrary widget tree. Forwarded to the inner StandardListItem — see its composite_tooltip.

pub fn depth(mut self, depth: usize) -> Self (default: 0)

Set the indent depth (0 = root level). Each level adds one STANDARD_ITEM_TREE_INDENT_STEP of leading whitespace.

pub fn has_children(mut self, has: bool) -> Self (default: false)

Declare whether the node has children, which determines whether the chevron column is interactive or decorative-only.

pub fn is_expanded(mut self, expanded: impl Into<Prop<bool>>) -> Self (default: false)

Set the expanded state, statically or reactively via a bound Signal<bool>.

pub fn from_entry(self, entry: &FlatEntry) -> Self

Convenience for the TreeView delegate path: .from_entry(entry) sets depth + has_children + is_expanded.

pub fn on_chevron_toggle( mut self, f: impl Fn(&mut teksilo_core::widget::EventContext) + 'static, ) -> Self

Click handler for the chevron — the expand / collapse control, not the row's checkbox, which is on_checkbox_toggle on the inner item. Wired only when has_children is true. Typical use: .on_chevron_toggle(ctx.toggle_callback()) from a TreeRowContext (see TreeView::new_with_context).

The callback receives the firing EventContext so apps can dispatch an intent (e.g. lazy-load children on expand), open a dialog, or otherwise route the toggle through the framework before mutating model state.

pub fn on_chevron_toggle_rc( mut self, f: Rc<dyn Fn(&mut teksilo_core::widget::EventContext)>, ) -> Self (default: None)

Variant accepting an already-Rc'd callback. Useful when the same callback is shared across multiple call sites without an extra clone — e.g. TreeRowContext::toggle_callback() returns this shape directly.