Skip to content
W WRNexusJS
core component

StatusBanner

Reusable status banner component.

@wrnexus/ui 0.2.679 props0 slots1 events

Usage

Components are auto-discovered. Use the component directly in any .wrn view:

<StatusBanner
  type="info"
  title="title"
  description="description"
  actionLabel="actionLabel"
  actionHref="actionHref"
/>

Legacy mount name: data-component="StatusBanner".

Props and attributes

PropTypeRequirementDefault
classstringOptional""
typestringOptional"info"
titlestringOptional""
descriptionstringOptional""
actionLabelstringOptional""
actionHrefstringOptional""
dismissiblebooleanOptionaltrue
compactbooleanOptionalfalse
detailsstringOptional[]

Slots

This component does not declare a slot.

Events

  • click

Source contract

Installed source: components/StatusBanner.wrn

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