Skip to content

Thirteen Switch instances render with no accessible name, including entry publish state #15391

Description

@bpmore

Bug description

ui/Switch.vue renders a role="switch" button whose only child is a decorative SwitchThumb. It declares no aria-label or aria-labelledby prop, so unless a call site passes one the control has no accessible name at all. A screen reader announces "switch, on" with no indication of what is on.

ToggleFieldtype does pass :aria-label="__(config.display)" and is fine. Thirteen other call sites do not:

File Line Control
globals/Sites.vue 21 site enabled
entries/PublishForm.vue 126 entry published state
roles/PublishForm.vue 52 super user
field-conditions/Builder.vue 39, 47 always save, reserve space
field-conditions/Condition.vue 41 condition value
fieldtypes/RevealerFieldtype.vue 4 revealer
fieldtypes/bard/Set.vue 53 set enabled
fieldtypes/replicator/Set.vue 176 set enabled
field-validation/Builder.vue 8, 16 required, sometimes
pages/collections/Scaffold.vue 70, 85 index, template

The entry publish toggle is the notable one: it is arguably the single most important control in the CP.

axe-core reports button-name (critical) on 39 nodes across 6 screens.

Source: https://github.com/statamic/cms/blob/v6.31.0/resources/js/components/ui/Switch.vue

WCAG 2.1 SC 4.1.2 Name, Role, Value (Level A).

How to reproduce

  1. composer create-project statamic/statamic
  2. Open any entry for editing
  3. Inspect the published-state toggle in the sidebar

Expected: an aria-label or aria-labelledby. Actual: <button role="switch" aria-checked="true"> with no name.

Same on /cp/sites (site enabled) and /cp/roles/create (super user).

Suggested fix

Add a label / ariaLabel prop to ui/Switch.vue and pass a real name at each of the thirteen call sites.

Two of them already have the right string sitting in a v-tooltip (__('Included in output') / __('Hidden from output') in the Bard and Replicator sets); it just needs to reach aria-label too.

Making the prop required would prevent the class of bug from coming back.

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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions