59 lines
1.8 KiB
TypeScript
59 lines
1.8 KiB
TypeScript
'use client';
|
||
|
||
import { cn } from '@/lib';
|
||
import { useControllableValue } from 'ahooks';
|
||
import { InputLeft } from '.';
|
||
import { Switch as SwitchPrimitive } from 'radix-ui';
|
||
|
||
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,
|
||
onChange: onChangeProps,
|
||
value: valueProps,
|
||
...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>
|
||
);
|
||
}
|