From 423aedcd8753efe0a413937213eecb6ae93cd96a Mon Sep 17 00:00:00 2001 From: Marcel Date: Sat, 13 Jun 2026 22:38:00 +0200 Subject: [PATCH] fix(a11y): 44px remove targets + empty states on person/document pickers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Both PersonMultiSelect and DocumentMultiSelect remove buttons were ~12px tap targets (below the 44px WCAG minimum) — pad them to min-h/min-w 44px with a focus-visible ring (SVG stays 12px). Add an optional emptyLabel slot inside the chip container and a hiddenInputName prop on PersonMultiSelect (mirroring DocumentMultiSelect) so EventForm can wire personIds without touching WhoWhenSection. Document the intentional bare typeahead fetch in documentTypeahead.ts (same-origin in prod, Vite-proxied in dev). Refs #781 Co-Authored-By: Claude Opus 4.8 --- .../lib/document/DocumentMultiSelect.svelte | 11 +++++++++-- frontend/src/lib/document/documentTypeahead.ts | 4 ++++ .../src/lib/person/PersonMultiSelect.svelte | 18 +++++++++++++++--- 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/frontend/src/lib/document/DocumentMultiSelect.svelte b/frontend/src/lib/document/DocumentMultiSelect.svelte index c95b9cff..6bf8ed02 100644 --- a/frontend/src/lib/document/DocumentMultiSelect.svelte +++ b/frontend/src/lib/document/DocumentMultiSelect.svelte @@ -11,12 +11,15 @@ interface Props { selectedDocuments?: DocumentOption[]; placeholder?: string; hiddenInputName?: string; + /** Empty-state text shown inside the chip container when nothing is selected. */ + emptyLabel?: string; } let { selectedDocuments = $bindable([]), placeholder = m.geschichte_editor_search_document(), - hiddenInputName = 'documentIds' + hiddenInputName = 'documentIds', + emptyLabel = undefined }: Props = $props(); let searchTerm = $state(''); @@ -73,7 +76,7 @@ function removeDocument(id: string | undefined) {