Skip to content

BBBToggle: helper text in the accessible name, aria props on the wrong element, role is checkbox #88

Description

@germanocaumo

Describe the bug
BBBToggle with label and helperText exposes the wrong accessible name, description and role to assistive technology:

  1. The helper text becomes part of the accessible name. The <label htmlFor={id}> (Styled.TextWrapper) wraps both the title span and the helper span. The browser therefore names the input from the whole label content.
  2. aria-labelledby / aria-describedby / aria-label never reach the <input>. Toggle passes them as root props of MUI Switch. SwitchBase forwards unknown root props to its ButtonBase span, not to the input. The ${id}-label / ${id}-helper wiring has no effect.
  3. The role is checkbox, not switch. MUI Switch renders <input type="checkbox"> without role="switch", so screen readers announce a checkbox.

The same structure is still on main (src/components/Toggle/component.tsx, last touched in cb49ba4), so this isn't specific to the version below.

To Reproduce

<BBBToggle
  checked={false}
  onChange={() => {}}
  label="Hide participants without camera"
  helperText="Show only active cameras"
  textPosition="right"
/>

Inspect the accessibility tree (Chrome DevTools → Accessibility, or Playwright ariaSnapshot()).

Expected behavior

  • Name: Hide participants without camera
  • Description: Show only active cameras
  • Role: switch
  • aria-labelledby / aria-describedby / aria-label set on the <input>

Actual behavior
Playwright ariaSnapshot() of the rendered toggle:

- checkbox "Hide participants without camera Show only active cameras"

DOM, where the aria attributes end up:

<span class="MuiButtonBase-root MuiSwitch-switchBase ..."
      aria-labelledby=":r8:-label" aria-describedby=":r8:-helper">
  <input type="checkbox" id=":r8:" class="MuiSwitch-input ...">

getByRole('switch') finds nothing. getByRole('checkbox', { name: 'Hide participants without camera Show only active cameras' }) matches.

Suggested fix

  • Pass the aria props through inputProps (or slotProps.input) so they land on the <input>, and add role: 'switch' there.
  • Keep only the title inside the <label htmlFor>, and render the helper text as a sibling referenced by aria-describedby. Clicking the helper text can stay wired through its own click handler if that behavior matters.

Workaround used downstream in the meantime: pass a fixed id and inputProps={{ 'aria-labelledby': ${id}-label, 'aria-describedby': ${id}-helper, role: 'switch' }}. That still leaves the helper text inside the label.

BBB version, plugin in which the bug happened and SDK version:

  • @bigbluebutton/bbb-ui-components-react 0.7.0; source unchanged on main (v2.3.0)
  • @mui/material 6.1.6
  • BigBlueButton 4.0 HTML5 client (the mconf-live develop branch): a new "Layout view" popover in the actions bar, not a plugin

Desktop (please complete the following information):

  • OS: Linux (Ubuntu 22.04)
  • Browser: Chromium (Playwright build 1194), headless

Additional context
Found in an accessibility review of a client feature that uses BBBToggle in a popover. The component's own intent (labelId / helperTextId and the ariaLabelledBy / ariaDescribedBy props) is right; the attributes just end up on the wrong element.

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

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions