fix(stammbaum): SVG node font 14→16px and reliable keyboard focus ring

CSS box-shadow rings (focus-visible:ring-*) are invisible inside SVG.
Replace with a conditional <rect> drawn at -3px offset that renders in
all browsers. Name font-size bumped from 14 to 16px for the 60+
transcriber audience (WCAG readability, Leonie medium concerns).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Marcel
2026-04-28 13:01:58 +02:00
committed by marcel
parent ea97bdd869
commit 93f4a00032

View File

@@ -286,6 +286,8 @@ function nodeCenter(id: string): { x: number; y: number } | null {
return { x: p.x + NODE_W / 2, y: p.y + NODE_H / 2 }; return { x: p.x + NODE_W / 2, y: p.y + NODE_H / 2 };
} }
let focusedId = $state<string | null>(null);
function handleNodeKey(event: KeyboardEvent, id: string) { function handleNodeKey(event: KeyboardEvent, id: string) {
if (event.key === 'Enter' || event.key === ' ') { if (event.key === 'Enter' || event.key === ' ') {
event.preventDefault(); event.preventDefault();
@@ -479,6 +481,7 @@ const parentLinks = $derived.by<ParentLinks>(() => {
{@const pos = layout.positions.get(node.id)} {@const pos = layout.positions.get(node.id)}
{#if pos} {#if pos}
{@const isSelected = selectedId === node.id} {@const isSelected = selectedId === node.id}
{@const isFocused = focusedId === node.id}
<g <g
role="button" role="button"
tabindex="0" tabindex="0"
@@ -489,8 +492,22 @@ const parentLinks = $derived.by<ParentLinks>(() => {
transform="translate({pos.x}, {pos.y})" transform="translate({pos.x}, {pos.y})"
onclick={() => onSelect(node.id)} onclick={() => onSelect(node.id)}
onkeydown={(e) => handleNodeKey(e, node.id)} onkeydown={(e) => handleNodeKey(e, node.id)}
class="cursor-pointer focus:outline-none focus-visible:ring-2 focus-visible:ring-primary" onfocus={() => (focusedId = node.id)}
onblur={() => (focusedId = null)}
class="cursor-pointer focus:outline-none"
> >
{#if isFocused}
<rect
x="-3"
y="-3"
width={NODE_W + 6}
height={NODE_H + 6}
rx="6"
fill="none"
stroke="var(--c-focus-ring)"
stroke-width="2"
/>
{/if}
<rect <rect
width={NODE_W} width={NODE_W}
height={NODE_H} height={NODE_H}
@@ -504,10 +521,10 @@ const parentLinks = $derived.by<ParentLinks>(() => {
{/if} {/if}
<text <text
x={NODE_W / 2} x={NODE_W / 2}
y={NODE_H / 2 - 4} y={NODE_H / 2 - 6}
text-anchor="middle" text-anchor="middle"
font-family="serif" font-family="serif"
font-size="14" font-size="16"
fill={isSelected ? 'var(--c-primary-fg)' : 'var(--c-ink)'} fill={isSelected ? 'var(--c-primary-fg)' : 'var(--c-ink)'}
> >
{node.displayName} {node.displayName}