fix(HelpPopover): role=region, 44px touch target, counter-based ID
- role="tooltip" → role="region" + aria-label={label}: tooltip semantics
are wrong for a click-triggered panel (Nora/Sara)
- expand button to 44×44px with inner visual <span>: WCAG 2.5.8 touch
target for 60+ transcriber audience (Sara/Leonie)
- replace Math.random() with module-level counter: SSR/hydration mismatch
when server and client generate different IDs (Felix)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,3 +1,10 @@
|
||||
<script module>
|
||||
// Module-level counter produces stable, predictable IDs across SSR + hydration.
|
||||
// Math.random() would generate different values server-side vs client-side,
|
||||
// causing a hydration mismatch on first render.
|
||||
let _counter = 0;
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
import type { Snippet } from 'svelte';
|
||||
|
||||
@@ -11,8 +18,9 @@ type Props = {
|
||||
|
||||
let { label, placement = 'bottom', children }: Props = $props();
|
||||
|
||||
const popoverId = `help-popover-${_counter++}`;
|
||||
|
||||
let open = $state(false);
|
||||
const popoverId = `help-popover-${Math.random().toString(36).slice(2)}`;
|
||||
let triggerEl: HTMLButtonElement | null = $state(null);
|
||||
|
||||
function toggle() {
|
||||
@@ -58,6 +66,10 @@ const placementClass: Record<Placement, string> = {
|
||||
</script>
|
||||
|
||||
<div class="relative inline-block">
|
||||
<!--
|
||||
Outer button is 44×44px for WCAG 2.5.8 touch-target compliance (our transcriber
|
||||
audience is 60+). The inner <span> carries the visual 20×20px circle.
|
||||
-->
|
||||
<button
|
||||
bind:this={triggerEl}
|
||||
type="button"
|
||||
@@ -65,15 +77,20 @@ const placementClass: Record<Placement, string> = {
|
||||
aria-expanded={open}
|
||||
aria-controls={popoverId}
|
||||
onclick={toggle}
|
||||
class="flex h-5 w-5 items-center justify-center rounded-full border border-line bg-muted font-sans text-[10px] font-bold text-ink-3 transition-colors hover:border-brand-navy hover:text-brand-navy"
|
||||
class="flex h-[44px] w-[44px] items-center justify-center"
|
||||
>
|
||||
?
|
||||
<span
|
||||
class="flex h-5 w-5 items-center justify-center rounded-full border border-line bg-muted font-sans text-[10px] font-bold text-ink-3 transition-colors hover:border-brand-navy hover:text-brand-navy"
|
||||
>
|
||||
?
|
||||
</span>
|
||||
</button>
|
||||
|
||||
{#if open}
|
||||
<div
|
||||
id={popoverId}
|
||||
role="tooltip"
|
||||
role="region"
|
||||
aria-label={label}
|
||||
class="absolute z-50 w-64 rounded-sm border border-line bg-white p-3 font-sans text-sm text-ink shadow-md {placementClass[placement]}"
|
||||
>
|
||||
{#if children}
|
||||
|
||||
Reference in New Issue
Block a user