feat(transcribe): add HelpPopover primitive and wire (?) chip into panel header

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Marcel
2026-04-24 21:19:48 +02:00
parent 7fb9d74515
commit 7c3a8e7651
4 changed files with 221 additions and 23 deletions

View File

@@ -0,0 +1,84 @@
<script lang="ts">
import type { Snippet } from 'svelte';
type Placement = 'bottom' | 'top' | 'left' | 'right';
type Props = {
label: string;
placement?: Placement;
children?: Snippet;
};
let { label, placement = 'bottom', children }: Props = $props();
let open = $state(false);
const popoverId = `help-popover-${Math.random().toString(36).slice(2)}`;
let triggerEl: HTMLButtonElement | null = $state(null);
function toggle() {
open = !open;
}
function close() {
open = false;
triggerEl?.focus();
}
$effect(() => {
if (!open) return;
function onKeyDown(e: KeyboardEvent) {
if (e.key === 'Escape') {
e.preventDefault();
close();
}
}
function onPointerDown(e: PointerEvent) {
if (triggerEl && (e.target === triggerEl || triggerEl.contains(e.target as Node))) return;
const popoverEl = document.getElementById(popoverId);
if (popoverEl && popoverEl.contains(e.target as Node)) return;
open = false;
}
document.addEventListener('keydown', onKeyDown);
document.addEventListener('pointerdown', onPointerDown);
return () => {
document.removeEventListener('keydown', onKeyDown);
document.removeEventListener('pointerdown', onPointerDown);
};
});
const placementClass: Record<Placement, string> = {
bottom: 'top-full mt-1.5 left-1/2 -translate-x-1/2',
top: 'bottom-full mb-1.5 left-1/2 -translate-x-1/2',
left: 'right-full mr-1.5 top-1/2 -translate-y-1/2',
right: 'left-full ml-1.5 top-1/2 -translate-y-1/2'
};
</script>
<div class="relative inline-block">
<button
bind:this={triggerEl}
type="button"
aria-label={label}
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"
>
?
</button>
{#if open}
<div
id={popoverId}
role="tooltip"
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}
{@render children()}
{/if}
</div>
{/if}
</div>