From 3c25bdfbd528c260375fae4bf74ad8a8e994910d Mon Sep 17 00:00:00 2001 From: cliffhall Date: Mon, 23 Mar 2026 12:28:15 -0400 Subject: [PATCH] refine InlineError, ServerCard, HistoryEntry, and LoggingScreen - InlineError: show more/less toggle on same line as message, collapsible details, doc link as button - ServerCard: use ContentViewer with CopyButton for command, remove onCopyCommand prop, combine action rows, add responsive Card variant - HistoryEntry: use ContentViewer with CopyButton for JSON blocks, swap duration and status badge positions - LoggingScreen: stretch log stream panel to full height, center empty message vertically Co-Authored-By: Claude Opus 4.6 (1M context) --- clients/web/src/App.css | 12 +++ .../atoms/InlineError/InlineError.tsx | 69 +++++++----- .../layouts/HomeLayout/HomeLayout.stories.tsx | 2 - .../molecules/HistoryEntry/HistoryEntry.tsx | 20 ++-- .../ServerCard/ServerCard.stories.tsx | 1 - .../molecules/ServerCard/ServerCard.tsx | 102 ++++++++---------- .../organisms/LoggingScreen/LoggingScreen.tsx | 29 ++--- .../ServerListScreen.stories.tsx | 2 - clients/web/src/theme/Card.ts | 4 + 9 files changed, 136 insertions(+), 105 deletions(-) diff --git a/clients/web/src/App.css b/clients/web/src/App.css index 4d054964..d8c779d4 100644 --- a/clients/web/src/App.css +++ b/clients/web/src/App.css @@ -103,3 +103,15 @@ .inspector-spin { animation: inspector-spin 1s linear infinite; } + +/* ── Responsive card ────────────────────────────────────── */ + +.card-responsive { + width: 100%; +} + +@media (min-width: 62em) { + .card-responsive { + width: 50%; + } +} diff --git a/clients/web/src/components/atoms/InlineError/InlineError.tsx b/clients/web/src/components/atoms/InlineError/InlineError.tsx index bca095c2..c4be1732 100644 --- a/clients/web/src/components/atoms/InlineError/InlineError.tsx +++ b/clients/web/src/components/atoms/InlineError/InlineError.tsx @@ -1,11 +1,11 @@ -import { Alert, Anchor, Group, Spoiler, Stack, Text } from "@mantine/core"; +import { Alert, Button, Collapse, Group, Stack, Text } from "@mantine/core"; +import { useState } from "react"; export interface InlineErrorProps { message: string; details?: string; retryCount?: number; maxRetries?: number; - onShowMore?: () => void; docLink?: string; } @@ -16,33 +16,52 @@ export function InlineError({ maxRetries, docLink, }: InlineErrorProps) { - const hasDetails = - retryCount !== undefined || details !== undefined || docLink !== undefined; + const [expanded, setExpanded] = useState(false); + const hasExpandable = details !== undefined || docLink !== undefined; return ( - - {hasDetails && ( - - {retryCount !== undefined && ( - - Retry attempt {retryCount} - {maxRetries !== undefined && ` of ${maxRetries}`} + + + + + + {message} + {retryCount !== undefined && ( + + Retry attempt {retryCount} + {maxRetries !== undefined && ` of ${maxRetries}`} + + )} + + {hasExpandable && ( + )} - {details && ( - - {details} - - )} - {docLink && ( - - - View Troubleshooting Guide → - - - )} - - )} + + + + {details && {details}} + {docLink && ( + + )} + + + ); } diff --git a/clients/web/src/components/layouts/HomeLayout/HomeLayout.stories.tsx b/clients/web/src/components/layouts/HomeLayout/HomeLayout.stories.tsx index fdc28fa3..23d327f4 100644 --- a/clients/web/src/components/layouts/HomeLayout/HomeLayout.stories.tsx +++ b/clients/web/src/components/layouts/HomeLayout/HomeLayout.stories.tsx @@ -20,7 +20,6 @@ type Story = StoryObj; function makeServerCallbacks(): Pick< ServerCardProps, | "onToggleConnection" - | "onCopyCommand" | "onServerInfo" | "onSettings" | "onEdit" @@ -29,7 +28,6 @@ function makeServerCallbacks(): Pick< > { return { onToggleConnection: fn(), - onCopyCommand: fn(), onServerInfo: fn(), onSettings: fn(), onEdit: fn(), diff --git a/clients/web/src/components/molecules/HistoryEntry/HistoryEntry.tsx b/clients/web/src/components/molecules/HistoryEntry/HistoryEntry.tsx index 634b640b..b7741572 100644 --- a/clients/web/src/components/molecules/HistoryEntry/HistoryEntry.tsx +++ b/clients/web/src/components/molecules/HistoryEntry/HistoryEntry.tsx @@ -2,12 +2,12 @@ import { Badge, Button, Card, - Code, Collapse, Group, Stack, Text, } from "@mantine/core"; +import { ContentViewer } from "../../atoms/ContentViewer/ContentViewer"; export interface HistoryChildEntry { timestamp: string; @@ -66,12 +66,12 @@ export function HistoryEntry({ )} - - {status === "success" ? "OK" : "Error"} - {durationMs}ms + + {status === "success" ? "OK" : "Error"} + @@ -93,13 +93,21 @@ export function HistoryEntry({ {parameters && ( Parameters: - {JSON.stringify(parameters, null, 2)} + )} {response && ( Response: - {JSON.stringify(response, null, 2)} + )} {childEntries && childEntries.length > 0 && ( diff --git a/clients/web/src/components/molecules/ServerCard/ServerCard.stories.tsx b/clients/web/src/components/molecules/ServerCard/ServerCard.stories.tsx index d42f42c7..5355f092 100644 --- a/clients/web/src/components/molecules/ServerCard/ServerCard.stories.tsx +++ b/clients/web/src/components/molecules/ServerCard/ServerCard.stories.tsx @@ -7,7 +7,6 @@ const meta: Meta = { component: ServerCard, args: { onToggleConnection: fn(), - onCopyCommand: fn(), onServerInfo: fn(), onSettings: fn(), onEdit: fn(), diff --git a/clients/web/src/components/molecules/ServerCard/ServerCard.tsx b/clients/web/src/components/molecules/ServerCard/ServerCard.tsx index fcde9295..e3c24fee 100644 --- a/clients/web/src/components/molecules/ServerCard/ServerCard.tsx +++ b/clients/web/src/components/molecules/ServerCard/ServerCard.tsx @@ -2,7 +2,6 @@ import { Badge, Button, Card, - Code, Group, Menu, Stack, @@ -11,7 +10,7 @@ import { import { StatusIndicator } from "../../atoms/StatusIndicator/StatusIndicator"; import { TransportBadge } from "../../atoms/TransportBadge/TransportBadge"; import { ConnectionToggle } from "../../atoms/ConnectionToggle/ConnectionToggle"; -import { CopyButton } from "../../atoms/CopyButton/CopyButton"; +import { ContentViewer } from "../../atoms/ContentViewer/ContentViewer"; import { InlineError } from "../../atoms/InlineError/InlineError"; export interface ServerCardProps { @@ -25,7 +24,6 @@ export interface ServerCardProps { error?: { message: string; details?: string }; canTestClientFeatures: boolean; onToggleConnection: (connect: boolean) => void; - onCopyCommand: () => void; onServerInfo: () => void; onSettings: () => void; onEdit: () => void; @@ -76,7 +74,7 @@ export function ServerCard({ return ( - + {name} @@ -101,14 +99,7 @@ export function ServerCard({ - - - - {command} - - - - + {error && ( )} - - - - {canTestClientFeatures && ( - - - - - - - Simulate Sampling Request - - - Simulate Elicitation (Form) - - - Simulate Elicitation (URL) - - - Configure Roots - - - - )} - - - - - - - + + + + + + + + + + {canTestClientFeatures && ( + + + + + + + Simulate Sampling Request + + + Simulate Elicitation (Form) + + + Simulate Elicitation (URL) + + + Configure Roots + + + + )} + + ); diff --git a/clients/web/src/components/organisms/LoggingScreen/LoggingScreen.tsx b/clients/web/src/components/organisms/LoggingScreen/LoggingScreen.tsx index b77ebb6d..91697b88 100644 --- a/clients/web/src/components/organisms/LoggingScreen/LoggingScreen.tsx +++ b/clients/web/src/components/organisms/LoggingScreen/LoggingScreen.tsx @@ -30,15 +30,15 @@ export function LoggingScreen({ onCopyAll, }: LoggingScreenProps) { return ( - + - + - - + + Log Stream @@ -52,17 +52,18 @@ export function LoggingScreen({ - - - {entries.map((entry, index) => ( - - ))} + {entries.length > 0 ? ( + + + {entries.map((entry, index) => ( + + ))} + + + ) : ( + + No log entries - - {entries.length === 0 && ( - - No log entries - )} diff --git a/clients/web/src/components/organisms/ServerListScreen/ServerListScreen.stories.tsx b/clients/web/src/components/organisms/ServerListScreen/ServerListScreen.stories.tsx index 47705eb0..1d04297a 100644 --- a/clients/web/src/components/organisms/ServerListScreen/ServerListScreen.stories.tsx +++ b/clients/web/src/components/organisms/ServerListScreen/ServerListScreen.stories.tsx @@ -19,7 +19,6 @@ type Story = StoryObj; function makeServerCallbacks(): Pick< ServerCardProps, | "onToggleConnection" - | "onCopyCommand" | "onServerInfo" | "onSettings" | "onEdit" @@ -32,7 +31,6 @@ function makeServerCallbacks(): Pick< > { return { onToggleConnection: fn(), - onCopyCommand: fn(), onServerInfo: fn(), onSettings: fn(), onEdit: fn(), diff --git a/clients/web/src/theme/Card.ts b/clients/web/src/theme/Card.ts index 46383bb0..014acace 100644 --- a/clients/web/src/theme/Card.ts +++ b/clients/web/src/theme/Card.ts @@ -6,4 +6,8 @@ export const ThemeCard = Card.extend({ radius: "md", withBorder: true, }, + classNames: (_theme, props) => { + if (props.variant === "responsive") return { root: "card-responsive" }; + return {}; + }, });