refactor organism components to use .withProps() subcomponents and extract inline code

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
cliffhall 2026-03-24 15:32:15 -04:00
commit ca6de91a96
7 changed files with 250 additions and 96 deletions

View file

@ -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 (
<Container size="xl" py="xl">
<Paper withBorder p="md">
<PageContainer>
<ContentPanel>
<Stack gap="md">
<Group justify="space-between" wrap="wrap">
<HeaderRow>
<Title order={3}>Request History</Title>
<Group>
<TextInput
@ -70,26 +113,17 @@ export function HistoryScreen({
onChange={(value) => onMethodFilterChange(value ?? "")}
clearable
/>
<Button variant="light" size="sm" onClick={onExport}>
Export JSON
</Button>
<Button variant="light" size="sm" onClick={onClearAll}>
Clear All
</Button>
<ToolbarButton onClick={onExport}>Export JSON</ToolbarButton>
<ToolbarButton onClick={onClearAll}>Clear All</ToolbarButton>
</Group>
</Group>
</HeaderRow>
{entries.length === 0 ? (
<Text c="dimmed" ta="center" py="xl">
No request history
</Text>
<EmptyState>No request history</EmptyState>
) : (
<Stack gap="md">
{entries.map((entry) => (
<HistoryEntry
key={`${entry.timestamp}-${entry.method}`}
{...entry}
/>
<HistoryEntry key={entryKey(entry)} {...entry} />
))}
</Stack>
)}
@ -97,30 +131,25 @@ export function HistoryScreen({
{pinnedEntries.length > 0 && (
<>
<Divider />
<Title order={4}>Pinned Requests ({pinnedEntries.length})</Title>
<Title order={4}>{formatPinnedTitle(pinnedEntries.length)}</Title>
<Stack gap="sm">
{pinnedEntries.map((entry) => (
<HistoryEntry
key={`${entry.timestamp}-${entry.method}`}
{...entry}
/>
<HistoryEntry key={entryKey(entry)} {...entry} />
))}
</Stack>
</>
)}
<Group justify="flex-end">
<Text size="sm" c="dimmed">
Showing {displayedCount} of {totalCount} entries
</Text>
<CountText>
{formatPagination(displayedCount, totalCount)}
</CountText>
{displayedCount < totalCount && (
<Button variant="light" size="sm" onClick={onLoadMore}>
Load More
</Button>
<ToolbarButton onClick={onLoadMore}>Load More</ToolbarButton>
)}
</Group>
</Stack>
</Paper>
</Container>
</ContentPanel>
</PageContainer>
);
}

View file

@ -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 (
<Container size="xl" py="xl">
<PageContainer>
<Grid align="stretch">
<Grid.Col span={3}>
<Card withBorder padding="lg">
<SidebarCard>
<LogControls {...controls} />
</Card>
</SidebarCard>
</Grid.Col>
<Grid.Col span={9}>
<Card withBorder padding="lg" h="100%">
<Stack gap="sm" h="100%">
<FullHeightCard>
<FullHeightStack>
<Group justify="space-between">
<Title order={4}>Log Stream</Title>
<Group>
@ -49,9 +81,7 @@ export function LoggingScreen({
checked={autoScroll}
onChange={onToggleAutoScroll}
/>
<Button variant="light" size="sm" onClick={onCopyAll}>
Copy All
</Button>
<ToolbarButton onClick={onCopyAll}>Copy All</ToolbarButton>
</Group>
</Group>
{entries.length > 0 ? (
@ -63,14 +93,14 @@ export function LoggingScreen({
</Stack>
</ScrollArea>
) : (
<Stack flex={1} align="center" justify="center">
<EmptyCenter>
<Text c="dimmed">No log entries</Text>
</Stack>
</EmptyCenter>
)}
</Stack>
</Card>
</FullHeightStack>
</FullHeightCard>
</Grid.Col>
</Grid>
</Container>
</PageContainer>
);
}

View file

@ -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 (
<Container size="xl" py="xl">
<PageContainer>
<Grid align="stretch">
<Grid.Col span={5}>
<Card withBorder padding="lg" h="100%">
<FullHeightCard>
<Stack gap="md">
<ListChangedIndicator
visible={listChanged}
@ -30,20 +47,20 @@ export function PromptsScreen({
/>
<PromptArgumentsForm {...promptForm} />
</Stack>
</Card>
</FullHeightCard>
</Grid.Col>
<Grid.Col span={7}>
<Card withBorder padding="lg" h="100%">
<FullHeightCard>
{messages ? (
<PromptMessagesDisplay {...messages} />
) : (
<Text c="dimmed" ta="center" py="xl">
<EmptyState>
Select a prompt and click Get Prompt to see messages
</Text>
</EmptyState>
)}
</Card>
</FullHeightCard>
</Grid.Col>
</Grid>
</Container>
</PageContainer>
);
}

View file

@ -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 (
<Container size="xl" py="xl">
<PageContainer>
<Grid align="stretch">
<Grid.Col span={4}>
<Card withBorder padding="lg" h="100%">
<FullHeightCard>
<Stack gap="sm">
<Title order={4}>Resources</Title>
<ListChangedIndicator
@ -72,7 +108,7 @@ export function ResourcesScreen({
<Accordion multiple defaultValue={openSections}>
<Accordion.Item value="resources">
<Accordion.Control disabled={filteredResources.length === 0}>
URIs ({filteredResources.length})
{formatSectionCount("URIs", filteredResources.length)}
</Accordion.Control>
<Accordion.Panel>
<Stack gap="xs">
@ -85,7 +121,7 @@ export function ResourcesScreen({
<Accordion.Item value="templates">
<Accordion.Control disabled={templates.length === 0}>
Templates ({templates.length})
{formatSectionCount("Templates", templates.length)}
</Accordion.Control>
<Accordion.Panel>
<Stack gap="xs">
@ -101,7 +137,7 @@ export function ResourcesScreen({
<Accordion.Item value="subscriptions">
<Accordion.Control disabled={subscriptions.length === 0}>
Subscriptions ({subscriptions.length})
{formatSectionCount("Subscriptions", subscriptions.length)}
</Accordion.Control>
<Accordion.Panel>
<Stack gap="xs">
@ -109,10 +145,9 @@ export function ResourcesScreen({
<Text key={sub.name} size="sm">
{sub.name}
{sub.lastUpdated && (
<Text span c="dimmed" size="xs">
{" "}
— {sub.lastUpdated}
</Text>
<SubscriptionMeta>
{formatLastUpdated(sub.lastUpdated)}
</SubscriptionMeta>
)}
</Text>
))}
@ -121,21 +156,19 @@ export function ResourcesScreen({
</Accordion.Item>
</Accordion>
</Stack>
</Card>
</FullHeightCard>
</Grid.Col>
<Grid.Col span={8}>
<Card withBorder padding="lg">
<DetailCard>
{selectedResource ? (
<ResourcePreviewPanel {...selectedResource} />
) : (
<Text c="dimmed" ta="center" py="xl">
Select a resource to preview
</Text>
<EmptyState>Select a resource to preview</EmptyState>
)}
</Card>
</DetailCard>
</Grid.Col>
</Grid>
</Container>
</PageContainer>
);
}

View file

@ -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 (
<Container size="xl" py="xl">
<PageContainer>
<Stack gap="lg">
<Group justify="flex-end">
<AddServerMenu
@ -28,9 +39,9 @@ export function ServerListScreen({
</Group>
{servers.length === 0 ? (
<Text c="dimmed" ta="center" py="xl">
<EmptyState>
No servers configured. Add a server to get started.
</Text>
</EmptyState>
) : (
<SimpleGrid
cols={{ base: 1, md: 2 }}
@ -43,6 +54,6 @@ export function ServerListScreen({
</SimpleGrid>
)}
</Stack>
</Container>
</PageContainer>
);
}

View file

@ -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 (
<Container size="xl" py="xl">
<Paper withBorder p="md">
<PageContainer>
<ContentPanel>
<Stack gap="lg">
<Group justify="space-between">
<Title order={4}>Active Tasks ({activeTasks.length})</Title>
<Button variant="light" size="xs" onClick={onRefresh}>
Refresh Tasks
</Button>
<Title order={4}>
{formatSectionTitle("Active Tasks", activeTasks.length)}
</Title>
<CompactButton onClick={onRefresh}>Refresh Tasks</CompactButton>
</Group>
{activeTasks.length === 0 ? (
<Text c="dimmed">No active tasks</Text>
@ -44,11 +63,13 @@ export function TasksScreen({
)}
<Group justify="space-between">
<Title order={4}>Completed Tasks ({completedTasks.length})</Title>
<Title order={4}>
{formatSectionTitle("Completed Tasks", completedTasks.length)}
</Title>
{completedTasks.length > 0 && (
<Button variant="light" size="xs" onClick={onClearHistory}>
<CompactButton onClick={onClearHistory}>
Clear History
</Button>
</CompactButton>
)}
</Group>
{completedTasks.length === 0 ? (
@ -61,7 +82,7 @@ export function TasksScreen({
</Stack>
)}
</Stack>
</Paper>
</Container>
</ContentPanel>
</PageContainer>
);
}

View file

@ -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 (
<Container size="xl" py="xl">
<PageContainer>
<Grid align="stretch">
<Grid.Col span={3}>
<Card withBorder padding="lg" h="100%">
<FullHeightCard>
<Stack gap="sm">
<Title order={4}>Tools</Title>
<ListChangedIndicator
@ -66,33 +83,29 @@ export function ToolsScreen({
/>
))}
</Stack>
</Card>
</FullHeightCard>
</Grid.Col>
<Grid.Col span={5}>
<Card withBorder padding="lg" h="100%">
<FullHeightCard>
{selectedTool ? (
<ToolDetailPanel {...selectedTool} />
) : (
<Text c="dimmed" ta="center" py="xl">
Select a tool to view details
</Text>
<EmptyState>Select a tool to view details</EmptyState>
)}
</Card>
</FullHeightCard>
</Grid.Col>
<Grid.Col span={4}>
<Card withBorder padding="lg" h="100%">
<FullHeightCard>
{result ? (
<ResultPanel {...result} />
) : (
<Text c="dimmed" ta="center" py="xl">
Results will appear here
</Text>
<EmptyState>Results will appear here</EmptyState>
)}
</Card>
</FullHeightCard>
</Grid.Col>
</Grid>
</Container>
</PageContainer>
);
}