UIPackage

Alert

Vue feedback
Edit on GitHub

Static, in-flow notice block with a leading icon, title, and description. Use for inline page-level messages — info banners, success confirmations, warning callouts. Two tones: `default` and `destructive`.

Also available for React ->

Installation

$ npx shadcn-vue@latest add https://uipkge.dev/r/vue/alert.json

Or with the named registry: npx shadcn-vue@latest add @uipkge/alert

Examples

Props

Name Type / Values Default Required
class HTMLAttributes['class'] optional
variant
'default''destructive'
optional
icon
'info''warning''error''success'
optional
title string optional
text string optional

Dependencies

Files (5)

  • app/components/ui/alert/Alert.vue 1.3 kB
    <script setup lang="ts">
    import type { HTMLAttributes } from 'vue'
    import { AlertCircle, CheckCircle, Info, TriangleAlert } from 'lucide-vue-next'
    import { cn } from '@/lib/utils'
    import { alertVariants } from './alert.variants'
    
    // Inlined union: SFC compiler can't extract runtime props from
    // `AlertVariants['variant']`.
    const props = defineProps<{
      class?: HTMLAttributes['class']
      variant?: 'default' | 'destructive'
      icon?: 'info' | 'warning' | 'error' | 'success'
      title?: string
      text?: string
    }>()
    </script>
    
    <template>
      <div role="alert" data-uipkge data-slot="alert" :class="cn(alertVariants({ variant }), props.class)">
        <div v-if="icon" data-uipkge data-slot="alert-icon" class="absolute top-4 left-4">
          <AlertCircle v-if="icon === 'error'" class="size-4" aria-hidden="true" />
          <CheckCircle v-else-if="icon === 'success'" class="size-4" aria-hidden="true" />
          <TriangleAlert v-else-if="icon === 'warning'" class="size-4" aria-hidden="true" />
          <Info v-else class="size-4" aria-hidden="true" />
        </div>
        <div data-uipkge data-slot="alert-content" class="[&_p]:text-sm [&_p]:leading-relaxed">
          <p v-if="title" class="text-sm font-medium">{{ title }}</p>
          <p v-if="text" class="text-muted-foreground text-sm">{{ text }}</p>
          <slot />
        </div>
      </div>
    </template>
  • app/components/ui/alert/AlertDescription.vue 0.4 kB
    <script setup lang="ts">
    import type { HTMLAttributes } from 'vue'
    import { cn } from '@/lib/utils'
    
    const props = defineProps<{
      class?: HTMLAttributes['class']
    }>()
    </script>
    
    <template>
      <div
        data-uipkge
        data-slot="alert-description"
        :class="cn('text-muted-foreground text-sm leading-relaxed [&_p]:leading-relaxed', props.class)"
      >
        <slot />
      </div>
    </template>
  • app/components/ui/alert/AlertTitle.vue 0.4 kB
    <script setup lang="ts">
    import type { HTMLAttributes } from 'vue'
    import { cn } from '@/lib/utils'
    
    const props = defineProps<{
      as?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'div'
      class?: HTMLAttributes['class']
    }>()
    </script>
    
    <template>
      <component
        :is="props.as ?? 'h5'"
        data-uipkge
        data-slot="alert-title"
        :class="cn('mb-1 text-sm leading-none font-medium tracking-tight', props.class)"
      >
        <slot />
      </component>
    </template>
  • app/components/ui/alert/alert.variants.ts 1 kB
    import type { VariantProps } from 'class-variance-authority'
    import { cva } from 'class-variance-authority'
    
    /**
     * Variant definitions live in their own file (rather than the package
     * `index.ts`) so `Alert.vue` can `import { alertVariants } from
     * './alert.variants'` without creating a circular dependency through the
     * index. See card.variants.ts for the same pattern + the SSR symptom that
     * motivated the split.
     */
    export const alertVariants = cva(
      'relative w-full rounded-lg border p-4 [&>svg]:text-foreground [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg+div]:translate-y-[-3px] [&:has([data-slot=alert-icon])]:pl-12 [&:has([data-slot=alert-description])]:pt-7',
      {
        variants: {
          variant: {
            default: 'bg-background text-foreground border-border',
            destructive: 'border-destructive/20 text-destructive bg-destructive/5 [&>svg]:text-destructive',
          },
        },
        defaultVariants: {
          variant: 'default',
        },
      },
    )
    
    export type AlertVariants = VariantProps<typeof alertVariants>
  • app/components/ui/alert/index.ts 0.4 kB
    export { default as Alert } from './Alert.vue'
    export { default as AlertDescription } from './AlertDescription.vue'
    export { default as AlertTitle } from './AlertTitle.vue'
    
    // Re-export variant API from the sibling file (kept separate to avoid the
    // Alert.vue <-> index.ts circular import that broke dev SSR for Card).
    export { alertVariants, type AlertVariants } from './alert.variants'

Raw manifest: https://uipkge.dev/r/vue/alert.json