- Replace one-shot $derived(.matches) snapshot with $state + addEventListener so the static/animated branch reacts when the user toggles OS reduced-motion at runtime (Felix: non-reactive media query) - Replace bg-[#FAF8F1] raw hex with bg-parchment design token so the SVG background remaps correctly in dark mode (Felix/Markus) Also update TranscriptionPanelHeader.svelte.test.ts to expect role="region" after the HelpPopover ARIA fix. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
218 lines
5.6 KiB
Svelte
218 lines
5.6 KiB
Svelte
<script lang="ts">
|
|
// $derived from .matches is a one-shot snapshot — it doesn't react when the
|
|
// user toggles the OS setting at runtime. Use $state + addEventListener instead.
|
|
let prefersReducedMotion = $state(
|
|
typeof window !== 'undefined' && window.matchMedia('(prefers-reduced-motion: reduce)').matches
|
|
);
|
|
|
|
$effect(() => {
|
|
if (typeof window === 'undefined') return;
|
|
const mql = window.matchMedia('(prefers-reduced-motion: reduce)');
|
|
const handler = (e: MediaQueryListEvent) => {
|
|
prefersReducedMotion = e.matches;
|
|
};
|
|
mql.addEventListener('change', handler);
|
|
return () => mql.removeEventListener('change', handler);
|
|
});
|
|
</script>
|
|
|
|
{#if prefersReducedMotion}
|
|
<!-- Static final frame for reduced-motion users -->
|
|
<svg
|
|
role="img"
|
|
aria-label="Eine gestrichelte Umrandung markiert eine Zeile Kurrentschrift auf dem Dokument."
|
|
viewBox="0 0 600 180"
|
|
class="border-brand-sand block w-full rounded-sm border bg-parchment"
|
|
>
|
|
<g
|
|
stroke="#2a2a2a"
|
|
stroke-width="1.6"
|
|
fill="none"
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
>
|
|
<path d="M 70 100 q 4 -25 10 -8 q 6 22 14 -2 q 4 -20 10 -3 q 6 22 12 -6 q 4 -18 10 2" />
|
|
<path d="M 145 100 q 5 -28 14 -2 q 5 -20 12 -4 q 6 22 14 -6 q 4 -15 10 4" />
|
|
<path d="M 230 100 q 6 -26 14 -2 q 5 -22 12 1 q 5 25 14 -5 q 4 -18 10 3 q 5 -20 10 1" />
|
|
<path d="M 340 100 q 5 -30 12 -4 q 6 -18 14 5 q 5 -24 12 0 q 6 24 14 -10" />
|
|
<path d="M 440 100 q 6 -28 14 0 q 5 -22 12 -4 q 6 24 14 -1 q 4 -18 10 2" />
|
|
</g>
|
|
<line
|
|
x1="60"
|
|
y1="120"
|
|
x2="540"
|
|
y2="120"
|
|
stroke="#D4D1C4"
|
|
stroke-width="0.8"
|
|
stroke-dasharray="2 3"
|
|
/>
|
|
<rect
|
|
x="55"
|
|
y="68"
|
|
width="470"
|
|
height="57"
|
|
fill="rgba(166, 218, 216, 0.12)"
|
|
stroke="#002850"
|
|
stroke-width="2.2"
|
|
/>
|
|
<g transform="translate(515, 58)">
|
|
<circle cx="0" cy="0" r="9" fill="#002850" />
|
|
<path
|
|
d="M -4 0 L -1 3 L 4 -3"
|
|
stroke="white"
|
|
stroke-width="2"
|
|
fill="none"
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
/>
|
|
</g>
|
|
</svg>
|
|
{:else}
|
|
<!-- Animated 5-second drawing loop -->
|
|
<svg
|
|
role="img"
|
|
aria-label="Animation: Ein Cursor zieht einen gestrichelten Rahmen um eine Zeile Kurrentschrift. Beim Loslassen wird der Rahmen durchgehend und ein Häkchen erscheint."
|
|
viewBox="0 0 600 180"
|
|
class="border-brand-sand block w-full rounded-sm border bg-parchment"
|
|
>
|
|
<!-- Kurrent writing (static) -->
|
|
<g
|
|
stroke="#2a2a2a"
|
|
stroke-width="1.6"
|
|
fill="none"
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
>
|
|
<path d="M 70 100 q 4 -25 10 -8 q 6 22 14 -2 q 4 -20 10 -3 q 6 22 12 -6 q 4 -18 10 2" />
|
|
<path d="M 145 100 q 5 -28 14 -2 q 5 -20 12 -4 q 6 22 14 -6 q 4 -15 10 4" />
|
|
<path d="M 230 100 q 6 -26 14 -2 q 5 -22 12 1 q 5 25 14 -5 q 4 -18 10 3 q 5 -20 10 1" />
|
|
<path d="M 340 100 q 5 -30 12 -4 q 6 -18 14 5 q 5 -24 12 0 q 6 24 14 -10" />
|
|
<path d="M 440 100 q 6 -28 14 0 q 5 -22 12 -4 q 6 24 14 -1 q 4 -18 10 2" />
|
|
</g>
|
|
<line
|
|
x1="60"
|
|
y1="120"
|
|
x2="540"
|
|
y2="120"
|
|
stroke="#D4D1C4"
|
|
stroke-width="0.8"
|
|
stroke-dasharray="2 3"
|
|
/>
|
|
|
|
<!-- Click ripple -->
|
|
<circle cx="55" cy="68" r="0" fill="none" stroke="#A6DAD8" stroke-width="2.5" opacity="0">
|
|
<animate
|
|
attributeName="r"
|
|
values="0;0;4;18;0;0"
|
|
keyTimes="0;0.17;0.19;0.24;0.26;1"
|
|
dur="5s"
|
|
repeatCount="indefinite"
|
|
/>
|
|
<animate
|
|
attributeName="opacity"
|
|
values="0;0;1;0;0;0"
|
|
keyTimes="0;0.17;0.19;0.24;0.26;1"
|
|
dur="5s"
|
|
repeatCount="indefinite"
|
|
/>
|
|
</circle>
|
|
|
|
<!-- Growing selection rectangle -->
|
|
<rect
|
|
x="55"
|
|
y="68"
|
|
width="0"
|
|
height="0"
|
|
fill="rgba(166, 218, 216, 0.12)"
|
|
stroke="#002850"
|
|
stroke-width="2"
|
|
stroke-dasharray="5 4"
|
|
opacity="0"
|
|
>
|
|
<animate
|
|
attributeName="opacity"
|
|
values="0;0;1;1;1;1;0;0"
|
|
keyTimes="0;0.18;0.20;0.88;0.92;0.94;0.98;1"
|
|
dur="5s"
|
|
repeatCount="indefinite"
|
|
/>
|
|
<animate
|
|
attributeName="width"
|
|
values="0;0;470;470;470;470;0"
|
|
keyTimes="0;0.20;0.62;0.88;0.94;0.98;1"
|
|
dur="5s"
|
|
repeatCount="indefinite"
|
|
/>
|
|
<animate
|
|
attributeName="height"
|
|
values="0;0;57;57;57;57;0"
|
|
keyTimes="0;0.20;0.62;0.88;0.94;0.98;1"
|
|
dur="5s"
|
|
repeatCount="indefinite"
|
|
/>
|
|
<animate
|
|
attributeName="stroke-dasharray"
|
|
values="5 4;5 4;5 4;1 0;1 0;5 4"
|
|
keyTimes="0;0.60;0.64;0.68;0.94;1"
|
|
dur="5s"
|
|
repeatCount="indefinite"
|
|
/>
|
|
<animate
|
|
attributeName="stroke-width"
|
|
values="2;2;2;3.2;2.2;2;2"
|
|
keyTimes="0;0.64;0.66;0.68;0.72;0.90;1"
|
|
dur="5s"
|
|
repeatCount="indefinite"
|
|
/>
|
|
</rect>
|
|
|
|
<!-- Confirmation checkmark badge -->
|
|
<g opacity="0" transform="translate(515, 58)">
|
|
<circle cx="0" cy="0" r="9" fill="#002850" />
|
|
<path
|
|
d="M -4 0 L -1 3 L 4 -3"
|
|
stroke="white"
|
|
stroke-width="2"
|
|
fill="none"
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
/>
|
|
<animate
|
|
attributeName="opacity"
|
|
values="0;0;1;1;0;0"
|
|
keyTimes="0;0.66;0.70;0.86;0.92;1"
|
|
dur="5s"
|
|
repeatCount="indefinite"
|
|
/>
|
|
</g>
|
|
|
|
<!-- Cursor arrow -->
|
|
<g>
|
|
<animateTransform
|
|
attributeName="transform"
|
|
type="translate"
|
|
values="15,20; 55,68; 55,68; 525,125; 525,125; 15,20"
|
|
keyTimes="0; 0.15; 0.20; 0.62; 0.92; 1"
|
|
calcMode="spline"
|
|
keySplines="0.4 0 0.2 1; 0 0 1 1; 0.4 0 0.2 1; 0 0 1 1; 0.4 0 0.2 1"
|
|
dur="5s"
|
|
repeatCount="indefinite"
|
|
/>
|
|
<animate
|
|
attributeName="opacity"
|
|
values="1;1;1;0;0;1"
|
|
keyTimes="0;0.92;0.94;0.96;0.99;1"
|
|
dur="5s"
|
|
repeatCount="indefinite"
|
|
/>
|
|
<path
|
|
d="M 0 0 L 0 16 L 4.5 12 L 7.5 18 L 10.5 16.6 L 7.8 10.6 L 13 9 Z"
|
|
fill="#002850"
|
|
stroke="white"
|
|
stroke-width="0.8"
|
|
stroke-linejoin="round"
|
|
/>
|
|
</g>
|
|
</svg>
|
|
{/if}
|