TypeScript · 2911 bytes Raw Blame History
1 import ReactMarkdown, { type Components } from "react-markdown";
2 import remarkGfm from "remark-gfm";
3
4 interface TextBlockProps {
5 text: string;
6 /** Tighter spacing + monospace inside tool-use input previews. */
7 compact?: boolean;
8 }
9
10 const components: Components = {
11 code({ className, children, ...props }) {
12 const isInline = !className?.includes("language-");
13 if (isInline) {
14 return (
15 <code
16 className="rounded bg-bg-3 px-1 py-0.5 font-mono text-[12px] text-fg-0"
17 {...props}
18 >
19 {children}
20 </code>
21 );
22 }
23 return (
24 <code className={`font-mono text-[12px] ${className ?? ""}`} {...props}>
25 {children}
26 </code>
27 );
28 },
29 pre({ children, ...props }) {
30 return (
31 <pre
32 className="my-2 overflow-x-auto rounded border border-border bg-bg-2 p-3 text-[12px] leading-relaxed"
33 {...props}
34 >
35 {children}
36 </pre>
37 );
38 },
39 a({ children, href, ...props }) {
40 return (
41 <a
42 href={href}
43 className="text-accent underline decoration-accent/40 underline-offset-2 hover:decoration-accent"
44 target="_blank"
45 rel="noreferrer noopener"
46 {...props}
47 >
48 {children}
49 </a>
50 );
51 },
52 p({ children, ...props }) {
53 return (
54 <p className="my-2 leading-relaxed text-fg-1" {...props}>
55 {children}
56 </p>
57 );
58 },
59 ul({ children, ...props }) {
60 return (
61 <ul className="my-2 list-disc pl-5 text-fg-1" {...props}>
62 {children}
63 </ul>
64 );
65 },
66 ol({ children, ...props }) {
67 return (
68 <ol className="my-2 list-decimal pl-5 text-fg-1" {...props}>
69 {children}
70 </ol>
71 );
72 },
73 li({ children, ...props }) {
74 return (
75 <li className="my-0.5" {...props}>
76 {children}
77 </li>
78 );
79 },
80 h1({ children, ...props }) {
81 return (
82 <h1 className="mb-2 mt-3 text-lg font-semibold text-fg-0" {...props}>
83 {children}
84 </h1>
85 );
86 },
87 h2({ children, ...props }) {
88 return (
89 <h2 className="mb-2 mt-3 text-base font-semibold text-fg-0" {...props}>
90 {children}
91 </h2>
92 );
93 },
94 h3({ children, ...props }) {
95 return (
96 <h3 className="mb-1 mt-2 text-sm font-semibold text-fg-0" {...props}>
97 {children}
98 </h3>
99 );
100 },
101 blockquote({ children, ...props }) {
102 return (
103 <blockquote
104 className="my-2 border-l-2 border-border pl-3 text-fg-2 italic"
105 {...props}
106 >
107 {children}
108 </blockquote>
109 );
110 },
111 };
112
113 export function TextBlock({ text, compact }: TextBlockProps) {
114 return (
115 <div
116 className={
117 compact
118 ? "font-mono text-[12px] text-fg-1 [&>p]:my-1"
119 : "text-[13px]"
120 }
121 >
122 <ReactMarkdown remarkPlugins={[remarkGfm]} components={components}>
123 {text}
124 </ReactMarkdown>
125 </div>
126 );
127 }