## Summary
Right-clicking a text selection in the message composer left the
selection formatting tray floating over the native context menu. This
suppresses the tray for the duration of the right-click interaction.
## Changes
- `SelectionFormattingTray.tsx`: a `contextmenu` listener on the editor
DOM sets a suppression ref, cancels any queued rAF reposition, and hides
the tray. Suppression clears on the next left-click `pointerdown` or
`keydown` in the editor, which reschedules a normal position update.
- `scheduleUpdate`/`updatePosition` both honor the suppression ref, so
editor `selectionUpdate`/`transaction`/`focus` events fired during the
right-click can't bring the tray back.
- Extracted `cancelScheduledUpdate` to replace the duplicated rAF-cancel
logic, and reset suppression on editor change / cleanup.
- E2E coverage in `composer-selection-formatting.spec.ts`: double-click
to select, assert the tray shows, right-click and assert the tray hides
*and* that `contextmenu` is not `defaultPrevented` (the native menu
still opens), then re-select and assert the tray returns.
## Testing
`just` pre-push gate ran green: `desktop-check`, `desktop-typecheck`,
`desktop-test` (5397 passing), `file-size-check`.
## Demo
https://github.com/user-attachments/assets/2fdfced9-6cd6-4eb2-a6df-c03164ab1c42
Signed-off-by: Matt Toohey <contact@matttoohey.com>
**Category:** fix
**User Impact:** Composer block formatting now applies to the intended
line or selection without collapsing multiline content.
**Problem:** Block formatting from a Shift+Enter line could convert the
entire draft, selected visual lines could collapse into one list item,
and code conversion could lose line breaks. **Solution:** Scope caret
formatting to its hard-break-delimited line and normalize explicit
selections for the destination block type while preserving neighboring
content and visual line boundaries.
<details>
<summary>File changes</summary>
**desktop/src/features/messages/lib/selectionBlockFormatting.ts**
Scopes collapsed-caret block actions to the active visual line and
normalizes multiline selections for lists and code blocks.
**desktop/src/features/messages/lib/selectionBlockFormatting.test.mjs**
Adds unit coverage for caret-line isolation across line positions and
selection directions.
**desktop/src/features/messages/ui/FormattingToolbar.tsx**
Routes list, quote, and code-block actions through the selection-aware
formatting transaction.
**desktop/tests/e2e/composer-selection-formatting.spec.ts**
Covers caret-only formatting, multiline list conversion, list-to-code
conversion, preserved hard breaks, Markdown output, and backward
selections.
</details>
## Reproduction steps
1. In the desktop composer, enter several lines using Shift+Enter and
place the caret on one line.
2. Apply a bullet list, ordered list, quote, or code block; only the
caret line should change.
3. Select several Shift+Enter lines and apply a list; each visual line
should become its own item.
4. Select several list items and apply Code block; they should become
one multiline code block while unselected neighbors remain intact.
5. Select several Shift+Enter lines and apply Code block; each line
break should remain visible.
## Screenshots/Demos
<img width="508" height="222" alt="Screen Recording 2026-07-27 at 5 29
19 PM"
src="https://github.com/user-attachments/assets/35640dea-0cfb-44f1-9b0b-a993c69cb55f"
/>
Expected multiline code-block result:
https://buzz.block.builderlab.xyz/media/d2e2668093af3b67d896a32e9799daccd236da9fc9e24ec56ddb4ebf7d01dd96.png
---------
Signed-off-by: Taylor Ho <taylorkmho@gmail.com>
Co-authored-by: npub1223z34hd7vtwc6qj4s7flsxkj644nlre2nthu7lrrmkumhu3xddsrx9r6w <52a228d6edf316ec6812ac3c9fc0d696ab59fc7954d77e7be31eedcddf91335b@buzz.block.builderlab.xyz>