Switch
A BOUNCY spring toggle that shows the accent when on.
Email notifications
Tell me when a new order arrives
Public profile
Anyone can see your profile
'use client';
import { useState } from 'react';
import { Switch } from '@/components/ui/switch';
export default function SwitchDemo() {
const [a, setA] = useState(true);
const [b, setB] = useState(false);
return (
<div className="flex w-full max-w-[320px] flex-col gap-4">
{[
['Email notifications', 'Tell me when a new order arrives', a, setA],
['Public profile', 'Anyone can see your profile', b, setB],
].map(([t, d, v, set]) => (
<div key={t as string} className="flex items-center justify-between gap-4">
<div>
<div className="text-sm font-medium text-text-primary">{t as string}</div>
<div className="text-[13px] text-text-secondary">{d as string}</div>
</div>
<Switch label={t as string} checked={v as boolean} onChange={set as (v: boolean) => void} />
</div>
))}
</div>
);
}
Installation
'use client';
import { motion } from 'motion/react';
import { SPRING_BOUNCY } from '@/lib/motion';
export function Switch({
checked,
onChange,
label,
}: {
checked: boolean;
onChange: (v: boolean) => void;
label: string;
}) {
return (
<button
role="switch"
aria-checked={checked}
aria-label={label}
onClick={() => onChange(!checked)}
className={
'cds-focus relative inline-flex h-5 w-9 shrink-0 items-center rounded-full p-[2px] transition-colors duration-[120ms] ' +
(checked ? 'bg-accent-brand justify-end' : 'bg-hairline-strong justify-start')
}
>
<motion.span layout transition={SPRING_BOUNCY} className="size-4 rounded-full bg-white shadow-[0_1px_2px_rgba(0,0,0,0.2)]" />
</button>
);
}
Usage
<Switch label="Email notifications" checked={on} onChange={setOn} />