Alert
Static inline banner — no open/close motion, no portal. Carries a title, description, and optional leading icon or trailing action. Quiet by default, destructive when it matters.
Usage
Heads up
You can add components to your app using the CLI. Run `bloom add` to scaffold.
alert.svelte
<script lang="ts" module>
import { type VariantProps, tv } from 'tailwind-variants';
export const alertVariants = tv({
base: "grid gap-0.5 rounded-lg border px-4 py-3 text-left text-sm has-data-[slot=alert-action]:relative has-data-[slot=alert-action]:pr-18 has-[>svg]:grid-cols-[auto_1fr] has-[>svg]:gap-x-2.5 *:[svg]:row-span-2 *:[svg]:translate-y-0.5 *:[svg]:text-current *:[svg:not([class*='size-'])]:size-4 group/alert relative w-full",
variants: {
variant: {
default: 'bg-card text-card-foreground',
destructive:
'text-destructive bg-card *:data-[slot=alert-description]:text-destructive/90 *:[svg]:text-current',
/* Status variants mirror Badge's opacity recipe (bg /10 + border /20 + text status) so
* Alert and Badge read as siblings in the same alert-bar / list contexts. */
success:
'bg-success/10 border-success/20 text-success *:data-[slot=alert-description]:text-success/90 *:[svg]:text-current dark:bg-success/15',
warning:
'bg-warning/10 border-warning/20 text-warning *:data-[slot=alert-description]:text-warning/90 *:[svg]:text-current dark:bg-warning/15',
info: 'bg-info/10 border-info/20 text-info *:data-[slot=alert-description]:text-info/90 *:[svg]:text-current dark:bg-info/15'
}
},
defaultVariants: {
variant: 'default'
}
});
export type AlertVariant = VariantProps<typeof alertVariants>['variant'];
</script>
<script lang="ts">
import type { HTMLAttributes } from 'svelte/elements';
import { cn, type WithElementRef } from '$lib/utils.js';
let {
ref = $bindable(null),
class: className,
variant = 'default',
children,
...restProps
}: WithElementRef<HTMLAttributes<HTMLDivElement>> & {
variant?: AlertVariant;
} = $props();
</script>
<div
bind:this={ref}
data-slot="alert"
data-substrate="3"
role="alert"
class={cn(alertVariants({ variant }), className)}
{...restProps}
>
{@render children?.()}
</div>
Destructive
Something went wrong
Your session expired while saving. Reload the page and try the action again.
alert-destructive.svelte
<script lang="ts" module>
import { type VariantProps, tv } from 'tailwind-variants';
export const alertVariants = tv({
base: "grid gap-0.5 rounded-lg border px-4 py-3 text-left text-sm has-data-[slot=alert-action]:relative has-data-[slot=alert-action]:pr-18 has-[>svg]:grid-cols-[auto_1fr] has-[>svg]:gap-x-2.5 *:[svg]:row-span-2 *:[svg]:translate-y-0.5 *:[svg]:text-current *:[svg:not([class*='size-'])]:size-4 group/alert relative w-full",
variants: {
variant: {
default: 'bg-card text-card-foreground',
destructive:
'text-destructive bg-card *:data-[slot=alert-description]:text-destructive/90 *:[svg]:text-current',
/* Status variants mirror Badge's opacity recipe (bg /10 + border /20 + text status) so
* Alert and Badge read as siblings in the same alert-bar / list contexts. */
success:
'bg-success/10 border-success/20 text-success *:data-[slot=alert-description]:text-success/90 *:[svg]:text-current dark:bg-success/15',
warning:
'bg-warning/10 border-warning/20 text-warning *:data-[slot=alert-description]:text-warning/90 *:[svg]:text-current dark:bg-warning/15',
info: 'bg-info/10 border-info/20 text-info *:data-[slot=alert-description]:text-info/90 *:[svg]:text-current dark:bg-info/15'
}
},
defaultVariants: {
variant: 'default'
}
});
export type AlertVariant = VariantProps<typeof alertVariants>['variant'];
</script>
<script lang="ts">
import type { HTMLAttributes } from 'svelte/elements';
import { cn, type WithElementRef } from '$lib/utils.js';
let {
ref = $bindable(null),
class: className,
variant = 'default',
children,
...restProps
}: WithElementRef<HTMLAttributes<HTMLDivElement>> & {
variant?: AlertVariant;
} = $props();
</script>
<div
bind:this={ref}
data-slot="alert"
data-substrate="3"
role="alert"
class={cn(alertVariants({ variant }), className)}
{...restProps}
>
{@render children?.()}
</div>
With action
Invite sent
Pedro will receive an email with a signup link. It's valid for 24 hours.
alert-action.svelte
<script lang="ts" module>
import { type VariantProps, tv } from 'tailwind-variants';
export const alertVariants = tv({
base: "grid gap-0.5 rounded-lg border px-4 py-3 text-left text-sm has-data-[slot=alert-action]:relative has-data-[slot=alert-action]:pr-18 has-[>svg]:grid-cols-[auto_1fr] has-[>svg]:gap-x-2.5 *:[svg]:row-span-2 *:[svg]:translate-y-0.5 *:[svg]:text-current *:[svg:not([class*='size-'])]:size-4 group/alert relative w-full",
variants: {
variant: {
default: 'bg-card text-card-foreground',
destructive:
'text-destructive bg-card *:data-[slot=alert-description]:text-destructive/90 *:[svg]:text-current',
/* Status variants mirror Badge's opacity recipe (bg /10 + border /20 + text status) so
* Alert and Badge read as siblings in the same alert-bar / list contexts. */
success:
'bg-success/10 border-success/20 text-success *:data-[slot=alert-description]:text-success/90 *:[svg]:text-current dark:bg-success/15',
warning:
'bg-warning/10 border-warning/20 text-warning *:data-[slot=alert-description]:text-warning/90 *:[svg]:text-current dark:bg-warning/15',
info: 'bg-info/10 border-info/20 text-info *:data-[slot=alert-description]:text-info/90 *:[svg]:text-current dark:bg-info/15'
}
},
defaultVariants: {
variant: 'default'
}
});
export type AlertVariant = VariantProps<typeof alertVariants>['variant'];
</script>
<script lang="ts">
import type { HTMLAttributes } from 'svelte/elements';
import { cn, type WithElementRef } from '$lib/utils.js';
let {
ref = $bindable(null),
class: className,
variant = 'default',
children,
...restProps
}: WithElementRef<HTMLAttributes<HTMLDivElement>> & {
variant?: AlertVariant;
} = $props();
</script>
<div
bind:this={ref}
data-slot="alert"
data-substrate="3"
role="alert"
class={cn(alertVariants({ variant }), className)}
{...restProps}
>
{@render children?.()}
</div>
Success
Confirms a positive outcome. Mirrors Badge's status palette so they read as siblings in alert lists.
Payment received
Your invoice for May has been settled.
alert-success.svelte
<Alert.Root variant="success" class="w-full max-w-lg">
<Icon name="checkbox-circle-line" />
<Alert.Title>Payment received</Alert.Title>
<Alert.Description>Your invoice for May has been settled.</Alert.Description>
</Alert.Root>Warning
Use for soft-fail conditions or upcoming actions that aren't yet errors.
API key expires soon
Rotate within 7 days to avoid downtime.
alert-warning.svelte
<Alert.Root variant="warning" class="w-full max-w-lg">
<Icon name="alert-line" />
<Alert.Title>API key expires soon</Alert.Title>
<Alert.Description>Rotate within 7 days to avoid downtime.</Alert.Description>
</Alert.Root>Info
Neutral context — release notes, tips, or quiet announcements.
New release available
Bloom v0.3 is out — visit the changelog for details.
alert-info.svelte
<Alert.Root variant="info" class="w-full max-w-lg">
<Icon name="information-line" />
<Alert.Title>New release available</Alert.Title>
<Alert.Description>Bloom v0.3 is out — visit the changelog for details.</Alert.Description>
</Alert.Root>Alert.Root props
Inherits native HTMLDivElement attributes via spread. Renders role='alert' on the root.
| Prop | Type | Default | Description |
|---|---|---|---|
'default' | 'destructive' | 'success' | 'warning' | 'info' | 'default' | Tone. Destructive uses the destructive token; success/warning/info mirror Badge status colors with /10 (light) / /15 (dark) tinted backgrounds. | |
string | — | Merged onto the root via tailwind-merge. | |
HTMLDivElement | null | null | Two-way-bindable element reference. |