️ fix: resolve all svelte-check a11y warnings across web apps

- Fix 121 accessibility warnings across 9 web apps (manacore, clock, chat,
  manadeck, calendar, zitare, contacts, picture, todo)
- Add proper ARIA attributes (role, tabindex, aria-label) to interactive elements
- Add onkeydown handlers alongside onclick for keyboard accessibility
- Add svelte-ignore comments for intentional patterns (modals, dropdowns)
- Update svelte-check threshold from error to warning in pre-commit hook
- Fix script compatibility for bash 3.x (remove associative arrays)
- Add comprehensive documentation for svelte-check patterns and fixes

All web apps now pass svelte-check with 0 errors and 0 warnings.
Pre-commit hooks will block any future commits with warnings.
This commit is contained in:
Wuesteon 2025-12-15 19:09:01 +01:00
parent b949037fa5
commit 42e5e97390
101 changed files with 1048 additions and 558 deletions

View file

@ -1,7 +1,14 @@
<script lang="ts">
import type { Snippet } from 'svelte';
type ButtonVariant = 'primary' | 'secondary' | 'ghost' | 'danger' | 'outline' | 'success';
type ButtonVariant =
| 'primary'
| 'secondary'
| 'ghost'
| 'danger'
| 'destructive'
| 'outline'
| 'success';
type ButtonSize = 'sm' | 'md' | 'lg' | 'xl';
interface Props {
@ -31,6 +38,7 @@
secondary: 'bg-menu text-theme hover:bg-menu-hover border-theme',
ghost: 'bg-transparent text-theme hover:bg-menu-hover border-transparent',
danger: 'bg-red-600 text-white hover:bg-red-700 border-transparent',
destructive: 'bg-red-600 text-white hover:bg-red-700 border-transparent',
outline: 'bg-transparent text-primary border-primary hover:bg-primary/10',
success: 'bg-green-600 text-white hover:bg-green-700 border-transparent',
};

View file

@ -86,7 +86,6 @@
{#if visible}
<!-- Backdrop to block clicks on elements behind -->
<!-- svelte-ignore a11y_no_static_element_interactions -->
<div
class="context-menu-backdrop"
onpointerdown={(e) => {
@ -104,9 +103,17 @@
e.stopPropagation();
onClose();
}}
onkeydown={(e) => {
if (e.key === 'Escape' || e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
e.stopPropagation();
onClose();
}
}}
role="presentation"
aria-hidden="true"
></div>
<!-- svelte-ignore a11y_no_noninteractive_element_interactions -->
<div
bind:this={menuElement}
class="context-menu"

View file

@ -217,8 +217,20 @@
<svelte:window onkeydown={handleKeydown} onclick={handleClickOutside} />
<!-- Trigger wrapper -->
<!-- svelte-ignore a11y_click_events_have_key_events a11y_no_static_element_interactions -->
<div class="confirmation-popover-trigger" bind:this={triggerRef} onclick={handleTriggerClick}>
<div
class="confirmation-popover-trigger"
bind:this={triggerRef}
onclick={handleTriggerClick}
onkeydown={(e) => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
handleTriggerClick(e as unknown as MouseEvent);
}
}}
role="button"
tabindex="0"
aria-expanded={visible}
>
{@render children()}
</div>

View file

@ -16,6 +16,8 @@
class?: string;
id?: string;
name?: string;
minlength?: number;
maxlength?: number;
}
let {
@ -33,6 +35,8 @@
class: className = '',
id = `input-${Math.random().toString(36).slice(2, 9)}`,
name,
minlength,
maxlength,
}: Props = $props();
function handleInput(e: Event) {
@ -65,6 +69,8 @@
{placeholder}
{disabled}
{required}
{minlength}
{maxlength}
autocomplete={autocomplete as HTMLInputAttributes['autocomplete']}
oninput={handleInput}
onchange={handleChange}

View file

@ -56,6 +56,7 @@
let showFilters = $state(false);
let showKeyboardHelp = $state(false);
let strengthValue = $state(minStrength);
// svelte-ignore non_reactive_update - Element reference doesn't need reactivity
let searchInputElement: HTMLInputElement;
// Sync searchInput with external searchQuery