## tabs (`poetry_tabs`)

A tablist of triggers that switch between content panels.

Class: Poetry::Ui::Tabs::Component - BEM block `poetry-ui-tabs`.
Slot REQUIRED: with_tab (at least one tab) - a call without it raises.
- `default:` (string) - The value of the server-rendered active tab; defaults to the first enabled tab. Raises when it matches no tab.
- `label:` (string) - The tablist's accessible name - recommended when a page has several tab sets.
- `orientation:` (symbol) - one of horizontal|vertical, default "horizontal" - The tab axis; :vertical stacks the triggers and flips the arrow keys.
- `variant:` (symbol) - one of default|line, default "default" - The list's visual treatment: :default a filled capsule, :line an underline indicator.
Slots: tabs (Declares one tab: the title, its value:, and the panel as the block (defer: swaps in a lazy turbo-frame panel; panel: false declares a list-only tab). Omitting all three raises.; many; with_tab yields NOTHING to the block - no |param|, write content directly).
- PART `tabs` - Root wrapper - the orientation rides here and flips the flex direction | states: data-orientation=horizontal|vertical (the tab axis (matches aria-orientation on the list))
- PART `tabs-list` - The role=tablist row of triggers - the roving-focus keyboard group and the visual variant ride here | states: data-variant (the list treatment - default (filled capsule) or line (underline indicator))
- PART `tabs-trigger` - One role=tab button per tab | states: data-active (the selected tab (the controller moves it with aria-selected on activation)); data-disabled (tab is disabled - also filters it from the roving-focus collection); data-value (the tab's value - the key the controller matches panels against)
- PART `tabs-content` - One role=tabpanel per tab - only the active panel is visible | states: data-hidden (panel is inactive (paired with the hidden property - the controller flips both)); data-value (the owning tab's value)
- WIRING root: `poetry--core--tabs` registers
- WIRING list: `poetry--core--roving-focus` registers; values orientation, loop; actions keydown on keydown | `poetry--core--tabs` actions focusActivate on poetry--core--roving-focus:entry
- WIRING trigger: `poetry--core--tabs` actions activate on click
- tool set_value (mutating; params: value (string, required)) - Activate the tab whose value matches and show its panel. [opt in with webmcp: "name" on the call; dispatches poetry--core--tabs#setValue]
- RULE: Declare tabs with with_tab(title, value:) + the panel block (or defer: for a lazy turbo-frame panel) - never hand-wire role=tab/tabpanel ids.
- RULE: panel: false declares a list-only tab (no tabpanel renders, the trigger drops aria-controls) - for demos/pattern shells; real tab sets carry panels.
- RULE: default: picks the server-rendered active tab (the first enabled tab otherwise) - the panel is visible without JS.
- RULE: label: names the tablist (aria-label) - recommended whenever the page has several tab sets.
- RULE: Tabs switch VIEWS of one context; use navigation (links) when the URL should change.
