123 lines
6.9 KiB
Plaintext
123 lines
6.9 KiB
Plaintext
component StatusBanner {
|
|
props {
|
|
class: string = ""
|
|
type = "info"
|
|
|
|
title = ""
|
|
description = ""
|
|
|
|
actionLabel = ""
|
|
actionHref = ""
|
|
|
|
dismissible = true
|
|
compact = false
|
|
|
|
details = []
|
|
}
|
|
|
|
state visible = true
|
|
|
|
view {
|
|
<aside
|
|
role="{type === 'error' ? 'alert' : 'status'}"
|
|
aria-live="{type === 'error' ? 'assertive' : 'polite'}"
|
|
class="relative overflow-hidden {class}"
|
|
class:hidden="!visible"
|
|
>
|
|
<div
|
|
class=" relative overflow-hidden rounded-2xl {compact ? 'px-4 py-3' : 'px-5 py-4 sm:px-6'} {type === 'success' ? 'bg-emerald-50 text-emerald-950 ring-1 ring-inset ring-emerald-200 dark:bg-emerald-500/10 dark:text-emerald-100 dark:ring-emerald-500/20' : type === 'warning' ? 'bg-amber-50 text-amber-950 ring-1 ring-inset ring-amber-200 dark:bg-amber-500/10 dark:text-amber-100 dark:ring-amber-500/20' : type === 'error' ? 'bg-rose-50 text-rose-950 ring-1 ring-inset ring-rose-200 dark:bg-rose-500/10 dark:text-rose-100 dark:ring-rose-500/20' : 'bg-indigo-50 text-indigo-950 ring-1 ring-inset ring-indigo-200 dark:bg-indigo-500/10 dark:text-indigo-100 dark:ring-indigo-500/20' } "
|
|
>
|
|
<!-- Decorative glow -->
|
|
<div aria-hidden="true" class=" pointer-events-none absolute -right-16 -top-20 h-40 w-40 rounded-full blur-3xl {type === 'success' ? 'bg-emerald-300/30 dark:bg-emerald-500/10' : type === 'warning' ? 'bg-amber-300/30 dark:bg-amber-500/10' : type === 'error' ? 'bg-rose-300/30 dark:bg-rose-500/10' : 'bg-indigo-300/30 dark:bg-indigo-500/10' } " ></div>
|
|
|
|
<div
|
|
class="relative flex gap-4"
|
|
class:items-center="compact"
|
|
class:items-start="!compact"
|
|
>
|
|
<!-- Icon -->
|
|
<span
|
|
class=" grid shrink-0 place-items-center rounded-xl {compact ? 'h-9 w-9' : 'h-10 w-10'} {type === 'success' ? 'bg-emerald-100 text-emerald-700 dark:bg-emerald-500/15 dark:text-emerald-300' : type === 'warning' ? 'bg-amber-100 text-amber-700 dark:bg-amber-500/15 dark:text-amber-300' : type === 'error' ? 'bg-rose-100 text-rose-700 dark:bg-rose-500/15 dark:text-rose-300' : 'bg-indigo-100 text-indigo-700 dark:bg-indigo-500/15 dark:text-indigo-300' } "
|
|
>
|
|
<span class=" h-5 w-5 {type === 'success' ? 'icon-[lucide--circle-check]' : type === 'warning' ? 'icon-[lucide--triangle-alert]' : type === 'error' ? 'icon-[lucide--circle-x]' : 'icon-[lucide--info]' } " aria-hidden="true" ></span>
|
|
</span>
|
|
|
|
<!-- Content -->
|
|
<div class="min-w-0 flex-1">
|
|
<div
|
|
class="flex flex-col gap-3 sm:flex-row sm:justify-between"
|
|
class:sm:items-center="compact"
|
|
class:sm:items-start="!compact"
|
|
>
|
|
<div class="min-w-0">
|
|
<h2
|
|
class="font-bold"
|
|
class:text-sm="compact"
|
|
class:text-base="!compact"
|
|
class:hidden="title === ''"
|
|
>
|
|
{title}
|
|
</h2>
|
|
|
|
<p
|
|
class="text-sm leading-6 opacity-80"
|
|
class:mt-1="title !== ''"
|
|
class:hidden="description === ''"
|
|
>
|
|
{description}
|
|
</p>
|
|
</div>
|
|
|
|
<!-- Actions -->
|
|
<div class="flex shrink-0 items-center gap-2">
|
|
<a
|
|
href="{actionHref}"
|
|
class=" h-9 items-center justify-center gap-1.5 rounded-lg px-3 text-xs font-bold transition {type === 'success' ? 'bg-emerald-600 text-white hover:bg-emerald-500' : type === 'warning' ? 'bg-amber-600 text-white hover:bg-amber-500' : type === 'error' ? 'bg-rose-600 text-white hover:bg-rose-500' : 'bg-indigo-600 text-white hover:bg-indigo-500' } "
|
|
class:hidden="actionLabel === ''"
|
|
class:inline-flex="actionLabel !== ''"
|
|
>
|
|
{actionLabel}
|
|
|
|
<span class="icon-[lucide--arrow-up-right] h-3.5 w-3.5" aria-hidden="true" ></span>
|
|
</a>
|
|
|
|
<button
|
|
type="button"
|
|
@click="visible = false"
|
|
aria-label="Dismiss notice"
|
|
class="grid h-9 w-9 place-items-center rounded-lg opacity-60 transition hover:bg-black/5 hover:opacity-100 focus:outline-none focus-visible:ring-2 focus-visible:ring-current dark:hover:bg-white/10"
|
|
class:hidden="!dismissible"
|
|
>
|
|
<span class="icon-[lucide--x] h-4 w-4" aria-hidden="true" ></span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Dynamic details -->
|
|
<div
|
|
class="mt-4 flex flex-wrap gap-x-5 gap-y-2 border-t pt-4 text-xs font-medium"
|
|
class:hidden="compact || details.length === 0"
|
|
class:border-emerald-200="type === 'success'"
|
|
class:border-amber-200="type === 'warning'"
|
|
class:border-rose-200="type === 'error'"
|
|
class:border-indigo-200="type === 'info'"
|
|
class:dark:border-emerald-500/20="type === 'success'"
|
|
class:dark:border-amber-500/20="type === 'warning'"
|
|
class:dark:border-rose-500/20="type === 'error'"
|
|
class:dark:border-indigo-500/20="type === 'info'"
|
|
>
|
|
{#each details.slice(0, 4) as detail}
|
|
<span class="inline-flex items-center gap-2 opacity-80">
|
|
<span class="{detail.iconClass} h-3.5 w-3.5" aria-hidden="true" ></span>
|
|
|
|
{detail.label}
|
|
</span>
|
|
{/each}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</aside>
|
|
}
|
|
}
|