@@ -262,13 +262,18 @@ export class Checkbox implements ComponentInterface {
262262
263263 renderHiddenInput ( true , el , name , checked ? value : '' , disabled ) ;
264264
265+ // Determine appropriate accessible name
266+ const hasLabelContent = el . textContent !== '' ;
267+ const hasLabelId = inputId + '-lbl' ;
268+
265269 return (
266270 < Host
267271 role = "checkbox"
268272 aria-checked = { indeterminate ? 'mixed' : `${ checked } ` }
269273 aria-describedby = { this . getHintTextID ( ) }
270274 aria-invalid = { this . getHintTextID ( ) === this . errorTextId }
271- aria-labelledby = { inputId + '-lbl' }
275+ aria-labelledby = { hasLabelContent ? hasLabelId : null }
276+ aria-label = { ! hasLabelContent ? inheritedAttributes [ 'aria-label' ] || 'checkbox' : null }
272277 aria-disabled = { disabled ? 'true' : null }
273278 tabindex = "0"
274279 onKeyDown = { this . onKeyDown }
@@ -287,13 +292,12 @@ export class Checkbox implements ComponentInterface {
287292 >
288293 < label class = "checkbox-wrapper" htmlFor = { inputId } >
289294 { /*
290- The native control must be rendered
291- before the visible label text due to https://bugs.webkit.org/show_bug.cgi?id=251951
295+ The native control must be rendered with display:none instead of aria-hidden
296+ to avoid nested interactive elements accessibility issues
292297 */ }
293298 < input
294299 type = "checkbox"
295- aria-hidden = "true"
296- tabindex = "-1"
300+ style = { { display : 'none' } }
297301 checked = { checked ? true : undefined }
298302 disabled = { disabled }
299303 id = { inputId }
@@ -307,10 +311,10 @@ export class Checkbox implements ComponentInterface {
307311 < div
308312 class = { {
309313 'label-text-wrapper' : true ,
310- 'label-text-wrapper-hidden' : el . textContent === '' ,
314+ 'label-text-wrapper-hidden' : ! hasLabelContent ,
311315 } }
312316 part = "label"
313- id = { inputId + '-lbl' }
317+ id = { hasLabelId }
314318 >
315319 < slot > </ slot >
316320 { this . renderHintText ( ) }
0 commit comments