Heads up!
You can add components and dependencies to your app using the cli.
1import { Callout } from "@/components/ui/pxl/callout";2
3export default function CalloutDemo() {4 return (5 <div className="max-w-md">6 <Callout variant="info" title="Heads up!">7 You can add components and dependencies to your app using the cli.8 </Callout>9 </div>10 );11}The Callout component is a styled and customized version of the Alert component including additional features such as collapsible content.
Installation
Section titled “Installation”pnpm dlx shadcn@latest add pxl-ui/registry/callout
Install the following dependencies:
pnpm add @base-ui/react
Copy and paste the following code into your project.
1import type { CollapsibleRootChangeEventDetails } from "@base-ui/react/collapsible";2import { cva, type VariantProps } from "class-variance-authority";3import type { ComponentProps, SVGProps } from "react";4
5import {6 Collapsible,7 CollapsibleContent,8 CollapsibleTrigger,9} from "@/components/ui/pxl/collapsible";10import { cn } from "@/lib/utils";11
12const calloutVariants = cva(13 "group/callout relative grid w-full gap-0.5 rounded-none text-card-foreground px-2.5 py-2 text-left text-xs has-data-[slot=callout-action]:relative has-data-[slot=callout-action]:pr-18 has-[>svg]:grid-cols-[auto_1fr] has-[>svg]:gap-x-2 *:[svg]:row-span-2 *:[svg]:translate-y-0 *:[svg:not([class*='size-'])]:size-4",14 {15 variants: {16 border: {17 solid:18 "pixel-border pixel-size-lg px-[calc(--spacing(2.5)+var(--pixel-size))] py-[calc(--spacing(2)+var(--pixel-size))]",19 rounded:20 "pixel-rounded pixel-size-lg px-[calc(--spacing(2.5)+var(--pixel-size))] py-[calc(--spacing(2)+var(--pixel-size))]",21 none: "",22 },23 variant: {24 abstract:25 "bg-info pixel-color-info-foreground *:data-[slot=callout-title]:text-info-foreground *:data-[slot=callout-description]:text-foreground *:[svg]:text-info-foreground",26 attention:27 "bg-warning pixel-color-warning-foreground *:data-[slot=callout-title]:text-warning-foreground *:data-[slot=callout-description]:text-foreground *:[svg]:text-warning-foreground",28 bug: "bg-danger pixel-color-danger-foreground *:data-[slot=callout-title]:text-danger-foreground *:data-[slot=callout-description]:text-foreground *:[svg]:text-danger-foreground",29 caution:30 "bg-warning pixel-color-warning-foreground *:data-[slot=callout-title]:text-warning-foreground *:data-[slot=callout-description]:text-foreground *:[svg]:text-warning-foreground",31 check:32 "bg-success pixel-color-success-foreground *:data-[slot=callout-title]:text-success-foreground *:data-[slot=callout-description]:text-foreground *:[svg]:text-success-foreground",33 cite: "bg-card pixel-color-border *:data-[slot=callout-title]:text-card-foreground *:data-[slot=callout-description]:text-muted-foreground *:[svg]:text-card-foreground",34 danger:35 "bg-danger pixel-color-danger-foreground *:data-[slot=callout-title]:text-danger-foreground *:data-[slot=callout-description]:text-foreground *:[svg]:text-danger-foreground",36 default:37 "bg-card pixel-color-border *:data-[slot=callout-title]:text-card-foreground *:data-[slot=callout-description]:text-muted-foreground *:[svg]:text-card-foreground",38 done: "bg-success pixel-color-success-foreground *:data-[slot=callout-title]:text-success-foreground *:data-[slot=callout-description]:text-foreground *:[svg]:text-success-foreground",39 error:40 "bg-danger pixel-color-danger-foreground *:data-[slot=callout-title]:text-danger-foreground *:data-[slot=callout-description]:text-foreground *:[svg]:text-danger-foreground",41 example:42 "bg-violet-100 dark:bg-violet-800 pixel-color-violet-600 dark:pixel-color-violet-400 *:data-[slot=callout-title]:text-violet-600 dark:*:data-[slot=callout-title]:text-violet-400 *:data-[slot=callout-description]:text-foreground *:[svg]:text-violet-600 dark:*:[svg]:text-violet-400",43 fail: "bg-danger pixel-color-danger-foreground *:data-[slot=callout-title]:text-danger-foreground *:data-[slot=callout-description]:text-foreground *:[svg]:text-danger-foreground",44 failure:45 "bg-danger pixel-color-danger-foreground *:data-[slot=callout-title]:text-danger-foreground *:data-[slot=callout-description]:text-foreground *:[svg]:text-danger-foreground",46 faq: "bg-warning pixel-color-warning-foreground *:data-[slot=callout-title]:text-warning-foreground *:data-[slot=callout-description]:text-foreground *:[svg]:text-warning-foreground",47 help: "bg-warning pixel-color-warning-foreground *:data-[slot=callout-title]:text-warning-foreground *:data-[slot=callout-description]:text-foreground *:[svg]:text-warning-foreground",48 hint: "bg-info pixel-color-info-foreground *:data-[slot=callout-title]:text-info-foreground *:data-[slot=callout-description]:text-foreground *:[svg]:text-info-foreground",49 important:50 "bg-info pixel-color-info-foreground *:data-[slot=callout-title]:text-info-foreground *:data-[slot=callout-description]:text-foreground *:[svg]:text-info-foreground",51 info: "bg-primary pixel-color-primary-foreground *:data-[slot=callout-title]:text-primary-foreground *:data-[slot=callout-description]:text-foreground *:[svg]:text-primary-foreground",52 missing:53 "bg-danger pixel-color-danger-foreground *:data-[slot=callout-title]:text-danger-foreground *:data-[slot=callout-description]:text-foreground *:[svg]:text-danger-foreground",54 note: "bg-primary pixel-color-primary-foreground *:data-[slot=callout-title]:text-primary-foreground *:data-[slot=callout-description]:text-foreground *:[svg]:text-primary-foreground",55 question:56 "bg-warning pixel-color-warning-foreground *:data-[slot=callout-title]:text-warning-foreground *:data-[slot=callout-description]:text-foreground *:[svg]:text-warning-foreground",57 quote:58 "bg-muted pixel-color-muted-foreground *:data-[slot=callout-title]:text-muted-foreground *:data-[slot=callout-description]:text-foreground *:[svg]:text-muted-foreground",59 success:60 "bg-success pixel-color-success-foreground *:data-[slot=callout-title]:text-success-foreground *:data-[slot=callout-description]:text-foreground *:[svg]:text-success-foreground",61 summary:62 "bg-info pixel-color-info-foreground *:data-[slot=callout-title]:text-info-foreground *:data-[slot=callout-description]:text-foreground *:[svg]:text-info-foreground",63 tip: "bg-info pixel-color-info-foreground *:data-[slot=callout-title]:text-info-foreground *:data-[slot=callout-description]:text-foreground *:[svg]:text-info-foreground",64 tldr: "bg-info pixel-color-info-foreground *:data-[slot=callout-title]:text-info-foreground *:data-[slot=callout-description]:text-foreground *:[svg]:text-info-foreground",65 todo: "bg-primary pixel-color-primary-foreground *:data-[slot=callout-title]:text-primary-foreground *:data-[slot=callout-description]:text-foreground *:[svg]:text-primary-foreground",66 warning:67 "bg-warning pixel-color-warning-foreground *:data-[slot=callout-title]:text-warning-foreground *:data-[slot=callout-description]:text-foreground *:[svg]:text-warning-foreground",68 },69 },70 defaultVariants: {71 border: "solid",72 variant: "default",73 },74 compoundVariants: [75 {76 border: "rounded",77 variant: "default",78 className: "bg-border/30 dark:bg-card",79 },80 ],81 },82);83
84type CalloutVariant = NonNullable<85 VariantProps<typeof calloutVariants>["variant"]86>;87
88const CalloutIcon: Record<89 CalloutVariant,90 ((props: SVGProps<SVGSVGElement>) => React.JSX.Element) | undefined91> = {92 abstract(props: SVGProps<SVGSVGElement>) {93 return (94 <svg95 xmlns="http://www.w3.org/2000/svg"96 fill="currentColor"97 viewBox="0 0 24 24"98 {...props}99 >100 <path d="M18 22H6v-2h12v2ZM6 20H4V6h2v14Zm14 0h-2V6h2v14Zm-8-4H8v-2h4v2Zm4-4H8v-2h8v2Zm0-8h2v2h-2v2H8V6H6V4h2V2h8v2Zm-6 2h4V4h-4v2Z"></path>101 </svg>102 );103 },104 attention(props: SVGProps<SVGSVGElement>) {105 return (106 <svg107 xmlns="http://www.w3.org/2000/svg"108 fill="currentColor"109 viewBox="0 0 24 24"110 {...props}111 >112 <path d="M14 22h-4v-2h4v2Zm-4-2H8v-2h2v2Zm6 0h-2v-2h2v2Zm-8-2H6v-2h2v2Zm10 0h-2v-2h2v2Zm-5-1h-2v-2h2v2Zm-7-1H4v-2h2v2Zm14 0h-2v-2h2v2ZM4 14H2v-4h2v4Zm18 0h-2v-4h2v4Zm-9-7v6h-2V7h2Zm-7 3H4V8h2v2Zm14 0h-2V8h2v2ZM8 8H6V6h2v2Zm10 0h-2V6h2v2Zm-8-2H8V4h2v2Zm6 0h-2V4h2v2Zm-2-2h-4V2h4v2Z" />113 </svg>114 );115 },116 bug(props: SVGProps<SVGSVGElement>) {117 return (118 <svg119 xmlns="http://www.w3.org/2000/svg"120 fill="currentColor"121 viewBox="0 0 24 24"122 {...props}123 >124 <path d="M2 5h2v4H2zm20 0h-2v4h2zM4 9h2v2H4zm16 0h-2v2h2zM2 13h4v2H2zm20 0h-4v2h4zM4 17h2v2H4zm16 0h-2v2h2zM2 19h2v2H2zm20 0h-2v2h2zM6 11h12v2H6z" />125 <path d="M6 7h2v12H6zm10 0h2v12h-2zM8 19h8v2H8zM8 5h8v2H8z" />126 <path d="M11 15h2v6h-2zM8 1h2v6H8zm6 0h2v6h-2z" />127 </svg>128 );129 },130 caution(props: SVGProps<SVGSVGElement>) {131 return (132 <svg133 xmlns="http://www.w3.org/2000/svg"134 fill="currentColor"135 viewBox="0 0 24 24"136 {...props}137 >138 <path d="M14 22h-4v-2h4v2Zm-4-2H8v-2h2v2Zm6 0h-2v-2h2v2Zm-8-2H6v-2h2v2Zm10 0h-2v-2h2v2Zm-5-1h-2v-2h2v2Zm-7-1H4v-2h2v2Zm14 0h-2v-2h2v2ZM4 14H2v-4h2v4Zm18 0h-2v-4h2v4Zm-9-7v6h-2V7h2Zm-7 3H4V8h2v2Zm14 0h-2V8h2v2ZM8 8H6V6h2v2Zm10 0h-2V6h2v2Zm-8-2H8V4h2v2Zm6 0h-2V4h2v2Zm-2-2h-4V2h4v2Z" />139 </svg>140 );141 },142 check(props: SVGProps<SVGSVGElement>) {143 return (144 <svg145 xmlns="http://www.w3.org/2000/svg"146 fill="currentColor"147 viewBox="0 0 24 24"148 {...props}149 >150 <path d="M10 18H8v-2h2v2Zm-2-2H6v-2h2v2Zm4-2v2h-2v-2h2Zm-6 0H4v-2h2v2Zm8 0h-2v-2h2v2Zm2-2h-2v-2h2v2Zm2-2h-2V8h2v2Zm2-2h-2V6h2v2Z"></path>151 </svg>152 );153 },154 cite(props: SVGProps<SVGSVGElement>) {155 return (156 <svg157 xmlns="http://www.w3.org/2000/svg"158 fill="currentColor"159 viewBox="0 0 24 24"160 {...props}161 >162 <path d="M10 2H2v1H1v8h1v1h5v4H6v1H4v1H3v3h1v1h2v-1h2v-1h1v-1h1v-2h1V3h-1zm-1 9H8v-1H3V4h6zm13-8V2h-8v1h-1v8h1v1h5v4h-1v1h-2v1h-1v3h1v1h2v-1h2v-1h1v-1h1v-2h1V3zm-7 7V4h6v7h-1v-1z" />163 </svg>164 );165 },166 danger(props: SVGProps<SVGSVGElement>) {167 return (168 <svg169 xmlns="http://www.w3.org/2000/svg"170 fill="currentColor"171 viewBox="0 0 24 24"172 {...props}173 >174 <path d="M4 13h8v6h2v2h-2v2h-2v-8H2v-4h2v2Zm12 6h-2v-2h2v2Zm2-2h-2v-2h2v2Zm2-2h-2v-2h2v2Zm-6-6h8v4h-2v-2h-8V5h-2V3h2V1h2v8Zm-8 2H4V9h2v2Zm2-2H6V7h2v2Zm2-2H8V5h2v2Z" />175 </svg>176 );177 },178 default: undefined,179 done(props: SVGProps<SVGSVGElement>) {180 return (181 <svg182 xmlns="http://www.w3.org/2000/svg"183 fill="currentColor"184 viewBox="0 0 24 24"185 {...props}186 >187 <path d="M10 18H8v-2h2v2Zm-2-2H6v-2h2v2Zm4-2v2h-2v-2h2Zm-6 0H4v-2h2v2Zm8 0h-2v-2h2v2Zm2-2h-2v-2h2v2Zm2-2h-2V8h2v2Zm2-2h-2V6h2v2Z"></path>188 </svg>189 );190 },191 error(props: SVGProps<SVGSVGElement>) {192 return (193 <svg194 xmlns="http://www.w3.org/2000/svg"195 fill="currentColor"196 viewBox="0 0 24 24"197 {...props}198 >199 <path d="M4 13h8v6h2v2h-2v2h-2v-8H2v-4h2v2Zm12 6h-2v-2h2v2Zm2-2h-2v-2h2v2Zm2-2h-2v-2h2v2Zm-6-6h8v4h-2v-2h-8V5h-2V3h2V1h2v8Zm-8 2H4V9h2v2Zm2-2H6V7h2v2Zm2-2H8V5h2v2Z" />200 </svg>201 );202 },203 example(props: SVGProps<SVGSVGElement>) {204 return (205 <svg206 xmlns="http://www.w3.org/2000/svg"207 fill="currentColor"208 viewBox="0 0 24 24"209 {...props}210 >211 <path d="M10 5h12v2H10zm0 4h8v2h-8zm0 4h12v2H10zm0 4h8v2h-8zm-4-6H4V9h2v2ZM4 9H2V7h2v2Zm4 0H6V7h2v2ZM6 7H4V5h2v2Zm-2 6h2v2H4zm0 4h2v2H4zm-2 0v-2h2v2zm4 0v-2h2v2z" />212 </svg>213 );214 },215 fail(props: SVGProps<SVGSVGElement>) {216 return (217 <svg218 xmlns="http://www.w3.org/2000/svg"219 fill="currentColor"220 viewBox="0 0 24 24"221 {...props}222 >223 <path d="M7 19H5v-2h2v2Zm12 0h-2v-2h2v2ZM9 15v2H7v-2h2Zm8 2h-2v-2h2v2Zm-6-2H9v-2h2v2Zm4 0h-2v-2h2v2Zm-2-2h-2v-2h2v2Zm-2-2H9V9h2v2Zm4 0h-2V9h2v2ZM9 9H7V7h2v2Zm8 0h-2V7h2v2ZM7 7H5V5h2v2Zm12 0h-2V5h2v2Z" />224 </svg>225 );226 },227 failure(props: SVGProps<SVGSVGElement>) {228 return (229 <svg230 xmlns="http://www.w3.org/2000/svg"231 fill="currentColor"232 viewBox="0 0 24 24"233 {...props}234 >235 <path d="M7 19H5v-2h2v2Zm12 0h-2v-2h2v2ZM9 15v2H7v-2h2Zm8 2h-2v-2h2v2Zm-6-2H9v-2h2v2Zm4 0h-2v-2h2v2Zm-2-2h-2v-2h2v2Zm-2-2H9V9h2v2Zm4 0h-2V9h2v2ZM9 9H7V7h2v2Zm8 0h-2V7h2v2ZM7 7H5V5h2v2Zm12 0h-2V5h2v2Z" />236 </svg>237 );238 },239 faq(props: SVGProps<SVGSVGElement>) {240 return (241 <svg242 xmlns="http://www.w3.org/2000/svg"243 fill="currentColor"244 viewBox="0 0 24 24"245 {...props}246 >247 <path d="M18 22H6V20H18V22ZM6 20H4V18H6V20ZM20 20H18V18H20V20ZM4 18H2V6H4V18ZM13 18H11V16H13V18ZM22 18H20V6H22V18ZM15 13H13V15H11V11H15V13ZM17 11H15V8H17V11ZM9 10H7V8H9V10ZM15 8H9V6H15V8ZM6 6H4V4H6V6ZM20 6H18V4H20V6ZM18 4H6V2H18V4Z"></path>248 </svg>249 );250 },251 help(props: SVGProps<SVGSVGElement>) {252 return (253 <svg254 xmlns="http://www.w3.org/2000/svg"255 fill="currentColor"256 viewBox="0 0 24 24"257 {...props}258 >259 <path d="M18 22H6V20H18V22ZM6 20H4V18H6V20ZM20 20H18V18H20V20ZM4 18H2V6H4V18ZM13 18H11V16H13V18ZM22 18H20V6H22V18ZM15 13H13V15H11V11H15V13ZM17 11H15V8H17V11ZM9 10H7V8H9V10ZM15 8H9V6H15V8ZM6 6H4V4H6V6ZM20 6H18V4H20V6ZM18 4H6V2H18V4Z"></path>260 </svg>261 );262 },263 hint(props: SVGProps<SVGSVGElement>) {264 return (265 <svg266 xmlns="http://www.w3.org/2000/svg"267 fill="currentColor"268 viewBox="0 0 24 24"269 {...props}270 >271 <path d="M16 22H8v-2h8v2Zm-8-2H6v-2h2v2Zm10 0h-2v-2h2v2ZM6 18H4v-6h2v6Zm14 0h-2v-8h2v8Zm-10-4H8v-2h2v2Zm-2-2H6V8h2v4Zm4-8h2v2h-2v6h-2V2h2v2Zm6 6h-2V8h2v2Zm-2-2h-2V6h2v2Z"></path>272 </svg>273 );274 },275 important(props: SVGProps<SVGSVGElement>) {276 return (277 <svg278 xmlns="http://www.w3.org/2000/svg"279 fill="currentColor"280 viewBox="0 0 24 24"281 {...props}282 >283 <path d="M16 22H8v-2h8v2Zm-8-2H6v-2h2v2Zm10 0h-2v-2h2v2ZM6 18H4v-6h2v6Zm14 0h-2v-8h2v8Zm-10-4H8v-2h2v2Zm-2-2H6V8h2v4Zm4-8h2v2h-2v6h-2V2h2v2Zm6 6h-2V8h2v2Zm-2-2h-2V6h2v2Z"></path>284 </svg>285 );286 },287 info(props: SVGProps<SVGSVGElement>) {288 return (289 <svg290 xmlns="http://www.w3.org/2000/svg"291 fill="currentColor"292 viewBox="0 0 24 24"293 {...props}294 >295 <path d="M18 22H6V20H18V22ZM6 20H4V18H6V20ZM20 20H18V18H20V20ZM4 18H2V6H4V18ZM22 18H20V6H22V18ZM13 17H11V11H13V17ZM13 9H11V7H13V9ZM6 6H4V4H6V6ZM20 6H18V4H20V6ZM18 4H6V2H18V4Z" />296 </svg>297 );298 },299 missing(props: SVGProps<SVGSVGElement>) {300 return (301 <svg302 xmlns="http://www.w3.org/2000/svg"303 fill="currentColor"304 viewBox="0 0 24 24"305 {...props}306 >307 <path d="M7 19H5v-2h2v2Zm12 0h-2v-2h2v2ZM9 15v2H7v-2h2Zm8 2h-2v-2h2v2Zm-6-2H9v-2h2v2Zm4 0h-2v-2h2v2Zm-2-2h-2v-2h2v2Zm-2-2H9V9h2v2Zm4 0h-2V9h2v2ZM9 9H7V7h2v2Zm8 0h-2V7h2v2ZM7 7H5V5h2v2Zm12 0h-2V5h2v2Z" />308 </svg>309 );310 },311 note(props: SVGProps<SVGSVGElement>) {312 return (313 <svg314 xmlns="http://www.w3.org/2000/svg"315 fill="currentColor"316 viewBox="0 0 24 24"317 {...props}318 >319 <path d="M4 20h4v2H2v-6h2v4Zm6 0H8v-2h2v2Zm2-2h-2v-2h2v2Zm-6-2H4v-2h2v2Zm8 0h-2v-2h2v2Zm-6-2H6v-2h2v2Zm8 0h-2v-2h2v2Zm-6-2H8v-2h2v2Zm8 0h-2v-2h2v2Zm-6-2h-2V8h2v2Zm4 0h-2V8h2v2Zm4 0h-2V8h2v2Zm-6-2h-2V6h2v2Zm8 0h-2V6h2v2Zm-6-2h-2V4h2v2Zm4 0h-2V4h2v2Zm-2-2h-2V2h2v2Z"></path>320 </svg>321 );322 },323 question(props: SVGProps<SVGSVGElement>) {324 return (325 <svg326 xmlns="http://www.w3.org/2000/svg"327 fill="currentColor"328 viewBox="0 0 24 24"329 {...props}330 >331 <path d="M18 22H6V20H18V22ZM6 20H4V18H6V20ZM20 20H18V18H20V20ZM4 18H2V6H4V18ZM13 18H11V16H13V18ZM22 18H20V6H22V18ZM15 13H13V15H11V11H15V13ZM17 11H15V8H17V11ZM9 10H7V8H9V10ZM15 8H9V6H15V8ZM6 6H4V4H6V6ZM20 6H18V4H20V6ZM18 4H6V2H18V4Z"></path>332 </svg>333 );334 },335 quote(props: SVGProps<SVGSVGElement>) {336 return (337 <svg338 xmlns="http://www.w3.org/2000/svg"339 fill="currentColor"340 viewBox="0 0 24 24"341 {...props}342 >343 <path d="M10 2H2v1H1v8h1v1h5v4H6v1H4v1H3v3h1v1h2v-1h2v-1h1v-1h1v-2h1V3h-1zm-1 9H8v-1H3V4h6zm13-8V2h-8v1h-1v8h1v1h5v4h-1v1h-2v1h-1v3h1v1h2v-1h2v-1h1v-1h1v-2h1V3zm-7 7V4h6v7h-1v-1z" />344 </svg>345 );346 },347 success(props: SVGProps<SVGSVGElement>) {348 return (349 <svg350 xmlns="http://www.w3.org/2000/svg"351 fill="currentColor"352 viewBox="0 0 24 24"353 {...props}354 >355 <path d="M10 18H8v-2h2v2Zm-2-2H6v-2h2v2Zm4-2v2h-2v-2h2Zm-6 0H4v-2h2v2Zm8 0h-2v-2h2v2Zm2-2h-2v-2h2v2Zm2-2h-2V8h2v2Zm2-2h-2V6h2v2Z"></path>356 </svg>357 );358 },359 summary(props: SVGProps<SVGSVGElement>) {360 return (361 <svg362 xmlns="http://www.w3.org/2000/svg"363 fill="currentColor"364 viewBox="0 0 24 24"365 {...props}366 >367 <path d="M18 22H6v-2h12v2ZM6 20H4V6h2v14Zm14 0h-2V6h2v14Zm-8-4H8v-2h4v2Zm4-4H8v-2h8v2Zm0-8h2v2h-2v2H8V6H6V4h2V2h8v2Zm-6 2h4V4h-4v2Z"></path>368 </svg>369 );370 },371 tip(props: SVGProps<SVGSVGElement>) {372 return (373 <svg374 xmlns="http://www.w3.org/2000/svg"375 fill="currentColor"376 viewBox="0 0 24 24"377 {...props}378 >379 <path d="M16 22H8v-2h8v2Zm-8-2H6v-2h2v2Zm10 0h-2v-2h2v2ZM6 18H4v-6h2v6Zm14 0h-2v-8h2v8Zm-10-4H8v-2h2v2Zm-2-2H6V8h2v4Zm4-8h2v2h-2v6h-2V2h2v2Zm6 6h-2V8h2v2Zm-2-2h-2V6h2v2Z"></path>380 </svg>381 );382 },383 tldr(props: SVGProps<SVGSVGElement>) {384 return (385 <svg386 xmlns="http://www.w3.org/2000/svg"387 fill="currentColor"388 viewBox="0 0 24 24"389 {...props}390 >391 <path d="M18 22H6v-2h12v2ZM6 20H4V6h2v14Zm14 0h-2V6h2v14Zm-8-4H8v-2h4v2Zm4-4H8v-2h8v2Zm0-8h2v2h-2v2H8V6H6V4h2V2h8v2Zm-6 2h4V4h-4v2Z"></path>392 </svg>393 );394 },395 todo(props: SVGProps<SVGSVGElement>) {396 return (397 <svg398 xmlns="http://www.w3.org/2000/svg"399 fill="currentColor"400 viewBox="0 0 24 24"401 {...props}402 >403 <path d="M18 22H6v-2h12v2ZM6 20H4v-2h2v2Zm14 0h-2v-2h2v2ZM4 18H2V6h2v12Zm18 0h-2V6h2v12Zm-11-2H9v-2h2v2Zm-2-2H7v-2h2v2Zm4 0h-2v-2h2v2Zm2-2h-2v-2h2v2Zm2-2h-2V8h2v2ZM6 6H4V4h2v2Zm14 0h-2V4h2v2Zm-2-2H6V2h12v2Z"></path>404 </svg>405 );406 },407 warning(props: SVGProps<SVGSVGElement>) {408 return (409 <svg410 xmlns="http://www.w3.org/2000/svg"411 fill="currentColor"412 viewBox="0 0 24 24"413 {...props}414 >415 <path d="M14 22h-4v-2h4v2Zm-4-2H8v-2h2v2Zm6 0h-2v-2h2v2Zm-8-2H6v-2h2v2Zm10 0h-2v-2h2v2Zm-5-1h-2v-2h2v2Zm-7-1H4v-2h2v2Zm14 0h-2v-2h2v2ZM4 14H2v-4h2v4Zm18 0h-2v-4h2v4Zm-9-7v6h-2V7h2Zm-7 3H4V8h2v2Zm14 0h-2V8h2v2ZM8 8H6V6h2v2Zm10 0h-2V6h2v2Zm-8-2H8V4h2v2Zm6 0h-2V4h2v2Zm-2-2h-4V2h4v2Z" />416 </svg>417 );418 },419};420
421function CalloutTitle({ className, ...props }: ComponentProps<"div">) {422 return (423 <div424 data-slot="callout-title"425 className={cn(426 "font-medium group-has-[>svg]/callout:col-start-2 [&_a]:underline [&_a]:underline-offset-3 [&_a]:hover:text-foreground",427 className,428 )}429 {...props}430 />431 );432}433
434function CalloutDescription({ className, ...props }: ComponentProps<"div">) {435 return (436 <div437 data-slot="callout-description"438 className={cn(439 "text-xs/relaxed text-balance md:text-pretty [&_a]:underline [&_a]:underline-offset-3 [&_a]:hover:text-foreground [&_p:not(:last-child)]:mb-2",440 className,441 )}442 {...props}443 />444 );445}446
447function Callout({448 border = "rounded",449 children,450 className,451 collapsible = false,452 defaultOpen,453 Icon: IconOverride,454 onOpenChange,455 open,456 title,457 variant = "default",458 ...props459}: ComponentProps<"div"> &460 VariantProps<typeof calloutVariants> & {461 collapsible?: boolean;462 defaultOpen?: boolean;463 Icon?: (props: SVGProps<SVGSVGElement>) => React.JSX.Element;464 onOpenChange?: (465 open: boolean,466 eventDetails: CollapsibleRootChangeEventDetails,467 ) => void;468 open?: boolean;469 title?: string;470 }) {471 const Icon = IconOverride ?? (variant ? CalloutIcon[variant] : undefined);472 const calloutTitle =473 title ??474 (variant ? variant.charAt(0).toUpperCase() + variant.slice(1) : undefined);475
476 if (collapsible) {477 return (478 <Collapsible479 defaultOpen={defaultOpen}480 onOpenChange={onOpenChange}481 open={open}482 render={483 <div484 data-slot="callout"485 role="alert"486 className={cn(calloutVariants({ border, variant }), className)}487 {...props}488 />489 }490 >491 {Icon && <CollapsibleTrigger492 nativeButton={false}493 render={<Icon />} />}494 <CollapsibleTrigger495 nativeButton={false}496 render={497 <CalloutTitle className="flex gap-0.5" data-slot="callout-title">498 {calloutTitle}499 <svg500 className="size-4 transition-transform group-data-open/callout:rotate-90"501 xmlns="http://www.w3.org/2000/svg"502 fill="currentColor"503 viewBox="0 0 24 24"504 >505 <path d="M16 13v-2h-2v2h2Zm-2-2V9h-2v2h2Zm0 4v-2h-2v2h2Zm-2-6V7h-2v2h2Zm0 8v-2h-2v2h2ZM10 7V5H8v2h2Zm0 12v-2H8v2h2Z" />506 </svg>507 </CalloutTitle>508 }509 />510 <CollapsibleContent transition="easeOut">511 {children && <CalloutDescription>{children}</CalloutDescription>}512 </CollapsibleContent>513 </Collapsible>514 );515 }516
517 return (518 <div519 data-slot="callout"520 role="alert"521 className={cn(calloutVariants({ border, variant }), className)}522 {...props}523 >524 {Icon && <Icon />}525 <CalloutTitle>{calloutTitle}</CalloutTitle>526 {children && <CalloutDescription>{children}</CalloutDescription>}527 </div>528 );529}530
531export { Callout, CalloutIcon, type CalloutVariant, calloutVariants };Update the import paths to match your project setup.
import { Callout } from "@/components/ui/pxl/callout"<Callout callout="info" title="Heads up!"> You can add components and dependencies to your app using the cli.</Callout>Alert vs Callout
Section titled “Alert vs Callout”Use the Callout if you need to display admonitions/callouts for example from Markdown sources. Use the Alert component if you need deeper control or advanced customization.
Collapsible
Section titled “Collapsible”Use the collapsible and collapsed props to make the callout collapsible.
Are callouts foldable?
1import { Callout } from "@/components/ui/pxl/callout";2
3export default function CalloutCollapsibleExample() {4 return (5 <div className="max-w-md w-full">6 <Callout variant="info" title="Are callouts foldable?" collapsible>7 Yes! In a foldable callout, the contents are hidden when the callout is collapsed.8 </Callout>9 </div>10 );11}Use the callout prop to change the callout styles.
Note
Abstract
Aliases: summary, tldr
Info
Todo
Tip
Aliases: hint, important
Success
Aliases: check, done
Question
Aliases: help, faq
Warning
Aliases: caution, attention
Failure
Aliases: fail, missing
Danger
Aliases: error
Bug
Example
Quote
Aliases: cite
1import { Callout } from "@/components/ui/pxl/callout";2import { Separator } from "@/components/ui/pxl/separator";3
4export default function CalloutTypesExample() {5 return (6 <div className="flex flex-col gap-3 max-w-md w-full">7 <div>8 <Callout variant="note" collapsible>9 Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do10 eiusmod tempor incididunt ut labore et dolore magna aliqua.11 </Callout>12 <Separator border="dashed" className="mt-3" />13 </div>14 <div>15 <Callout variant="abstract" collapsible>16 Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do17 eiusmod tempor incididunt ut labore et dolore magna aliqua.18 </Callout>19
20 <p className="typeset mt-2">21 Aliases: <code>summary</code>, <code>tldr</code>22 </p>23
24 <Separator border="dashed" className="mt-3" />25 </div>26 <div>27 <Callout variant="info" collapsible>28 Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do29 eiusmod tempor incididunt ut labore et dolore magna aliqua.30 </Callout>31
32 <Separator border="dashed" className="mt-3" />33 </div>34 <div>35 <Callout variant="todo" collapsible>36 Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do37 eiusmod tempor incididunt ut labore et dolore magna aliqua.38 </Callout>39
40 <Separator border="dashed" className="mt-3" />41 </div>42 <div>43 <Callout variant="tip" collapsible>44 Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do45 eiusmod tempor incididunt ut labore et dolore magna aliqua.46 </Callout>47
48 <p className="typeset mt-2">49 Aliases: <code>hint</code>, <code>important</code>50 </p>51
52 <Separator border="dashed" className="mt-3" />53 </div>54 <div>55 <Callout variant="success" collapsible>56 Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do57 eiusmod tempor incididunt ut labore et dolore magna aliqua.58 </Callout>59
60 <p className="typeset mt-2">61 Aliases: <code>check</code>, <code>done</code>62 </p>63
64 <Separator border="dashed" className="mt-3" />65 </div>66 <div>67 <Callout variant="question" collapsible>68 Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do69 eiusmod tempor incididunt ut labore et dolore magna aliqua.70 </Callout>71
72 <p className="typeset mt-2">73 Aliases: <code>help</code>, <code>faq</code>74 </p>75
76 <Separator border="dashed" className="mt-3" />77 </div>78 <div>79 <Callout variant="warning" collapsible>80 Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do81 eiusmod tempor incididunt ut labore et dolore magna aliqua.82 </Callout>83
84 <p className="typeset mt-2">85 Aliases: <code>caution</code>, <code>attention</code>86 </p>87
88 <Separator border="dashed" className="mt-3" />89 </div>90 <div>91 <Callout variant="failure" collapsible>92 Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do93 eiusmod tempor incididunt ut labore et dolore magna aliqua.94 </Callout>95
96 <p className="typeset mt-2">97 Aliases: <code>fail</code>, <code>missing</code>98 </p>99
100 <Separator border="dashed" className="mt-3" />101 </div>102 <div>103 <Callout variant="danger" collapsible>104 Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do105 eiusmod tempor incididunt ut labore et dolore magna aliqua.106 </Callout>107
108 <p className="typeset mt-2">109 Aliases: <code>error</code>110 </p>111
112 <Separator border="dashed" className="mt-3" />113 </div>114 <div>115 <Callout variant="bug" collapsible>116 Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do117 eiusmod tempor incididunt ut labore et dolore magna aliqua.118 </Callout>119
120 <Separator border="dashed" className="mt-3" />121 </div>122 <div>123 <Callout variant="example" collapsible>124 Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do125 eiusmod tempor incididunt ut labore et dolore magna aliqua.126 </Callout>127
128 <Separator border="dashed" className="mt-3" />129 </div>130 <div>131 <Callout variant="quote" collapsible>132 Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do133 eiusmod tempor incididunt ut labore et dolore magna aliqua.134 </Callout>135
136 <p className="typeset mt-2">137 Aliases: <code>cite</code>138 </p>139 </div>140 </div>141 );142}