Files
triggerdotdev--trigger.dev/apps/webapp/app/components/primitives/Callout.tsx
T
2026-07-13 13:32:57 +08:00

170 lines
5.1 KiB
TypeScript

import {
CreditCardIcon,
ExclamationCircleIcon,
ExclamationTriangleIcon,
InformationCircleIcon,
LightBulbIcon,
} from "@heroicons/react/20/solid";
import {
ArrowTopRightOnSquareIcon,
BookOpenIcon,
CheckCircleIcon,
ChevronRightIcon,
} from "@heroicons/react/24/solid";
import { Link } from "@remix-run/react";
import { cn } from "~/utils/cn";
import { Paragraph } from "./Paragraph";
import { Spinner } from "./Spinner";
export const variantClasses = {
info: {
className: "border-grid-bright bg-background-bright",
icon: <InformationCircleIcon className="h-5 w-5 shrink-0 text-text-dimmed" />,
textColor: "text-text-bright",
linkClassName: "transition hover:bg-background-hover",
},
warning: {
className: "border-warning/20 bg-warning/10",
icon: <ExclamationTriangleIcon className="h-5 w-5 shrink-0 text-warning" />,
textColor: "text-callout-warning-text",
linkClassName: "transition hover:bg-warning/20",
},
error: {
className: "border-error/20 bg-error/10",
icon: <ExclamationCircleIcon className="h-5 w-5 shrink-0 text-error" />,
textColor: "text-callout-error-text",
linkClassName: "transition hover:bg-error/20",
},
idea: {
className: "border-success/20 bg-success/10",
icon: <LightBulbIcon className="h-5 w-5 shrink-0 text-success" />,
textColor: "text-callout-success-text",
linkClassName: "transition hover:bg-success/20",
},
success: {
className: "border-success/20 bg-success/10",
icon: <CheckCircleIcon className="h-5 w-5 shrink-0 text-success" />,
textColor: "text-callout-success-text",
linkClassName: "transition hover:bg-success/20",
},
docs: {
className: "border-callout-docs/20 bg-callout-docs/10",
icon: <BookOpenIcon className="mt-0.5 h-5 w-5 shrink-0 text-callout-docs" />,
textColor: "text-callout-docs-text",
linkClassName: "transition hover:bg-callout-docs/20",
},
pending: {
className: "border-callout-pending/20 bg-callout-pending-bg/30",
icon: <Spinner className="h-5 w-5 shrink-0 " />,
textColor: "text-callout-pending-text",
linkClassName: "transition hover:bg-callout-pending/20",
},
pricing: {
className: "border-callout-pricing/20 bg-callout-pricing-bg/30",
icon: <CreditCardIcon className="h-5 w-5 shrink-0 text-callout-pricing" />,
textColor: "text-callout-pricing-text",
linkClassName: "transition hover:bg-callout-pricing/20",
},
} as const;
export type CalloutVariant = keyof typeof variantClasses;
export function Callout({
children,
className,
icon,
cta,
variant,
to,
}: {
children?: React.ReactNode;
className?: string;
icon?: React.ReactNode;
cta?: React.ReactNode;
variant: CalloutVariant;
to?: string;
}) {
const variantDefinition = variantClasses[variant];
if (to !== undefined) {
if (to.startsWith("http")) {
return (
<a
href={to}
target="_blank"
className={cn(
`flex w-full items-start justify-between gap-2.5 rounded-md border py-2 pl-2 pr-3 shadow-md backdrop-blur-xs`,
variantDefinition.className,
variantDefinition.linkClassName,
className
)}
>
<div className={"flex w-full items-start gap-x-2"}>
{icon ? icon : variantDefinition.icon}
{typeof children === "string" ? (
<Paragraph variant={"small"} className={variantDefinition.textColor}>
{children}
</Paragraph>
) : (
children
)}
</div>
<ArrowTopRightOnSquareIcon className={cn("h-5 w-5", variantDefinition.textColor)} />
</a>
);
} else {
return (
<Link
to={to}
className={cn(
`flex w-full items-start justify-between gap-2.5 rounded-md border py-2 pl-2 pr-3 shadow-md backdrop-blur-xs`,
variantDefinition.className,
variantDefinition.linkClassName,
className
)}
>
<div className={"flex w-full items-start gap-x-2"}>
{icon ? icon : variantDefinition.icon}
{typeof children === "string" ? (
<Paragraph variant={"small"} className={variantDefinition.textColor}>
{children}
</Paragraph>
) : (
children
)}
</div>
<div className="flex h-full items-center">
<ChevronRightIcon className={cn("h-5 w-5", variantDefinition.textColor)} />
</div>
</Link>
);
}
}
return (
<div
className={cn(
"flex w-full items-start gap-2 rounded-md border pl-2 pr-2 shadow-md backdrop-blur-xs",
cta ? "py-2" : "py-2.5",
variantDefinition.className,
className
)}
>
<div className={cn(`flex w-full items-start gap-2.5`)}>
{icon ? icon : variantDefinition.icon}
{typeof children === "string" ? (
<Paragraph variant={"small"} className={variantDefinition.textColor}>
{children}
</Paragraph>
) : (
<span>{children}</span>
)}
</div>
{cta && cta}
</div>
);
}