mirror of
https://github.com/bretzel-app/crumbs.git
synced 2026-10-12 20:06:57 +02:00
fix: resolve all svelte-check warnings (a11y + state_referenced_locally)
- Add svelte-ignore for intentional state_referenced_locally patterns - Wrap clickable images in button elements for keyboard accessibility - Add proper ARIA roles (dialog, textbox) with tabindex and focus management - Fix lightbox Escape key handling to not close parent editor overlay Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
d3334ad91d
commit
48f23cbecc
@@ -19,6 +19,7 @@
|
||||
|
||||
let { content, onChange }: Props = $props();
|
||||
|
||||
// svelte-ignore state_referenced_locally
|
||||
let items = $state<ChecklistItem[]>(parseChecklist(content));
|
||||
let doneExpanded = $state(true);
|
||||
const flipDurationMs = 150;
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
|
||||
const { src, alt, onClose }: Props = $props();
|
||||
|
||||
let dialogEl: HTMLDivElement | undefined = $state();
|
||||
|
||||
function handleKeydown(e: KeyboardEvent) {
|
||||
if (e.key === 'Escape') {
|
||||
e.stopPropagation();
|
||||
@@ -21,14 +23,21 @@
|
||||
onClose();
|
||||
}
|
||||
}
|
||||
|
||||
$effect(() => {
|
||||
dialogEl?.focus();
|
||||
});
|
||||
</script>
|
||||
|
||||
<svelte:window onkeydown={handleKeydown} />
|
||||
|
||||
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
||||
<div
|
||||
bind:this={dialogEl}
|
||||
class="fixed inset-0 z-50 flex items-center justify-center bg-black/80 animate-[fade-in_150ms_ease-out]"
|
||||
onclick={handleBackgroundClick}
|
||||
onkeydown={handleKeydown}
|
||||
role="dialog"
|
||||
aria-modal="true"
|
||||
aria-label="Image lightbox"
|
||||
tabindex="-1"
|
||||
data-testid="image-lightbox"
|
||||
>
|
||||
<button
|
||||
|
||||
@@ -119,14 +119,18 @@
|
||||
{@const isPending = 'pending' in attachment && attachment.pending}
|
||||
{@const imgSrc = isPending ? attachment.path : `/api/notes/${noteId}/attachments?attachmentId=${attachment.id}`}
|
||||
<div class="group relative">
|
||||
<!-- svelte-ignore a11y_no_noninteractive_element_interactions a11y_click_events_have_key_events -->
|
||||
<img
|
||||
src={imgSrc}
|
||||
alt={attachment.filename}
|
||||
class="h-20 w-20 cursor-pointer rounded-sm object-cover {isPending ? 'opacity-70' : ''}"
|
||||
<button
|
||||
type="button"
|
||||
class="h-20 w-20 cursor-pointer rounded-sm p-0 border-0 bg-transparent overflow-hidden"
|
||||
onclick={() => { lightboxSrc = imgSrc; lightboxAlt = attachment.filename; }}
|
||||
data-testid="attachment-thumbnail"
|
||||
/>
|
||||
>
|
||||
<img
|
||||
src={imgSrc}
|
||||
alt={attachment.filename}
|
||||
class="h-20 w-20 object-cover {isPending ? 'opacity-70' : ''}"
|
||||
/>
|
||||
</button>
|
||||
{#if isPending}
|
||||
<div class="absolute bottom-0.5 left-0.5 rounded-sm bg-black/50 p-0.5" title="Pending sync">
|
||||
<RefreshCw class="h-3 w-3 text-white" />
|
||||
|
||||
@@ -73,6 +73,7 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- svelte-ignore a11y_no_noninteractive_element_to_interactive_role -->
|
||||
<article
|
||||
class="group relative cursor-pointer rounded-sm border border-[var(--border-subtle)] p-4 transition-all hover:border-[var(--primary)] shadow-[var(--card-shadow)] hover:shadow-[var(--card-shadow-hover)] {fullHeight ? 'h-full' : ''}"
|
||||
style={cardStyle}
|
||||
@@ -88,15 +89,19 @@
|
||||
<div class="-mx-4 -mt-4 mb-3 flex overflow-hidden rounded-t-sm" data-testid="card-thumbnails">
|
||||
{#each featuredAttachments.slice(0, 3) as attachment}
|
||||
<div class="relative min-w-0 flex-1">
|
||||
<!-- svelte-ignore a11y_no_noninteractive_element_interactions a11y_click_events_have_key_events -->
|
||||
<img
|
||||
src="/api/notes/{note.id}/attachments?attachmentId={attachment.id}&thumb=1"
|
||||
alt={attachment.filename}
|
||||
class="h-24 w-full cursor-pointer object-cover"
|
||||
loading="lazy"
|
||||
<button
|
||||
type="button"
|
||||
class="h-24 w-full cursor-pointer p-0 border-0 bg-transparent"
|
||||
onclick={(e) => { e.stopPropagation(); lightboxSrc = `/api/notes/${note.id}/attachments?attachmentId=${attachment.id}`; lightboxAlt = attachment.filename; }}
|
||||
data-testid="card-thumbnail"
|
||||
/>
|
||||
>
|
||||
<img
|
||||
src="/api/notes/{note.id}/attachments?attachmentId={attachment.id}&thumb=1"
|
||||
alt={attachment.filename}
|
||||
class="h-24 w-full object-cover"
|
||||
loading="lazy"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
{/each}
|
||||
{#if featuredAttachments.length > 3}
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
let checklistMode = $state(note?.checklistMode ?? false);
|
||||
let showColorPicker = $state(false);
|
||||
let showImageUpload = $state(false);
|
||||
// svelte-ignore state_referenced_locally
|
||||
let rawMarkdownMode = $state(note?.checklistMode ?? false);
|
||||
let textareaEl: HTMLTextAreaElement | undefined = $state();
|
||||
let tiptapEditor: Editor | undefined = $state();
|
||||
|
||||
@@ -57,11 +57,14 @@
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- svelte-ignore a11y_click_events_have_key_events a11y_no_static_element_interactions -->
|
||||
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
||||
<div
|
||||
bind:this={element}
|
||||
class="tiptap-wrapper prose prose-sm flex min-h-[300px] max-w-none flex-col px-4 py-2 text-[var(--text)]"
|
||||
data-testid="tiptap-editor"
|
||||
role="textbox"
|
||||
aria-multiline="true"
|
||||
tabindex="0"
|
||||
onclick={() => editor?.commands.focus()}
|
||||
></div>
|
||||
|
||||
|
||||
@@ -14,7 +14,9 @@
|
||||
let { data } = $props();
|
||||
|
||||
// Profile state
|
||||
// svelte-ignore state_referenced_locally
|
||||
let displayName = $state(data.user?.displayName || '');
|
||||
// svelte-ignore state_referenced_locally
|
||||
let email = $state(data.user?.email || '');
|
||||
let profileMsg = $state('');
|
||||
let profileError = $state(false);
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
import PasswordStrengthMeter from '$lib/components/PasswordStrengthMeter.svelte';
|
||||
|
||||
let { data } = $props();
|
||||
// svelte-ignore state_referenced_locally
|
||||
let users = $state<User[]>(data.users);
|
||||
|
||||
// Create user form
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
// svelte-ignore state_referenced_locally
|
||||
const providers = data.providers ?? [];
|
||||
</script>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user