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
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.
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.
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.
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.
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.
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.
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.
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.
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(...).
| Input | Type | Default | Effect |
|---|---|---|---|
name | str | None | None | Sets the optional native/FormData name. |
value | str | "on" | Sets the submitted token while checked. |
id | str | None | None | Sets native input identity and the label relationship. |
checked | bool | False | Sets server default checkedness. |
required | bool | None | None | Requires the setting to be on; CField owns it when composed. |
disabled | bool | None | None | Disables activation and submission; Field/Form remain dominant. |
invalid | bool | None | None | Sets 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) | None | Adds root classes and merges them with attrs. |
style | str | Mapping[str, str | int | float | bool | None] | Sequence[CStyleValue] | None (CStyleValue) | None | Adds root inline styles and merges them with attrs. |
attrs | Mapping[str, object] | None | None | Adds copied trusted nonconflicting metadata and targeted Alpine attributes to the root. |
input_attrs | Mapping[str, object] | None | None | Adds 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 />.
| Input | Type | Omitted behavior | Effect |
|---|---|---|---|
checked | boolean | Releases control to native checkedness. | Controls current checkedness; omission releases control. |
value | string | Uses the server fallback. | Controls the native submission token. |
required | boolean | Uses the server or Field fallback. | Controls native required state outside Field. |
disabled | boolean | Uses the server or Field/Form fallback. | Controls local disabled state outside Field. |
invalid | boolean | Uses 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
| Slot | Required | Data | Fallback |
|---|---|---|---|
default | no | {} (CSwitchDefaultSlotData) | Label-free standalone Switch requires an ARIA name; the slot is forbidden under CField. |
description | no | {} (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.
| Variable | Type | Purpose | Default |
|---|---|---|---|
--cui-switch-off-color | color | Track color while off. | Scheme-aware neutral. |
--cui-switch-on-color | color | Track color while on. | Scheme-aware primary. |
--cui-switch-thumb-color | color | Thumb fill. | Canvas. |
--cui-switch-foreground | color | Label and description foreground. | CanvasText. |
--cui-switch-focus-color | color | Keyboard focus ring. | Highlight. |
--cui-switch-invalid-color | color | Invalid-state outline. | Scheme-aware danger. |
--cui-switch-disabled-opacity | number | Disabled root opacity. | 0.52. |
--cui-switch-width | length | Track inline size. | Size-derived length. |
--cui-switch-height | length | Track block size. | Size-derived length. |
--cui-switch-padding | length | Track inset around the thumb. | 0.1875rem. |
--cui-switch-gap | length | Track-to-label spacing. | 0.625rem. |
--cui-switch-duration | time | Track 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
| Attribute | Element | Type | Meaning |
|---|---|---|---|
role | Native input | "switch" | Exposes on/off semantics. |
checked | Native input | boolean present or absent | Server default checkedness; current checkedness is the native property. |
required | Native input | boolean present or absent | Native required state. |
disabled | Native input | boolean present or absent | Native disabled state. |
data-checked | Root | boolean present or absent | Mirrors current native checkedness. |
data-required | Root | boolean present or absent | Mirrors effective required state. |
data-disabled | Root | boolean present or absent | Mirrors effective disabled state. |
data-invalid | Root | boolean present or absent | Mirrors explicit or native invalid state. |
data-size | Root | "sm" | "md" | "lg" | Mirrors effective size. |
data-label-pos | Root | "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
| Selector | Element | Purpose |
|---|---|---|
[data-citry-ui-part="switch"] | Root span | Root styling and attrs destination. |
[data-citry-ui-part="input"] | Native checkbox input | Focus form state and native events. |
[data-citry-ui-part="surface"] | Presentation span | Shared track and text layout surface. |
[data-citry-ui-part="track"] | Decorative span | Off/on visual track. |
[data-citry-ui-part="thumb"] | Decorative span | Moving state indicator. |
[data-citry-ui-part="body"] | Text wrapper span | Label and description layout. |
[data-citry-ui-part="label"] | Visible label span | Stable setting name. |
[data-citry-ui-part="description"] | Description span | Optional connected guidance. |
Interfaces
Aliases and data shapes referenced above.
Input type aliases
| Interface | Definition |
|---|---|
CClassValue | str | Mapping[str, bool] | Sequence[CClassValue] |
CStyleValue | str | Mapping[str, str | int | float | bool | None] | Sequence[CStyleValue] |
CSwitchSize | Literal["sm", "md", "lg"] |
CSwitchLabelPos | Literal["start", "end"] |
CSwitchDefaultSlotData
Empty dataclass: {}.
CSwitchDescriptionSlotData
Empty dataclass: {}.
Translation keys
-