1import { Callout, CalloutContent, CalloutTitle } from "~/components/ui/callout";2
3export default function CalloutDemo() {4 return (5 <div class="grid grid-cols-2 gap-4">6 <Callout variant="success">7 <CalloutTitle>Success</CalloutTitle>8 <CalloutContent>This is a success callout</CalloutContent>9 </Callout>10 <Callout variant="info">11 <CalloutTitle>Info</CalloutTitle>12 <CalloutContent>This is an info callout</CalloutContent>13 </Callout>14 <Callout variant="warning">15 <CalloutTitle>Warning</CalloutTitle>16 <CalloutContent>This is a warning callout</CalloutContent>17 </Callout>18 <Callout variant="error">19 <CalloutTitle>Error</CalloutTitle>20 <CalloutContent>This is an error callout</CalloutContent>21 </Callout>22 </div>23 );24}
npx shadcn@latest add https://solid-ui-neobrutalism.vercel.app/r/callout.json
yarn shadcn@latest add https://solid-ui-neobrutalism.vercel.app/r/callout.json
pnpm dlx shadcn@latest add https://solid-ui-neobrutalism.vercel.app/r/callout.json
bunx --bun shadcn@latest add https://solid-ui-neobrutalism.vercel.app/r/callout.json
Copy and paste the following code into your project
1import type { VariantProps } from "class-variance-authority";2import type { Component, ComponentProps, JSX } from "solid-js";3
4import { Show, splitProps } from "solid-js";5import { cva } from "class-variance-authority";6import CircleCheckIcon from "lucide-solid/icons/circle-check";7import CircleXIcon from "lucide-solid/icons/circle-x";8import InfoIcon from "lucide-solid/icons/info";9import TriangleAlertIcon from "lucide-solid/icons/triangle-alert";10
11import { cn } from "~/lib/utils";12
13const calloutVariants = cva("rounded-base border-2 px-4 py-3", {14 variants: {15 variant: {16 default: "border-primary bg-background text-primary",17 success: "border-success-foreground bg-success text-success-foreground",18 info: "border-info-foreground bg-info text-info-foreground",19 warning: "border-warning-foreground bg-warning text-warning-foreground",20 error: "border-error-foreground bg-error text-error-foreground",21 },22 },23 defaultVariants: {24 variant: "default",25 },26});27
28type CalloutProps = ComponentProps<"div"> &29 VariantProps<typeof calloutVariants>;30
31type CalloutVariant = NonNullable<32 VariantProps<typeof calloutVariants>["variant"]33>;34
35type IconMap = Exclude<CalloutVariant, "default">;36
37const iconMap: {38 [key in IconMap]: (props: { class?: string }) => JSX.Element;39} = {40 success: (props) => <CircleCheckIcon class={props.class} />,41 info: (props) => <InfoIcon class={props.class} />,42 warning: (props) => <TriangleAlertIcon class={props.class} />,43 error: (props) => <CircleXIcon class={props.class} />,44};45
46const Callout: Component<CalloutProps> = (props) => {47 const [local, others] = splitProps(props, ["class", "variant"]);48
49 return (50 <div51 data-slot="callout"52 data-variant={local.variant}53 class={cn(calloutVariants({ variant: local.variant }), local.class)}54 {...others}55 />56 );57};58
59const CalloutTitle: Component<60 ComponentProps<"h3"> & {61 icon?: JSX.Element | (() => JSX.Element);62 }63> = (props) => {64 const [local, others] = splitProps(props, ["class"]);65 return (66 <div class="flex items-center gap-2">67 <Show when={props.icon}>68 {typeof props.icon === "function" ? <props.icon /> : props.icon}69 </Show>70 <h371 data-slot="callout-title"72 class={cn("font-semibold", local.class)}73 {...others}74 />75 </div>76 );77};78
79const CalloutContent: Component<ComponentProps<"div">> = (props) => {80 const [local, others] = splitProps(props, ["class"]);81 return (82 <div83 data-slot="callout-content"84 class={cn("mt-2", local.class)}85 {...others}86 />87 );88};89
90export { Callout, CalloutTitle, CalloutContent, iconMap as calloutIconMap };
Update the import paths to match your project setup.
1import { Callout, CalloutContent, CalloutTitle } from "~/components/ui/callout";
1<Callout variant="success">2 <CalloutTitle>Success</CalloutTitle>3 <CalloutContent>This is a success callout</CalloutContent>4</Callout>