Modal: add a real focus trap, restore focus on close, and use a unique title id

Open
#35 0 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

Nobody has claimed this yet.

Assessment

Difficulty
3/5
Estimated time
1-2 days
Newbie friendliness
80/100
Issue type
Feature
Clarity
Clearly specified
Activity status
Active
Tech stack
next.js, playwright, react, typescript

Research direction

Start with frontend/src/components/ui/Modal.tsx, especially the focus effect and dialog header ARIA attributes, then review the modal consumers src/components/credits/BuyCreditsModal.tsx and src/components/shared/ModelDownloadModal.tsx. Add the Playwright coverage alongside the existing e2e tests, using CONTRIBUTING.md for setup commands. Done means focus remains within each open dialog, Escape restores focus to its trigger, modal instances have unique title and description IDs, and lint, build, and e2e tests pass.

Written by the indexing model from the issue text.

Description

accessibility help wanted ui
Context

Modal is the shared dialog for the whole app. Its comment says "Focus trap", but the code only focuses the dialog container when it opens. Tab can move out of the dialog into the page behind it, and focus is not returned to the control that opened it. aria-labelledby points to a hard-coded 'modal-title' id, so nested or stacked modals produce duplicate ids, and the description is not linked with aria-describedby.

Where
  • frontend/src/components/ui/Modal.tsx:60-65: "focus trap" effect that only calls .focus()
  • Modal.tsx:82: aria-labelledby={title ? 'modal-title' : undefined}
  • the h2/p title and description inside the dialog header (about :104-113)
  • consumers include src/components/credits/BuyCreditsModal.tsx and src/components/shared/ModelDownloadModal.tsx
What to do
  1. Generate ids with useId() for the title and description, and wire aria-labelledby and aria-describedby.
  2. Trap Tab/Shift+Tab within the dialog's focusable elements, with no new dependency. Save document.activeElement on open and restore it on close.
  3. Keep the current Escape and backdrop behaviour, which depends on closeButton.
Acceptance criteria
  • A Playwright spec opens a modal, presses Tab repeatedly, and asserts that focus stays inside; after Escape, focus is back on the trigger
  • Two modal instances never share ids
  • lint, build and existing e2e tests pass
Getting started

Read CONTRIBUTING.md for dev setup and the quality bar (no facades, evidence before done). Comment here to claim the issue.

Dominant language
TypeScript
Stars
0
Forks
3
Avg merge
1d 4h
Merged PRs (30d)
5

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from BeyondITL/contentine-create

All issues in BeyondITL/contentine-create

Similar issues

More TypeScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.