@@ -8,12 +8,15 @@ import { Label } from '@o2s/ui/elements/label';
88
99type CheckboxProps = React . ComponentPropsWithoutRef < typeof CheckboxPrimitive . Root > & {
1010 ref ?: React . Ref < React . ComponentRef < typeof CheckboxPrimitive . Root > > ;
11+ hasError ?: boolean ;
1112} ;
12- const Checkbox = ( { className, ref, ...props } : CheckboxProps ) => (
13+ const Checkbox = ( { className, ref, hasError , ...props } : CheckboxProps ) => (
1314 < CheckboxPrimitive . Root
1415 ref = { ref }
1516 className = { cn (
1617 'peer h-4 w-4 shrink-0 rounded-sm border border-primary ring-offset-background focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground' ,
18+ hasError &&
19+ 'border-destructive data-[state=checked]:bg-destructive data-[state=checked]:border-destructive' ,
1720 className ,
1821 ) }
1922 { ...props }
@@ -24,26 +27,73 @@ const Checkbox = ({ className, ref, ...props }: CheckboxProps) => (
2427 </ CheckboxPrimitive . Root >
2528) ;
2629
27- export interface CheckboxWithLabelProps extends React . ComponentPropsWithoutRef < typeof CheckboxPrimitive . Root > {
30+ export interface CheckboxWithLabelProps extends Readonly < CheckboxProps > {
2831 label : string | React . ReactNode ;
2932 labelClassName ?: string ;
33+ children ?: React . ReactNode ;
34+ isRequired ?: boolean ;
35+ requiredLabel ?: string ;
36+ optionalLabel ?: string ;
3037}
3138
3239type CheckboxWithLabelOwnProps = CheckboxWithLabelProps & {
3340 ref ?: React . Ref < React . ComponentRef < typeof CheckboxPrimitive . Root > > ;
41+ hasError ?: boolean ;
3442} ;
35- const CheckboxWithLabel = ( { className, label, labelClassName, id, ref, ...props } : CheckboxWithLabelOwnProps ) => {
43+ const CheckboxWithLabel = ( {
44+ className,
45+ label,
46+ labelClassName,
47+ id,
48+ children,
49+ hasError,
50+ isRequired,
51+ requiredLabel = '' ,
52+ optionalLabel = '' ,
53+ ref,
54+ ...props
55+ } : CheckboxWithLabelOwnProps ) => {
3656 const generatedId = React . useId ( ) ;
3757 const checkboxId = id || generatedId ;
3858
3959 return (
4060 < div className = "flex items-start space-x-2" >
41- < Checkbox id = { checkboxId } ref = { ref } { ...props } className = { className } />
42- < Label htmlFor = { checkboxId } className = { cn ( 'mt-[1px]' , labelClassName ) } >
43- { label }
44- </ Label >
61+ < Checkbox id = { checkboxId } ref = { ref } { ...props } className = { className } hasError = { hasError } />
62+ < div className = "space-y-1 leading-none" >
63+ < Label
64+ htmlFor = { checkboxId }
65+ className = { cn (
66+ 'mt-[1px]' ,
67+ labelClassName ,
68+ hasError && 'text-destructive' ,
69+ props . disabled && 'opacity-70 cursor-default' ,
70+ ) }
71+ >
72+ < span className = "pr-2" > { label } </ span >
73+ < span className = "font-normal text-sm" > { isRequired ? requiredLabel : optionalLabel } </ span >
74+ </ Label >
75+ { children }
76+ </ div >
4577 </ div >
4678 ) ;
4779} ;
4880
49- export { Checkbox , Label , CheckboxWithLabel } ;
81+ export type CheckboxWithDetailsProps = Readonly <
82+ CheckboxWithLabelProps & {
83+ description ?: string ;
84+ errorMessage ?: string ;
85+ }
86+ > ;
87+
88+ const CheckboxWithDetails = React . forwardRef < React . ElementRef < typeof CheckboxPrimitive . Root > , CheckboxWithDetailsProps > (
89+ ( { description, errorMessage, ...props } , ref ) => {
90+ return (
91+ < CheckboxWithLabel { ...props } ref = { ref } >
92+ { description && < p className = "text-sm text-muted-foreground" > { description } </ p > }
93+ { errorMessage && props . hasError && < p className = "text-sm text-destructive" > { errorMessage } </ p > }
94+ </ CheckboxWithLabel >
95+ ) ;
96+ } ,
97+ ) ;
98+
99+ export { Checkbox , Label , CheckboxWithLabel , CheckboxWithDetails } ;
0 commit comments