Switch

A binary toggle for on/off states, built on a native checkbox input.

Quick Start

<%= kui(:switch) %>

Locals

Local Type Default
color: :primary | :secondary | :success | :info | :warning | :error | :neutral :primary
size: :sm | :md :md
checked: Boolean false
css_classes: String ""
**component_options Hash {}

All standard HTML input attributes (name:, id:, value:, disabled:, required:, etc.) pass through via **component_options.

Usage

Color

The color applies to the checked state background.

<%= kui(:switch, color: :primary, checked: true) %>
<%= kui(:switch, color: :success, checked: true) %>
<%= kui(:switch, color: :error, checked: true) %>

Size

<%= kui(:switch, size: :sm) %>
<%= kui(:switch, size: :md) %>
Size Track Thumb
sm h-4 w-8 size-3
md (default) h-5 w-9 size-4

With Field

Pair with Field for label, description, and accessible structure.

<%= kui(:field, orientation: :horizontal) do %>
  <%= kui(:switch, id: :marketing, name: :marketing, value: "1") %>
  <%= kui(:field, :content) do %>
    <%= kui(:field, :label, for: :marketing) { "Marketing emails" } %>
    <%= kui(:field, :description) { "Receive emails about new products." } %>
  <% end %>
<% end %>

Disabled

<%= kui(:switch, disabled: true) %>
<%= kui(:switch, checked: true, disabled: true) %>

With Rails Form Helpers

Use the theme classes directly with Rails form builders:

<%= f.check_box :dark_mode,
    class: "peer sr-only",
    role: :switch %>

Or render the full component by passing form attributes:

<%= kui(:switch, id: :dark_mode, name: "user[dark_mode]", value: "1") %>

Theme

# lib/kiso/themes/switch.rb (track)
Kiso::Themes::SwitchTrack = ClassVariants.build(
  base: "relative inline-flex shrink-0 cursor-pointer items-center
         rounded-full border-2 border-transparent shadow-xs
         outline-none bg-accented transition-colors
         has-[:focus-visible]:ring-[3px]
         has-[:disabled]:cursor-not-allowed has-[:disabled]:opacity-50",
  variants: {
    color: { primary: "", ... },
    size: { sm: "h-4 w-8", md: "h-5 w-9" }
  },
  compound_variants: [
    { color: :primary, class: "has-[:checked]:bg-primary
        has-[:focus-visible]:ring-primary/50" },
    ...
  ],
  defaults: { color: :primary, size: :md }
)

# Thumb
Kiso::Themes::SwitchThumb = ClassVariants.build(
  base: "pointer-events-none block rounded-full bg-background
         shadow-lg ring-0 transition-transform translate-x-0.5",
  variants: {
    size: {
      sm: "size-3 peer-checked:translate-x-4",
      md: "size-4 peer-checked:translate-x-4"
    }
  },
  defaults: { size: :md }
)

The <label> element serves as the track, wrapping an sr-only checkbox input and a thumb <span>. has-[:checked] drives the track color, peer-checked: drives the thumb translation.

Accessibility

Attribute Value
data-slot "switch"
role "switch"
type "checkbox"
disabled Native attribute

The hidden <input> has role="switch" for screen readers.

Keyboard

Key Action
Tab Moves focus to/from the switch.
Space Toggles the switch state.