fix HistoryEntry children prop conflict and overlay CopyButton in ContentViewer
Rename HistoryEntry's children prop to childEntries to avoid React's reserved prop name. Replace ContentViewer's onCopy callback with a copyable flag and overlay CopyButton in the top-right corner. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
5d35a5f94c
commit
8d434e2381
4 changed files with 38 additions and 17 deletions
|
|
@ -1,5 +1,4 @@
|
|||
import type { Meta, StoryObj } from "@storybook/react-vite";
|
||||
import { fn } from "storybook/test";
|
||||
import { ContentViewer } from "./ContentViewer";
|
||||
|
||||
const meta: Meta<typeof ContentViewer> = {
|
||||
|
|
@ -74,6 +73,15 @@ export const WithCopyButton: Story = {
|
|||
args: {
|
||||
type: "text",
|
||||
content: "Hello, world!\nThis text can be copied.",
|
||||
onCopy: fn(),
|
||||
copyable: true,
|
||||
},
|
||||
};
|
||||
|
||||
export const JsonWithCopy: Story = {
|
||||
args: {
|
||||
type: "json",
|
||||
content:
|
||||
'{"name":"my-app","version":"1.0.0","description":"Sample configuration file"}',
|
||||
copyable: true,
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
import { Button, Code, Image, Stack } from "@mantine/core";
|
||||
import { Code, Flex, Image, Stack } from "@mantine/core";
|
||||
import { CopyButton } from "../CopyButton/CopyButton";
|
||||
|
||||
export interface ContentViewerProps {
|
||||
type: "text" | "json" | "image" | "audio";
|
||||
content: string;
|
||||
mimeType?: string;
|
||||
onCopy?: () => void;
|
||||
copyable?: boolean;
|
||||
}
|
||||
|
||||
function formatJson(content: string): string {
|
||||
|
|
@ -15,16 +16,33 @@ function formatJson(content: string): string {
|
|||
}
|
||||
}
|
||||
|
||||
const ContentWrapper = Flex.withProps({
|
||||
pos: "relative",
|
||||
direction: "column",
|
||||
});
|
||||
|
||||
export function ContentViewer({
|
||||
type,
|
||||
content,
|
||||
mimeType,
|
||||
onCopy,
|
||||
copyable = false,
|
||||
}: ContentViewerProps) {
|
||||
const showCopy = copyable && (type === "text" || type === "json");
|
||||
|
||||
return (
|
||||
<Stack gap="xs">
|
||||
{type === "json" && <Code block>{formatJson(content)}</Code>}
|
||||
{type === "text" && <Code block>{content}</Code>}
|
||||
{(type === "json" || type === "text") && (
|
||||
<ContentWrapper>
|
||||
<Code block p={36}>
|
||||
{type === "json" ? formatJson(content) : content}
|
||||
</Code>
|
||||
{showCopy && (
|
||||
<Flex pos="absolute" top={4} right={4}>
|
||||
<CopyButton value={content} />
|
||||
</Flex>
|
||||
)}
|
||||
</ContentWrapper>
|
||||
)}
|
||||
{type === "image" && (
|
||||
<Image
|
||||
src={`data:${mimeType || "image/png"};base64,${content}`}
|
||||
|
|
@ -38,11 +56,6 @@ export function ContentViewer({
|
|||
<source src={`data:${mimeType || "audio/wav"};base64,${content}`} />
|
||||
</audio>
|
||||
)}
|
||||
{onCopy && (
|
||||
<Button variant="light" size="xs" onClick={onCopy}>
|
||||
Copy
|
||||
</Button>
|
||||
)}
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ export const WithChildren: Story = {
|
|||
response: {
|
||||
result: "completed",
|
||||
},
|
||||
children: [
|
||||
childEntries: [
|
||||
{
|
||||
timestamp: "+120ms",
|
||||
method: "sampling/createMessage",
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ export interface HistoryEntryProps {
|
|||
durationMs: number;
|
||||
parameters?: Record<string, unknown>;
|
||||
response?: Record<string, unknown>;
|
||||
children?: HistoryChildEntry[];
|
||||
childEntries?: HistoryChildEntry[];
|
||||
isPinned: boolean;
|
||||
pinLabel?: string;
|
||||
isExpanded: boolean;
|
||||
|
|
@ -42,7 +42,7 @@ export function HistoryEntry({
|
|||
durationMs,
|
||||
parameters,
|
||||
response,
|
||||
children,
|
||||
childEntries,
|
||||
isPinned,
|
||||
pinLabel,
|
||||
isExpanded,
|
||||
|
|
@ -102,9 +102,9 @@ export function HistoryEntry({
|
|||
<Code block>{JSON.stringify(response, null, 2)}</Code>
|
||||
</Stack>
|
||||
)}
|
||||
{children && children.length > 0 && (
|
||||
{childEntries && childEntries.length > 0 && (
|
||||
<Stack gap="xs">
|
||||
{children.map((child, index) => (
|
||||
{childEntries.map((child, index) => (
|
||||
<Group key={index} pl="lg" gap="sm">
|
||||
<Text size="sm" c="dimmed" ff="monospace">
|
||||
+--{" "}
|
||||
|
|
|
|||
Loading…
Reference in a new issue