Skip to content

Fix: Reveal captions, chapters and speed menus while they have focus (fixes #232 #297) - #371

Open
swashbuck wants to merge 1 commit into
masterfrom
issue/232
Open

Fix: Reveal captions, chapters and speed menus while they have focus (fixes #232 #297)#371
swashbuck wants to merge 1 commit into
masterfrom
issue/232

Conversation

@swashbuck

Copy link
Copy Markdown
Contributor

Fixes #232
Fixes #297

Both menus are unusable by keyboard, but for two different reasons, so this is one PR rather than two.

Captions and chapters. MediaElement leaves the visually-hidden .mejs__offscreen class applied to the menu while it holds focus, so a keyboard user tabs into a live list of radios and arrows through real options with nothing on screen. The focusout handler re-adds the class in a setTimeout(…, 0), so moving between options fires focusout then focusinfocusin removes the class and the queued timeout puts it straight back. That is the flicker described in #232. Upstream: mediaelement/mediaelement#2949

Speed. This one is not .mejs__offscreen — MediaElement does remove that class on focusin. The menu is hidden by visibility: hidden in our vendored plugin-speed.less, revealed only on .mejs__speed-button:hover. visibility: hidden also makes the radios unfocusable, so the speed options cannot be reached by keyboard at all: document.activeElement stays on body when you try. A clip-only override does not fix it; the rule has to set visibility: visible.

Fix

  • Reveal the captions, chapters and speed menus whenever focus is anywhere inside their button, mirroring the existing hover behaviour and what MediaElement's own focusin handler is trying to do.
  • Give the focused option a visible focus indicator. The radio inputs are positioned off screen so that only their labels show, so without this the revealed menu gives no indication of which option has focus.

Affects WCAG 2.1.1 Keyboard (A) for the speed menu, and 2.4.7 Focus Visible and 2.4.11 Focus Not Obscured (Minimum) (AA) for all three.

Notes on the approach, since a few of the choices are deliberate:

  • The rules go in the override layers rather than in mediaelementplayer.less or plugin-speed.less, so they survive the next MediaElement re-vendor. The comment linking the upstream issue is in the Less as agreed in Cannot navigate caption button language menu with accessibility  #232.
  • :focus-within hooks the button, not the selector. On the selector it can never fire for speed, because visibility: hidden stops focus getting inside to trigger it.
  • The rules do not test for .mejs__offscreen. That class is added and removed by racing handlers, so the reveal must hold whichever way the race lands.
  • Only the properties .mejs__offscreen contributes are undone. Width, border, overflow and the negative right margin that centres the captions menu come from the more specific .mejs__captions-button > .mejs__captions-selector rule and still apply — resetting margin wholesale would break the centring.
  • .mejs__captions-button-toggle is excluded. In that mode MediaElement still builds the list (addTrackButton runs before the mode branch) but binds no handlers to it, so a blanket reveal would surface an inert menu.
  • The focus ring sits on the list item rather than the label because the speed label is wider than its 60px menu, which has overflow: hidden, so an outline on the label is clipped on the right. :has() is already in use in adapt-contrib-vanilla.

Testing

Verified in Chrome on framework 5.56.2. less/ is byte-identical between v7.0.6 and v7.1.0.

Set up a media component with a video that has two or more caption tracks, toggleCaptionsButtonWhenOnlyOne false, and speed in _playerOptions.features.

  1. Using the keyboard only, tab through the control bar. The captions menu should be visible for as long as focus is on the captions button or inside its list, and hidden again once focus leaves.
  2. Arrow through the caption options. Each option should show a focus indicator, and the caption track should change as you move.
  3. Tab to the speed button. The speed menu should appear. Tab again — focus should land in the speed radio group, which was previously unreachable.
  4. Arrow through the speed options. The focused option should show an indicator, the playback rate should change, and the button label should update.
  5. With the mouse, hover the speed and captions buttons. Behaviour should be unchanged.
  6. Set a single caption track with toggleCaptionsButtonWhenOnlyOne true and focus the captions button. No menu should appear — the button is an on/off toggle in that mode.

Confirmed by measurement in step 4 that video.playbackRate follows the arrow keys (1 to 1.25), and in step 2 that the selected track's TextTrack.mode changes from hidden to showing.

Not covered: screen reader passes with JAWS and NVDA.

Related

Two unrelated defects turned up while testing this and will be raised separately: the caption track labels' for attribute is missing the -btn suffix present on the input id, so those radios have no accessible name; and in toggleCaptionsButtonWhenOnlyOne mode the inert caption radios remain focusable.

Posted via collaboration with Claude Code

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

Projects

Status: Needs Reviewing

Development

Successfully merging this pull request may close these issues.

Video Speed menu is not accessible Cannot navigate caption button language menu with accessibility

3 participants