Skip to content

fix: keep editor focus when clicking toolbar buttons (#387) - #388

Merged
hunghg255 merged 1 commit into
mainfrom
fix/toolbar-focus-387
Oct 19, 2026
Merged

hunghg255 merged 1 commit into
mainfrom
fix/toolbar-focus-387

Conversation

@hunghg255

Copy link
Copy Markdown
Owner

Cause

Toolbar buttons are rendered by the shared ActionButton (a Radix Toggle <button>). On desktop browsers, mousedown on a button moves focus to it, so the ProseMirror editor blurs before the click handler runs. Actions like Bold call editor.commands.toggleBold() without .focus(), so focus stays on the button and the caret disappears. Mobile browsers don't focus buttons on tap, which is why it only happens on desktop.

Fix

In src/components/ActionButton.tsx, call preventDefault() on mousedown (after any onMouseDown passed in by the caller). The button no longer takes focus, so the editor keeps its focus and selection for every toolbar button built on ActionButton, not just Bold.

  • click still fires, so actions and Radix Popover/Dialog/DropdownMenu triggers (which open on click/pointerdown) work as before. Their content still moves focus where it needs to.
  • Keyboard focus (Tab, focus-visible ring) is unchanged.
  • ActionMenuButton (Heading/FontSize/FontFamily dropdowns) is unchanged.

How I verified it

  • pnpm lint: 0 errors (only warnings that were already there)
  • pnpm type-check: passes
  • oxfmt --check on the changed file: passes
  • pnpm build:lib: passes. pnpm test:types: passes.
  • esno --test for word-export, locale-loading, katex-loader, iframe-utils, ai-client and rangi-performance: all pass
  • node --test tests/bundle-isolation.test.mjs: 1 failure (a.default.extend is not a function). It fails the same way on main, so this change didn't cause it.
  • Headless Chrome (playwright-core) against the playground dev server:
    • Before the fix: type in the editor, then click Italic/Bold/Underline. document.activeElement became the toolbar button, and text typed next was not formatted.
    • After the fix: activeElement stays .ProseMirror after clicking Bold/Italic/Underline, and the next typed text is formatted.
    • All 12 aria-haspopup toolbar triggers (color, align, link, image, video, table, katex, excalidraw, drawer, etc.) and the Heading dropdown behaved the same before and after the change.

No unit test added: the repo has no DOM/React component test setup (tests are node:test without jsdom).

Fixes #387

Prevent the default mousedown behavior in the shared ActionButton so desktop
browsers don't move focus from the editor to the clicked toolbar button.
Click handlers, popover/dialog/dropdown triggers and keyboard focus are
unaffected.
@vercel

vercel Bot commented Oct 19, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
reactjs-tiptap-editor Ready Ready Preview Oct 19, 2026 3:53am UTC

@github-actions

github-actions Bot commented Oct 19, 2026 •

Copy link
Copy Markdown
Name
🎊 Status ♻️ Destroyed
💬 Latest commit 523866a
🔍 Latest deploy log https://github.com/hunghg255/reactjs-tiptap-editor/runs/117883608722
⌛ Build time ...
🚀 Deploy Preview https://hunghg255-reactjs-tiptap-editor-preview-playground-pr-388.surge.sh
📱 Preview on mobile
Click me

Use your smartphone camera to open QR code link.

Mobile

🤖 Contribute at surge-preview

@hunghg255
hunghg255 merged commit 207221e into main Oct 19, 2026
4 checks passed
@hunghg255
hunghg255 deleted the fix/toolbar-focus-387 branch October 19, 2026 04:03

This branch was successfully deployed

1 active deployment
Preview — 523866a3 Deployed Oct 19, 2026 by vercel[bot]
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.

[Bug]: textarea loses focus.

1 participant