visual-novel-web/src/components/ui/inputs/switch.tsx

51 lines
1.7 KiB
TypeScript
Raw Normal View History

2025-10-28 07:59:26 +00:00
'use client';
import { cn } from '@/lib';
import { useControllableValue } from 'ahooks';
import { InputLeft } from '.';
2025-10-31 02:59:49 +00:00
import * as SwitchPrimitive from '@radix-ui/react-switch';
2025-10-28 07:59:26 +00:00
const { Root, Thumb } = SwitchPrimitive;
type SwitchProps = {
value?: boolean;
onChange?: (value: boolean) => void;
icon?: any;
text?: string;
} & React.HTMLAttributes<HTMLDivElement>;
export default function Switch(props: SwitchProps) {
const { icon, text, ...rest } = props;
const [value, onChange] = useControllableValue(props);
return (
<div {...rest} className={cn('input-view justify-between', rest.className)}>
<InputLeft icon={icon} text={text} />
<Root
checked={value}
onCheckedChange={onChange}
className={cn(
'relative inline-flex h-[28px] w-[52px] shrink-0 items-center',
'cursor-pointer rounded-full',
'transition-colors duration-200 ease-in-out',
'focus-visible:ring-2 focus-visible:ring-white/20 focus-visible:outline-none',
'disabled:cursor-not-allowed disabled:opacity-50',
// 未选中状态 - 灰色背景
'bg-white/20',
// 选中状态 - 绿色背景
'data-[state=checked]:bg-[rgb(0,110,74)]' // 注意RGB 值之间不能有空格
)}
>
<Thumb
className={cn(
'pointer-events-none block h-[24px] w-[24px] rounded-full',
'bg-white shadow-lg',
'transition-transform duration-200 ease-in-out',
// 未选中时在左侧2px 偏移)
'translate-x-[2px]',
// 选中时移到右侧52px - 24px - 2px = 26px
'data-[state=checked]:translate-x-[26px]'
)}
/>
</Root>
</div>
);
}