Files
app-261004/components/mdx/callout.tsx
T
2026-10-08 11:09:37 +08:00

68 lines
1.7 KiB
TypeScript

import type { ReactNode } from "react";
import { Info, Lightbulb, TriangleAlert, CircleAlert } from "lucide-react";
import { cn } from "@/lib/utils";
/**
* 提示块:可在 MDX 正文中直接使用。
*
* 颜色取自 DESIGN.md 的语义色:
* - info → brand-tag(信息蓝)
* - tip → brand-green(品牌绿)
* - warning → brand-warn(警告橙)
* - danger → brand-error(错误红)
*/
const CALLOUT_VARIANTS = {
info: {
icon: Info,
label: "说明",
className: "border-brand-tag/30 bg-brand-tag/[0.06] text-brand-tag",
},
tip: {
icon: Lightbulb,
label: "提示",
className:
"border-brand-green/40 bg-brand-green/[0.07] text-brand-green-deep",
},
warning: {
icon: TriangleAlert,
label: "注意",
className: "border-brand-warn/30 bg-brand-warn/[0.07] text-brand-warn",
},
danger: {
icon: CircleAlert,
label: "警告",
className: "border-brand-error/30 bg-brand-error/[0.06] text-brand-error",
},
} as const;
export type CalloutType = keyof typeof CALLOUT_VARIANTS;
export interface CalloutProps {
type?: CalloutType;
title?: string;
children: ReactNode;
}
export function Callout({ type = "info", title, children }: CalloutProps) {
const variant = CALLOUT_VARIANTS[type] ?? CALLOUT_VARIANTS.info;
const Icon = variant.icon;
return (
<aside
className={cn(
"my-xl flex gap-sm rounded-md border p-md",
variant.className,
)}
>
<Icon className="mt-[2px] size-4 shrink-0" aria-hidden="true" />
<div className="flex-1 text-body-sm">
<p className="mb-xxs font-semibold">
{title ?? variant.label}
</p>
<div className="text-slate [&>p]:text-slate [&>p+p]:mt-xs">{children}</div>
</div>
</aside>
);
}