Alert

A hand-drawn alert callout styled with shadcn conventions. Like Card, it can carry a paper texture.

Alert
A hand-drawn callout whose outline is sketched around the message.
Default
Destructive
With action
Paper texturesPatterns from Hero Patterns
Title only

Installation

npx shadcn@latest add https://sketchcn.chuwii.com/r/alert.json

Styles

Alert leans on these rules from sketch.css. The shadcn CLI installs the file with sketch-provider; copying the component by hand means copying them too.

@keyframes sketch-icon-wiggle {
  0%,
  100% {
    transform: rotate(-5deg);
  }

  50% {
    transform: rotate(5deg);
  }
}

[data-paper]:not([data-paper="default"])::before,
[data-slot="card"][data-variant]:not([data-variant="default"])::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background-color: var(--paper-pattern);
  opacity: var(--paper-opacity, 0.4);
  mask-image: var(--paper-image);
  -webkit-mask-image: var(--paper-image);
  mask-repeat: repeat;
  -webkit-mask-repeat: repeat;
}

Read the whole file for the drawing variables, paper textures and reduced-motion rules.

Usage

import { Info } from "@matita/icons/react";
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";

export function FreshInk() {
  return (
    <Alert>
      <Info />
      <AlertTitle>Fresh ink</AlertTitle>
      <AlertDescription>No two outlines match.</AlertDescription>
    </Alert>
  );
}

An svg as the first child becomes the leading icon and the grid switches to two columns automatically.

Parts

PartDescription
AlertThe outlined container with role="alert".
AlertTitleHeading line.
AlertDescriptionSupporting text.
AlertActionPinned to the right edge, for a dismiss or undo control.

Props

PropTypeDefaultDescription
paper"default" | "polkadots" | "hexagons" | "graph" | "plus" | "filled-dots""default"Paper texture drawn behind the content.

variant is the standard default and destructive pair; destructive tints the drawn border along with the text.

Examples

Release note

import { Info } from "@matita/icons/react";
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";

export function ReleaseNote() {
  return (
    <Alert>
      <Info />
      <AlertTitle>Sketchcn 1.2 is out</AlertTitle>
      <AlertDescription>
        Alerts now draw their own outline with RoughJS.
      </AlertDescription>
    </Alert>
  );
}

Upload error

import { TriangleAlert } from "@matita/icons/react";
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";

export function UploadError() {
  return (
    <Alert variant="destructive">
      <TriangleAlert />
      <AlertTitle>Upload failed</AlertTitle>
      <AlertDescription>
        The file is larger than the 5 MB limit.
      </AlertDescription>
    </Alert>
  );
}

With action

import { CircleCheck } from "@matita/icons/react";
import {
  Alert,
  AlertAction,
  AlertDescription,
  AlertTitle,
} from "@/components/ui/alert";
import { Button } from "@/components/ui/button";

export function DraftSaved() {
  return (
    <Alert>
      <CircleCheck />
      <AlertTitle>Draft saved</AlertTitle>
      <AlertDescription>You can keep sketching from any device.</AlertDescription>
      <AlertAction>
        <Button size="xs" variant="ghost">
          Undo
        </Button>
      </AlertAction>
    </Alert>
  );
}

Paper texture

import { TriangleAlert } from "@matita/icons/react";
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";

export function MaintenanceNotice() {
  return (
    <Alert paper="graph" variant="destructive">
      <TriangleAlert />
      <AlertTitle>Scheduled maintenance</AlertTitle>
      <AlertDescription>
        Sketches are read-only until 18:00.
      </AlertDescription>
    </Alert>
  );
}

Steadier outline

import { Alert, AlertTitle } from "@/components/ui/alert";

export function CalmAlert() {
  return (
    <Alert className="[--sketch-roughness:0.4] [--sketch-bowing:0.6]">
      <AlertTitle>A steadier hand drew this one</AlertTitle>
    </Alert>
  );
}

Animation

Hovering the alert wiggles its leading icon with the sketch-icon-wiggle keyframe from sketch.css.

"hover:*:[svg:not([data-sketch-outline])]:animate-[sketch-icon-wiggle_180ms_ease-in-out_infinite] motion-reduce:hover:*:[svg:not([data-sketch-outline])]:animate-none"

The paper texture is drawn through data-paper, so --paper-pattern and --paper-opacity tune it. Alert already lowers the opacity to keep the text readable.

<Alert paper="graph" className="[--paper-opacity:0.4]">
  <AlertTitle>Denser paper</AlertTitle>
</Alert>