{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "callout",
  "type": "registry:ui",
  "title": "Callout",
  "description": "An inline note in the page flow: a tip, a heads-up or a result to act on. A raised surface with a 16px icon, a title, a line of detail, and an optional action and close button. Only the icon takes the status color, and a hidden word before the title says the same thing, so there is never a rail, a tinted fill or a colored border. It measures its own width and drops the action below the text under 28rem.",
  "registryDependencies": [
    "https://littmd.vercel.app/r/litt.json",
    "https://littmd.vercel.app/r/button.json",
    "https://littmd.vercel.app/r/icons.json"
  ],
  "files": [
    {
      "path": "registry/litt/ui/callout.tsx",
      "type": "registry:ui",
      "content": "\"use client\";\n// @litt/callout 2026.11.06. What changed: https://littmd.vercel.app/changelog.md\n\n/**\n * Callout: an inline note in the page flow. A tip, a heads-up, or a result to act on, such as\n * \"Try H to snooze\" or \"Your Framer plan renews in 3 days\".\n *\n * - Flat: a grey card (surface-3) with no hairline.\n * - Surface (components.md, Callout): `.litt-raised`, because it sits in the flow. Never glass (R3),\n *   no shadow (R3), and never a left rail, a tinted background or a colored border. A status that\n *   colored the whole box would turn a note into an alarm, and a rail is the one thing litt bans.\n * - Anatomy: a 16px icon at the start, aligned with the title's first line; the title (body, fg);\n *   an optional description (small, fg-subtle); an optional `action` at the end (an sm secondary\n *   Button or a Kbd); and, with `onDismiss`, an icon-only ghost close button at the top end.\n *   Padding is space-4 and the gap space-3. Everything lines up on the title's first line through\n *   a one-line-tall cell (`1lh`), so a taller button hangs evenly above and below the line.\n * - Color: only the icon, in the tone's status color. Neutral is fg-subtle. A non-neutral tone also\n *   puts hidden text before the title (\"Warning: \"), so color is never the only signal.\n * - Container: the callout measures itself (a container query), not the window. Under 28rem wide\n *   the action drops below the text, aligned with it, so a narrow column or a phone never squeezes\n *   the words.\n * - Semantics: a `note` by default. `live` makes it a `status`, or an `alert` for danger, for a\n *   callout that appears after something the person did, so a screen reader hears it arrive.\n * - Touch: the close button and a Button action grow to 44px on a coarse pointer, and a Kbd action\n *   is hidden, as every key hint is on touch.\n * - Motion: none of its own. Dismissing just unmounts it, so the caller decides what replaces it.\n */\nimport type { HTMLAttributes, ReactNode } from \"react\";\nimport { Button } from \"./button\";\nimport { CheckCircleIcon, InfoIcon, WarningIcon, XCircleIcon, XIcon } from \"./icons\";\n\n/** Neutral for a tip or a note. Success, warning and danger color the icon and add a hidden word before the title. */\nexport type CalloutTone = \"neutral\" | \"success\" | \"warning\" | \"danger\";\n\nconst ICON: Record<CalloutTone, ReactNode> = {\n  neutral: <InfoIcon />,\n  success: <CheckCircleIcon />,\n  warning: <WarningIcon />,\n  danger: <XCircleIcon />,\n};\n\nconst COLOR: Record<CalloutTone, string> = {\n  neutral: \"text-litt-fg-subtle\",\n  success: \"text-litt-success\",\n  warning: \"text-litt-warning\",\n  danger: \"text-litt-danger\",\n};\n\n/* What a screen reader hears before the title, so the icon's color is never the only signal. */\nconst SAID: Record<CalloutTone, string> = { neutral: \"\", success: \"Success: \", warning: \"Warning: \", danger: \"Error: \" };\n\nexport type CalloutProps = Omit<HTMLAttributes<HTMLDivElement>, \"title\"> & {\n  /** What the note says, in a short sentence: \"Your Framer plan renews in 3 days\". */\n  title: ReactNode;\n  /** One line of detail under the title, in the quieter tone. */\n  description?: ReactNode;\n  /** Neutral is the default. Success, warning and danger color the icon, and a hidden word before the title says the same thing. */\n  tone?: CalloutTone;\n  /** Replaces the tone's icon, such as a lightbulb for a tip. It is drawn in the tone's color, so make it a 16px icon in currentColor. */\n  icon?: ReactNode;\n  /** The one thing to do about it, at the end: an sm secondary Button or a Kbd. It drops below the text when the callout is under 28rem wide. */\n  action?: ReactNode;\n  /** Shows an icon-only close button at the top end and calls this when it is pressed. Remove the callout in the handler, because it does not hide itself. */\n  onDismiss?: () => void;\n  /** Set it for a callout that appears after something the person did: a screen reader announces it as a status, or as an alert for danger. */\n  live?: boolean;\n  /** Extra classes for the callout, such as a top margin. It fills the width of its container. */\n  className?: string;\n};\n\n/** An inline note: a raised surface with an icon, a title, a line of detail, an optional action and an optional close button. */\nexport function Callout({\n  title,\n  description,\n  tone = \"neutral\",\n  icon,\n  action,\n  onDismiss,\n  live = false,\n  className = \"\",\n  ...rest\n}: CalloutProps) {\n  const role = live ? (tone === \"danger\" ? \"alert\" : \"status\") : \"note\";\n  /* With an action there is a column for it; without one the close button takes its place. */\n  const cols = action\n    ? \"grid-cols-[auto_minmax(0,1fr)_auto_auto] @max-[28rem]:grid-cols-[auto_minmax(0,1fr)_auto]\"\n    : \"grid-cols-[auto_minmax(0,1fr)_auto]\";\n  const closeAt = action ? \"col-start-4 @max-[28rem]:col-start-3\" : \"col-start-3\";\n  return (\n    <div role={role} className={`@container ${className}`} {...rest}>\n      <div className={`litt-raised in-[[data-material=flat]]:bg-litt-surface-3 in-[[data-material=flat]]:shadow-none grid items-start gap-x-3 p-4 ${cols}`}>\n        <span className={`flex h-[1lh] items-center text-litt-body [&>svg]:size-4 [&>svg]:shrink-0 ${COLOR[tone]}`}>\n          {icon ?? ICON[tone]}\n        </span>\n        <div className=\"min-w-0\">\n          <p className=\"text-litt-body font-litt-title text-litt-fg\">\n            {SAID[tone] && <span className=\"sr-only\">{SAID[tone]}</span>}\n            {title}\n          </p>\n          {description && <p className=\"mt-1 text-litt-small text-litt-fg-subtle\">{description}</p>}\n        </div>\n        {action && (\n          <div\n            className={\n              \"col-start-3 flex h-[1lh] items-center text-litt-body \" +\n              \"@max-[28rem]:col-start-2 @max-[28rem]:row-start-2 @max-[28rem]:mt-3 @max-[28rem]:h-auto \" +\n              \"pointer-coarse:[&_button]:h-litt-control-md pointer-coarse:has-[>kbd]:hidden\"\n            }\n          >\n            {action}\n          </div>\n        )}\n        {onDismiss && (\n          <div className={`row-start-1 flex h-[1lh] items-center text-litt-body ${closeAt}`}>\n            <Button\n              size=\"sm\"\n              variant=\"ghost\"\n              iconOnly\n              aria-label=\"Dismiss\"\n              className=\"-mr-1 pointer-coarse:-mr-2.5 pointer-coarse:h-litt-control-md pointer-coarse:w-litt-control-md\"\n              onClick={onDismiss}\n            >\n              <XIcon />\n            </Button>\n          </div>\n        )}\n      </div>\n    </div>\n  );\n}\n",
      "target": "components/litt/callout.tsx"
    }
  ],
  "docs": "Import Callout from components/litt/callout. Pass a title, a description and a tone, and an action (an sm Button or a Kbd) or onDismiss when there is something to do. Set live for a callout that appears after an action. It fills the width of its container, so give the container a width.",
  "meta": {
    "version": "2026.11.06",
    "released": "2026-11-06",
    "changelog": "https://littmd.vercel.app/changelog.md"
  }
}
