Last active
February 24, 2023 03:23
-
-
Save abdmmar/0189119c9308b5f07c5dd579af608e1e to your computer and use it in GitHub Desktop.
Checkbox implementation using Radix UI, Tailwind CSS, CVA, and Tailwind Merge
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import * as CheckboxPrimitive from '@radix-ui/react-checkbox' | |
| import { Label } from '@radix-ui/react-label' | |
| import { HiCheck } from 'react-icons/hi' | |
| import { tm } from '@/lib' // custom tailwind merge | |
| import { Prettify } from '@/lib/types' // types utility to make union type more readable | |
| import { | |
| checkboxContainerVariants, | |
| checkboxVariants, | |
| CheckBoxVariantSizeProps, | |
| labelVariants, | |
| } from './checkbox.variant' | |
| type CheckboxProps = Prettify< | |
| { | |
| label?: string | |
| onChange: (checked: CheckboxPrimitive.CheckedState) => void | |
| width?: 'full' | 'fit' | |
| } & CheckboxPrimitive.CheckboxProps & | |
| CheckBoxVariantSizeProps | |
| > | |
| const Checkbox = ({ | |
| id: _id, | |
| label, | |
| checked, | |
| onChange, | |
| className, | |
| width, | |
| disabled, | |
| size, | |
| }: CheckboxProps) => { | |
| const id = _id || label | |
| return ( | |
| <div className={checkboxContainerVariants({ width })}> | |
| <Label className={labelVariants({ size, disabled })} htmlFor={id}> | |
| {label} | |
| </Label> | |
| <CheckboxPrimitive.Root | |
| id={id} | |
| checked={checked} | |
| disabled={disabled} | |
| className={tm(checkboxVariants({ checked, size, className }))} | |
| onCheckedChange={(checked) => { | |
| if (checked !== 'indeterminate') { | |
| onChange(checked) | |
| } | |
| }} | |
| > | |
| <CheckboxPrimitive.Indicator className="text-neutral-20"> | |
| <HiCheck /> | |
| </CheckboxPrimitive.Indicator> | |
| </CheckboxPrimitive.Root> | |
| </div> | |
| ) | |
| } | |
| export default Checkbox |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import { cva, VariantProps } from 'cva' | |
| export const checkboxContainerVariants = cva('items-center', { | |
| variants: { | |
| width: { | |
| full: 'flex justify-between', | |
| fit: 'inline-flex justify-center', | |
| }, | |
| }, | |
| defaultVariants: { | |
| width: 'fit', | |
| }, | |
| }) | |
| export const labelVariants = cva('mr-2', { | |
| variants: { | |
| size: { | |
| // .text-m-regular { | |
| // font-size: 14px; | |
| // line-height: 20px; | |
| // font-weight: 400; | |
| // } | |
| s: 'text-m-regular', // custom utility | |
| m: 'text-m-regular', | |
| l: 'text-l-regular', | |
| xl: 'text-l-regular', | |
| }, | |
| disabled: { | |
| true: 'text-neutral-60', | |
| false: 'text-neutral-90', | |
| }, | |
| }, | |
| }) | |
| export const checkboxVariants = cva( | |
| [ | |
| 'peer', | |
| 'rounded-md', | |
| 'border', | |
| 'flex items-center justify-center', | |
| 'disabled:hover:border-neutral-50', | |
| 'disabled:border-neutral-50', | |
| 'disabled:cursor-not-allowed', | |
| // 'disabled:', // disabled state | |
| // 'data-[state=checked]:' // checked state | |
| // 'disabled:data-[state=checked]', // disabled checked state | |
| ], | |
| { | |
| variants: { | |
| checked: { | |
| false: ['bg-white', 'border-neutral-50', 'hover:border-neutral-60'], | |
| true: ['bg-teal-600', 'border-teal-600', 'hover:border-teal-800'], | |
| indeterminate: [''], | |
| }, | |
| size: { | |
| s: 'w-5 h-5', | |
| m: 'w-6 h-6', | |
| l: 'w-7 h-7', | |
| xl: 'w-8 h-8', | |
| }, | |
| }, | |
| defaultVariants: { | |
| checked: false, | |
| size: 'm', | |
| }, | |
| }, | |
| ) | |
| export type CheckBoxVariantProps = VariantProps<typeof checkboxVariants> | |
| export type CheckBoxVariantSizeProps = Pick<CheckBoxVariantProps, 'size'> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment