Theme
Version
GitHub PyPI Discord
On this page

Switch

Use CSwitch for a setting that takes effect immediately. Use Checkbox for a selection or acknowledgement, and Button for an action.

Switch at a glance

Switch at a glance
Show code
import citry_ui
from citry import Component, citry

citry.register_library(citry_ui)


class SwitchAtAGlance(Component):
    template = """
      <section class="switch-room">
        <h2>Evening room</h2>
        <c-CSwitch checked>Reading lamp</c-CSwitch>
        <c-CSwitch>Window shades</c-CSwitch>
        <c-CSwitch checked>
          <c-fill name="default">Quiet ventilation</c-fill>
          <c-fill name="description">Keep air moving below the bedroom.</c-fill>
        </c-CSwitch>
      </section>
    """
    css = """
      :where(.switch-room) {
        display: grid;
        gap: 0.9rem;
        max-inline-size: 28rem;
        padding: 1.25rem;
        border: 1px solid light-dark(#c8bda8, #665d50);
        border-radius: 0.9rem;
        color: CanvasText;
        font-family: ui-sans-serif, system-ui, sans-serif;
      }

      :where(.switch-room h2) {
        margin: 0;
      }
    """


preview = SwitchAtAGlance()

preview  # noqa: B018

Change an immediate setting

The visible label describes the setting and stays the same when state changes.

Change home settings
Show code
import citry_ui
from citry import Component, citry

citry.register_library(citry_ui)


class HomeSettings(Component):
    template = """
      <c-CStack>
        <c-CSwitch checked>Porch light</c-CSwitch>
        <c-CSwitch>Robot vacuum schedule</c-CSwitch>
        <c-CSwitch checked>Door chime</c-CSwitch>
      </c-CStack>
    """


preview = HomeSettings()

preview  # noqa: B018

Add descriptions

Description content is connected to the native Switch. Disabled switches stay visible but cannot change or submit.

Describe Switch settings
Show code
import citry_ui
from citry import Component, citry

citry.register_library(citry_ui)


class DescribedSwitches(Component):
    template = """
      <c-CStack>
        <c-CSwitch checked>
          <c-fill name="default">Air purifier</c-fill>
          <c-fill name="description">Runs quietly until the room reaches clean-air target.</c-fill>
        </c-CSwitch>
        <c-CSwitch disabled>
          <c-fill name="default">Fireplace fan</c-fill>
          <c-fill name="description">Available while the fireplace is warm.</c-fill>
        </c-CSwitch>
      </c-CStack>
    """


preview = DescribedSwitches()

preview  # noqa: B018

Control state in the browser

Pass checked through $c-props="{...}"; handle native input with $event.target.checked. Omit the prop to release browser ownership.

Control a Switch
Show code
import citry_ui
from citry import Component, citry

citry.register_library(citry_ui)


class ControlledSwitch(Component):
    template = """
      <section class="switch-controlled" x-data="{enabled: true}">
        <c-CSwitch
          $c-props="{checked: enabled}"
          @input="enabled = $event.target.checked"
        >Reading mode</c-CSwitch>
        <output x-text="enabled ? 'Reading mode is on' : 'Reading mode is off'"></output>
      </section>
    """
    css = """
      :where(.switch-controlled) {
        display: grid;
        gap: 0.7rem;
        color: CanvasText;
        font-family: ui-sans-serif, system-ui, sans-serif;
      }

      :where(.switch-controlled output) {
        color: light-dark(#3f6212, #bef264);
        font-size: 0.82rem;
      }
    """


preview = ControlledSwitch()

preview  # noqa: B018

Submit and validate

A checked named Switch contributes its value to FormData. Required means the setting must be on.

Submit Switch settings
Show code
import citry_ui
from citry import Component, citry

citry.register_library(citry_ui)


class SwitchForm(Component):
    template = """
      <form
        class="switch-form"
        x-data="{result: ''}"
        @submit.prevent="result = new FormData($event.target).has('quiet_hours') ? 'Saved' : 'Enable quiet hours'"
      >
        <c-CSwitch name="quiet_hours" value="enabled" required>Quiet hours</c-CSwitch>
        <c-CGroup>
          <c-CButton type="submit">Save home settings</c-CButton>
          <button type="reset">Reset</button>
        </c-CGroup>
        <output x-text="result"></output>
      </form>
    """
    css = """
      :where(.switch-form) {
        display: grid;
        gap: 1rem;
        color: CanvasText;
        font-family: ui-sans-serif, system-ui, sans-serif;
      }
    """


preview = SwitchForm()

preview  # noqa: B018

Choose size and label position

Use sm, md, or lg. label_pos="start" puts text before the control in logical reading order.

Compare Switch presentation
Show code
import citry_ui
from citry import Component, citry

citry.register_library(citry_ui)


class SwitchPresentation(Component):
    class Kwargs:
        pass

    class Slots:
        pass

    template = """
      <c-CStack>
        <c-for each="size in sizes">
          <c-CSwitch c-size="size" checked>{{ size }} switch</c-CSwitch>
        </c-for>
        <c-CSwitch label_pos="start" checked>Label before track</c-CSwitch>
      </c-CStack>
    """

    def template_data(
        self,
        kwargs: Kwargs,  # noqa: ARG002
        slots: Slots,  # noqa: ARG002
    ) -> dict[str, object]:
        return {"sizes": ("sm", "md", "lg")}


preview = SwitchPresentation()

preview  # noqa: B018

Compose with Field

Inside CField, Field owns label, description, error, required, disabled, and invalid state. Do not add Switch slots there.

Compose Switch with Field
Show code
import citry_ui
from citry import Component, citry

citry.register_library(citry_ui)


class SwitchField(Component):
    template = """
      <c-CField control_id="away-mode" required>
        <c-fill name="label">Away mode</c-fill>
        <c-fill name="default"><c-CSwitch name="away_mode" /></c-fill>
        <c-fill name="description">Lower heating and pause routine lighting.</c-fill>
        <c-fill name="error">Enable away mode before leaving.</c-fill>
      </c-CField>
    """


preview = SwitchField()

preview  # noqa: B018

Use Switch semantics deliberately

Switches announce on/off. Keep their labels stable and use them only for immediate settings.

Choose Switch or Checkbox
Show code
import citry_ui
from citry import Component, citry

citry.register_library(citry_ui)


class ChoiceSemantics(Component):
    template = """
      <c-CStack>
        <c-CSwitch checked>
          <c-fill name="default">Automatic hallway lighting</c-fill>
          <c-fill name="description">Takes effect immediately.</c-fill>
        </c-CSwitch>
        <c-CCheckbox>
          <c-fill name="default">Include spare keys in the move checklist</c-fill>
          <c-fill name="description">A selection, not an immediate setting.</c-fill>
        </c-CCheckbox>
      </c-CStack>
    """


preview = ChoiceSemantics()

preview  # noqa: B018

Customize Switch

Override public colors, geometry, motion, and part selectors.

Customize Switch with public CSS
Show code
import citry_ui
from citry import Component, citry

citry.register_library(citry_ui)


class CustomSwitch(Component):
    template = """
      <section class="switch-oak">
        <c-CSwitch checked size="lg">Oak reading nook</c-CSwitch>
      </section>
    """
    css = """
      :where(.switch-oak) {
        --cui-switch-on-color: light-dark(#7c4a25, #d8a06f);
        --cui-switch-off-color: light-dark(#8f8376, #9f9385);
        --cui-switch-thumb-color: light-dark(#fffaf2, #2a2119);
        --cui-switch-width: 3.4rem;
        --cui-switch-height: 1.9rem;
        padding: 1rem;
        border: 1px solid light-dark(#c6ad91, #725b44);
        border-radius: 0.8rem;
      }
    """


preview = CustomSwitch()

preview  # noqa: B018

API reference

Inputs

CSwitch server inputs

Server inputs are passed in a template through <c-CSwitch ... /> or in Python through CSwitch(...).

InputTypeDefaultEffect
namestr | NoneNoneSets the optional native/FormData name.
valuestr"on"Sets the submitted token while checked.
idstr | NoneNoneSets native input identity and the label relationship.
checkedboolFalseSets server default checkedness.
requiredbool | NoneNoneRequires the setting to be on; CField owns it when composed.
disabledbool | NoneNoneDisables activation and submission; Field/Form remain dominant.
invalidbool | NoneNoneSets explicit invalid styling and relationships; CField owns it when composed.
size"sm" | "md" | "lg" (CSwitchSize)"md"Sets control and text scale.
label_pos"start" | "end" (CSwitchLabelPos)"end"Places the visible label before or after the track.
class_str | Mapping[str, bool] | Sequence[CClassValue] | None (CClassValue)NoneAdds root classes and merges them with attrs.
stylestr | Mapping[str, str | int | float | bool | None] | Sequence[CStyleValue] | None (CStyleValue)NoneAdds root inline styles and merges them with attrs.
attrsMapping[str, object] | NoneNoneAdds copied trusted nonconflicting metadata and targeted Alpine attributes to the root.
input_attrsMapping[str, object] | NoneNoneAdds copied trusted nonconflicting naming metadata and native listeners to the input.

CSwitch client inputs

Client inputs are passed in the browser through the $c-props="{ ... }" attribute on <c-CSwitch />.

InputTypeOmitted behaviorEffect
checkedbooleanReleases control to native checkedness.Controls current checkedness; omission releases control.
valuestringUses the server fallback.Controls the native submission token.
requiredbooleanUses the server or Field fallback.Controls native required state outside Field.
disabledbooleanUses the server or Field/Form fallback.Controls local disabled state outside Field.
invalidbooleanUses the server or Field fallback.Controls explicit invalid state outside Field.
size"sm" | "md" | "lg"Uses the server fallback.Controls public size.
label_pos"start" | "end"Uses the server fallback.Controls logical label placement.

Slots

Slots are passed as nested content or <c-fill> tags in a template, or through the slots={...} argument in Python.

CSwitch slots

SlotRequiredDataFallback
defaultno{} (CSwitchDefaultSlotData)Label-free standalone Switch requires an ARIA name; the slot is forbidden under CField.
descriptionno{} (CSwitchDescriptionSlotData)Description and relationship are omitted; the slot is forbidden under CField.

Events

-

Methods

-

CSS

CSS variables to theme the components. Set them on an ancestor or the component itself.

CSwitch CSS variables

Apply these variables to CSwitch or one of its ancestors.

VariableTypePurposeDefault
--cui-switch-off-colorcolorTrack color while off.Scheme-aware neutral.
--cui-switch-on-colorcolorTrack color while on.Scheme-aware primary.
--cui-switch-thumb-colorcolorThumb fill.Canvas.
--cui-switch-foregroundcolorLabel and description foreground.CanvasText.
--cui-switch-focus-colorcolorKeyboard focus ring.Highlight.
--cui-switch-invalid-colorcolorInvalid-state outline.Scheme-aware danger.
--cui-switch-disabled-opacitynumberDisabled root opacity.0.52.
--cui-switch-widthlengthTrack inline size.Size-derived length.
--cui-switch-heightlengthTrack block size.Size-derived length.
--cui-switch-paddinglengthTrack inset around the thumb.0.1875rem.
--cui-switch-gaplengthTrack-to-label spacing.0.625rem.
--cui-switch-durationtimeTrack and thumb transition duration.140ms.

Attributes

HTML attributes defined on the components that you can refer to for CSS, inspection, and testing. Read-only.

CSwitch attributes

AttributeElementTypeMeaning
roleNative input"switch"Exposes on/off semantics.
checkedNative inputboolean present or absentServer default checkedness; current checkedness is the native property.
requiredNative inputboolean present or absentNative required state.
disabledNative inputboolean present or absentNative disabled state.
data-checkedRootboolean present or absentMirrors current native checkedness.
data-requiredRootboolean present or absentMirrors effective required state.
data-disabledRootboolean present or absentMirrors effective disabled state.
data-invalidRootboolean present or absentMirrors explicit or native invalid state.
data-sizeRoot"sm" | "md" | "lg"Mirrors effective size.
data-label-posRoot"start" | "end"Mirrors logical label placement.

Selectors

Selectors for the DOM nodes in the components that you can use for CSS, inspection, and testing.

CSwitch selectors

SelectorElementPurpose
[data-citry-ui-part="switch"]Root spanRoot styling and attrs destination.
[data-citry-ui-part="input"]Native checkbox inputFocus form state and native events.
[data-citry-ui-part="surface"]Presentation spanShared track and text layout surface.
[data-citry-ui-part="track"]Decorative spanOff/on visual track.
[data-citry-ui-part="thumb"]Decorative spanMoving state indicator.
[data-citry-ui-part="body"]Text wrapper spanLabel and description layout.
[data-citry-ui-part="label"]Visible label spanStable setting name.
[data-citry-ui-part="description"]Description spanOptional connected guidance.

Interfaces

Aliases and data shapes referenced above.

Input type aliases

InterfaceDefinition
CClassValuestr | Mapping[str, bool] | Sequence[CClassValue]
CStyleValuestr | Mapping[str, str | int | float | bool | None] | Sequence[CStyleValue]
CSwitchSizeLiteral["sm", "md", "lg"]
CSwitchLabelPosLiteral["start", "end"]

CSwitchDefaultSlotData

Empty dataclass: {}.

CSwitchDescriptionSlotData

Empty dataclass: {}.

Translation keys

-