From ca6de91a962f2d489957d2509f01bf1df3658fab Mon Sep 17 00:00:00 2001 From: cliffhall Date: Tue, 24 Mar 2026 15:32:15 -0400 Subject: [PATCH] refactor organism components to use .withProps() subcomponents and extract inline code Co-Authored-By: Claude Opus 4.6 (1M context) --- .../organisms/HistoryScreen/HistoryScreen.tsx | 89 ++++++++++++------- .../organisms/LoggingScreen/LoggingScreen.tsx | 56 +++++++++--- .../organisms/PromptsScreen/PromptsScreen.tsx | 33 +++++-- .../ResourcesScreen/ResourcesScreen.tsx | 65 ++++++++++---- .../ServerListScreen/ServerListScreen.tsx | 19 +++- .../organisms/TasksScreen/TasksScreen.tsx | 43 ++++++--- .../organisms/ToolsScreen/ToolsScreen.tsx | 41 ++++++--- 7 files changed, 250 insertions(+), 96 deletions(-) diff --git a/clients/web/src/components/organisms/HistoryScreen/HistoryScreen.tsx b/clients/web/src/components/organisms/HistoryScreen/HistoryScreen.tsx index f868bbec..6e292e82 100644 --- a/clients/web/src/components/organisms/HistoryScreen/HistoryScreen.tsx +++ b/clients/web/src/components/organisms/HistoryScreen/HistoryScreen.tsx @@ -38,6 +38,49 @@ const METHOD_OPTIONS = [ "elicitation/create", ]; +const PageContainer = Container.withProps({ + size: "xl", + py: "xl", +}); + +const ContentPanel = Paper.withProps({ + withBorder: true, + p: "md", +}); + +const HeaderRow = Group.withProps({ + justify: "space-between", + wrap: "wrap", +}); + +const ToolbarButton = Button.withProps({ + variant: "light", + size: "sm", +}); + +const EmptyState = Text.withProps({ + c: "dimmed", + ta: "center", + py: "xl", +}); + +const CountText = Text.withProps({ + size: "sm", + c: "dimmed", +}); + +function entryKey(entry: HistoryEntryProps): string { + return `${entry.timestamp}-${entry.method}`; +} + +function formatPinnedTitle(count: number): string { + return `Pinned Requests (${count})`; +} + +function formatPagination(displayed: number, total: number): string { + return `Showing ${displayed} of ${total} entries`; +} + export function HistoryScreen({ entries, pinnedEntries, @@ -52,10 +95,10 @@ export function HistoryScreen({ onExport, }: HistoryScreenProps) { return ( - - + + - + Request History onMethodFilterChange(value ?? "")} clearable /> - - + Export JSON + Clear All - + {entries.length === 0 ? ( - - No request history - + No request history ) : ( {entries.map((entry) => ( - + ))} )} @@ -97,30 +131,25 @@ export function HistoryScreen({ {pinnedEntries.length > 0 && ( <> - Pinned Requests ({pinnedEntries.length}) + {formatPinnedTitle(pinnedEntries.length)} {pinnedEntries.map((entry) => ( - + ))} )} - - Showing {displayedCount} of {totalCount} entries - + + {formatPagination(displayedCount, totalCount)} + {displayedCount < totalCount && ( - + Load More )} - - + + ); } diff --git a/clients/web/src/components/organisms/LoggingScreen/LoggingScreen.tsx b/clients/web/src/components/organisms/LoggingScreen/LoggingScreen.tsx index dd736b4a..bd461b6b 100644 --- a/clients/web/src/components/organisms/LoggingScreen/LoggingScreen.tsx +++ b/clients/web/src/components/organisms/LoggingScreen/LoggingScreen.tsx @@ -23,6 +23,38 @@ export interface LoggingScreenProps { onCopyAll: () => void; } +const PageContainer = Container.withProps({ + size: "xl", + py: "xl", +}); + +const SidebarCard = Card.withProps({ + withBorder: true, + padding: "lg", +}); + +const FullHeightCard = Card.withProps({ + withBorder: true, + padding: "lg", + h: "100%", +}); + +const FullHeightStack = Stack.withProps({ + gap: "sm", + h: "100%", +}); + +const ToolbarButton = Button.withProps({ + variant: "light", + size: "sm", +}); + +const EmptyCenter = Stack.withProps({ + flex: 1, + align: "center", + justify: "center", +}); + export function LoggingScreen({ controls, entries, @@ -31,16 +63,16 @@ export function LoggingScreen({ onCopyAll, }: LoggingScreenProps) { return ( - + - + - + - - + + Log Stream @@ -49,9 +81,7 @@ export function LoggingScreen({ checked={autoScroll} onChange={onToggleAutoScroll} /> - + Copy All {entries.length > 0 ? ( @@ -63,14 +93,14 @@ export function LoggingScreen({ ) : ( - + No log entries - + )} - - + + - + ); } diff --git a/clients/web/src/components/organisms/PromptsScreen/PromptsScreen.tsx b/clients/web/src/components/organisms/PromptsScreen/PromptsScreen.tsx index 7715d311..0b69fcc2 100644 --- a/clients/web/src/components/organisms/PromptsScreen/PromptsScreen.tsx +++ b/clients/web/src/components/organisms/PromptsScreen/PromptsScreen.tsx @@ -12,6 +12,23 @@ export interface PromptsScreenProps { onRefreshList: () => void; } +const PageContainer = Container.withProps({ + size: "xl", + py: "xl", +}); + +const FullHeightCard = Card.withProps({ + withBorder: true, + padding: "lg", + h: "100%", +}); + +const EmptyState = Text.withProps({ + c: "dimmed", + ta: "center", + py: "xl", +}); + export function PromptsScreen({ promptForm, messages, @@ -19,10 +36,10 @@ export function PromptsScreen({ onRefreshList, }: PromptsScreenProps) { return ( - + - + - + - + {messages ? ( ) : ( - + Select a prompt and click Get Prompt to see messages - + )} - + - + ); } diff --git a/clients/web/src/components/organisms/ResourcesScreen/ResourcesScreen.tsx b/clients/web/src/components/organisms/ResourcesScreen/ResourcesScreen.tsx index 4e3e08fb..2873e919 100644 --- a/clients/web/src/components/organisms/ResourcesScreen/ResourcesScreen.tsx +++ b/clients/web/src/components/organisms/ResourcesScreen/ResourcesScreen.tsx @@ -33,6 +33,42 @@ export interface ResourcesScreenProps { onSelectResource: (uri: string) => void; } +const PageContainer = Container.withProps({ + size: "xl", + py: "xl", +}); + +const FullHeightCard = Card.withProps({ + withBorder: true, + padding: "lg", + h: "100%", +}); + +const DetailCard = Card.withProps({ + withBorder: true, + padding: "lg", +}); + +const EmptyState = Text.withProps({ + c: "dimmed", + ta: "center", + py: "xl", +}); + +const SubscriptionMeta = Text.withProps({ + span: true, + c: "dimmed", + size: "xs", +}); + +function formatSectionCount(label: string, count: number): string { + return `${label} (${count})`; +} + +function formatLastUpdated(lastUpdated: string): string { + return ` — ${lastUpdated}`; +} + export function ResourcesScreen({ resources, templates, @@ -54,10 +90,10 @@ export function ResourcesScreen({ ]; return ( - + - + Resources - URIs ({filteredResources.length}) + {formatSectionCount("URIs", filteredResources.length)} @@ -85,7 +121,7 @@ export function ResourcesScreen({ - Templates ({templates.length}) + {formatSectionCount("Templates", templates.length)} @@ -101,7 +137,7 @@ export function ResourcesScreen({ - Subscriptions ({subscriptions.length}) + {formatSectionCount("Subscriptions", subscriptions.length)} @@ -109,10 +145,9 @@ export function ResourcesScreen({ {sub.name} {sub.lastUpdated && ( - - {" "} - — {sub.lastUpdated} - + + {formatLastUpdated(sub.lastUpdated)} + )} ))} @@ -121,21 +156,19 @@ export function ResourcesScreen({ - + - + {selectedResource ? ( ) : ( - - Select a resource to preview - + Select a resource to preview )} - + - + ); } diff --git a/clients/web/src/components/organisms/ServerListScreen/ServerListScreen.tsx b/clients/web/src/components/organisms/ServerListScreen/ServerListScreen.tsx index 2b710427..a77f493f 100644 --- a/clients/web/src/components/organisms/ServerListScreen/ServerListScreen.tsx +++ b/clients/web/src/components/organisms/ServerListScreen/ServerListScreen.tsx @@ -10,6 +10,17 @@ export interface ServerListScreenProps { onImportServerJson: () => void; } +const PageContainer = Container.withProps({ + size: "xl", + py: "xl", +}); + +const EmptyState = Text.withProps({ + c: "dimmed", + ta: "center", + py: "xl", +}); + export function ServerListScreen({ servers, onAddManually, @@ -17,7 +28,7 @@ export function ServerListScreen({ onImportServerJson, }: ServerListScreenProps) { return ( - + {servers.length === 0 ? ( - + No servers configured. Add a server to get started. - + ) : ( )} - + ); } diff --git a/clients/web/src/components/organisms/TasksScreen/TasksScreen.tsx b/clients/web/src/components/organisms/TasksScreen/TasksScreen.tsx index 58a2d352..6942bb04 100644 --- a/clients/web/src/components/organisms/TasksScreen/TasksScreen.tsx +++ b/clients/web/src/components/organisms/TasksScreen/TasksScreen.tsx @@ -17,6 +17,25 @@ export interface TasksScreenProps { onClearHistory: () => void; } +const PageContainer = Container.withProps({ + size: "xl", + py: "xl", +}); + +const ContentPanel = Paper.withProps({ + withBorder: true, + p: "md", +}); + +const CompactButton = Button.withProps({ + variant: "light", + size: "xs", +}); + +function formatSectionTitle(label: string, count: number): string { + return `${label} (${count})`; +} + export function TasksScreen({ activeTasks, completedTasks, @@ -24,14 +43,14 @@ export function TasksScreen({ onClearHistory, }: TasksScreenProps) { return ( - - + + - Active Tasks ({activeTasks.length}) - + + {formatSectionTitle("Active Tasks", activeTasks.length)} + + Refresh Tasks {activeTasks.length === 0 ? ( No active tasks @@ -44,11 +63,13 @@ export function TasksScreen({ )} - Completed Tasks ({completedTasks.length}) + + {formatSectionTitle("Completed Tasks", completedTasks.length)} + {completedTasks.length > 0 && ( - + )} {completedTasks.length === 0 ? ( @@ -61,7 +82,7 @@ export function TasksScreen({ )} - - + + ); } diff --git a/clients/web/src/components/organisms/ToolsScreen/ToolsScreen.tsx b/clients/web/src/components/organisms/ToolsScreen/ToolsScreen.tsx index 16e8c69a..47d8bd33 100644 --- a/clients/web/src/components/organisms/ToolsScreen/ToolsScreen.tsx +++ b/clients/web/src/components/organisms/ToolsScreen/ToolsScreen.tsx @@ -26,6 +26,23 @@ export interface ToolsScreenProps { onSelectTool: (name: string) => void; } +const PageContainer = Container.withProps({ + size: "xl", + py: "xl", +}); + +const FullHeightCard = Card.withProps({ + withBorder: true, + padding: "lg", + h: "100%", +}); + +const EmptyState = Text.withProps({ + c: "dimmed", + ta: "center", + py: "xl", +}); + export function ToolsScreen({ tools, selectedTool, @@ -43,10 +60,10 @@ export function ToolsScreen({ : tools; return ( - + - + Tools ))} - + - + {selectedTool ? ( ) : ( - - Select a tool to view details - + Select a tool to view details )} - + - + {result ? ( ) : ( - - Results will appear here - + Results will appear here )} - + - + ); }