feat: add banner component

This commit is contained in:
madkarmaa
2025-11-12 10:42:52 +01:00
parent 1f5122cc49
commit baea96a4be
3 changed files with 112 additions and 0 deletions

View File

@@ -0,0 +1,87 @@
<script lang="ts">
import { onMount } from 'svelte';
import { slide } from 'svelte/transition';
import { cubicInOut } from 'svelte/easing';
import storable from '@madkarma/svelte-storable';
import type { WithChildren } from '$types';
import Info from 'virtual:icons/material-symbols/info-outline';
import Warning from 'virtual:icons/material-symbols/warning-outline';
import Error from 'virtual:icons/material-symbols/error-outline';
import Close from 'virtual:icons/material-symbols/close';
const readBannerIds = storable<string[]>('read_banner_ids', []);
type Props = {
type: 'info' | 'warning' | 'error';
id: string;
permanent?: boolean;
closed?: boolean;
} & WithChildren;
let {
type,
children,
id,
permanent = false,
closed = $bindable($readBannerIds.includes(id))
}: Props = $props();
const Icon = type === 'info' ? Info : type === 'warning' ? Warning : Error;
let visible = $state(false);
onMount(() => {
if (closed) return;
visible = true;
});
</script>
{#if visible}
<div class="banner {type}" {id} transition:slide={{ duration: 200, easing: cubicInOut }}>
<Icon />
<div class="content">
{@render children()}
</div>
{#if !permanent}
<button
class="close"
type="button"
onclick={() => {
closed = true;
visible = false;
$readBannerIds = [...$readBannerIds, id];
}}
>
<Close />
</button>
{/if}
</div>
{/if}
<style>
.banner {
display: flex;
align-items: center;
justify-content: space-between;
gap: 1rem;
padding: 1rem 2rem;
position: sticky;
top: 0;
left: 0;
z-index: 9999;
&.info {
}
&.warning {
}
&.error {
}
}
.content {
flex: 1;
}
</style>