Skip to content

Improve Castos player accessibility (#811)#894

Merged
zahardev merged 1 commit intodevelopfrom
version/3.16.0-player-a11y
May 4, 2026
Merged

Improve Castos player accessibility (#811)#894
zahardev merged 1 commit intodevelopfrom
version/3.16.0-player-a11y

Conversation

@zahardev
Copy link
Copy Markdown
Collaborator

@zahardev zahardev commented May 4, 2026

Summary

  • Add WCAG ARIA attributes to the Castos podcast player for screen reader support
  • Mute button: aria-pressed toggle; speed button: dynamic aria-label with current speed
  • Subscribe/Share panels: aria-expanded on trigger buttons, Escape key to close
  • Playlist items: role="listbox"/role="option" with aria-selected on active item
  • Copy actions: aria-live="polite" region announces "Copied" to screen readers
  • Close buttons changed from <div> to semantic <button> with aria-label
  • Dynamic JS labels use wp_localize_script for i18n support

Test plan

  • Verify player controls are keyboard-navigable (Tab, Space, Arrow keys, M for mute, Shift+./Shift+, for speed)
  • Test mute button announces pressed/not-pressed state in screen reader
  • Test speed button announces current speed on change
  • Test Subscribe/Share panels: aria-expanded toggles, Escape closes and returns focus
  • Test playlist items: Tab to navigate, active item announced as selected
  • Test copy buttons (RSS, Link, Embed): screen reader announces "Copied"
  • Verify no visual regression in player appearance
  • Run WPUnit tests (codecept run WPUnit PlayersControllerTest)

Summary by CodeRabbit

  • New Features

    • Added keyboard shortcut (Escape key) to close subscribe/share panels and return focus to the triggering button
  • Enhancements

    • Improved control button labels and interface descriptions for better clarity
    • Enhanced playlist item navigation and interaction controls
    • Added internationalization support to player interface elements

Adds ARIA attributes for screen reader support: aria-pressed on mute toggle,
dynamic aria-label on speed button, aria-expanded on panel triggers, Escape
to close panels, aria-selected on playlist items, and aria-live announcement
for copy actions. Close buttons changed from div to button elements.

Co-Authored-By: Claude via AIContext
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 4, 2026

📝 Walkthrough

Walkthrough

This pull request enhances the Castos player's accessibility by introducing localized screen reader text, adding ARIA roles and attributes to controls and regions, creating utility helpers for screen reader announcements and panel management, and extending keyboard handling with Escape-key support for closing panels.

Changes

Player Accessibility Enhancements

Layer / File(s) Summary
i18n Setup & Localization
php/classes/controllers/class-players-controller.php, assets/js/castos-player.js
Controller now localizes ssp_player_i18n strings ("playback_speed", "copied") once per request; JS initializes from window.ssp_player_i18n.
Accessibility Helpers
assets/js/castos-player.js
New togglePanel(panel, triggerBtn) helper manages aria-expanded and panel focus; new announceToScreenReader(message) helper creates an offscreen live region for screen reader announcements.
Semantic Markup & ARIA Attributes
templates/players/castos-player.php
Player container now uses role="region" with aria-label; playback buttons gain aria-label attributes; subscribe/share panel close controls change from div to button; playlist <ul> gets role="listbox"; playlist items get tabindex, role="option", and aria-selected.
Keyboard & Focus Management
assets/js/castos-player.js
Mute toggle updates aria-pressed; speed changes update aria-label with localized text; playlist activation manages aria-selected states; Escape key closes open panels and returns focus to trigger buttons; copy action triggers screen reader announcement.
Tests & Assertions
tests/WPUnit/PlayersControllerTest.php
Updated expected player HTML to include new role, aria-label, aria-live, and aria-selected attributes; assertions match updated close button and share icon markup.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~23 minutes

Possibly related PRs

  • Version 3.12.0 #866: Modifies playlist-item HTML generation in the player script and also touches ARIA/accessibility attributes on dynamically created playlist items.

Poem

🐰 A player now speaks in many tongues clear,
With regions and labels for those who must hear,
When Escape is pressed, panels fade from sight,
And focus hops back to the button so bright!
Accessibility blooms—the user's delight! 🎧✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 16.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Improve Castos player accessibility (#811)' directly and clearly summarizes the main objective of the pull request, which is adding WCAG ARIA attributes and accessibility improvements to the Castos podcast player across JavaScript, PHP template, and test files.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch version/3.16.0-player-a11y

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 PHPStan (2.1.51)

Composer install failed: this project depends on private packages that require authentication (e.g. GitLab/GitHub, Laravel Nova, etc.).
CodeRabbit tooling environment cannot access private registries.
If your project requires private packages, disable the PHPStan tool in your coderabbit settings.

Instead, run PHPStan in a CI/CD pipeline where you can use custom packages — our pipeline remediation tool can use the PHPStan output from your CI/CD pipeline.


Review rate limit: 4/5 reviews remaining, refill in 12 minutes.

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
templates/players/castos-player.php (1)

116-124: 💤 Low value

Consider adding aria-label to subscribe links for consistency with share links.

The share links (Facebook, Twitter, Download) at lines 149-158 include aria-label attributes, but the subscribe links in this loop only have title. For consistent accessibility, consider adding aria-label here as well.

♿ Optional: Add aria-label to subscribe links
 <a href="<?php echo esc_url( $subscribe_link['url'] ) ?>" target="_blank" rel="noopener noreferrer"
    class="<?php echo esc_attr( $subscribe_link['class'] ) ?>"
-   title="Subscribe on  <?php echo esc_attr( $subscribe_link['label'] ) ?>">
+   title="Subscribe on  <?php echo esc_attr( $subscribe_link['label'] ) ?>"
+   aria-label="<?php printf( esc_attr__( 'Subscribe on %s', 'seriously-simple-podcasting' ), esc_attr( $subscribe_link['label'] ) ); ?>">
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@templates/players/castos-player.php` around lines 116 - 124, The subscribe
link anchors in the foreach over $subscribe_links (using $subscribe_link) only
set a title but lack an aria-label for accessibility consistency with the share
links; update the anchor in templates/players/castos-player.php to add an
aria-label attribute (e.g. aria-label="<?php echo esc_attr( 'Subscribe on ' .
$subscribe_link['label'] ) ?>") alongside the existing title, ensuring you use
esc_attr() for escaping the label text just as is done for title and class.
assets/js/castos-player.js (1)

84-96: 💤 Low value

Reconsider aria-pressed usage on play/pause buttons.

The aria-pressed attribute is typically used for toggle buttons. Here, the play and pause buttons are separate elements where one is always hidden. Setting aria-pressed on a hidden button doesn't provide value to assistive technology users.

Consider either:

  1. Using a single toggle button with aria-pressed and dynamic aria-label ("Play"/"Pause")
  2. Removing aria-pressed from these buttons entirely since they're not toggles

The current approach where the hidden pause button has aria-pressed="true" when audio is paused doesn't align with standard ARIA patterns.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@assets/js/castos-player.js` around lines 84 - 96, syncPlayButton currently
toggles aria-pressed on two separate elements (playBtn and pauseBtn), which is
not appropriate for separate show/hide buttons; remove all aria-pressed
manipulation from syncPlayButton and instead update the accessible label of the
visible control (use playBtn.setAttribute('aria-label', 'Play') when
audio.paused and pauseBtn.setAttribute('aria-label', 'Pause') when playing, or
simpler: clear aria-label on the hidden button and set the correct aria-label on
the visible one), ensuring the hidden element does not present conflicting ARIA
state; reference the syncPlayButton function and the playBtn, pauseBtn and audio
variables when making the change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@assets/js/castos-player.js`:
- Around line 84-96: syncPlayButton currently toggles aria-pressed on two
separate elements (playBtn and pauseBtn), which is not appropriate for separate
show/hide buttons; remove all aria-pressed manipulation from syncPlayButton and
instead update the accessible label of the visible control (use
playBtn.setAttribute('aria-label', 'Play') when audio.paused and
pauseBtn.setAttribute('aria-label', 'Pause') when playing, or simpler: clear
aria-label on the hidden button and set the correct aria-label on the visible
one), ensuring the hidden element does not present conflicting ARIA state;
reference the syncPlayButton function and the playBtn, pauseBtn and audio
variables when making the change.

In `@templates/players/castos-player.php`:
- Around line 116-124: The subscribe link anchors in the foreach over
$subscribe_links (using $subscribe_link) only set a title but lack an aria-label
for accessibility consistency with the share links; update the anchor in
templates/players/castos-player.php to add an aria-label attribute (e.g.
aria-label="<?php echo esc_attr( 'Subscribe on ' . $subscribe_link['label'] )
?>") alongside the existing title, ensuring you use esc_attr() for escaping the
label text just as is done for title and class.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 4ff8c6bc-28ba-48f7-887c-eaef1c94b9f7

📥 Commits

Reviewing files that changed from the base of the PR and between 89626a3 and a41675b.

📒 Files selected for processing (4)
  • assets/js/castos-player.js
  • php/classes/controllers/class-players-controller.php
  • templates/players/castos-player.php
  • tests/WPUnit/PlayersControllerTest.php

@zahardev zahardev merged commit df6baa0 into develop May 4, 2026
2 checks passed
@coderabbitai coderabbitai Bot mentioned this pull request May 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant