Skip to content

Add focus restoration to ManageCookies button (CORE-1503)#110

Draft
OpenStaxClaude wants to merge 1 commit intomainfrom
CORE-1503-manage-cookies-focus
Draft

Add focus restoration to ManageCookies button (CORE-1503)#110
OpenStaxClaude wants to merge 1 commit intomainfrom
CORE-1503-manage-cookies-focus

Conversation

@OpenStaxClaude
Copy link
Contributor

Summary

Implements WCAG-compliant focus restoration for the Manage Cookies button when the CookieYes modal closes, addressing a critical accessibility violation.

Jira Ticket: https://openstax.atlassian.net/browse/CORE-1503

Problem

When users close the CookieYes cookie consent modal, keyboard focus does not return to the "Manage Cookies" button that opened it. This violates WCAG 2.4.3 (Focus Order) and causes:

  • Screen reader users to become disoriented
  • Screen magnification users to lose their place
  • Keyboard users to have to navigate through the entire page to return to their previous location

Solution

Added focus restoration logic to the ManageCookiesLink component that:

  1. Stores button reference: Uses a ref to capture the button element
  2. Detects modal close: Uses MutationObserver to watch for the cky-modal-open class being removed from the .cky-modal element
  3. Restores focus: Calls button.focus() when modal closes
  4. Cleans up: Disconnects observer after use and on component unmount to prevent memory leaks

Implementation Details

Key Approach

Based on Roy Johnson's investigation, CookieYes maintains a .cky-modal div in the DOM that:

  • Gets the cky-modal-open class when the modal is open
  • Has the cky-modal-open class removed when the modal closes

This predictable class change allows us to use a MutationObserver to detect modal closure without relying on CookieYes events (which don't exist for modal close actions).

Code Changes

  • Added buttonRef to capture the button element
  • Added observerRef to track the MutationObserver instance
  • Created handleClick handler that:
    • Stores the button reference
    • Calls any existing onClick handler
    • Sets up MutationObserver to watch .cky-modal for class changes
    • Restores focus and cleans up when cky-modal-open is removed
  • Added cleanup effect to disconnect observer on unmount
  • Small 100ms delay allows CookieYes to add the modal to DOM before observation starts

Testing

Manual Testing Steps

  1. Navigate to a page with the Manage Cookies button (e.g., REX footer)
  2. Tab to the "Manage Cookies" button
  3. Press Enter to open the CookieYes modal
  4. Close the modal (press Escape or click the X button)
  5. Verify focus returns to the "Manage Cookies" button

Expected Behavior

  • ✅ Focus moves to the Manage Cookies button after modal closes
  • ✅ Works for both Escape key and X button close methods
  • ✅ No memory leaks from observers
  • ✅ No console errors

Browser Compatibility

Uses standard browser APIs:

  • MutationObserver - Supported in all modern browsers
  • classList.contains() - Widely supported
  • Element.focus() - Universal support

Impact

This change affects all uses of ManageCookiesLink across OpenStax products, including:

  • REX (Reading Experience) footer
  • Other OpenStax sites using this component

Since the change is self-contained in the component, no updates to consuming code are required.

WCAG Compliance

This implementation follows WCAG 2.1 Level AA guidelines:

  • Success Criterion 2.4.3 (Focus Order): Focus follows a logical sequence
  • Success Criterion 2.1.1 (Keyboard): All functionality is keyboard accessible

References:

🤖 Generated with Claude Code

Co-Authored-By: Claude Sonnet 4.5 noreply@anthropic.com

Implements WCAG-compliant focus restoration for the Manage Cookies button
when the CookieYes modal closes.

Changes:
- Added MutationObserver to detect when CookieYes modal closes
- Store button reference when clicked
- Restore focus to button when cky-modal-open class is removed
- Cleanup observer on component unmount to prevent memory leaks

Implementation:
- Uses MutationObserver to watch for class changes on .cky-modal element
- Detects when cky-modal-open class is removed (modal closed)
- Small 100ms delay allows CookieYes to add modal to DOM
- Properly cleans up observer when done or on unmount

This ensures keyboard users don't lose their place when closing the
CookieYes modal, addressing critical accessibility violations
identified in CORE-1503.

Jira: https://openstax.atlassian.net/browse/CORE-1503

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
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