From b3fe9b1171b6134f077da4692ae0a4899b52e437 Mon Sep 17 00:00:00 2001 From: Marcel Date: Wed, 29 Apr 2026 21:29:49 +0200 Subject: [PATCH] refactor(PersonMentionEditor): use data-editor-inner attribute for stable querySelector Co-Authored-By: Claude Sonnet 4.6 --- frontend/src/lib/components/PersonMentionEditor.svelte | 6 ++++-- .../src/lib/components/PersonMentionEditor.svelte.spec.ts | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/frontend/src/lib/components/PersonMentionEditor.svelte b/frontend/src/lib/components/PersonMentionEditor.svelte index 58a2e9c6..aa2643b4 100644 --- a/frontend/src/lib/components/PersonMentionEditor.svelte +++ b/frontend/src/lib/components/PersonMentionEditor.svelte @@ -225,6 +225,7 @@ onMount(() => { role: 'textbox', 'aria-multiline': 'true', 'aria-label': m.transcription_editor_aria_label(), + 'data-editor-inner': '', class: [ 'min-h-[120px] px-1 py-2.5', 'font-serif text-base leading-relaxed text-ink', @@ -259,8 +260,9 @@ onDestroy(() => { // placeholder CSS only fires when there is no content (not just on blur). $effect(() => { if (!editor || !placeholder) return; - void value; // track value as dependency so this re-runs on content changes - const inner = editorEl?.querySelector('.tiptap-editor-inner') as HTMLElement | null; + void value; // Tiptap's onUpdate always fires on content change, but $effect needs a + // reactive read to re-run — void value registers value as a dependency without using it. + const inner = editorEl?.querySelector('[data-editor-inner]') as HTMLElement | null; if (!inner) return; if (editor.isEmpty) { inner.setAttribute('data-placeholder', placeholder); diff --git a/frontend/src/lib/components/PersonMentionEditor.svelte.spec.ts b/frontend/src/lib/components/PersonMentionEditor.svelte.spec.ts index 8d35cb99..15f04f7d 100644 --- a/frontend/src/lib/components/PersonMentionEditor.svelte.spec.ts +++ b/frontend/src/lib/components/PersonMentionEditor.svelte.spec.ts @@ -374,7 +374,7 @@ describe('PersonMentionEditor — placeholder behavior', () => { onChange: () => {} }); await vi.waitFor(() => { - const inner = document.querySelector('.tiptap-editor-inner') as HTMLElement | null; + const inner = document.querySelector('[data-editor-inner]') as HTMLElement | null; expect(inner).not.toBeNull(); expect(inner!.getAttribute('data-placeholder')).toBe('Gib Text ein...'); }); @@ -388,7 +388,7 @@ describe('PersonMentionEditor — placeholder behavior', () => { onChange: () => {} }); await vi.waitFor(() => { - const inner = document.querySelector('.tiptap-editor-inner') as HTMLElement | null; + const inner = document.querySelector('[data-editor-inner]') as HTMLElement | null; expect(inner).not.toBeNull(); expect(inner!.hasAttribute('data-placeholder')).toBe(false); });