0.1.0

Cycle Toggle

Cycle toggles advance through a fixed set of values on each click, such as theme preference, sort order, or any small exclusive choice.

Try it

Usage

Compose RuiCycleToggleItem children inside RuiCycleToggle. Only the active item is visible in the button. Listen for rui-change to react to the new detail.value.

import { RuiCycleToggle, RuiCycleToggleItem } from '@ecopages/radiant-ui/cycle-toggle';
 
<RuiCycleToggle value="system" label="Theme" variant="ghost" size="sm">
  <RuiCycleToggleItem id="system" selected>System</RuiCycleToggleItem>
  <RuiCycleToggleItem id="light">Light</RuiCycleToggleItem>
  <RuiCycleToggleItem id="dark">Dark</RuiCycleToggleItem>
</RuiCycleToggle>

Custom markup

<rui-cycle-toggle> coordinates any light-DOM tree that matches its query contract. The Rui* helpers stamp these targets; they are not required.

import '@ecopages/radiant-ui/cycle-toggle';
 
<rui-cycle-toggle value="light" label="Theme" variant="ghost" size="sm">
  <button type="button" data-cycle-toggle-button class="rui-button rui-cycle-toggle__button rui-button--ghost rui-button--sm">
    <span data-cycle-value="system" class="rui-cycle-toggle__item">System</span>
    <span data-cycle-value="light" class="rui-cycle-toggle__item">Light</span>
    <span data-cycle-value="dark" class="rui-cycle-toggle__item">Dark</span>
  </button>
</rui-cycle-toggle>

BEM classes are presentation-only. Do not set hidden on items — the host owns visibility.

Sort order

Theming

The cycle button reuses the rui-button action roles, never Tailwind palette steps. variant / size map straight to the button system:

PartCSS roles
Button (.rui-cycle-toggle__button)rui-button chrome, primary filled, on-surface ghost, error destructive
Item (.rui-cycle-toggle__item)space-inline gap

Button geometry (--size-control-*, --radius-control) is inherited from rui-button so the cycle control aligns with form rows. Override at the theme layer, not in component CSS.

API

RuiCycleToggle is a custom element (<rui-cycle-toggle>); the view composes the inner rui-button.

Attributes

AttributeTypeDefaultDescription
valuestring''Active item id.
variantfilled · outline · destructive · ghost · linkfilledButton variant passed to the inner button.
sizenone · sm · md · lgmdButton size passed to the inner button.
labelstring''Accessible name prefix for the cycle button.
disabledbooleanfalseDisables the cycle button.

Light-DOM contract

TargetRequiredHost writesAuthor owns
button[data-cycle-toggle-button]yesaria-label, disabled, rui-button--* classesthe button element
[data-cycle-value]yes (per item)hiddendata-cycle-value, aria-disabled

Do not set hidden on items. Nested hosts: none.

Events

EventDetailDescription
rui-change{ value: string }Emitted after value advances; detail.value is the new id.

Methods

MethodDescription
resync()Re-apply button labeling and visible item from the current value.

View helpers

ComponentTarget stampedNotes
RuiCycleToggle<rui-cycle-toggle> + RuiCycleToggleButtonWraps items in the button.
RuiCycleToggleItem[data-cycle-value]Pass id; maps to data-cycle-value.
RuiCycleToggleButtonbutton[data-cycle-toggle-button]Composes rui-button variant/size classes.

CSS classes

Public BEM classes (documented via @cssclass):

ClassDescription
.rui-cycle-toggle__buttonCycle toggle button root (adds rui-button rui-button--*).
.rui-cycle-toggle__itemCycle option row (icon + label).

Theme roles

PartCSS variables consumed
Button chrome--primary, --on-primary, --size-control-*, --radius-control (via rui-button)
Item--space-inline

Accessibility

  • The host label sets aria-label on the cycle button.
  • Item children can include visible text, icons, or screen-reader-only labels.
  • Space and Enter activate the native button.