Alert component with semantic variants
Payment successful
Your payment of $29.99 has been processed. A receipt has been sent to your email address.
New feature available
We've added dark mode support. You can enable it in your account settings.
import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert'
...import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert'
function StatusIcon(props: { kind: 'check' | 'info' }) {
return (
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true">
{props.kind === 'check' ? (
<>
<circle cx="12" cy="12" r="9" />
<path d="m9 12 2 2 4-4" />
</>
) : (
<>
<circle cx="12" cy="12" r="9" />
<path d="M12 11v5M12 8h.01" />
</>
)}
</svg>
)
}
export default function AlertDemoExample() {
return (
<div class="grid gap-4">
<Alert>
<StatusIcon kind="check" />
<AlertTitle>Payment successful</AlertTitle>
<AlertDescription>
Your payment of $29.99 has been processed. A receipt has been sent to your email address.
</AlertDescription>
</Alert>
<Alert>
<StatusIcon kind="info" />
<AlertTitle>New feature available</AlertTitle>
<AlertDescription>
We've added dark mode support. You can enable it in your account settings.
</AlertDescription>
</Alert>
</div>
)
}
Installation
npx @fictjs/shadcn@latest add alertInstall the runtime dependencies:
npm install class-variance-authorityCopy the Fict shadcn component into your project.
Source
components/ui/alert.tsx
src/components/ui/alert.tsx
import { cva, type VariantProps } from 'class-variance-authority'
import { cn } from '@/lib/cn'
const alertVariants = cva('relative w-full rounded-lg border p-4 text-sm [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-2px]', {
variants: {
variant: {
default: 'bg-background text-foreground',
destructive: 'border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive',
success: 'border-emerald-500/40 text-emerald-700 dark:text-emerald-300 [&>svg]:text-emerald-600',
},
},
defaultVariants: {
variant: 'default',
},
})
type AlertProps = JSX.IntrinsicElements['div'] & VariantProps<typeof alertVariants>
type AlertTitleProps = JSX.IntrinsicElements['h5']
type AlertDescriptionProps = JSX.IntrinsicElements['div']
export function Alert(props: AlertProps) {
const { class: className, variant, ...rest } = props
return <div role='alert' class={cn(alertVariants({ variant }), className)} {...rest} />
}
export function AlertTitle(props: AlertTitleProps) {
const { class: className, ...rest } = props
return <h5 class={cn('mb-1 font-medium leading-none tracking-tight', className)} {...rest} />
}
export function AlertDescription(props: AlertDescriptionProps) {
const { class: className, ...rest } = props
return <div class={cn('text-sm [&_p]:leading-relaxed', className)} {...rest} />
}
Usage
Examples
Basic
Account updated successfully
Your profile information has been saved. Changes will be reflected immediately.
import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert'
...import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert'
function CheckIcon() {
return (
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true">
<circle cx="12" cy="12" r="9" />
<path d="m9 12 2 2 4-4" />
</svg>
)
}
export default function AlertBasicExample() {
return (
<Alert>
<CheckIcon />
<AlertTitle>Account updated successfully</AlertTitle>
<AlertDescription>
Your profile information has been saved. Changes will be reflected immediately.
</AlertDescription>
</Alert>
)
}
Destructive
Payment failed
Your payment could not be processed. Please check your payment method and try again.
import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert'
...import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert'
function ErrorIcon() {
return (
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true">
<circle cx="12" cy="12" r="9" />
<path d="M12 8v4M12 16h.01" />
</svg>
)
}
export default function AlertDestructiveExample() {
return (
<Alert variant="destructive">
<ErrorIcon />
<AlertTitle>Payment failed</AlertTitle>
<AlertDescription>
Your payment could not be processed. Please check your payment method and try again.
</AlertDescription>
</Alert>
)
}
Action
import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert'
import { Button } from '@/components/ui/button'
...import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert'
import { Button } from '@/components/ui/button'
export default function AlertActionExample() {
return (
<Alert class="grid grid-cols-[1fr_auto] items-center gap-x-4">
<div>
<AlertTitle>Dark mode is now available</AlertTitle>
<AlertDescription>Enable it under your profile settings to get started.</AlertDescription>
</div>
<Button size="sm" variant="outline">
Enable
</Button>
</Alert>
)
}
Colors
Your subscription will expire in 3 days.
Renew now to avoid service interruption or upgrade to a paid plan to continue using the service.
import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert'
...import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert'
function WarningIcon() {
return (
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true">
<path d="M12 3 2.8 19h18.4L12 3Z" />
<path d="M12 9v4M12 16h.01" />
</svg>
)
}
export default function AlertColorsExample() {
return (
<Alert class="border-amber-500/50 text-amber-700 dark:text-amber-300">
<WarningIcon />
<AlertTitle>Your subscription will expire in 3 days.</AlertTitle>
<AlertDescription>
Renew now to avoid service interruption or upgrade to a paid plan to continue using the service.
</AlertDescription>
</Alert>
)
}
Rtl
تم الدفع بنجاح
تمت معالجة دفعتك البالغة 29.99 دولارًا. تم إرسال إيصال إلى عنوان بريدك الإلكتروني.
ميزة جديدة متاحة
لقد أضفنا دعم الوضع الداكن. يمكنك تفعيله في إعدادات حسابك.
import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert'
...import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert'
const translations = {
ar: [
[
'تم الدفع بنجاح',
'تمت معالجة دفعتك البالغة 29.99 دولارًا. تم إرسال إيصال إلى عنوان بريدك الإلكتروني.',
],
['ميزة جديدة متاحة', 'لقد أضفنا دعم الوضع الداكن. يمكنك تفعيله في إعدادات حسابك.'],
],
he: [
['התשלום בוצע בהצלחה', 'התשלום שלך בסך 29.99 דולר עובד. קבלה נשלחה לכתובת האימייל שלך.'],
['תכונה חדשה זמינה', 'הוספנו תמיכה במצב כהה. אתה יכול להפעיל אותו בהגדרות החשבון שלך.'],
],
en: [
[
'Payment successful',
'Your payment of $29.99 has been processed. A receipt has been sent to your email address.',
],
[
'New feature available',
"We've added dark mode support. You can enable it in your account settings.",
],
],
} as const
export default function AlertRtlExample() {
let language = $state<keyof typeof translations>('ar')
const direction = () => (language === 'en' ? 'ltr' : 'rtl')
return (
<div class="grid gap-4">
<select
value={language}
onChange={event => {
language = event.currentTarget.value as keyof typeof translations
}}
>
<option value="ar">Arabic (العربية)</option>
<option value="he">Hebrew (עברית)</option>
<option value="en">English</option>
</select>
<div class="grid gap-4" dir={direction()}>
{translations[language].map(([title, description]) => (
<Alert>
<AlertTitle>{title}</AlertTitle>
<AlertDescription>{description}</AlertDescription>
</Alert>
))}
</div>
</div>
)
}