Skip to content

fix(super-editor): restore toolbar dropdown keyboard focus#3304

Merged
caio-pizzol merged 3 commits into
superdoc-dev:mainfrom
sergiogomes:fix/toolbar-dropdown-keyboard-focus
May 15, 2026
Merged

fix(super-editor): restore toolbar dropdown keyboard focus#3304
caio-pizzol merged 3 commits into
superdoc-dev:mainfrom
sergiogomes:fix/toolbar-dropdown-keyboard-focus

Conversation

@sergiogomes
Copy link
Copy Markdown
Contributor

Summary

  • Opens toolbar dropdowns with Enter and Space.
  • Restores focus to the dropdown trigger when Escape closes the menu.
  • Adds unit coverage for dropdown keyboard activation and Escape focus restoration.

Test plan

  • Targeted toolbar tests:
pnpm exec vitest run packages/super-editor/src/editors/v1/components/toolbar/ButtonGroup.test.js packages/super-editor/src/editors/v1/components/toolbar/ToolbarDropdown.test.js
  • pnpm run format:check
  • pnpm run lint
  • Manual: open font dropdown, navigate with arrow keys, press Escape, confirm focus returns to the trigger.

Note: local commands printed existing warnings outside the toolbar files touched in this PR.

image

@sergiogomes sergiogomes force-pushed the fix/toolbar-dropdown-keyboard-focus branch from 0bb5ffe to 518d0db Compare May 14, 2026 15:59
@sergiogomes
Copy link
Copy Markdown
Contributor Author

Rebased onto the latest main and resolved the ButtonGroup.test.js conflict by keeping both the upstream argument-forwarding tests and this PR’s dropdown keyboard activation coverage.

@caio-pizzol caio-pizzol self-assigned this May 14, 2026
…fter Escape

After Escape restored focus to the inner ToolbarButton (.toolbar-item),
@keydown.enter.stop on that element swallowed Enter before ButtonGroup's
roving-tabindex handler could see it. Result: pressing Enter on the
restored focus did nothing - the dropdown was unable to be reopened by
keyboard until focus moved elsewhere.

New prop `allowEnterPropagation` on ToolbarButton. When true (set by
ButtonGroup's dropdown branch), the keydown handler does not
stopPropagation, so Enter bubbles to .toolbar-item-ctn where
activateToolbarItem reopens the dropdown. Plain buttons keep the
default (false) so they do not double-fire their command emission.

Split buttons (Bullet list / Numbered list main) are unaffected:
handleSplitMainClick stops propagation internally, so Enter still
runs the main command and does not toggle the dropdown.

Tests added in ButtonGroup.test.js exercising the real
ButtonGroup + ToolbarButton + ToolbarDropdown stack:
- Enter on inner .toolbar-item opens the dropdown
- Escape-then-Enter on restored focus reopens the dropdown
- Space on inner .toolbar-item opens the dropdown
- Split button: Enter runs the main command, dropdown stays closed
Copy link
Copy Markdown
Contributor

@caio-pizzol caio-pizzol left a comment

Choose a reason for hiding this comment

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

@sergiogomes after Escape, focus lands on the inner button, but Enter on it was being stopped before the toolbar could see it, so the dropdown couldn't reopen by keyboard.

i pushed a follow-up commit (c68770b3c): a new allowEnterPropagation prop lets Enter bubble from the dropdown branch only, plus tests for Escape-then-Enter and the Bullet/Numbered list case.

two PR-description notes: Bullet/Numbered list main keeps running its main action on Enter (menu does not open), and preventDefault now only fires for keys you actually handle.

lgtm once CI is green.

Comment on lines +288 to +289
trigger.setAttribute('tabindex', '-1');
trigger.focus();
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.

this branch never runs for any real dropdown (checked every one in the dev app). worth a one-line comment saying it's there to guard against trigger slots with no focusable child inside.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@caio-pizzol thanks for the review, detailed feedback, and follow-up improvements 👊🏻

@caio-pizzol caio-pizzol enabled auto-merge (squash) May 15, 2026 12:41
@codecov-commenter
Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@caio-pizzol caio-pizzol merged commit f271df9 into superdoc-dev:main May 15, 2026
68 checks passed
@superdoc-bot
Copy link
Copy Markdown
Contributor

superdoc-bot Bot commented May 15, 2026

🎉 This PR is included in @superdoc-dev/mcp v0.3.0-next.104

The release is available on GitHub release

@superdoc-bot
Copy link
Copy Markdown
Contributor

superdoc-bot Bot commented May 15, 2026

🎉 This PR is included in vscode-ext v2.3.0-next.150

@superdoc-bot
Copy link
Copy Markdown
Contributor

superdoc-bot Bot commented May 15, 2026

🎉 This PR is included in @superdoc-dev/react v1.2.0-next.148

The release is available on GitHub release

@superdoc-bot
Copy link
Copy Markdown
Contributor

superdoc-bot Bot commented May 15, 2026

🎉 This PR is included in superdoc-cli v0.8.0-next.119

The release is available on GitHub release

@superdoc-bot
Copy link
Copy Markdown
Contributor

superdoc-bot Bot commented May 15, 2026

🎉 This PR is included in superdoc-sdk v1.8.0-next.102

@superdoc-bot
Copy link
Copy Markdown
Contributor

superdoc-bot Bot commented May 15, 2026

🎉 This PR is included in superdoc v1.30.0-next.98

The release is available on GitHub release

@sergiogomes sergiogomes deleted the fix/toolbar-dropdown-keyboard-focus branch May 15, 2026 16:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants