web: unify empty + loading states behind EmptyState/InlineLoader
Replaces ad-hoc "Loading…" text and bare empty messages with two
shared feedback primitives that carry subtle lucide icons, consistent
muted-foreground/destructive tones, and a11y signaling (role=status,
aria-busy, role=alert on destructive empties). Loading copy gains
context ("Loading photos/folders/heaps/metadata…") and the right-
sidebar idle state moves from a "ⓘ" glyph to a MousePointerClick
icon. SkeletonGrid stays as the initial-grid loader.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
39
web/src/lib/components/feedback/InlineLoader.svelte
Normal file
39
web/src/lib/components/feedback/InlineLoader.svelte
Normal file
@@ -0,0 +1,39 @@
|
||||
<!--
|
||||
Tiny "Loading…" indicator: spinner + label. Use this for in-flight queries
|
||||
in sidebars, popovers, and right rails. For the initial photo-grid load,
|
||||
use SkeletonGrid instead (layout-preserving).
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { Loader2 } from 'lucide-svelte';
|
||||
|
||||
interface Props {
|
||||
label?: string;
|
||||
size?: 'sm' | 'default';
|
||||
align?: 'left' | 'center';
|
||||
srOnly?: boolean;
|
||||
polite?: boolean;
|
||||
}
|
||||
|
||||
let {
|
||||
label = 'Loading…',
|
||||
size = 'default',
|
||||
align = 'left',
|
||||
srOnly = false,
|
||||
polite = true
|
||||
}: Props = $props();
|
||||
|
||||
const textSize = $derived(size === 'sm' ? 'text-[11px]' : 'text-xs');
|
||||
const iconSize = $derived(size === 'sm' ? 'h-3 w-3' : 'h-3.5 w-3.5');
|
||||
const padding = $derived(size === 'sm' ? 'px-3 py-2' : 'px-3 py-2');
|
||||
const justify = $derived(align === 'center' ? 'justify-center' : 'justify-start');
|
||||
</script>
|
||||
|
||||
<p
|
||||
role="status"
|
||||
aria-busy="true"
|
||||
aria-live={polite ? 'polite' : 'off'}
|
||||
class="flex items-center gap-1.5 {padding} {textSize} {justify} text-muted-foreground"
|
||||
>
|
||||
<Loader2 class="{iconSize} animate-spin" aria-hidden="true" />
|
||||
<span class={srOnly ? 'sr-only' : ''}>{label}</span>
|
||||
</p>
|
||||
Reference in New Issue
Block a user