a11y(transcription): announce @mention empty state via aria-live

Collapse the two empty-state branches into a single p[aria-live=polite]
whose text derives from the search query. Screen readers now hear the
transition between "Namen eingeben…" and "Keine Personen gefunden".
Leonie FINDING-MENTION-002 on PR #629.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Marcel
2026-05-19 22:20:16 +02:00
committed by marcel
parent 1c94a43cb5
commit a47027d67a
2 changed files with 20 additions and 9 deletions

View File

@@ -178,15 +178,16 @@ function selectItem(item: Person) {
</div> </div>
</div> </div>
{#if model.items.length === 0} {#if model.items.length === 0}
{#if searchQuery.trim() === ''} <!--
<p class="px-3 py-2.5 font-sans text-sm text-ink-3"> Single live region so screen readers announce the transition between
{m.person_mention_search_prompt()} "Namen eingeben…" (empty search) and "Keine Personen gefunden"
</p> (searched but empty). Leonie FINDING-MENTION-002 on PR #629.
{:else} -->
<p class="px-3 py-2.5 font-sans text-sm text-ink-3"> <p class="px-3 py-2.5 font-sans text-sm text-ink-3" aria-live="polite">
{m.person_mention_popup_empty()} {searchQuery.trim() === ''
</p> ? m.person_mention_search_prompt()
{/if} : m.person_mention_popup_empty()}
</p>
<!-- <!--
Empty-state escape hatch — without it the transcriber has to close Empty-state escape hatch — without it the transcriber has to close
the dropdown, navigate to /persons/new, come back, and re-type the the dropdown, navigate to /persons/new, come back, and re-type the

View File

@@ -154,6 +154,16 @@ describe('MentionDropdown — search input', () => {
expect(input.className).toContain('min-h-[44px]'); expect(input.className).toContain('min-h-[44px]');
}); });
it('announces empty-state copy via aria-live="polite" (Leonie FINDING-MENTION-002 on PR #629)', async () => {
render(MentionDropdown, { props: { model: baseModel() } });
const listbox = document.querySelector('[role="listbox"]');
expect(listbox).not.toBeNull();
const live = listbox!.querySelector('p[aria-live="polite"]');
expect(live).not.toBeNull();
expect(live!.textContent ?? '').toContain(m.person_mention_search_prompt());
});
it('renders the magnifier icon at h-5 w-5 with text-ink-2 (Leonie BLOCKER on PR #629)', async () => { it('renders the magnifier icon at h-5 w-5 with text-ink-2 (Leonie BLOCKER on PR #629)', async () => {
render(MentionDropdown, { props: { model: baseModel() } }); render(MentionDropdown, { props: { model: baseModel() } });