Expand description
SegmentedControl — mutually exclusive segments in a horizontal row.
Each segment is a real composed widget — a centered icon + label with
a reactive tint — built from a Segment descriptor. Selection is
bound to a Signal<Option<SegmentId>>: keyed, not positional, so
inserting or removing a segment never silently re-points the
selection at a different one. The chrome (rounded frame, hover tint,
selected-segment surface) is delegated to the active
SegmentedControlStyle.
const LIST: SegmentId = SegmentId::from_u64(1);
const GRID: SegmentId = SegmentId::from_u64(2);
let view = ctx.signal(Some(LIST));
SegmentedControl::new(view.clone())
.segment(Segment::new(tr!(list_view())).id(LIST).icon(|| IconWidget::list(14.0)))
.segment(Segment::new(tr!(grid_view())).id(GRID).icon(|| IconWidget::grid(14.0)))
// Pairing with a Switcher:
Switcher::new(segmented_control::index_signal(&view, &[LIST, GRID]))§When to use
- Use a
SegmentedControlfor mutually exclusive modes that read well as a compact horizontal strip (view mode, time period). - Prefer a
ComboBoxwhen the options are many and the strip form buys nothing — though a segmented control no longer breaks down at seven segments, because it overflows (below). - Prefer
RadioButton/RadioTileGroupwhen the options need vertical space or descriptions.
§Width: overflow, not squeeze
When the segments do not fit, the ones that do not fit move into a
trailing chevron menu rather than all of them compressing into
ellipsised stubs (SegmentOverflow::Menu, the default; opt out with
SegmentOverflow::Compress).
Declaration order is stable, with exactly one exception: the selected segment is always visible. If it would have been pushed into the menu it takes the last slot, and it stays there until another segment is chosen from the menu — so the strip does not reshuffle under the pointer, and the promotion is forgotten once the control is wide enough to show everything again.
Declared: [A][B][C][D][E][F][G] fits 4 + chevron
start, A selected [A][B][C][D][v] menu: E F G
pick F from menu [A][B][C][F][v] menu: D E G
click A (F stays) [A][B][C][F][v] menu: D E G
widen to full fit [A][B][C][D][E][F][G]§Accessibility
Role::RadioGroup on the control with active_descendant pointing at
the selected segment; Role::RadioButton per segment, carrying
“N of M” over the whole segment list — including segments currently in
the overflow menu, which are still reachable. Arrow keys cycle
selection (RTL-aware, resolved at event time) and Home/End jump to the
ends, both skipping disabled segments; stepping onto an overflowed
segment promotes it into view. Increment/Decrement AT actions
mirror the arrows.
The strip is one tab stop. While the control is overflowing the chevron adds a second, because an overflow menu that no keyboard can reach is not an overflow menu; it cannot join the arrow sequence, since here arrows move selection rather than a roving focus.
Structs§
- Segment
- One segment descriptor: a localized label with a stable
SegmentId, an optional leading icon, a hover tooltip, and reactive disabled / visible flags. - Segment
Id - Stable identity of a segment. Cheap to copy; survives rebuilds, locale changes, and segments being inserted around it.
- Segmented
Control - A segmented control binding a
Signal<Option<SegmentId>>to a row of mutually exclusive segments. Build the segment list withsegmentorsegments.
Enums§
- Segment
Display - What a segment paints: its icon, its label, or both.
- Segment
Overflow - What the control does when its segments do not fit.
- Segment
Sizing - How the visible segments divide the control’s width.
Functions§
- index_
signal - Derive a
Switcher-compatible index from a keyed selection.