index.tsx 1.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. import type { ReactElement } from 'react'
  2. import { useId } from 'react'
  3. import { useContext } from 'use-context-selector'
  4. import RadioGroupContext from '../../context'
  5. import s from '../../style.module.css'
  6. import cn from '@/utils/classnames'
  7. export type IRadioProps = {
  8. className?: string
  9. labelClassName?: string
  10. children?: string | ReactElement
  11. checked?: boolean
  12. value?: string | number
  13. disabled?: boolean
  14. onChange?: (e?: IRadioProps['value']) => void
  15. }
  16. export default function Radio({
  17. className = '',
  18. labelClassName,
  19. children = '',
  20. checked,
  21. value,
  22. disabled,
  23. onChange,
  24. }: IRadioProps): JSX.Element {
  25. const groupContext = useContext(RadioGroupContext)
  26. const labelId = useId()
  27. const handleChange = (e: IRadioProps['value']) => {
  28. if (disabled)
  29. return
  30. onChange?.(e)
  31. groupContext?.onChange(e)
  32. }
  33. const isChecked = groupContext ? groupContext.value === value : checked
  34. const divClassName = `
  35. flex items-center py-1 relative
  36. px-7 cursor-pointer hover:bg-gray-200 rounded
  37. `
  38. return (
  39. <div className={cn(
  40. s.label,
  41. disabled ? s.disabled : '',
  42. isChecked ? 'bg-white shadow' : '',
  43. divClassName,
  44. className)}
  45. onClick={() => handleChange(value)}
  46. >
  47. {children && (
  48. <label className={
  49. cn(labelClassName, 'text-sm cursor-pointer')
  50. }
  51. id={labelId}
  52. >
  53. {children}
  54. </label>
  55. )}
  56. </div>
  57. )
  58. }