import * as React from 'react'; import { cva, type VariantProps } from '@/lib/cva'; import { cn } from '@/lib/utils'; import { colorPalettes } from '@/lib/cva-presets'; const alertVariants = cva( cn( 'relative grid w-full grid-cols-[0_1fr] items-start rounded-md text-left', 'has-[>svg]:grid-cols-[auto_1fr]', '[&>svg]:translate-y-0.5 [&>svg]:text-current' ), { variants: { /* * CBAR's four treatments, drawn from the active palette's `--ctl-*` roles. * Unlike Button's, none of them carry a hover state: an alert is not * interactive, and lighting up under the cursor would suggest it is. */ variant: { solid: 'bg-(--ctl-solid) text-(--ctl-solid-fg)', subtle: 'bg-(--ctl-subtle) text-(--ctl-fg)', surface: 'border border-(--ctl-border) bg-(--ctl-subtle) text-(--ctl-fg)', outline: 'border border-(--ctl-border) text-(--ctl-fg)', /* * One-word shorthands, kept from the kit's pre-CBAR API. Like Badge's * and Button's, they paint from the semantic roles rather than the * `--ctl-*` palette roles — that pins their colour instead of putting * them in a specificity race with `colorPalette`. */ default: 'bg-card text-card-foreground', destructive: 'bg-card text-destructive *:data-[slot=alert-description]:text-destructive/90', success: 'bg-card text-success *:data-[slot=alert-description]:text-success/90', warning: 'bg-card text-warning *:data-[slot=alert-description]:text-warning/90', }, colorPalette: colorPalettes, /* * CBAR's three sizes. It names the smallest one "default"; this kit calls * it `sm` so the ladder reads like every other component's, and keeps `md` * as the default the way the rest of the kit does. * * Two things below are part of the size rather than an accident, both read * off the Alert set (`2446:316`): CBAR sets the small alert's title in * semibold and the two larger ones in medium, and it steps the description * 12 / 16 / 18px. The description size is therefore stated here on all * three rungs instead of being fixed on `AlertDescription` — it is a * property of the alert, not of the slot. */ size: { sm: cn( 'gap-y-1.5 p-3 text-sm has-[>svg]:gap-x-2.5 [&>svg]:size-4', '*:data-[slot=alert-title]:font-semibold', '*:data-[slot=alert-description]:text-xs' ), md: cn( 'gap-y-1.5 p-4 text-base has-[>svg]:gap-x-2.5 [&>svg]:size-5', '*:data-[slot=alert-description]:text-base' ), lg: cn( 'gap-y-1.5 p-4.5 text-lg has-[>svg]:gap-x-3 [&>svg]:size-6', '*:data-[slot=alert-description]:text-lg' ), }, }, defaultVariants: { variant: 'solid', colorPalette: 'primary', size: 'md', }, } ); export interface AlertProps extends React.ComponentProps<'div'>, VariantProps {} /** * Inline message about the state of the page or a section of it. * * Carries `role="alert"`, so screen readers announce it as soon as it appears — * do not use it for static explanatory copy. * * Status is expressed through `colorPalette` rather than a separate `status` * prop: `red` for errors, `green` for success, `yellow` for warnings, * `secondary` for information, and `primary` for the emphasised informational * treatment CBAR calls `info-secondary`. */ function Alert({ className, variant, colorPalette, size, ...props }: AlertProps) { return (
); } function AlertTitle({ className, ...props }: React.ComponentProps<'div'>) { return (
); } /** * Supporting copy under the title. It inherits the alert's own colour instead * of dimming to `muted-foreground`, because on a solid fill there is no muted * role that stays legible. * * Its font size comes from the alert's `size` (see `alertVariants` above), not * from here — CBAR steps the description with the control rather than pinning * it, so a `text-*` class on this element would have to be overridden at two of * the three rungs. */ function AlertDescription({ className, ...props }: React.ComponentProps<'div'>) { return (
); } export { Alert, AlertTitle, AlertDescription, alertVariants };