Back to Plate

Suggestion Mention Backspace

docs/plans/2026-04-08-suggestion-mention-backspace.md

53.0.54.9 KB
Original Source

Suggestion Mention Backspace

Task

  • Fix the failing regression in packages/suggestion/src/lib/withSuggestion.spec.tsx.
  • Scope: suggestion-mode deleteBackward('character') on a previous mention-shaped inline void.
  • Goal: backspace should mark the mention as a remove suggestion instead of doing nothing.

Plan

  1. Keep the new failing spec red as the guardrail.
  2. Inspect the mention vs link delete path in deleteSuggestion.
  3. Apply the narrowest package fix in packages/suggestion.
  4. Re-run targeted test plus required package verification.
  5. Decide whether a changeset and compound doc are warranted.

Findings

  • Existing withSuggestion tests cover text and block suggestions, but not inline void mentions.
  • The new regression spec fails because the mention node never gets suggestion: true.
  • deleteSuggestion exits early when editor.api.string(range) is empty before reaching setSuggestionNodes(...).
  • Links still work because their inline text makes the range string non-empty.
  • Mentions are inline void + markable void, so the same range can be semantically deletable while string-empty.
  • After allowing string-empty inline ranges through, deleteSuggestion still treated mention deletion like a character loop instead of an inline-void unit.
  • That let the loop continue into adjacent text nodes and moved the selection to [0,0]:0 instead of the mention's left edge at [0,0]:1.
  • block-discussion-index.ts only folded Text nodes and block suggestions into summary text, so inline void suggestions like mention/date/inline equation disappeared from Delete: cards.
  • The visible symptom matched the screenshot exactly: the summary kept surrounding text but dropped inline void labels, leaving strings like dates like or use inline equations: .
  • Continuous backward deletion across an inline void was creating a second suggestion id for adjacent text because findSuggestionProps only looked for adjacent text suggestions, not adjacent inline suggestion elements.
  • Once the inline void delete branch returned to the left edge of the element, the next backspace reused no metadata and produced a second discussion card.
  • Backspace at the start of a paragraph in suggestion mode was marking the previous block itself as a generic remove suggestion instead of creating a remove line-break suggestion.
  • That shape mismatch skipped the intended “accept merges paragraphs” path and looked like deleting the whole previous line rather than deleting the boundary between paragraphs.
  • Deleting backward after an inline link marked the preceding text and the link together because the character loop kept running after reaching a point inside a non-void inline element.
  • The underlying issue was that the inline-as-a-unit delete branch only handled inline voids, while links are inline elements with text content.

Progress

  • 2026-04-08: Added a failing regression case to packages/suggestion/src/lib/withSuggestion.spec.tsx.
  • 2026-04-08: Verified the new case fails with bun test packages/suggestion/src/lib/withSuggestion.spec.tsx.
  • 2026-04-08: Ran pnpm install, pnpm turbo build --filter=./packages/suggestion, pnpm turbo typecheck --filter=./packages/suggestion, and pnpm lint:fix.
  • 2026-04-09: Tightened the regression to assert that only the mention gets a remove mark and that the cursor lands at [0,0]:1.
  • 2026-04-09: Fixed inline-void deletion by marking the void element directly and selecting editor.api.before(pointNext) instead of continuing the character loop.
  • 2026-04-09: Added apps/www/src/registry/ui/block-discussion-index.spec.tsx with JSX-like Slate fixtures covering remove summaries for date, inline_equation, and mention.
  • 2026-04-09: Fixed discussion summary extraction by mapping inline suggestion elements to display text via value, formatted date, and texExpression.
  • 2026-04-09: Added a findSuggestionProps regression proving backward deletion from the left edge of an inline void must reuse that void's remove-suggestion metadata.
  • 2026-04-09: Fixed continuous inline-void deletion by letting findSuggestionProps inspect adjacent inline suggestion elements when adjacent text suggestions are absent.
  • 2026-04-09: Added a withSuggestion regression for deleteBackward at the start of a paragraph, asserting it creates a remove line-break suggestion and preserves the next paragraph.
  • 2026-04-09: Fixed cross-block suggestion deletion by tagging the previous block with isLineBreak: true for remove suggestions, aligning it with the existing accept/reject merge semantics.
  • 2026-04-09: Added regressions proving that deleting backward after a link must only mark the link, not the preceding text, and that discussion summaries still show link text.
  • 2026-04-09: Generalized the inline-element delete-as-a-unit branch from inline voids to inline elements whose selection is outside the element boundary, so links now behave like a single removable unit at their edge.