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

RadioGroup

RadioGroup preview

RadioGroup — invisible layout container that groups RadioButtons and wires their accessibility metadata.

Public functions

RadioGroup

Detailed description

Radios are a fundamentally group-based control: screen readers need to announce "2 of 3" positional info, which AccessKit models via push_to_radio_group([sibling_ids]) on each radio button. Loose RadioButtons scattered in an HStack can't self-assemble this relation because they have no knowledge of their siblings.

RadioGroup solves this by owning a shared Rc<RefCell<Vec<WidgetId>>> buffer, injecting it into each RadioButton child before adding them to the arena, and populating the buffer with each radio's WidgetId as it's created. RadioButton::accessibility() reads the buffer and emits the push_to_radio_group calls.

The widget is a pure layout wrapper — it delegates actual rendering to an HStack or VStack under the hood. Its own accessibility node carries Role::RadioGroup + an optional accessible name.

let selected = ctx.signal(0_usize);
RadioGroup::new()
    .label(lit!("Theme"))
    .radio(RadioButton::new(0, selected.clone()).label(lit!("Light")))
    .radio(RadioButton::new(1, selected.clone()).label(lit!("Dark")))
    .radio(RadioButton::new(2, selected.clone()).label(lit!("System")))

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

RadioGroup at Touch density

API reference

📖 Full rustdoc API for this module

pub struct RadioGroup

Import: use teksilo::widgets::RadioGroup;

Invisible layout container that groups RadioButtons for accessibility. Arranges children in an HStack or VStack and carries Role::RadioGroup on its own a11y node.

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

Methods

pub fn new() -> Self

Create an empty radio group with vertical orientation and 8 dp spacing.

pub fn orientation(mut self, orientation: Orientation) -> Self

Layout orientation. Defaults to Vertical — most radio groups read top-to-bottom.

pub fn spacing(mut self, spacing: f32) -> Self (default: 8.0)

Gap between children.

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

Accessible name for the group — e.g. "Theme", "Font family". Screen readers announce this before individual radio labels.

pub fn radio(mut self, button: RadioButton) -> Self

Add a radio button. The group's shared sibling-id buffer is injected into the radio at build time so its accessibility impl can publish group membership via push_to_radio_group.

pub fn radios(self, buttons: impl IntoIterator<Item = RadioButton>) -> Self

Add several radio buttons from an iterator, in order.

The loop form of radio, and the usual one: a radio group is normally generated from the list of choices it offers. Each button gets the group's shared sibling-id buffer exactly as radio gives it.

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

Add a non-radio child (divider, caption label, etc.). Passed straight through to the internal stack without a11y wiring.

pub fn children(self, iter: impl IntoIterator<Item = impl Widget + 'static>) -> Self

Add several non-radio children from an iterator, in order.

The loop form of child. Like child, none of these get the group's a11y wiring: use radios for the buttons.

pub fn child_opt(self, widget: Option<impl Widget + 'static>) -> Self

Attach widget when it is Some, and do nothing when it is None.

The conditional-child form. teksu!'s if without an else lowers to this, and it is what cond.then(|| w) is for in a builder chain. None adds no arena node, so nothing is laid out, painted, or published to the accessibility tree, and a stack applies no spacing around it.