mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-22 20:26:42 +02:00
♿️ 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:
parent
b949037fa5
commit
42e5e97390
101 changed files with 1048 additions and 558 deletions
|
|
@ -94,11 +94,11 @@
|
|||
}
|
||||
</script>
|
||||
|
||||
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
||||
<header
|
||||
class="calendar-header"
|
||||
class:compact={settingsStore.headerCompact}
|
||||
oncontextmenu={handleContextMenu}
|
||||
role="banner"
|
||||
>
|
||||
<h1 class="header-title">{title}</h1>
|
||||
</header>
|
||||
|
|
|
|||
|
|
@ -19,13 +19,19 @@
|
|||
// View type labels
|
||||
const viewLabels: Record<CalendarViewType, string> = {
|
||||
day: 'Tag',
|
||||
'3day': '3 Tage',
|
||||
'5day': '5 Tage',
|
||||
week: 'Woche',
|
||||
'10day': '10 Tage',
|
||||
'14day': '14 Tage',
|
||||
'30day': '30 Tage',
|
||||
'60day': '60 Tage',
|
||||
'90day': '90 Tage',
|
||||
'365day': '365 Tage',
|
||||
month: 'Monat',
|
||||
year: 'Jahr',
|
||||
agenda: 'Agenda',
|
||||
custom: 'Benutzerdefiniert',
|
||||
};
|
||||
|
||||
// Views to show in selector
|
||||
|
|
|
|||
|
|
@ -421,6 +421,7 @@
|
|||
<div class="edit-form">
|
||||
<div class="form-row">
|
||||
<div class="color-preview" style="background-color: {newTagColor}"></div>
|
||||
<!-- svelte-ignore a11y_autofocus -->
|
||||
<input
|
||||
type="text"
|
||||
bind:value={newTagName}
|
||||
|
|
@ -431,8 +432,8 @@
|
|||
/>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label class="form-label">Gruppe</label>
|
||||
<select bind:value={newTagGroupId} class="group-select">
|
||||
<label for="new-tag-group" class="form-label">Gruppe</label>
|
||||
<select id="new-tag-group" bind:value={newTagGroupId} class="group-select">
|
||||
<option value={null}>Keine Gruppe</option>
|
||||
{#each eventTagGroupsStore.groups as group (group.id)}
|
||||
<option value={group.id}>{group.name}</option>
|
||||
|
|
@ -471,6 +472,7 @@
|
|||
<div class="edit-form">
|
||||
<div class="form-row">
|
||||
<div class="color-preview" style="background-color: {editTagColor}"></div>
|
||||
<!-- svelte-ignore a11y_autofocus -->
|
||||
<input
|
||||
type="text"
|
||||
bind:value={editTagName}
|
||||
|
|
@ -481,8 +483,8 @@
|
|||
/>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label class="form-label">Gruppe</label>
|
||||
<select bind:value={editTagGroupId} class="group-select">
|
||||
<label for="edit-tag-group" class="form-label">Gruppe</label>
|
||||
<select id="edit-tag-group" bind:value={editTagGroupId} class="group-select">
|
||||
<option value={null}>Keine Gruppe</option>
|
||||
{#each eventTagGroupsStore.groups as group (group.id)}
|
||||
<option value={group.id}>{group.name}</option>
|
||||
|
|
@ -524,6 +526,7 @@
|
|||
<div class="edit-form">
|
||||
<div class="form-row">
|
||||
<div class="color-preview" style="background-color: {editGroupColor}"></div>
|
||||
<!-- svelte-ignore a11y_autofocus -->
|
||||
<input
|
||||
type="text"
|
||||
bind:value={editGroupName}
|
||||
|
|
@ -713,6 +716,7 @@
|
|||
<div class="new-group-form">
|
||||
<div class="form-row">
|
||||
<div class="color-preview" style="background-color: {newGroupColor}"></div>
|
||||
<!-- svelte-ignore a11y_autofocus -->
|
||||
<input
|
||||
type="text"
|
||||
bind:value={newGroupName}
|
||||
|
|
|
|||
|
|
@ -26,25 +26,37 @@
|
|||
// View labels (short versions for pill)
|
||||
const viewLabels: Record<CalendarViewType, string> = {
|
||||
day: '1',
|
||||
'3day': '3',
|
||||
'5day': '5',
|
||||
week: '7',
|
||||
'10day': '10',
|
||||
'14day': '14',
|
||||
'30day': '30',
|
||||
'60day': '60',
|
||||
'90day': '90',
|
||||
'365day': '365',
|
||||
month: 'M',
|
||||
year: 'Y',
|
||||
agenda: 'A',
|
||||
custom: '',
|
||||
};
|
||||
|
||||
// View titles for tooltip
|
||||
const viewTitles: Record<CalendarViewType, string> = {
|
||||
day: 'Tagesansicht',
|
||||
'3day': '3-Tage-Ansicht',
|
||||
'5day': '5-Tage-Ansicht',
|
||||
week: 'Wochenansicht',
|
||||
'10day': '10-Tage-Ansicht',
|
||||
'14day': '14-Tage-Ansicht',
|
||||
'30day': '30-Tage-Ansicht',
|
||||
'60day': '60-Tage-Ansicht',
|
||||
'90day': '90-Tage-Ansicht',
|
||||
'365day': '365-Tage-Ansicht',
|
||||
month: 'Monatsansicht',
|
||||
year: 'Jahresansicht',
|
||||
agenda: 'Agenda',
|
||||
custom: 'Benutzerdefiniert',
|
||||
};
|
||||
|
||||
// Get enabled views from settings
|
||||
|
|
|
|||
|
|
@ -183,9 +183,10 @@
|
|||
|
||||
{#if visible}
|
||||
<!-- Backdrop to block clicks on elements behind -->
|
||||
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
||||
<!-- svelte-ignore a11y_no_static_element_interactions a11y_click_events_have_key_events a11y_no_noninteractive_element_interactions -->
|
||||
<div
|
||||
class="context-menu-backdrop"
|
||||
role="presentation"
|
||||
onpointerdown={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
|
@ -384,6 +385,7 @@
|
|||
}
|
||||
.custom-input[type='number'] {
|
||||
-moz-appearance: textfield;
|
||||
appearance: textfield;
|
||||
}
|
||||
|
||||
.custom-unit {
|
||||
|
|
|
|||
|
|
@ -1230,12 +1230,6 @@
|
|||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.calendar-dot {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
/* Calendar pills */
|
||||
.calendar-pills-container {
|
||||
padding: 0.5rem 0;
|
||||
|
|
@ -1290,9 +1284,6 @@
|
|||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.calendar-pill-name {
|
||||
}
|
||||
|
||||
.row-content {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
|
|
|
|||
|
|
@ -77,8 +77,8 @@
|
|||
{#if groupTags.length > 0}
|
||||
<div class="group-section">
|
||||
<!-- Group Header -->
|
||||
<button type="button" onclick={() => toggleGroup(group.id)} class="group-header">
|
||||
<div class="flex items-center gap-2">
|
||||
<div class="group-header">
|
||||
<button type="button" onclick={() => toggleGroup(group.id)} class="group-toggle">
|
||||
{#if isExpanded(group.id)}
|
||||
<CaretDown size={16} weight="bold" class="text-muted-foreground" />
|
||||
{:else}
|
||||
|
|
@ -90,21 +90,18 @@
|
|||
></div>
|
||||
<span class="font-medium">{group.name}</span>
|
||||
<span class="text-xs text-muted-foreground">({groupTags.length})</span>
|
||||
</div>
|
||||
</button>
|
||||
{#if onEditGroup}
|
||||
<button
|
||||
type="button"
|
||||
onclick={(e) => {
|
||||
e.stopPropagation();
|
||||
onEditGroup(group);
|
||||
}}
|
||||
onclick={() => onEditGroup(group)}
|
||||
class="edit-group-btn"
|
||||
aria-label="Gruppe bearbeiten"
|
||||
>
|
||||
<Pencil size={14} />
|
||||
</button>
|
||||
{/if}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Tags in this group -->
|
||||
{#if isExpanded(group.id)}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ const birthdayCalendar: Calendar = {
|
|||
color: BIRTHDAY_CALENDAR.color,
|
||||
isDefault: false,
|
||||
isVisible: true, // Visibility controlled by settingsStore.showBirthdays
|
||||
timezone: 'UTC',
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
};
|
||||
|
|
|
|||
|
|
@ -4,7 +4,8 @@
|
|||
|
||||
interface SearchItem {
|
||||
id: string;
|
||||
[key: string]: unknown;
|
||||
title?: string;
|
||||
subtitle?: string;
|
||||
}
|
||||
|
||||
// State
|
||||
|
|
|
|||
|
|
@ -128,13 +128,19 @@
|
|||
// View labels
|
||||
const viewLabels: Record<CalendarViewType, string> = {
|
||||
day: 'Tag',
|
||||
'3day': '3 Tage',
|
||||
'5day': '5 Tage',
|
||||
week: 'Woche',
|
||||
'10day': '10 Tage',
|
||||
'14day': '14 Tage',
|
||||
'30day': '30 Tage',
|
||||
'60day': '60 Tage',
|
||||
'90day': '90 Tage',
|
||||
'365day': '365 Tage',
|
||||
month: 'Monat',
|
||||
year: 'Jahr',
|
||||
agenda: 'Agenda',
|
||||
custom: 'Benutzerdefiniert',
|
||||
};
|
||||
|
||||
// Duration options in minutes
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
Clock,
|
||||
CalendarCheck,
|
||||
Hourglass,
|
||||
type Icon as LucideIcon,
|
||||
} from 'lucide-svelte';
|
||||
import { subDays, addDays } from 'date-fns';
|
||||
|
||||
|
|
@ -39,42 +40,42 @@
|
|||
id: 'eventsToday',
|
||||
label: 'Heute',
|
||||
value: calendarStatisticsStore.eventsToday,
|
||||
icon: CalendarDays,
|
||||
icon: CalendarDays as any,
|
||||
variant: 'success',
|
||||
},
|
||||
{
|
||||
id: 'eventsThisWeek',
|
||||
label: 'Diese Woche',
|
||||
value: calendarStatisticsStore.eventsThisWeek,
|
||||
icon: Calendar,
|
||||
icon: Calendar as any,
|
||||
variant: 'primary',
|
||||
},
|
||||
{
|
||||
id: 'upcoming',
|
||||
label: 'Anstehend (7 Tage)',
|
||||
value: calendarStatisticsStore.upcomingEvents,
|
||||
icon: CalendarCheck,
|
||||
icon: CalendarCheck as any,
|
||||
variant: 'info',
|
||||
},
|
||||
{
|
||||
id: 'busyHours',
|
||||
label: 'Stunden/Woche',
|
||||
value: `${calendarStatisticsStore.busyHoursThisWeek}h`,
|
||||
icon: Clock,
|
||||
icon: Clock as any,
|
||||
variant: 'neutral',
|
||||
},
|
||||
{
|
||||
id: 'calendars',
|
||||
label: 'Kalender',
|
||||
value: calendarStatisticsStore.totalCalendars,
|
||||
icon: Calendar,
|
||||
icon: Calendar as any,
|
||||
variant: 'accent',
|
||||
},
|
||||
{
|
||||
id: 'avgDuration',
|
||||
label: 'Ø Dauer (Min)',
|
||||
value: calendarStatisticsStore.averageEventDuration,
|
||||
icon: Hourglass,
|
||||
icon: Hourglass as any,
|
||||
variant: 'info',
|
||||
},
|
||||
]);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue