Something went wrong. Try again.
This repository has no description
Something went wrong. Try again.
4.3 kB · 163 lines
TSX
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164import { cn } from "@/lib/utils";import { ExternalLink, LucideAlertOctagon, LucideAlertTriangle, LucideInfo, LucideLightbulb, LucideNotebookPen,} from "lucide-react";import { createContext, useContext } from "react";import { Card } from "./card";
const AdmonitionContext = createContext<{ type: string; size: "sm" | "md" | "lg";} | null>(null);
function useAdmonitionContext() { const ctx = useContext(AdmonitionContext); if (!ctx) { throw new Error( "Admonition subcomponents must be used within an <Admonition>", ); } return ctx;}
const ADMONITION_SIZES = { sm: "text-sm", md: "text-base", lg: "text-lg",} as const;
// Admonition component based off Cardfunction Admonition({ type, children, size = "md",}: { type: "note" | "tip" | "info" | "warning" | "danger"; children: React.ReactNode; size?: "sm" | "md" | "lg";}) { const sizes = { sm: "py-2 px-3", md: "py-2 px-3", lg: "py-2 px-3", }; const colors = { note: "bg-blue-50 text-blue-800 dark:bg-blue-400/20 dark:text-blue-100 border-blue-400/40", tip: "bg-green-50 text-green-800 dark:bg-green-400/20 dark:text-green-100 border-green-400/40", info: "bg-blue-50 text-blue-800 dark:bg-blue-400/20 dark:text-blue-100 border-blue-400/40", warning: "bg-yellow-50 text-yellow-800 dark:bg-yellow-500/25 dark:text-yellow-100 border-yellow-400/40", danger: "bg-red-50 text-red-800 dark:bg-red-900/20 dark:text-red-100 border-red-400/40", } as const;
const iconSize = { sm: "size-8 w-12", md: "size-12 w-16", lg: "size-14 w-20", };
const Icon = { note: LucideNotebookPen, tip: LucideLightbulb, info: LucideInfo, warning: LucideAlertTriangle, danger: LucideAlertOctagon, }[type as keyof typeof colors] || LucideInfo;
return ( <AdmonitionContext.Provider value={{ type, size }}> <Card className={`flex flex-col items-start ${colors[type as keyof typeof colors] || colors.info} border ${sizes[size]}`} > <div className="flex items-start gap-2"> <Icon className={cn(iconSize[size])} /> <div>{children}</div> </div> </Card> </AdmonitionContext.Provider> );}
function AdmonitionTitle({ children }: { children: React.ReactNode }) { const ctx = useAdmonitionContext(); return ( <h3 className={cn("text-base font-semibold", ADMONITION_SIZES[ctx.size])}> {children} </h3> );}
function AdmonitionDescription({ children }: { children: React.ReactNode }) { const ctx = useAdmonitionContext(); const size = { sm: "text-sm", md: "text-sm", lg: "text-base", }[ctx.size]; const colors = { note: "text-blue-800/80 dark:text-blue-100/80", tip: "text-green-800/80 dark:text-green-100/80", info: "text-blue-800/80 dark:text-blue-100/80", warning: "text-yellow-800/80 dark:text-yellow-100/80", danger: "text-red-800/80 dark:text-red-100/80", } as const; return <p className={cn(colors[ctx.type], size)}>{children}</p>;}
function AdmonitionLink({ children, href, external = true,}: { children: React.ReactNode; href: string; external?: boolean;}) { const ctx = useAdmonitionContext(); const size = { sm: "text-sm", md: "text-sm", lg: "text-base", }[ctx.size]; const iconSize = { sm: "size-4 mb-1", md: "size-4 mb-1", lg: "size-6 mb-1.5", }[ctx.size]; const colors = { note: "text-blue-700/80 dark:text-blue-200/80", tip: "text-green-700/80 dark:text-green-200/80", info: "text-blue-700/80 dark:text-blue-200/80", warning: "text-yellow-700/80 dark:text-yellow-200/80", danger: "text-red-700/80 dark:text-red-200/80", } as const; return ( <a href={href} target={external ? "_blank" : undefined} rel={external ? "noopener noreferrer" : undefined} className={cn( "font-medium hover:underline", colors[ctx.type as keyof typeof colors], size, )} > {children} <ExternalLink className={cn("inline", iconSize)} /> </a> );}
Admonition.Link = AdmonitionLink;
Admonition.Description = AdmonitionDescription;
Admonition.Title = AdmonitionTitle;
export { Admonition };