index.tsx 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
  1. 'use client'
  2. import React, { useState } from 'react'
  3. import classNames from 'classnames'
  4. import { Switch as OriginalSwitch } from '@headlessui/react'
  5. type SwitchProps = {
  6. onChange: (value: boolean) => void
  7. size?: 'md' | 'lg'
  8. defaultValue?: boolean
  9. disabled?: boolean
  10. }
  11. const Switch = ({ onChange, size = 'lg', defaultValue = false, disabled = false }: SwitchProps) => {
  12. const [enabled, setEnabled] = useState(defaultValue)
  13. const wrapStyle = {
  14. lg: 'h-6 w-11',
  15. md: 'h-4 w-7'
  16. }
  17. const circleStyle = {
  18. lg: 'h-5 w-5',
  19. md: 'h-3 w-3'
  20. }
  21. const translateLeft = {
  22. lg: 'translate-x-5',
  23. md: 'translate-x-3'
  24. }
  25. return (
  26. <OriginalSwitch
  27. checked={enabled}
  28. onChange={(checked: boolean) => {
  29. if (disabled) return;
  30. setEnabled(checked)
  31. onChange(checked)
  32. }}
  33. className={classNames(
  34. wrapStyle[size],
  35. enabled ? 'bg-blue-600' : 'bg-gray-200',
  36. 'relative inline-flex flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out',
  37. disabled ? '!opacity-50 !cursor-not-allowed' : '',
  38. )}
  39. >
  40. <span
  41. aria-hidden="true"
  42. className={classNames(
  43. circleStyle[size],
  44. enabled ? translateLeft[size] : 'translate-x-0',
  45. 'pointer-events-none inline-block transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out',
  46. )}
  47. />
  48. </OriginalSwitch>
  49. )
  50. }
  51. export default React.memo(Switch)