Cycle
A control that cycles through its options in place: the current value is all it shows, and every click, Enter, Space, Right/l, or Ctrl+N advances to the next — wrapping at the end. Left/h and Ctrl+P walk backward.
use ratcn::Cycle;
ctx.component(
"size",
Cycle::new(["Small", "Medium", "Large"])
.selection(|state| state.size, Msg::SetSize),
area,
);The row paints like a small ghost button: plain text at rest, a quiet fill while hovered or focused. A column of cycles reads as values, not as a wall of chrome — which is what makes the settings-row layout work: paint the setting's name at the left edge and declare the Cycle on the same row with .align(Alignment::Right) — the value hugs the right edge, paint and hit target together, and nothing needs measuring:
ctx.paint_widget(Line::from("Text size").style(name), row);
ctx.component(
"size",
Cycle::new(["Small", "Medium", "Large"])
.selection(|state| state.size, Msg::SetSize)
.align(Alignment::Right),
row,
);For layouts that reserve space instead, Cycle::width() (and MeasuredComponent) answer with the widest option — the columns no value ever outgrows.
Where a Checkbox ends
Two options are a Checkbox wearing its states as labels ([ON]/[off]). Three or more options, or an ordered scale such as Small/Medium/Large, are a Cycle.
State
The selection is app-owned and arrives through .selection(read, on_change): read returns the index shown each frame (an out-of-range answer clamps to the last option), and on_change receives the index the user moved to. Without the binding the Cycle paints but is not focusable and answers no events.
Paint-only widget
CycleWidget draws the current option across area, with no focus, events, or state:
use ratcn::CycleWidget;
const SIZES: [&str; 3] = ["Small", "Medium", "Large"];
frame.render_widget(CycleWidget::new(SIZES[state.size]).themed(&theme), area);The interactive component paints and answers events in exactly the columns its current value occupies — a Cycle is as wide as the text it shows, so rows of different settings end at different columns, and a fill on hover or focus hugs the value instead of stretching across the row. Replace .themed(...) with .style(...) to supply exact colors.
Full API
Every method, with binding requirements and edge-case detail: Cycle, CycleWidget, CycleStyle.
Mouse input needs capture enabled in the host. See Mouse input.
See also
Use Checkbox for two-state settings, or Select when the whole option list should open for browsing instead of cycling in place.