Files
mule-image/web/src/lib/components/feedback/InlineLoader.svelte
dtoro e364e4128f 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>
2026-05-20 08:26:12 +02:00

40 lines
1.1 KiB
Svelte

<!--
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>