Skip to content

🐛 Fixed keyboard focus trapping in empty comment threads - #29724

Merged
9larsons merged 1 commit into
mainfrom
codex/fix-comments-focus-trap
Aug 3, 2026
Merged

🐛 Fixed keyboard focus trapping in empty comment threads#29724
9larsons merged 1 commit into
mainfrom
codex/fix-comments-focus-trap

Conversation

@9larsons

@9larsons 9larsons commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Summary

  • keep the main comment form expanded while keyboard focus remains within any of its controls
  • allow focus to move from the editor through the profile action and out of the comments iframe
  • add an acceptance test covering a signed-in member tabbing past an empty comment thread

Root cause

The form was considered open only while the editor was focused or contained text. Tabbing from the editor to the dynamically rendered Add your expertise button blurred the editor, which immediately unmounted the focused button. With no comment controls following it, Firefox restarted sequential focus navigation at the beginning of the iframe.

Testing

  • pnpm exec playwright test test/e2e/main-form.test.ts --project=chromium --workers=1 --reporter=line
  • new focus regression verified with Playwright Firefox 151
  • pnpm --filter @tryghost/comments-ui test:types
  • pnpm --filter @tryghost/comments-ui lint:code

Fixes #29708

fixes #29708

Kept the form open while focus moves through its controls so keyboard navigation can continue beyond the comments iframe.
@coderabbitai

coderabbitai Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

The comments form now tracks whether focus remains within its descendants. Its open state includes internal focus, and blur handling clears that state only when focus leaves the form. The form ref uses HTMLDivElement. An end-to-end test verifies that Tab moves from an empty editor to the expertise button and then to a following page button.

Suggested reviewers: kevinansfield

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly describes the keyboard focus trapping fix implemented by the pull request.
Description check ✅ Passed The description explains the focus-trapping cause, the implemented fix, the regression test, and the linked issue.
Linked Issues check ✅ Passed The changes keep the form mounted during internal focus transitions and test focus leaving the iframe, satisfying issue #29708.
Out of Scope Changes check ✅ Passed The code and end-to-end test directly support the linked issue and contain no unrelated changes.
✨ 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 codex/fix-comments-focus-trap

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@9larsons
9larsons marked this pull request as ready for review August 3, 2026 15:39
@9larsons
9larsons enabled auto-merge (squash) August 3, 2026 15:39
@nx-cloud

nx-cloud Bot commented Aug 3, 2026

Copy link
Copy Markdown

🤖 Nx Cloud AI Fix

Ensure the fix-ci command is configured to always run in your CI pipeline to get automatic fixes in future runs. For more information, please see https://nx.dev/ci/features/self-healing-ci


View your CI Pipeline Execution ↗ for commit 324a514

Command Status Duration Result
nx run ghost-monorepo:lint:boundaries ✅ Succeeded 21s View ↗
nx run-many -t lint -p @tryghost/comments-ui,gh... ✅ Succeeded 7s View ↗
nx run @tryghost/admin:build ✅ Succeeded 12s View ↗
nx run-many -t test:unit -p @tryghost/comments-ui ✅ Succeeded 14s View ↗
nx run-many --target=build --projects=tag:publi... ✅ Succeeded 2s View ↗
nx run @tryghost/comments-ui:test:acceptance ✅ Succeeded 45s View ↗

💡 Verify your cache is correct by running tasks in a sandbox. Read docs ↗


☁️ Nx Cloud last updated this comment at 2026-08-03 15:49:24 UTC

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/comments-ui/test/e2e/main-form.test.ts`:
- Around line 58-63: Replace the arbitrary page.waitForTimeout(200) after
focusing the editor in the test flow with a condition-based assertion or wait
that verifies expertiseButton has received focus. Keep the existing editor and
expertiseButton locators unchanged, and preserve the Tab navigation behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: cfdf1cd2-8768-45cf-8fac-adc34d25f94b

📥 Commits

Reviewing files that changed from the base of the PR and between 70fd437 and 324a514.

📒 Files selected for processing (2)
  • apps/comments-ui/src/components/content/forms/main-form.tsx
  • apps/comments-ui/test/e2e/main-form.test.ts

Comment on lines +58 to +63
const editor = frame.getByTestId('editor');
const expertiseButton = frame.getByTestId('expertise-button');

await editor.focus();
await page.keyboard.press('Tab');
await page.waitForTimeout(200);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/usr/bin/env bash
set -u

rg -n -C 3 'data-testid=.*(editor|form-editor)' apps/comments-ui
rg -n -C 4 'waitEditorFocused|frame\.getByTestId' apps/comments-ui/test/e2e

Repository: TryGhost/Ghost

Length of output: 50371


🏁 Script executed:

#!/usr/bin/env bash
set -u

printf '--- main-form.test.ts relevant slice ---\n'
sed -n '1,90p' apps/comments-ui/test/e2e/main-form.test.ts | cat -n

printf '\n--- e2e utils relevant definitions ---\n'
rg -n -C 5 'waitEditorFocused|getModifierKey|selectText|setClipboard|function|const|export' apps/comments-ui/test/e2e/utils/e2e.ts

printf '\n--- editor.test.ts relevant slice ---\n'
sed -n '1,120p' apps/comments-ui/test/e2e/editor.test.ts | cat -n

printf '\n--- form component relevant slice ---\n'
sed -n '120,155p' apps/comments-ui/src/components/content/forms/form.tsx | cat -n

Repository: TryGhost/Ghost

Length of output: 11360


🏁 Script executed:

#!/usr/bin/env bash
set -u

printf '%s\n' '--- locate e2e utils files ---'
fd -t f 'e2e\.(ts|js)$' apps/comments-ui/test/e2e apps/comments-ui | sed -n '1,120p'

printf '%s\n' '--- read candidate e2e utils ---'
for f in $(fd -t f 'e2e\.(ts|js)$' apps/comments-ui/test/e2e apps/comments-ui | sed -n '1,5p'); do
  echo "--- $f ---"
  wc -l "$f"
  sed -n '1,220p' "$f" | cat -n
done

Repository: TryGhost/Ghost

Length of output: 9019


Use condition-based focus synchronization.

frame.getByTestId('editor') can resolve from the existing EditorContent test ID; it is not wrong just because form-editor is visible. The test should still avoid the arbitrary page.waitForTimeout(200) and wait for expertiseButton to become focused instead.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/comments-ui/test/e2e/main-form.test.ts` around lines 58 - 63, Replace
the arbitrary page.waitForTimeout(200) after focusing the editor in the test
flow with a condition-based assertion or wait that verifies expertiseButton has
received focus. Keep the existing editor and expertiseButton locators unchanged,
and preserve the Tab navigation behavior.

@9larsons
9larsons merged commit 3427f94 into main Aug 3, 2026
46 checks passed
@9larsons
9larsons deleted the codex/fix-comments-focus-trap branch August 3, 2026 16:08
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.

Ghost Comments traps keyboard focus when a post has no comments

1 participant