Bug description
Popup triggers across the CP render aria-controls="" — an empty string — when their popup element has not been created yet.
An empty aria-controls is an invalid attribute value, not a neutral one. Assistive technology is told a controlling relationship exists and then cannot resolve the target.
axe-core reports aria-valid-attr-value (critical, needs-review) on 25 nodes across 9 CP screens.
Examples:
<!-- date picker -->
<button aria-label="Open calendar" aria-haspopup="dialog" aria-expanded="false" aria-controls="">
<!-- combobox trigger -->
<div tabindex="0" aria-haspopup="listbox" aria-expanded="false" aria-controls="">
<!-- generic popover -->
<button data-ui-popover-trigger aria-haspopup="dialog" aria-expanded="false" aria-controls="">
<!-- command palette input -->
<input role="combobox" aria-autocomplete="list" aria-controls="">
Affects Combobox, Popover, the date field, and the command palette. There is a closed issue from the 3.x era on the same theme for SVGs (#2605), so this pattern has come up before.
WCAG 2.1 SC 4.1.2 Name, Role, Value (Level A).
How to reproduce
composer create-project statamic/statamic
- Add a
date field and a select field to a blueprint, open an entry
- In the console:
[...document.querySelectorAll('[aria-controls=""]')].map(e => e.outerHTML.slice(0, 120))
Returns the date-picker trigger and the select trigger, among others.
Suggested fix
Omit the attribute entirely until the popup element exists, rather than binding it to an empty string — i.e. :aria-controls="popupId || undefined" at the points where these are bound.
Since most of these come through reka-ui primitives, the fix may belong in how Statamic configures them (or may be worth an upstream report there).
Related: https://github.com/statamic/cms/blob/v6.31.0/resources/js/components/ui/Combobox/Combobox.vue#L390
Environment
Environment
Laravel Version: 13.30.1
PHP Version: 8.4.23
Composer Version: 2.10.2
Environment: local
Debug Mode: ENABLED
Maintenance Mode: OFF
Timezone: UTC
Locale: en
Cache
Config: NOT CACHED
Events: NOT CACHED
Routes: NOT CACHED
Views: CACHED
Drivers
Broadcasting: log
Cache: file
Database: sqlite
Logs: stack / single
Mail: log
Queue: sync
Session: file
Storage
public/storage: NOT LINKED
Statamic
Addons: 0
License Key: Not set
Sites: 1
Stache Watcher: Enabled (auto)
Static Caching: Disabled
Version: 6.31.0 PRO
Installation
Fresh statamic/statamic site via CLI
Additional details
Found during a WCAG 2.1 AA audit of a vanilla composer create-project statamic/statamic install with no addons and no custom code. Tested with axe-core 4.x on Chromium 153 at 1440x1000, plus manual keyboard traversal. Source references point at v6.31.0.
Bug description
Popup triggers across the CP render
aria-controls=""— an empty string — when their popup element has not been created yet.An empty
aria-controlsis an invalid attribute value, not a neutral one. Assistive technology is told a controlling relationship exists and then cannot resolve the target.axe-core reports
aria-valid-attr-value(critical, needs-review) on 25 nodes across 9 CP screens.Examples:
Affects Combobox, Popover, the date field, and the command palette. There is a closed issue from the 3.x era on the same theme for SVGs (#2605), so this pattern has come up before.
WCAG 2.1 SC 4.1.2 Name, Role, Value (Level A).
How to reproduce
composer create-project statamic/statamicdatefield and aselectfield to a blueprint, open an entryReturns the date-picker trigger and the select trigger, among others.
Suggested fix
Omit the attribute entirely until the popup element exists, rather than binding it to an empty string — i.e.
:aria-controls="popupId || undefined"at the points where these are bound.Since most of these come through reka-ui primitives, the fix may belong in how Statamic configures them (or may be worth an upstream report there).
Related: https://github.com/statamic/cms/blob/v6.31.0/resources/js/components/ui/Combobox/Combobox.vue#L390
Environment
Installation
Fresh statamic/statamic site via CLI
Additional details
Found during a WCAG 2.1 AA audit of a vanilla
composer create-project statamic/statamicinstall with no addons and no custom code. Tested with axe-core 4.x on Chromium 153 at 1440x1000, plus manual keyboard traversal. Source references point atv6.31.0.