Add tooltips with shortcut hints to the markdown editor toolbar#5414
Add tooltips with shortcut hints to the markdown editor toolbar#5414FadhlanR wants to merge 2 commits into
Conversation
Preview deploymentsHost Test Results 1 files ± 0 1 suites ±0 2h 53m 40s ⏱️ + 16m 59s Results for commit 476c4cd. ± Comparison against earlier commit db871d4. Realm Server Test Results 1 files ± 0 1 suites ±0 11m 45s ⏱️ +11s Results for commit 476c4cd. ± Comparison against earlier commit db871d4. |
d7c16b7 to
94c88e7
Compare
Every toolbar item renders a styled boxel-ui tooltip: the item label, plus a key-command badge (⌘ on macOS, Ctrl elsewhere) for items that have a CodeMirror binding — Bold, Italic, Code. The add-embed and edit-embed buttons get label-only tooltips. Tooltips are suppressed while a control is disabled, so the format buttons surface no hint until the editor holds focus. Tooltip gains an opt-in @disabled arg (boxel-ui) that hides the content on hover; it defaults to the previous always-show behavior. ModalContainer gains opt-in @closeButtonLabel / @closeButtonShortcut args: when a shortcut is supplied the close button renders the same styled tooltip (suppressed while the close button is disabled), so the markdown-embed chooser surfaces its ESC-to-close binding. The chooser stops the Escape at the modal so it no longer bubbles to the operator-mode handler and flips the card out of edit format. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
94c88e7 to
db871d4
Compare
There was a problem hiding this comment.
Pull request overview
This PR replaces native title-attribute hover text with styled boxel-ui tooltips across the rich-markdown editor toolbar, and extends the shared <Tooltip> component with an opt-in @disabled arg so disabled controls don’t reveal hints. It also enhances the modal close button to optionally show the same “label + shortcut badge” tooltip and fixes Escape handling in the embed chooser modal so it doesn’t bubble to the document.
Changes:
- Add styled tooltips (with optional shortcut badges) to CodeMirror editor toolbar controls, suppressing tooltip display while formatting controls are disabled.
- Extend
boxel-ui<Tooltip>with@disabledto prevent showing tooltip content. - Add optional close-button tooltip args to
ModalContainer, and stop Escape propagation in the markdown embed chooser modal; add/extend integration tests accordingly.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/base/codemirror-editor.gts | Wrapes toolbar items (including embed actions) in <Tooltip> blocks and adds shortcut badge support + styling. |
| packages/boxel-ui/addon/src/components/tooltip/index.gts | Adds @disabled support via a showContent gate for rendering tooltip content. |
| packages/host/app/components/modal-container.gts | Adds @closeButtonLabel / @closeButtonShortcut and renders close button inside a tooltip when provided. |
| packages/host/app/components/markdown-embed-chooser/modal.gts | Stops Escape keydown propagation before closing; opts into close-button tooltip with close + ESC. |
| packages/host/tests/integration/components/rich-markdown-field-test.gts | Adds coverage that disabled format controls don’t reveal tooltip content on hover. |
| packages/host/tests/integration/components/codemirror-embed-toolbar-test.gts | Asserts add/edit embed controls show label-only tooltips (no shortcut badge). |
| packages/host/tests/integration/components/markdown-embed-chooser-modal-test.gts | Asserts close button tooltip shows close + ESC, and Escape closes without reaching document. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| @action | ||
| private handleKeydown(event: Event) { | ||
| if ((event as KeyboardEvent).key === 'Escape') { | ||
| // Own the Escape here: stop it before it reaches the document-level | ||
| // operator-mode handler, which would otherwise flip the card out of edit | ||
| // format once closing this modal has cleared the `has-modal` guard. | ||
| event.preventDefault(); | ||
| event.stopPropagation(); | ||
| this.handleClose(); | ||
| } | ||
| } |
There was a problem hiding this comment.
[Claude Code 🤖] Kept event: Event with the cast. The handler is wired via {{on 'keydown' ...}}, and this repo's Glint typing for the on modifier provides (event: Event) — typing the param as KeyboardEvent fails ember-tsc (TS2345, handler not assignable to (event: Event) => void). Casting is the established convention for keydown handlers here (e.g. file-chooser/modal.gts, card-chooser/modal.gts, indexed-file-tree.gts).
| border-radius: var(--boxel-border-radius-xs, 4px); | ||
| background: rgb(0 0 0 / 35%); | ||
| color: #939393; | ||
| font-family: inherit; |
There was a problem hiding this comment.
[Claude Code 🤖] Done in 476c4cd — now color: var(--boxel-450, #939393). --boxel-450 is #919191, visually indistinguishable, and #939393 stays as the fallback.
| padding: 0 var(--boxel-sp-5xs); | ||
| border-radius: var(--boxel-border-radius-xs, 4px); | ||
| background: rgb(0 0 0 / 35%); | ||
| color: #939393; | ||
| font-family: inherit; | ||
| font-size: 0.9em; |
There was a problem hiding this comment.
[Claude Code 🤖] Done in 476c4cd — now color: var(--boxel-450, #939393). --boxel-450 is #919191, visually indistinguishable, and #939393 stays as the fallback.
Replace the hard-coded #939393 badge text color in the markdown toolbar and modal-container tooltips with the --boxel-450 token (same value), keeping #939393 as the fallback. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
What & why
The rich-markdown editor toolbar showed plain browser
titleattributes on hover, which can't render a styled "label + key-command badge". This gives every toolbar item a proper styled tooltip, surfacing the keyboard shortcut where one exists.Changes
packages/base/codemirror-editor.gts— Every toolbar item renders a styled boxel-ui<Tooltip>: the item label, plus a shortcut key badge for items that have a CodeMirror binding — Bold (⌘/Ctrl+B), Italic (⌘/Ctrl+I), Code (⌘/Ctrl+`). A localmodKeyhelper picks⌘on macOS /Ctrlelsewhere, mirroring CodeMirror'sMod-. Shortcut-less items (strikethrough, link, headings, lists, blockquote) and the add-embed / edit-embed buttons get label-only tooltips. The format-button tooltips are suppressed while the control is disabled, so no hint shows until the editor holds focus.packages/boxel-ui/addon/src/components/tooltip/index.gts— Adds an opt-in@disabledarg toTooltip: when true, hovering the trigger reveals no content. Defaults to the previous always-show behavior, so existing call sites are unchanged.packages/host/app/components/modal-container.gts— Adds opt-in@closeButtonLabel/@closeButtonShortcutargs. When a shortcut is supplied, the close button renders the same styled tooltip (suppressed while the close button is disabled, via the new@disabled); the absolute positioning moves to the tooltip trigger wrapper so the overlay anchors to the button. Modals that don't pass a shortcut are unchanged.packages/host/app/components/markdown-embed-chooser/modal.gts— Passes@closeButtonLabel='close'@closeButtonShortcut='ESC', surfacing the already-wired Escape-to-close binding as a tooltip. The chooser now stops the Escape keydown at the modal so it no longer bubbles to the document-level operator-mode handler — previously, closing via Escape (but not via the × button) flipped the underlying card out of edit format, because the modal cleared thehas-modalguard before the same event reached that handler.No new formatting keymap entries are added — only the three shortcuts that already exist in the CodeMirror keymap get badges. Further bindings are a follow-up pending design confirmation.
Testing
rich-markdown-field-test— every toolbar item is wrapped in a tooltip trigger; hovering a disabled control (format buttons are disabled until the editor is OS-focused, which headless CI can't grant) reveals no tooltip. ✅codemirror-embed-toolbar-test— the always-enabled Add / Edit embed buttons reveal a label-only tooltip on hover (no shortcut badge). ✅markdown-embed-chooser-modal-test— the close button shows aclose ESCtooltip on hover; pressing Escape closes the modal and is stopped at the modal (does not reach the document). ✅eslintandember-template-lintpass clean across the changed base + host + boxel-ui files.All affected test modules were also run in the browser against the live dev server and pass.
Note for review
The modal close button's absolute positioning was moved onto the
<Tooltip>trigger wrapper (the button itself becomesposition: staticinside it) so the overlay anchors correctly. Worth a quick visual check that the × still sits flush in the top-right corner.Screen Recording
Screen.Recording.2026-07-09.at.09.20.53.mov
Ref: CS-11679
🤖 Generated with Claude Code