Alert
An inline, non-blocking status message. Five variants, soft or solid.
<script setup lang="ts">
import SaAlert from '@shared/components/common/SaAlert.vue'
</script>
<template>
<SaAlert
variant="info"
title="Scheduled maintenance"
description="The API is read-only between 02:00 and 02:30 UTC on Sunday."
/>
</template>Usage
shadcn-vue ships an alert-dialog, which is a modal, but no inline alert. This is that: a message that sits in the page and blocks nothing.
title and description are the short form. Both have slots, and the default slot is the description, so a message with a link or a list goes in the slot instead.
Body text stays on the foreground and muted-foreground tokens rather than a tinted ramp. Colored text on a colored fill is where contrast problems live, and this has to hold in both color modes and after a buyer re-themes the primary color.
Examples
Variants
variant is default, info, success, warning or destructive. Each brings its own icon.
<script setup lang="ts">
import SaAlert from '@shared/components/common/SaAlert.vue'
</script>
<template>
<div class="space-y-3">
<SaAlert title="Default" description="No tint, for a neutral note." />
<SaAlert variant="info" title="Info" description="Something worth knowing." />
<SaAlert variant="success" title="Success" description="The import finished. 412 rows added." />
<SaAlert variant="warning" title="Warning" description="Your trial ends in three days." />
<SaAlert variant="destructive" title="Destructive" description="Two invoices failed to send." />
</div>
</template>Solid
appearance="solid" is for the rare alert that has to outrank everything around it. A solid fill owns its own text color.
<script setup lang="ts">
import SaAlert from '@shared/components/common/SaAlert.vue'
</script>
<template>
<div class="space-y-3">
<SaAlert
appearance="solid"
variant="destructive"
title="Payment failed"
description="We could not charge the card on file. Update it to keep the workspace open."
/>
<SaAlert
appearance="solid"
variant="success"
title="Deployed"
description="Version 2.4.0 is live in production."
/>
</div>
</template>Actions and dismiss
The actions slot holds buttons under the message. dismissible adds a close button that emits dismiss; the alert does not remove itself, so you decide what dismissing means.
<script setup lang="ts">
import SaAlert from '@shared/components/common/SaAlert.vue'
import { Button } from '@shared/components/ui/button'
import { ref } from 'vue'
const shown = ref(true)
const result = ref('')
</script>
<template>
<div class="space-y-3">
<SaAlert
v-if="shown"
variant="warning"
dismissible
title="Two-factor authentication is off"
@dismiss="shown = false"
>
Owners are required to turn it on before the end of the month.
<template #actions>
<Button size="sm" @click="result = 'Opened the setup dialog'">
Turn it on
</Button>
<Button size="sm" variant="ghost" @click="result = 'Postponed'">
Remind me later
</Button>
</template>
</SaAlert>
<p class="text-sm text-muted-foreground">
{{ shown ? (result || 'Nothing pressed yet') : 'Dismissed' }}
</p>
<Button v-if="!shown" size="sm" variant="outline" @click="shown = true">
Show it again
</Button>
</div>
</template>A different icon, or none
icon takes any component. Pass null for no icon at all.
<script setup lang="ts">
import SaAlert from '@shared/components/common/SaAlert.vue'
import { Rocket } from 'lucide-vue-next'
</script>
<template>
<div class="space-y-3">
<SaAlert :icon="Rocket" variant="info" title="A different icon" description="Pass any icon component." />
<SaAlert :icon="null" variant="info" title="No icon" description="Pass null to drop it." />
</div>
</template>API
Source: src/shared/components/common/SaAlert.vue
Props
| Prop | Type | Default | Description |
|---|---|---|---|
variant | 'default' | 'info' | 'success' | 'warning' | 'destructive' | 'default' | The tone, and the default icon. |
title | string | — | The bold first line. |
description | string | — | The body. Used when the default slot is empty. |
dismissible | boolean | — | Adds a close button that emits dismiss. |
icon | Component | null | — | Replaces the variant's icon. null removes it. |
appearance | 'soft' | 'solid' | 'soft' | soft is a tinted panel, solid a filled one. |
Emits
| Event | Payload | Description |
|---|---|---|
dismiss | — | Fires from the close button. The alert stays in the DOM. |
Slots
| Slot | Description |
|---|---|
title | Replaces title. |
default | Replaces description. |
actions | Buttons under the message. |
Accessibility
- The root is
role="alert", so a message that appears after the page has loaded is announced. - The icon is
aria-hidden, because the variant is already carried by the title and the text. - The close button is named "Dismiss".
- Soft variants keep body text on the neutral text tokens, which is what keeps them readable on the tint in both color modes.