diff --git a/.changeset/many-spoons-enjoy.md b/.changeset/many-spoons-enjoy.md new file mode 100644 index 000000000000..bf3eec6f0415 --- /dev/null +++ b/.changeset/many-spoons-enjoy.md @@ -0,0 +1,5 @@ +--- +'create-svelte': patch +--- + +fix: improve Sverdle a11y diff --git a/packages/create-svelte/templates/default/src/routes/styles.css b/packages/create-svelte/templates/default/src/routes/styles.css index 812d76cecc99..1441d9408f3a 100644 --- a/packages/create-svelte/templates/default/src/routes/styles.css +++ b/packages/create-svelte/templates/default/src/routes/styles.css @@ -8,7 +8,7 @@ --color-bg-1: hsl(209, 36%, 86%); --color-bg-2: hsl(224, 44%, 95%); --color-theme-1: #ff3e00; - --color-theme-2: #40b3ff; + --color-theme-2: #4075a6; --color-text: rgba(0, 0, 0, 0.7); --column-width: 42rem; --column-margin-top: 4rem; @@ -93,3 +93,15 @@ button:focus:not(:focus-visible) { font-size: 2.4rem; } } + +.visually-hidden { + border: 0; + clip: rect(0 0 0 0); + height: auto; + margin: 0; + overflow: hidden; + padding: 0; + position: absolute; + width: 1px; + white-space: nowrap; +} diff --git a/packages/create-svelte/templates/default/src/routes/sverdle/+page.svelte b/packages/create-svelte/templates/default/src/routes/sverdle/+page.svelte index 3953a2e3d722..feebe4bc89d7 100644 --- a/packages/create-svelte/templates/default/src/routes/sverdle/+page.svelte +++ b/packages/create-svelte/templates/default/src/routes/sverdle/+page.svelte @@ -2,6 +2,7 @@ import { confetti } from '@neoconfetti/svelte'; import { enhance } from '$app/forms'; import type { PageData, ActionData } from './$types'; + import { reduced_motion } from './reduced-motion'; /** @type {import('./$types').PageData} */ export let data: PageData; @@ -25,8 +26,16 @@ */ let classnames: Record; + /** + * A map of descriptions for all letters that have been guessed, + * used for adding text for assistive technology (e.g. screen readers) + * @type {Record} + */ + let description: Record; + $: { classnames = {}; + description = {}; data.answers.forEach((answer, i) => { const guess = data.guesses[i]; @@ -36,8 +45,10 @@ if (answer[i] === 'x') { classnames[letter] = 'exact'; + description[letter] = 'correct'; } else if (!classnames[letter]) { classnames[letter] = answer[i] === 'c' ? 'close' : 'missing'; + description[letter] = answer[i] === 'c' ? 'present' : 'absent'; } } }); @@ -83,6 +94,8 @@ +

Sverdle

+
{#each Array(6) as _, row} {@const current = row === i} - +

Row {row + 1}

{#each Array(5) as _, column} {@const answer = data.answers[row]?.[column]} - - + {@const value = data.guesses[row]?.[column] ?? ''} + {@const selected = current && column === data.guesses[row].length} + {@const exact = answer === 'x'} + {@const close = answer === 'c'} + {@const missing = answer === '_'} +
+ {value} + + {#if exact} + (correct) + {:else if close} + (present) + {:else if missing} + (absent) + {:else} + empty + {/if} + + +
{/each}
{/each} @@ -122,12 +145,12 @@ {#if !won && data.answer}

the answer was "{data.answer}"

{/if} - {:else}
- + @@ -165,6 +189,7 @@
{ + if (!browser) return false; + return window.matchMedia(reduced_motion_query).matches; +}; + +export const reduced_motion = readable(get_initial_motion_preference(), (set) => { + if (browser) { + /** + * @param {MediaQueryListEvent} event + */ + const set_reduced_motion = (event: MediaQueryListEvent) => { + set(event.matches); + }; + const media_query_list = window.matchMedia(reduced_motion_query); + media_query_list.addEventListener('change', set_reduced_motion); + + return () => { + media_query_list.removeEventListener('change', set_reduced_motion); + }; + } +});