Switch
BOUNCY 弹簧开关,开启时显示主题色。
邮件通知
有新订单时提醒我
公开个人主页
所有人都能看到你的资料
'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">
{[
['邮件通知', '有新订单时提醒我', a, setA],
['公开个人主页', '所有人都能看到你的资料', 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>
);
}
安装
'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>
);
}
用法
<Switch label="邮件通知" checked={on} onChange={setOn} />