## toggle_group (`poetry_toggle_group`)

A set of toggle buttons for single or multiple selection.

Class: Poetry::Ui::ToggleGroup::Component - BEM block `poetry-ui-toggle_group`.
Slot REQUIRED: with_item (at least one item) - a call without it raises.
- `size:` (symbol) - one of default|sm|lg, default "default", required - The shared Toggle size axis, cascaded from the root to every item (root wins).
- `variant:` (symbol) - one of default|outline, default "default", required - The shared Toggle variant axis, cascaded from the root to every item (root wins).
- `disabled:` (boolean) - default false - Disables every item in the group.
- `label:` (string) - The group's accessible name (aria-label) - a nameless radiogroup/toolbar logs a lint warning.
- `orientation:` (symbol) - one of horizontal|vertical, default "horizontal" - The roving axis; :vertical stacks the items and flips the arrow keys.
- `spacing:` (integer) - default 2 - 0 = the classic segmented control (joined corners, collapsed outline borders); >0 = free-standing items separated by that gap step.
- `type:` (symbol) - default "single" - :single keeps at most one item pressed; :multiple toggles items independently.
- `value:` (string) - single: the pressed item's value. ArgumentError with :multiple.
- `values:` (list) - default "dynamic" - multiple: the pressed items' values. ArgumentError with :single.
Slots: items (Declares one item: value: (unique - duplicates raise), label: (required when icon-only), disabled:; the block is the content. Pressed state comes from value:/values:.; many; with_item yields NOTHING to the block - no |param|, write content directly).
- PART `toggle-group` - The role=radiogroup (single) / role=toolbar (multiple) root - the value-set machine and roving focus ride here; the axes cascade to items | states: data-variant=default|outline (the shared Toggle variant (root wins)); data-size=default|sm|lg (the shared Toggle size (root wins)); data-spacing (the gap step - 0 is the segmented chain (joined corners), >0 free-standing); data-orientation=horizontal|vertical (the roving axis); data-disabled (the whole group is disabled (disables every item)) | vars: --gap (the item gap, set inline from spacing: - the root's gap utility consumes it)
- PART `toggle-group-item` - One dumb <button> under the group machine - Toggle-styled, no per-item controller | states: data-pressed (pressed (bare presence boolean - absent when off; the controller rederives the type-correct aria attribute from it)); data-disabled (the item (or the whole group) is disabled - the roving-focus collection filter); data-value (the item's key in the value set (always present, unique)); data-variant=default|outline (cascaded from the root); data-size=default|sm|lg (cascaded from the root); data-spacing (cascaded from the root - keys the segmented corner/border chain)
- WIRING root: `poetry--core--toggle-group` registers; values type | `poetry--core--roving-focus` registers; values orientation, loop; actions keydown on keydown
- WIRING item: `poetry--core--toggle-group` actions toggle on click
- RULE: Use poetry_toggle_group - never hand-assemble Toggles with your own exclusivity logic.
- RULE: ToggleGroup is UI state, NOT form data: submitting single-select -> RadioGroup; submitting multi-select -> Checkbox group. No name: exists; don't route around it.
- RULE: Every item MUST have a unique value: (ArgumentError on duplicates); icon-only items MUST pass label: (state-invariant).
- RULE: Name the group via label: - a nameless radiogroup/toolbar fails the audit.
- RULE: Exclusive view/mode switching that shows PANELS is Tabs (aria-selected + tabpanels), not a single ToggleGroup.
- RULE: Never mix vocabularies: single items carry aria-checked, multiple carry aria-pressed - the controller enforces it; agents patching DOM must too.
- RULE: single deselects to empty by re-press - if your UI needs always-one-selected, handle the empty change in the host.
