Viana Kitv0.1.4

Components

Alert

Displays a callout for user attention. Use it to communicate status, warnings, or contextual information inline on a page.

example.tsx

Import

tsx
import {
  AppAlert,
  AppAlertContent,
  AppAlertTitle,
  AppAlertDescription,
} from "@/components/primitives/AppAlert"

Variants

Use the variant prop to change the visual style.

VariantWhen to use
defaultNeutral or informational messages. Renders with brand primary background and icon color.
destructiveErrors, failures, or dangerous conditions. Renders with destructive background and icon color.
successConfirmation that an action completed successfully.
warningCaution — the action is allowed but has consequences.
infoSupplementary information the user should be aware of.

With close button

Place an AppButton after AppAlertContent to add a dismiss action. The flex layout pushes it to the right automatically.

tsx
<AppAlert>
  <InfoIcon className="w-8 h-8" />
  <AppAlertContent>
    <AppAlertTitle>Heads up</AppAlertTitle>
    <AppAlertDescription>You have a new message.</AppAlertDescription>
  </AppAlertContent>
  <AppButton variant="ghost" size="icon" className="ml-auto shrink-0 rounded-full">
    <XIcon className="h-4 w-4" />
  </AppButton>
</AppAlert>

API Reference

AppAlert extends all native <div> HTML attributes.

PropTypeDefaultDescription
variant"default" | "destructive" | "success" | "warning" | "info""default"Visual style of the alert.
classNamestringAdditional Tailwind classes merged via cn(). Applied after variant classes, so it always wins. Use for one-off overrides; prefer a wrapper block for reusable changes.

AppAlertContent groups AppAlertTitle and AppAlertDescription in a flex column and takes up the remaining horizontal space in the alert row. It extends all native <div> HTML attributes.

Source

src/components/primitives/AppAlert.tsx
import * as React from "react"
import { Alert, AlertTitle, AlertDescription } from "@/components/ui/alert"
import { cn } from "@/lib/utils"

const nativeVariantClasses = {
  default: "bg-background [&>svg]:text-gray-400",
  destructive: "bg-destructive/5 [&>svg]:text-destructive",
} as const

const extendedVariantClasses = {
  success: "border text-green-700 dark:text-green-700 [&>svg]:text-green-700",
  warning: "border text-amber-600 dark:text-amber-600 [&>svg]:text-amber-600",
  info: "border text-blue-400 dark:text-blue-400 [&>svg]:text-blue-400",
} as const

type ExtendedVariant = "default" | "destructive" | keyof typeof extendedVariantClasses

type AppAlertProps = Omit<React.ComponentProps<typeof Alert>, "variant"> & {
  variant?: ExtendedVariant
}

function AppAlert({ variant = "default", className, ...props }: AppAlertProps) {
  const isExtended = variant in extendedVariantClasses
  return (
    <Alert
      variant={isExtended ? "default" : (variant as "default" | "destructive")}
      className={cn(
        "flex items-center gap-3 px-3 py-2 [&>svg]:static [&>svg]:top-auto [&>svg]:left-auto [&>svg~*]:pl-0 [&>svg+div]:translate-y-0",
        isExtended
          ? extendedVariantClasses[variant as keyof typeof extendedVariantClasses]
          : nativeVariantClasses[variant as keyof typeof nativeVariantClasses],
        className
      )}
      {...props}
    />
  )
}

const AppAlertTitle = React.forwardRef<
  React.ComponentRef<typeof AlertTitle>,
  React.ComponentPropsWithoutRef<typeof AlertTitle>
>(({ className, ...props }, ref) => (
  <AlertTitle
    ref={ref}
    className={cn("text-base font-bold mb-0", className)}
    {...props}
  />
))
AppAlertTitle.displayName = "AppAlertTitle"

const AppAlertDescription = React.forwardRef<
  React.ComponentRef<typeof AlertDescription>,
  React.ComponentPropsWithoutRef<typeof AlertDescription>
>(({ className, ...props }, ref) => (
  <AlertDescription
    ref={ref}
    className={cn("text-sm text-muted-foreground", className)}
    {...props}
  />
))
AppAlertDescription.displayName = "AppAlertDescription"

const AppAlertContent = React.forwardRef<
  HTMLDivElement,
  React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => (
  <div
    ref={ref}
    className={cn("flex flex-col", className)}
    {...props}
  />
))
AppAlertContent.displayName = "AppAlertContent"

export { AppAlert, AppAlertTitle, AppAlertDescription, AppAlertContent }
export type { AppAlertProps }