Files
frontend-svelte/src/shared/ui/Loader/Loader.svelte

78 lines
2.3 KiB
Svelte

<!--
Component: Loader
Displays a loading spinner with an optional message.
-->
<script lang="ts">
import { fade } from 'svelte/transition';
interface Props {
/**
* Icon size (in pixels)
* @default 20
*/
size?: number;
/**
* Additional classes for container
*/
class?: string;
/**
* Message text
* @default analyzing_data
*/
message?: string;
}
let { size = 20, class: className = '', message = 'analyzing_data' }: Props = $props();
</script>
<div
class="absolute inset-x-0 inset-y-0 flex items-center justify-center gap-4 {className}"
in:fade={{ duration: 300 }}
out:fade={{ duration: 300 }}
>
<div style:width="{size}px" style:height="{size}px">
<svg class="stroke-gray-900 stroke-1" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(12, 12)">
<!-- Four corner brackets rotating -->
<g>
<path
d="M -8 -8 L -4 -8 M -8 -8 L -8 -4"
stroke="currentColor"
stroke-width="1"
stroke-linecap="round"
/>
<path
d="M 8 -8 L 4 -8 M 8 -8 L 8 -4"
stroke="currentColor"
stroke-width="1"
stroke-linecap="round"
/>
<path
d="M -8 8 L -4 8 M -8 8 L -8 4"
stroke="currentColor"
stroke-width="1"
stroke-linecap="round"
/>
<path d="M 8 8 L 4 8 M 8 8 L 8 4" stroke="currentColor" stroke-width="1" stroke-linecap="round" />
<animateTransform
attributeName="transform"
type="rotate"
from="0"
to="360"
dur="3s"
repeatCount="indefinite"
/>
</g>
</g>
</svg>
</div>
<!-- Divider -->
<div class="w-px h-3 bg-gray-400/50"></div>
<!-- Message -->
<span class="font-mono text-[10px] uppercase tracking-[0.2em] text-gray-600 font-medium">
{message}
</span>
</div>