[PR #1948] a11y(shared): make subscribe modal a real dialog for keyboard and screen-reader users #32212

Open
opened 2026-07-12 08:52:05 -05:00 by GiteaMirror · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/harvard-edge/cs249r_book/pull/1948
Author: @farhan523
Created: 7/7/2026
Status: 🔄 Open

Base: devHead: a11y/subscribe-modal-dialog


📝 Commits (1)

  • e3bfd43 a11y(shared): make subscribe modal a real dialog for keyboard and screen-reader users

📊 Changes

6 files changed (+252 additions, -12 deletions)

View changed files

📝 book/quarto/assets/scripts/subscribe-modal.js (+42 -2)
📝 kits/assets/scripts/subscribe-modal.js (+42 -2)
📝 labs/assets/scripts/subscribe-modal.js (+42 -2)
📝 mlsysim/docs/scripts/subscribe-modal.js (+42 -2)
📝 shared/scripts/subscribe-modal.js (+42 -2)
📝 site/assets/scripts/subscribe-modal.js (+42 -2)

📄 Description

Problem

The shared subscribe modal (shared/scripts/subscribe-modal.js, mirrored to the book, site, labs, kits, and mlsysim subsites) is a plain <div> overlay with several accessibility gaps:

  • Not announced as a dialog — no role="dialog", aria-modal, or accessible name. Screen-reader users get no announcement when it opens and can keep reading the page behind the overlay without knowing a form is blocking the view.
  • No focus trap — a few Tab presses inside the form move focus out of the modal into the visually hidden background page; the focus outline disappears behind the overlay (WCAG 2.4.3).
  • No focus restore — closing the modal drops keyboard users at the top of the document instead of back on the Subscribe link they activated (WCAG 4.1.2 context).
  • Motion regardless of preference — the slide-up/scale entrance plays even with prefers-reduced-motion: reduce set (WCAG 2.3.3).

Fix (canonical file only, mirrors regenerated)

  • role="dialog" aria-modal="true" aria-labelledby="subscribe-modal-title" on .modal-container, id added to the existing title → announced as "Stay in the Loop, dialog".
  • Tab/Shift+Tab cycle within the modal's visible, enabled controls. The focusable list is computed per keypress, so the trap also works on the post-submit success view where the form is hidden.
  • openModal() saves document.activeElement; closeModal() refocuses it.
  • @media (prefers-reduced-motion: reduce) disables the fadeIn/slideUp animations.

Behavior

No visual or functional change for mouse users: same design, same animations (when motion is allowed), Escape and overlay-click still close it.

Mirrors were regenerated with bash shared/scripts/sync-mirrors.sh (all six copies stay byte-identical for the CI drift check). Verified with node --check.


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/harvard-edge/cs249r_book/pull/1948 **Author:** [@farhan523](https://github.com/farhan523) **Created:** 7/7/2026 **Status:** 🔄 Open **Base:** `dev` ← **Head:** `a11y/subscribe-modal-dialog` --- ### 📝 Commits (1) - [`e3bfd43`](https://github.com/harvard-edge/cs249r_book/commit/e3bfd4383cb946225ee46fd7ae768e4e9d430ae7) a11y(shared): make subscribe modal a real dialog for keyboard and screen-reader users ### 📊 Changes **6 files changed** (+252 additions, -12 deletions) <details> <summary>View changed files</summary> 📝 `book/quarto/assets/scripts/subscribe-modal.js` (+42 -2) 📝 `kits/assets/scripts/subscribe-modal.js` (+42 -2) 📝 `labs/assets/scripts/subscribe-modal.js` (+42 -2) 📝 `mlsysim/docs/scripts/subscribe-modal.js` (+42 -2) 📝 `shared/scripts/subscribe-modal.js` (+42 -2) 📝 `site/assets/scripts/subscribe-modal.js` (+42 -2) </details> ### 📄 Description ## Problem The shared subscribe modal (`shared/scripts/subscribe-modal.js`, mirrored to the book, site, labs, kits, and mlsysim subsites) is a plain `<div>` overlay with several accessibility gaps: - **Not announced as a dialog** — no `role="dialog"`, `aria-modal`, or accessible name. Screen-reader users get no announcement when it opens and can keep reading the page *behind* the overlay without knowing a form is blocking the view. - **No focus trap** — a few Tab presses inside the form move focus out of the modal into the visually hidden background page; the focus outline disappears behind the overlay (WCAG 2.4.3). - **No focus restore** — closing the modal drops keyboard users at the top of the document instead of back on the Subscribe link they activated (WCAG 4.1.2 context). - **Motion regardless of preference** — the slide-up/scale entrance plays even with `prefers-reduced-motion: reduce` set (WCAG 2.3.3). ## Fix (canonical file only, mirrors regenerated) - `role="dialog" aria-modal="true" aria-labelledby="subscribe-modal-title"` on `.modal-container`, id added to the existing title → announced as "Stay in the Loop, dialog". - Tab/Shift+Tab cycle within the modal's visible, enabled controls. The focusable list is computed per keypress, so the trap also works on the post-submit success view where the form is hidden. - `openModal()` saves `document.activeElement`; `closeModal()` refocuses it. - `@media (prefers-reduced-motion: reduce)` disables the `fadeIn`/`slideUp` animations. ## Behavior No visual or functional change for mouse users: same design, same animations (when motion is allowed), Escape and overlay-click still close it. Mirrors were regenerated with `bash shared/scripts/sync-mirrors.sh` (all six copies stay byte-identical for the CI drift check). Verified with `node --check`. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
GiteaMirror added the pull-request label 2026-07-12 08:52:05 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/cs249r_book#32212