fix(a11y): announce HistoryPage inline-confirm armed state and tag-chip pressed state
This commit is contained in:
@@ -95,6 +95,18 @@
|
|||||||
if (bulkDeleteArmTimer) { clearTimeout(bulkDeleteArmTimer); bulkDeleteArmTimer = null; }
|
if (bulkDeleteArmTimer) { clearTimeout(bulkDeleteArmTimer); bulkDeleteArmTimer = null; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Screen-reader announcement for the inline-confirm flows. The button
|
||||||
|
// morphs into Confirm/Cancel pills, which is silent to assistive tech;
|
||||||
|
// this derived feeds an aria-live region near the page root so the
|
||||||
|
// armed state is announced as it arms and disarms.
|
||||||
|
let confirmAnnouncement = $derived(
|
||||||
|
clearAllArmed
|
||||||
|
? "Clear all armed. Click confirm to delete all history, or cancel to dismiss."
|
||||||
|
: bulkDeleteArmed
|
||||||
|
? `Delete ${selected.size} ${selected.size === 1 ? 'transcript' : 'transcripts'} armed. Click confirm or cancel to dismiss.`
|
||||||
|
: ""
|
||||||
|
);
|
||||||
|
|
||||||
onDestroy(() => {
|
onDestroy(() => {
|
||||||
stopPlayback();
|
stopPlayback();
|
||||||
if (clearAllArmTimer) clearTimeout(clearAllArmTimer);
|
if (clearAllArmTimer) clearTimeout(clearAllArmTimer);
|
||||||
@@ -569,6 +581,15 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="flex flex-col h-full overflow-y-auto animate-fade-in">
|
<div class="flex flex-col h-full overflow-y-auto animate-fade-in">
|
||||||
|
<!-- Off-screen live region for inline-confirm announcements. Sits at
|
||||||
|
the page root so it persists while the morphed Confirm/Cancel
|
||||||
|
pills mount and unmount in the header and bulk toolbar. -->
|
||||||
|
<div
|
||||||
|
class="sr-only"
|
||||||
|
aria-live="polite"
|
||||||
|
aria-atomic="true"
|
||||||
|
>{confirmAnnouncement}</div>
|
||||||
|
|
||||||
<!-- Header -->
|
<!-- Header -->
|
||||||
<div class="flex items-center gap-4 px-7 pt-6 pb-4">
|
<div class="flex items-center gap-4 px-7 pt-6 pb-4">
|
||||||
<h2 class="font-display text-[26px] italic text-text">History</h2>
|
<h2 class="font-display text-[26px] italic text-text">History</h2>
|
||||||
@@ -647,6 +668,7 @@
|
|||||||
<button
|
<button
|
||||||
class="inline-flex items-center gap-1 px-2 py-0.5 rounded-full border border-accent text-[12px] text-accent bg-accent/10"
|
class="inline-flex items-center gap-1 px-2 py-0.5 rounded-full border border-accent text-[12px] text-accent bg-accent/10"
|
||||||
onclick={() => (activeTagFilter = null)}
|
onclick={() => (activeTagFilter = null)}
|
||||||
|
aria-pressed="true"
|
||||||
title="Clear tag filter"
|
title="Clear tag filter"
|
||||||
>
|
>
|
||||||
{activeTagFilter}
|
{activeTagFilter}
|
||||||
@@ -657,6 +679,7 @@
|
|||||||
<button
|
<button
|
||||||
class="inline-flex items-center gap-1 px-2 py-0.5 rounded-full border border-border-subtle text-[12px] text-text-secondary hover:border-accent hover:text-accent"
|
class="inline-flex items-center gap-1 px-2 py-0.5 rounded-full border border-border-subtle text-[12px] text-text-secondary hover:border-accent hover:text-accent"
|
||||||
onclick={() => (activeTagFilter = t.tag)}
|
onclick={() => (activeTagFilter = t.tag)}
|
||||||
|
aria-pressed={activeTagFilter === t.tag}
|
||||||
>
|
>
|
||||||
{t.tag}
|
{t.tag}
|
||||||
<span class="text-[12px] text-text-secondary">{t.count}</span>
|
<span class="text-[12px] text-text-secondary">{t.count}</span>
|
||||||
|
|||||||
Reference in New Issue
Block a user