cubby-ui
uialertsource: ok · hit
Alert
A alert component.
npx shadcn add "https://www.cubby-ui.dev/r/alert.json"free
No selection tags yet — empty means no evidence, not lack of support.
Dependencies
Bundle weight · lightclass-variance-authority
Files1 · source cached 10/12/2026, 2:41:54 AM
registry/default/alert/alert.tsx
"use client";
import { cva, type VariantProps } from "class-variance-authority";
import { mergeProps } from "@base-ui/react/merge-props";
import { useRender } from "@base-ui/react/use-render";
import { cn } from "@/lib/utils";
// A title and description share the row only when both are there: set here
// on the root, with a direct child as the target, rather than as group-has
// variants on each, which compile to `:has()` inside `:is(… *)` and make
// Chrome restyle the whole page on any DOM insertion (~8ms on a docs page).
const alertVariants = cva(
"relative w-full rounded-lg border border-border/70 px-4 py-3 pl-6 text-sm grid has-[>svg]:grid-cols-[auto_1fr] grid-cols-[0_1fr] has-[>svg]:gap-x-3 gap-y-0.5 items-start [&>svg]:row-span-2 [&>svg]:text-current shadow-sm has-[*[data-slot=alert-action]]:grid-cols-[0_1fr] has-[>svg]:has-[*[data-slot=alert-action]]:grid-cols-[auto_1fr] sm:has-[*[data-slot=alert-action]]:grid-cols-[0_1fr_auto] sm:has-[>svg]:has-[*[data-slot=alert-action]]:grid-cols-[auto_1fr_auto] [&>svg]:size-5 [&:has(>[data-slot=alert-description])>[data-slot=alert-title]]:row-span-1 [&:has(>[data-slot=alert-title])>[data-slot=alert-description]]:row-span-1 group before:absolute before:left-2 before:top-2 before:bottom-2 before:w-1 before:rounded-full bg-card dark:bg-muted",
{
variants: {
variant: {
default: "[&>svg]:text-card-foreground before:bg-border",
warning:
" [&>svg]:text-warning-foreground before:bg-warning-foreground",
danger: " [&>svg]:text-danger-foreground before:bg-danger-foreground",
info: " [&>svg]:text-info-foreground before:bg-info-foreground",
success:
" [&>svg]:text-success-foreground before:bg-success-foreground",
},
},
defaultVariants: {
variant: "default",
},
},
);
export interface AlertProps
extends useRender.ComponentProps<"div">, VariantProps<typeof alertVariants> {}
function Alert({ className, variant, render, ...props }: AlertProps) {
const defaultProps = {
"data-slot": "alert",
role: "alert" as const,
className: cn(alertVariants({ variant }), className),
};
const element = useRender({
defaultTagName: "div",
render,
props: mergeProps<"div">(defaultProps, props),
});
return element;
}
export type AlertTitleProps = useRender.ComponentProps<"h4">;
function AlertTitle({ className, render, ...props }: AlertTitleProps) {
const defaultProps = {
"data-slot": "alert-title",
className: cn(
"col-start-2 min-h-4 font-medium tracking-tight row-span-2 self-center text-card-foreground",
className,
),
};
const element = useRender({
defaultTagName: "h4",
render,
props: mergeProps<"h4">(defaultProps, props),
});
return element;
}
export type AlertDescriptionProps = useRender.ComponentProps<"div">;
function AlertDescription({
className,
render,
...props
}: AlertDescriptionProps) {
const defaultProps = {
"data-slot": "alert-description",
className: cn(
"col-start-2 grid justify-items-start gap-1 text-sm [&_p]:leading-relaxed row-span-2 self-center text-muted-foreground",
className,
),
};
const element = useRender({
defaultTagName: "div",
render,
props: mergeProps<"div">(defaultProps, props),
});
return element;
}
export type AlertActionProps = useRender.ComponentProps<"div">;
function AlertAction({ className, render, ...props }: AlertActionProps) {
const defaultProps = {
"data-slot": "alert-action",
className: cn(
"col-start-2 flex gap-2 mt-2 sm:col-start-3 sm:row-start-1 sm:row-span-2 sm:self-center sm:ml-4 sm:mt-0 ",
className,
),
};
const element = useRender({
defaultTagName: "div",
render,
props: mergeProps<"div">(defaultProps, props),
});
return element;
}
export { Alert, AlertTitle, AlertDescription, AlertAction };