51 lines
1.5 KiB
TypeScript
51 lines
1.5 KiB
TypeScript
// components/Switch.tsx
|
|
'use client'
|
|
|
|
import React from 'react'
|
|
|
|
type SwitchProps = {
|
|
id: string
|
|
checked: boolean
|
|
onChange: (checked: boolean) => void
|
|
labelLeft?: string
|
|
labelRight?: string
|
|
className?: string
|
|
}
|
|
|
|
export default function Switch({
|
|
id,
|
|
checked,
|
|
onChange,
|
|
labelLeft,
|
|
labelRight,
|
|
className = '',
|
|
}: SwitchProps) {
|
|
return (
|
|
<div className={`flex items-center gap-x-3 ${className}`}>
|
|
{labelLeft && (
|
|
<label htmlFor={id} className="text-sm text-gray-500 dark:text-neutral-400">
|
|
{labelLeft}
|
|
</label>
|
|
)}
|
|
|
|
<label htmlFor={id} className="relative inline-block w-11 h-6 cursor-pointer">
|
|
<input
|
|
type="checkbox"
|
|
id={id}
|
|
className="peer sr-only"
|
|
checked={checked}
|
|
onChange={(e) => onChange(e.target.checked)}
|
|
/>
|
|
<span className="absolute inset-0 bg-gray-200 rounded-full transition-colors duration-200 ease-in-out peer-checked:bg-blue-600 dark:bg-neutral-700 dark:peer-checked:bg-blue-500 peer-disabled:opacity-50 peer-disabled:pointer-events-none"></span>
|
|
<span className="absolute top-1/2 start-0.5 -translate-y-1/2 size-5 bg-white rounded-full shadow-xs transition-transform duration-200 ease-in-out peer-checked:translate-x-full dark:bg-neutral-400 dark:peer-checked:bg-white"></span>
|
|
</label>
|
|
|
|
{labelRight && (
|
|
<label htmlFor={id} className="text-sm text-gray-500 dark:text-neutral-400 cursor-pointer">
|
|
{labelRight}
|
|
</label>
|
|
)}
|
|
</div>
|
|
)
|
|
}
|