Switch

A control that allows the user to toggle between checked and not checked.

Loading...
<div class="flex items-center space-x-2">
    <twig:Switch id="airplane-mode" />
    <twig:Label for="airplane-mode">Airplane Mode</twig:Label>
</div>

Installation

bin/console ux:install switch --kit shadcn

That's it!

Install the following Composer dependencies:

composer require tales-from-a-dev/twig-tailwind-extra:^1.0.0

Copy the following file(s) into your Symfony app:

templates/components/Switch.html.twig
{# @prop size 'default'|'sm' The switch size. Defaults to `default` #}
{# @prop checked boolean Whether the switch is initially checked. Defaults to `false` #}
{%- props size = 'default', checked = false -%}
<div
    data-slot="switch"
    data-size="{{ size }}"
    class="{{ ('group relative inline-flex shrink-0 cursor-pointer items-center rounded-full border border-transparent transition-all outline-none data-[size=default]:h-[18.4px] data-[size=default]:w-[32px] data-[size=sm]:h-[14px] data-[size=sm]:w-[24px] bg-input dark:bg-input/80 has-checked:bg-primary dark:has-checked:bg-primary has-focus-visible:border-ring has-focus-visible:ring-3 has-focus-visible:ring-ring/50 has-[input[aria-invalid]]:border-destructive has-[input[aria-invalid]]:ring-3 has-[input[aria-invalid]]:ring-destructive/20 dark:has-[input[aria-invalid]]:ring-destructive/40 dark:has-[input[aria-invalid]]:border-destructive/50 has-disabled:cursor-not-allowed has-disabled:opacity-50 ' ~ attributes.render('class'))|tailwind_merge }}"
>
    <span
        data-slot="switch-thumb"
        class="pointer-events-none block rounded-full bg-background ring-0 transition-transform group-data-[size=default]:size-4 group-data-[size=sm]:size-3 translate-x-0 group-has-checked:translate-x-[calc(100%-2px)] rtl:group-has-checked:-translate-x-[calc(100%-2px)] dark:bg-foreground dark:group-has-checked:bg-primary-foreground"
    ></span>
    <input
        type="checkbox"
        role="switch"
        class="absolute inset-0 size-full cursor-pointer appearance-none focus:outline-hidden disabled:cursor-not-allowed"
        {{ attributes.without('class').defaults({checked: checked}) }}
    />
</div>

Happy coding!

Usage

<twig:Switch />

Examples

Description

Loading...
<twig:Field orientation="horizontal" class="max-w-sm">
    <twig:Field:Content>
        <twig:Field:Label for="switch-focus-mode">Share across devices</twig:Field:Label>
        <twig:Field:Description>Focus is shared across devices, and turns off when you leave the app.</twig:Field:Description>
    </twig:Field:Content>
    <twig:Switch id="switch-focus-mode" />
</twig:Field>

Choice Card

Card-style selection where Field:Label wraps the entire Field for a clickable card pattern.

Loading...
<twig:Field:Group class="w-full max-w-sm">
    <twig:Field:Label for="switch-share">
        <twig:Field orientation="horizontal">
            <twig:Field:Content>
                <twig:Field:Title>Share across devices</twig:Field:Title>
                <twig:Field:Description>Focus is shared across devices, and turns off when you leave the app.</twig:Field:Description>
            </twig:Field:Content>
            <twig:Switch id="switch-share" />
        </twig:Field>
    </twig:Field:Label>
    <twig:Field:Label for="switch-notifications">
        <twig:Field orientation="horizontal">
            <twig:Field:Content>
                <twig:Field:Title>Enable notifications</twig:Field:Title>
                <twig:Field:Description>Receive notifications when focus mode is enabled or disabled.</twig:Field:Description>
            </twig:Field:Content>
            <twig:Switch id="switch-notifications" checked />
        </twig:Field>
    </twig:Field:Label>
</twig:Field:Group>

Disabled

Add the disabled prop to the Switch to disable it. Add the data-disabled prop to the Field for styling.

Loading...
<twig:Field orientation="horizontal" data-disabled class="w-fit">
    <twig:Switch id="switch-disabled-unchecked" disabled />
    <twig:Field:Label for="switch-disabled-unchecked">Disabled</twig:Field:Label>
</twig:Field>

Invalid

Add aria-invalid="true" to the Switch to indicate an invalid state. Add data-invalid to the Field for styling.

Loading...
<twig:Field orientation="horizontal" class="max-w-sm" data-invalid>
    <twig:Field:Content>
        <twig:Field:Label for="switch-terms">Accept terms and conditions</twig:Field:Label>
        <twig:Field:Description>You must accept the terms and conditions to continue.</twig:Field:Description>
    </twig:Field:Content>
    <twig:Switch id="switch-terms" aria-invalid="true" />
</twig:Field>

Size

Use the size prop to change the size of the switch.

Loading...
<twig:Field:Group class="w-full max-w-[10rem]">
    <twig:Field orientation="horizontal">
        <twig:Switch id="switch-size-sm" size="sm" />
        <twig:Field:Label for="switch-size-sm">Small</twig:Field:Label>
    </twig:Field>
    <twig:Field orientation="horizontal">
        <twig:Switch id="switch-size-default" size="default" />
        <twig:Field:Label for="switch-size-default">Default</twig:Field:Label>
    </twig:Field>
</twig:Field:Group>

RTL

To enable RTL support, set the dir="rtl" attribute on the root element.

Loading...
<div class="w-full flex flex-col items-center gap-8">
    <twig:Field orientation="horizontal" class="max-w-sm" dir="rtl">
        <twig:Field:Content>
            <twig:Field:Label for="switch-rtl-ar">المشاركة عبر الأجهزة</twig:Field:Label>
            <twig:Field:Description>يتم مشاركة التركيز عبر الأجهزة، ويتم إيقاف تشغيله عند مغادرة التطبيق.</twig:Field:Description>
        </twig:Field:Content>
        <twig:Switch id="switch-rtl-ar" />
    </twig:Field>

    <twig:Field orientation="horizontal" class="max-w-sm" dir="rtl">
        <twig:Field:Content>
            <twig:Field:Label for="switch-rtl-he">שיתוף בין מכשירים</twig:Field:Label>
            <twig:Field:Description>המיקוד משותף בין מכשירים, וכבה כשאתה עוזב את התוכנה.</twig:Field:Description>
        </twig:Field:Content>
        <twig:Switch id="switch-rtl-he" />
    </twig:Field>
</div>

API Reference

Component Switch

Prop Type Description
size 'default'|'sm' The switch size. Defaults to default
checked boolean Whether the switch is initially checked. Defaults to false