You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

82 lines
2.0 KiB

import React from 'react';
interface StatusSwitchProps {
checked: boolean;
onChange: () => void;
activeText?: string;
inactiveText?: string;
disabled?: boolean;
}
const SWITCH_WIDTH = 72;
const SWITCH_HEIGHT = 28;
const THUMB_SIZE = 22;
const StatusSwitch: React.FC<StatusSwitchProps> = ({
checked,
onChange,
activeText = '正常',
inactiveText = '禁用',
disabled = false,
}) => {
const handleClick = (e: React.MouseEvent<HTMLDivElement>) => {
if (disabled) {
e.preventDefault();
return;
}
console.log('switch click');
onChange();
};
return (
<div
className={`
relative flex items-center box-border font-medium p-0 select-none transition-all duration-200
${checked
? 'bg-primary border-primary'
: 'bg-muted border-muted-foreground/20'
}
${disabled ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer'}
`}
style={{
width: SWITCH_WIDTH,
height: SWITCH_HEIGHT,
borderRadius: SWITCH_HEIGHT / 2,
border: '1px solid',
}}
onClick={handleClick}
>
{/* 文字 */}
<span
className={`
absolute text-xs font-medium pointer-events-none whitespace-nowrap z-10
transition-all duration-200
${checked
? 'text-primary-foreground left-3 text-left'
: 'text-muted-foreground right-3 text-right'
}
`}
style={{
minWidth: 28,
}}
>
{checked ? activeText : inactiveText}
</span>
{/* 圆点 */}
<div
className="absolute bg-background border border-border shadow-sm z-20 transition-all duration-200 ease-out"
style={{
width: THUMB_SIZE,
height: THUMB_SIZE,
borderRadius: '50%',
top: (SWITCH_HEIGHT - THUMB_SIZE) / 2 - 1,
left: checked
? SWITCH_WIDTH - THUMB_SIZE - 4
: 4,
}}
/>
</div>
);
};
export default StatusSwitch;