@@ -86,6 +86,12 @@ export const CheckboxWithLabel = React.forwardRef<HTMLInputElement, CheckboxProp
8686 ) => {
8787 const [ isChecked , setIsChecked ] = useState < boolean > ( defaultChecked ?? false ) ;
8888 const [ isDisabled , setIsDisabled ] = useState < boolean > ( disabled ?? false ) ;
89+ const generatedId = React . useId ( ) ;
90+ const inputId = id ?? generatedId ;
91+ const labelId = `${ inputId } -label` ;
92+ const descriptionId = `${ inputId } -description` ;
93+ const ariaLabelledBy =
94+ props [ "aria-label" ] || props [ "aria-labelledby" ] ? props [ "aria-labelledby" ] : labelId ;
8995
9096 const buttonClassName = variants [ variant ] . button ;
9197 const labelClassName = variants [ variant ] . label ;
@@ -109,7 +115,7 @@ export const CheckboxWithLabel = React.forwardRef<HTMLInputElement, CheckboxProp
109115 } , [ defaultChecked ] ) ;
110116
111117 return (
112- < div
118+ < label
113119 className = { cn (
114120 "group flex items-start gap-x-2 transition " ,
115121 props . readOnly || disabled ? "cursor-default" : "cursor-pointer" ,
@@ -118,22 +124,21 @@ export const CheckboxWithLabel = React.forwardRef<HTMLInputElement, CheckboxProp
118124 ( isDisabled || props . readOnly ) && isDisabledClassName ,
119125 className
120126 ) }
121- onClick = { ( e ) => {
122- //returning false is not setting the state to false, it stops the event from bubbling up
123- if ( isDisabled || props . readOnly === true ) return false ;
124- setIsChecked ( ( c ) => ! c ) ;
125- } }
126127 >
127128 < input
128129 { ...props }
129130 name = { name }
130131 type = "checkbox"
131132 value = { value }
132133 checked = { isChecked }
134+ aria-labelledby = { ariaLabelledBy }
135+ aria-describedby = {
136+ props [ "aria-describedby" ] ??
137+ ( variant === "description" && description ? descriptionId : undefined )
138+ }
133139 onChange = { ( e ) => {
134- //returning false is not setting the state to false, it stops the event from bubbling up
135- if ( isDisabled || props . readOnly === true ) return false ;
136- setIsChecked ( ! isChecked ) ;
140+ if ( isDisabled || props . readOnly === true ) return ;
141+ setIsChecked ( e . target . checked ) ;
137142 } }
138143 disabled = { isDisabled }
139144 className = { cn (
@@ -145,22 +150,21 @@ export const CheckboxWithLabel = React.forwardRef<HTMLInputElement, CheckboxProp
145150 ( isDisabled || props . readOnly ) &&
146151 "bg-background-raised! checked:bg-background-raised! checked:group-hover:bg-background-raised! group-hover:bg-background-raised!"
147152 ) }
148- id = { id }
153+ id = { inputId }
149154 ref = { ref }
150155 />
151156 < div >
152157 < div className = "flex items-center gap-x-2" >
153- < label
154- htmlFor = { id }
158+ < span
159+ id = { labelId }
155160 className = { cn (
156161 props . readOnly || disabled ? "cursor-default" : "cursor-pointer" ,
157162 labelClassName ,
158163 externalLabelClassName
159164 ) }
160- onClick = { ( e ) => e . preventDefault ( ) }
161165 >
162166 { label }
163- </ label >
167+ </ span >
164168 { badges && (
165169 < span className = "-mr-2 flex gap-x-1.5" >
166170 { badges . map ( ( badge ) => (
@@ -170,12 +174,16 @@ export const CheckboxWithLabel = React.forwardRef<HTMLInputElement, CheckboxProp
170174 ) }
171175 </ div >
172176 { variant === "description" && (
173- < Paragraph variant = "small" className = { cn ( "mt-0.5" , descriptionClassName ) } >
177+ < Paragraph
178+ id = { descriptionId }
179+ variant = "small"
180+ className = { cn ( "mt-0.5" , descriptionClassName ) }
181+ >
174182 { description }
175183 </ Paragraph >
176184 ) }
177185 </ div >
178- </ div >
186+ </ label >
179187 ) ;
180188 }
181189) ;
0 commit comments