54 lines
1.5 KiB
TypeScript
54 lines
1.5 KiB
TypeScript
import clsx from 'clsx';
|
|
import React, { useRef } from 'react';
|
|
|
|
interface IToggle extends Pick<React.InputHTMLAttributes<HTMLInputElement>, 'id' | 'name' | 'checked' | 'onChange' | 'required' | 'disabled'> {
|
|
size?: 'sm' | 'md'
|
|
}
|
|
|
|
/** A glorified checkbox. */
|
|
const Toggle: React.FC<IToggle> = ({ id, size = 'md', name, checked, onChange, required, disabled }) => {
|
|
const input = useRef<HTMLInputElement>(null);
|
|
|
|
const handleClick: React.MouseEventHandler<HTMLButtonElement> = (e) => {
|
|
e.preventDefault();
|
|
input.current?.focus();
|
|
input.current?.click();
|
|
};
|
|
|
|
return (
|
|
<button
|
|
className={clsx('flex-none rounded-full', {
|
|
'bg-gray-500': !checked && !disabled,
|
|
'bg-primary-600': checked && !disabled,
|
|
'bg-gray-200': !checked && disabled,
|
|
'bg-primary-200': checked && disabled,
|
|
'w-9 p-0.5': size === 'sm',
|
|
'w-11 p-0.5': size === 'md',
|
|
'cursor-default': disabled,
|
|
})}
|
|
onClick={handleClick}
|
|
>
|
|
<div className={clsx('rounded-full bg-white transition-transform', {
|
|
'h-4.5 w-4.5': size === 'sm',
|
|
'translate-x-3.5': size === 'sm' && checked,
|
|
'h-6 w-6': size === 'md',
|
|
'translate-x-4': size === 'md' && checked,
|
|
})}
|
|
/>
|
|
|
|
<input
|
|
id={id}
|
|
ref={input}
|
|
name={name}
|
|
type='checkbox'
|
|
className='sr-only'
|
|
checked={checked}
|
|
onChange={onChange}
|
|
required={required}
|
|
disabled={disabled}
|
|
/>
|
|
</button>
|
|
);
|
|
};
|
|
|
|
export default Toggle;
|