feat(transcription): re-edit existing @mention by pre-filling the search input #628

Open
opened 2026-05-19 21:31:41 +02:00 by marcel · 1 comment
Owner

Context

Follow-up split off from #380 ("decouple @mention display text from person search").

Issue #380 acceptance criterion 7 reads:

Given an existing @mention is re-opened for editing, when the dropdown appears, then the search field is pre-filled with the saved display text.

While implementing #380 we verified empirically that Tiptap's suggestion plugin (@tiptap/extension-mention@3.23.4) does not fire onStart/onUpdate when a cursor enters an existing mention node — the suggestion is only triggered by typing a fresh @. AC-7 was therefore split out of #380 per the original triage decision ("If it's free include it, otherwise create issue") and lands here.

User Story

As a transcriber, when I move the cursor into an already-saved @mention, I want the search dropdown to re-open with the search field pre-filled with the stored display text, so that I can correct or re-link the person without retyping the mention from scratch.

Acceptance Criteria

  1. Given the cursor is positioned inside an existing @mention node, when the position settles (selection update), then the mention dropdown opens at that mention.

  2. Given the dropdown opened for an existing mention, when it appears, then the search input is pre-filled with the mention's stored displayName.

  3. Given the search input has been pre-filled from an existing mention, when the user picks a different person from the dropdown, then the existing mention node's personId is replaced; the displayed text remains exactly what the user types (#380 AC-1 invariant).

  4. Given the search input has been pre-filled from an existing mention, when the user closes the dropdown via Escape, then the mention node is unchanged.

  5. Given the search input has been pre-filled and edited, when the user picks a person, then the linked personId updates AND the displayed text remains exactly what the user originally typed (the #380 AC-1 "display text stays exactly as typed" invariant takes precedence over the search input's content).

    AC-5 rationale: previously the AC contained an (a) / (b) ambiguity with the recommended answer hidden in Open Decisions. Folded back into the AC list per comment #11033 — Elicit on PR #629 #10962. If (b) "update display text to search input value" is ever wanted, file a sibling issue rather than reintroduce the branch here.

NFR Notes

  • Accessibility: Selection-driven dropdown opens must be debounced enough to avoid flicker on caret motion; keyboard navigation must remain intact.
  • Responsive: Mention nodes on tablet need a tap target of at least 44 px — currently the rendered <span class="mention-token"> is font-medium underline text, which is taps-through at ~22 px. Consider adding inline-block min-h-[44px] or similar for tablet ergonomics.
  • Performance: A selectionUpdate listener fires on every caret move — the mention-detection check must be O(1) (read selection.$anchor.parent.type.name), not a tree walk.

Implementation Notes

The hard work is in frontend/src/lib/shared/discussion/PersonMentionEditor.svelte:

  • Add editor.on('selectionUpdate', ...) that checks if the parent node at the caret is mention.
  • If yes, programmatically open the dropdown (via the suggestion plugin's command API, or by mounting MentionDropdown directly with the mention's attributes).
  • Pass the mention's stored displayName as editorQuery so the existing #380 mirror-then-debounce path renders correctly.
  • On selection (commit), replace the existing mention node with a fresh one carrying the new personId (display text unchanged per AC-5).

References:

Out of Scope

  • Anything covered by #380 (decoupling, debounced search, empty-state prompt). This issue only adds the re-edit entry point.
  • Bulk mention re-linking. Single-mention focus only.
  • The alternative (b) display-text-rewrites-from-search-input behaviour — if ever wanted, a separate issue.
## Context Follow-up split off from #380 ("decouple @mention display text from person search"). [Issue #380 acceptance criterion 7](https://git.raddatz.cloud/marcel/familienarchiv/issues/380) reads: > **Given** an existing @mention is re-opened for editing, **when** the dropdown appears, **then** the search field is pre-filled with the saved display text. While implementing #380 we verified empirically that Tiptap's suggestion plugin (`@tiptap/extension-mention@3.23.4`) does **not** fire `onStart`/`onUpdate` when a cursor enters an existing mention node — the suggestion is only triggered by typing a fresh `@`. AC-7 was therefore split out of #380 per the original triage decision (["If it's free include it, otherwise create issue"](https://git.raddatz.cloud/marcel/familienarchiv/issues/380#issuecomment-10883)) and lands here. ## User Story As a transcriber, when I move the cursor into an already-saved `@mention`, I want the search dropdown to re-open with the search field pre-filled with the stored display text, so that I can correct or re-link the person without retyping the mention from scratch. ## Acceptance Criteria 1. **Given** the cursor is positioned inside an existing `@mention` node, **when** the position settles (selection update), **then** the mention dropdown opens at that mention. 2. **Given** the dropdown opened for an existing mention, **when** it appears, **then** the search input is pre-filled with the mention's stored `displayName`. 3. **Given** the search input has been pre-filled from an existing mention, **when** the user picks a different person from the dropdown, **then** the existing mention node's `personId` is replaced; the displayed text remains exactly what the user types (#380 AC-1 invariant). 4. **Given** the search input has been pre-filled from an existing mention, **when** the user closes the dropdown via Escape, **then** the mention node is unchanged. 5. **Given** the search input has been pre-filled and edited, **when** the user picks a person, **then** the linked `personId` updates AND the displayed text remains exactly what the user originally typed (the #380 AC-1 "display text stays exactly as typed" invariant takes precedence over the search input's content). _AC-5 rationale: previously the AC contained an (a) / (b) ambiguity with the recommended answer hidden in Open Decisions. Folded back into the AC list per comment [#11033](https://git.raddatz.cloud/marcel/familienarchiv/issues/628#issuecomment-11033) — Elicit on PR #629 #10962. If (b) "update display text to search input value" is ever wanted, file a sibling issue rather than reintroduce the branch here._ ## NFR Notes - **Accessibility:** Selection-driven dropdown opens must be debounced enough to avoid flicker on caret motion; keyboard navigation must remain intact. - **Responsive:** Mention nodes on tablet need a tap target of at least 44 px — currently the rendered `<span class="mention-token">` is `font-medium underline` text, which is taps-through at ~22 px. Consider adding `inline-block min-h-[44px]` or similar for tablet ergonomics. - **Performance:** A `selectionUpdate` listener fires on every caret move — the mention-detection check must be O(1) (read `selection.$anchor.parent.type.name`), not a tree walk. ## Implementation Notes The hard work is in `frontend/src/lib/shared/discussion/PersonMentionEditor.svelte`: - Add `editor.on('selectionUpdate', ...)` that checks if the parent node at the caret is `mention`. - If yes, programmatically open the dropdown (via the suggestion plugin's command API, or by mounting `MentionDropdown` directly with the mention's attributes). - Pass the mention's stored `displayName` as `editorQuery` so the existing #380 mirror-then-debounce path renders correctly. - On selection (commit), replace the existing mention node with a fresh one carrying the new `personId` (display text unchanged per AC-5). References: - Source comment in `PersonMentionEditor.svelte` documenting the suggestion lifecycle. - Tiptap mention extension API: https://tiptap.dev/api/nodes/mention ## Out of Scope - Anything covered by #380 (decoupling, debounced search, empty-state prompt). This issue only adds the re-edit entry point. - Bulk mention re-linking. Single-mention focus only. - The alternative (b) display-text-rewrites-from-search-input behaviour — if ever wanted, a separate issue.
marcel added the P2-mediumfeatureui labels 2026-05-19 21:32:39 +02:00
Author
Owner

AC-5 — promote Open Decision to explicit AC (Elicit on PR #629 #10962)

Elicit flagged on PR #629 that AC-5 is currently a multi-branch sentence with the answer hidden in Open Decisions — which leaves the implementer staring at the same sticky-takeover ambiguity Felix raised in round 1.

Suggested AC-5 rewrite (defaulting to the #380 AC-1 invariant):

5. Given the search input has been pre-filled and edited, when the user picks a person, then the linked personId updates AND the displayed text remains exactly what the user originally typed (the #380 AC-1 "display text stays exactly as typed" invariant takes precedence over the search input's content).

This collapses the (a) / (b) branch into the single behaviour the recommend already nominates, and drops the Open Decision entirely — moving it to the AC list. If you ever do want (b) later, it becomes its own issue rather than a hidden branch in this one.

No edit to the issue body required from my side — flagging as a suggested one-line update before #628 enters refinement.

## AC-5 — promote Open Decision to explicit AC (Elicit on PR #629 #10962) Elicit flagged on PR #629 that AC-5 is currently a multi-branch sentence with the answer hidden in Open Decisions — which leaves the implementer staring at the same sticky-takeover ambiguity Felix raised in round 1. Suggested AC-5 rewrite (defaulting to the #380 AC-1 invariant): > **5. Given** the search input has been pre-filled and edited, **when** the user picks a person, **then** the linked `personId` updates AND the displayed text remains exactly what the user originally typed (the #380 AC-1 "display text stays exactly as typed" invariant takes precedence over the search input's content). This collapses the (a) / (b) branch into the single behaviour the recommend already nominates, and drops the Open Decision entirely — moving it to the AC list. If you ever do want (b) later, it becomes its own issue rather than a hidden branch in this one. No edit to the issue body required from my side — flagging as a suggested one-line update before #628 enters refinement.
Sign in to join this conversation.
No Label P2-medium feature ui
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: marcel/familienarchiv#628