import { CheckIcon, MinusIcon } from 'lucide-react'; import type { ReactNode } from 'react'; import type { ValidationResult } from 'react-aria-components'; import { Checkbox as AriaCheckbox, CheckboxGroup as AriaCheckboxGroup, type CheckboxGroupProps as AriaCheckboxGroupProps, type CheckboxProps, } from 'react-aria-components/CheckboxGroup'; import { composeRenderProps } from 'react-aria-components/composeRenderProps'; import { tv } from 'tailwind-variants'; import { Description, FieldError, Label } from './Field'; import { composeTailwindRenderProps, focusRing } from './utils'; export interface CheckboxGroupProps extends Omit< AriaCheckboxGroupProps, 'children' > { label?: string; children?: ReactNode; description?: string; errorMessage?: string | ((validation: ValidationResult) => string); } export function CheckboxGroup(props: CheckboxGroupProps) { return ( {props.children} {props.description && {props.description}} {props.errorMessage} ); } const checkboxStyles = tv({ base: 'group pressed:bg-zinc-100 dark:pressed:bg-zinc-800 flex items-center gap-2 text-sm transition', variants: { isDisabled: { false: 'text-gray-800 dark:text-zinc-200', true: 'text-gray-300 dark:text-zinc-600 forced-colors:text-[GrayText]', }, }, }); const boxStyles = tv({ extend: focusRing, base: 'flex size-5 shrink-0 items-center justify-center rounded border-2 transition', variants: { isSelected: { false: 'group-pressed:[--color:var(--color-secondary-600)] dark:group-pressed:[--color:var(--color-secondary-600)] border-(--color) bg-white [--color:var(--color-secondary-800)] dark:bg-zinc-900 dark:[--color:var(--color-secondary-400)]', true: 'group-pressed:[--color:var(--color-secondary-700)] dark:group-pressed:[--color:var(--color-secondary-800)] border-(--color) bg-(--color) [--color:var(--color-secondary-800)] dark:[--color:var(--color-secondary-500)]', }, isInvalid: { true: 'group-pressed:[--color:var(--color-warning-800)] dark:group-pressed:[--color:var(--color-warning-700)] [--color:var(--color-warning-700)] dark:[--color:var(--color-warning-600)] forced-colors:![--color:Mark]', }, isDisabled: { true: '[--color:var(--color-gray-200)] dark:[--color:var(--color-zinc-700)] forced-colors:![--color:GrayText]', }, }, }); const iconStyles = 'w-full stroke-[4] h-4 text-white group-disabled:text-gray-400 dark:text-white dark:group-disabled:text-slate-600 forced-colors:text-[HighlightText]'; export function Checkbox(props: CheckboxProps) { return ( checkboxStyles({ ...renderProps, className }), )} > {({ isSelected, isIndeterminate, ...renderProps }) => ( <>
{isIndeterminate ? ( ) : isSelected ? ( ) : null}
{props.children as ReactNode} )}
); }