Files
Oxicloud/frontend/src/lib/components/EmptyState.svelte
T
Bradley Nelson e6279da5ce svelte refactor
2026-06-17 22:30:56 -06:00

55 lines
1.5 KiB
Svelte

<script lang="ts">
import type { Snippet } from 'svelte';
import Icon from '$lib/icons/Icon.svelte';
interface Props {
/** Icon-registry name shown above the title (omit for a text-only state). */
icon?: string;
/** Primary line. */
title?: string;
/** Secondary explanatory line. */
hint?: string;
/** Error styling (danger-coloured icon) + assertive `role="alert"`. */
error?: boolean;
/** Extra content (e.g. a call-to-action button) rendered below the hint. */
children?: Snippet;
}
let { icon, title, hint, error = false, children }: Props = $props();
</script>
<div class="empty-state" class:empty-state--error={error} role={error ? 'alert' : undefined}>
{#if icon}<Icon name={icon} class="empty-state__icon" />{/if}
{#if title}<p class="empty-state__title">{title}</p>{/if}
{#if hint}<p class="empty-state__hint">{hint}</p>{/if}
{@render children?.()}
</div>
<style>
/* Layout comes from the global `.empty-state` (styles/ported/content.css);
these refine the icon/title/hint elements consistently across views. */
.empty-state :global(.empty-state__icon) {
font-size: var(--text-5xl);
color: var(--color-text-faint);
margin-bottom: var(--space-2);
}
.empty-state--error :global(.empty-state__icon) {
color: var(--color-danger-text);
}
.empty-state__title {
margin: 0;
font-size: var(--text-lg);
font-weight: var(--weight-semibold);
color: var(--color-text-heading);
}
.empty-state__hint {
margin: 0;
max-width: 28rem;
font-size: var(--text-sm);
color: var(--color-text-muted);
}
</style>