Component
Alert
The vault box on the lilac, the pale cyan info note, the sand warning banner with a note at the right, and a red error.
npx -y github:anwarlemu/inkbox-brand-cli#release add alertThe vault is zero-knowledge: all encryption and decryption happens in your browser. The server never sees your secrets.
Copy this API key now
For security, the full key cannot be shown again.
Webhook delivery failed
https://hooks.example.com/inkbox returned 502 three times. Deliveries are paused until it responds.
Usage
Use default for a panel that introduces a setup step (Initialize vault: glyph, 16px title, muted description). Use info for a fact the person should know (The vault is zero-knowledge), warning for something to act on now (Copy this API key now, with the reason in AlertAction), destructive for a failure. Lead with a filled Phosphor glyph.
Avoid
- A dark or saturated alert background
- More than one alert stacked for one message
- Dismissable warnings for security notes
- A bold title
Exports: Alert, AlertAction, AlertDescription, AlertTitle, alertVariants. Read the examples for composition and props.
Dependencies: class-variance-authority.
Example
import { InfoIcon, LockIcon, WarningIcon, XCircleIcon } from "@phosphor-icons/react/ssr";import { Alert, AlertAction, AlertDescription, AlertTitle } from "@/components/ui/alert";import { Button } from "@/components/ui/button";export function Preview() { return ( <Alert className="max-w-200"> <LockIcon weight="fill" /> <AlertTitle>Initialize vault</AlertTitle> <AlertDescription className="grid gap-2"> <p>Create an encrypted vault for your organization. The vault can store login credentials including MFA one-time passwords (OTP), SSH keys, API keys and other secrets for your agents.</p> <Alert variant="info"> <InfoIcon weight="fill" /> <AlertTitle>The vault is zero-knowledge: all encryption and decryption happens in your browser. The server never sees your secrets.</AlertTitle> </Alert> </AlertDescription> </Alert> );}export function Info() { return ( <Alert variant="info" className="max-w-200"> <InfoIcon weight="fill" /> <AlertTitle>The vault is zero-knowledge: all encryption and decryption happens in your browser. The server never sees your secrets.</AlertTitle> </Alert> );}export function Warning() { return ( <Alert variant="warning" className="max-w-180"> <WarningIcon weight="fill" /> <AlertTitle>Copy this API key now</AlertTitle> <AlertAction>For security, the full key cannot be shown again.</AlertAction> </Alert> );}export function Destructive() { return ( <Alert variant="destructive" className="max-w-180"> <XCircleIcon weight="fill" /> <AlertTitle>Webhook delivery failed</AlertTitle> <AlertDescription>https://hooks.example.com/inkbox returned 502 three times. Deliveries are paused until it responds.</AlertDescription> <AlertAction> <Button variant="outline" size="sm">Retry</Button> </AlertAction> </Alert> );}Source
import * as React from "react";import { cva, type VariantProps } from "class-variance-authority";import { cn } from "@/lib/utils";// The console's notes (Figma 427:2715). `default` is the vault box: a lilac panel with 8px corners, a 22px filled ink// glyph beside a 16px regular title, then a 14px muted description across the full width (it can hold an info note). `info` is the zero-knowledge note: pale cyan, 8px corners,// a filled info glyph and 14px deep teal text. `warning` is the copy-this-key banner: pale sand, 10px corners, a filled// warning glyph, a 14px medium title and a 13px note at the right (AlertAction). `destructive` borrows the failed// field's red. Put a Phosphor glyph first; the title and description line up beside it.const alertVariants = cva( "group/alert relative grid w-full grid-cols-[minmax(0,1fr)_auto] items-start gap-x-2.5 gap-y-0.5 font-sans text-body leading-body has-[>svg]:grid-cols-[auto_minmax(0,1fr)_auto] [&>svg]:shrink-0", { variants: { variant: { default: "items-center rounded-control bg-subtle px-3.5 py-3 text-fg [&>svg]:size-6 [&>svg]:text-icon-default [&>[data-slot=alert-description]]:col-span-full [&>[data-slot=alert-description]]:col-start-1 [&>[data-slot=alert-description]]:text-fg-muted [&>[data-slot=alert-title]]:text-body-lg [&>[data-slot=alert-title]]:leading-snug", info: "rounded-control bg-info-bg px-4 py-2 text-info-fg [&>svg]:size-5 [&>svg]:text-info", warning: "rounded-panel bg-warning-bg px-4 py-2 text-warning-fg [&>svg]:size-5.5 [&>svg]:text-warning [&>[data-slot=alert-action]]:text-warning-muted [&>[data-slot=alert-description]]:text-warning-muted [&>[data-slot=alert-title]]:font-medium", destructive: "rounded-control border border-danger bg-surface px-3.5 py-3 text-danger [&>svg]:size-5.5 [&>svg]:text-danger-strong [&>[data-slot=alert-description]]:text-fg-secondary [&>[data-slot=alert-title]]:font-medium", }, }, defaultVariants: { variant: "default" }, },);function Alert({ className, variant, ...props }: React.ComponentProps<"div"> & VariantProps<typeof alertVariants>) { return <div data-slot="alert" data-variant={variant ?? "default"} role="alert" className={cn(alertVariants({ variant }), className)} {...props} />;}function AlertTitle({ className, ...props }: React.ComponentProps<"div">) { return ( <div data-slot="alert-title" className={cn( "col-start-1 min-w-0 leading-body group-has-[>svg]/alert:col-start-2", className, )} {...props} /> );}function AlertDescription({ className, ...props }: React.ComponentProps<"div">) { return ( <div data-slot="alert-description" className={cn( "col-start-1 min-w-0 text-body leading-body group-has-[>svg]/alert:col-start-2 [&_p]:leading-body", className, )} {...props} /> );}/** What sits at the right of an alert: a note (For security, the full key cannot be shown again) or a button. */function AlertAction({ className, ...props }: React.ComponentProps<"div">) { return ( <div data-slot="alert-action" className={cn("col-start-2 row-span-2 row-start-1 self-center text-right text-body-sm group-has-[>svg]/alert:col-start-3", className)} {...props} /> );}export { Alert, AlertAction, AlertDescription, AlertTitle, alertVariants };Reference: Figma 427:2715: Vault (Initialize vault, zero-knowledge note), Modal - Created (Copy this API key now).