From f674ce0c22e7b0a9611636e0fe16d1d70019a4fe Mon Sep 17 00:00:00 2001 From: cliffhall Date: Mon, 23 Mar 2026 16:56:53 -0400 Subject: [PATCH] refine UI layout, theming, and component consistency across screens - Add MCP logo (light/dark variants) to ConnectedLayout header - Replace Tabs with SegmentedControl in header, split into 1/3 sections - Wrap all screens in Container for consistent margins - Use Card instead of Paper for panel backgrounds across all screens - Add SubscribeButton atom, CopyButton for resource URI - Move annotations from ResourceListItem to ResourcePreviewPanel - Improve AnnotationBadge colors for dark mode visibility - Add Tools, Resources, and Prompts headers to list panels - Add ConnectedLayout stories for Tools, Resources, and Prompts tabs - Remove unused onCopy prop and copy button from PromptMessagesDisplay Co-Authored-By: Claude Opus 4.6 (1M context) --- .../atoms/AnnotationBadge/AnnotationBadge.tsx | 17 +- .../SubscribeButton.stories.tsx | 26 +++ .../atoms/SubscribeButton/SubscribeButton.tsx | 17 ++ .../ConnectedLayout.stories.tsx | 148 +++++++++++++++++- .../ConnectedLayout/ConnectedLayout.tsx | 52 +++--- .../PromptArgumentsForm.tsx | 2 +- .../PromptMessagesDisplay.stories.tsx | 4 +- .../PromptMessagesDisplay.tsx | 7 +- .../ResourceListItem/ResourceListItem.tsx | 30 +--- .../ResourcePreviewPanel.tsx | 89 ++++++----- .../ResourceTemplateInput.tsx | 1 - .../ToolDetailPanel/ToolDetailPanel.tsx | 5 - .../organisms/LoggingScreen/LoggingScreen.tsx | 3 + .../PromptsScreen/PromptsScreen.stories.tsx | 1 - .../organisms/PromptsScreen/PromptsScreen.tsx | 14 +- .../ResourcesScreen.stories.tsx | 1 - .../ResourcesScreen/ResourcesScreen.tsx | 31 ++-- .../ServerListScreen/ServerListScreen.tsx | 4 +- .../organisms/TasksScreen/TasksScreen.tsx | 19 ++- .../organisms/ToolsScreen/ToolsScreen.tsx | 19 ++- clients/web/src/theme/assets/MCP-dark.svg | 12 ++ clients/web/src/theme/assets/MCP.svg | 12 ++ 22 files changed, 357 insertions(+), 157 deletions(-) create mode 100644 clients/web/src/components/atoms/SubscribeButton/SubscribeButton.stories.tsx create mode 100644 clients/web/src/components/atoms/SubscribeButton/SubscribeButton.tsx create mode 100644 clients/web/src/theme/assets/MCP-dark.svg create mode 100644 clients/web/src/theme/assets/MCP.svg diff --git a/clients/web/src/components/atoms/AnnotationBadge/AnnotationBadge.tsx b/clients/web/src/components/atoms/AnnotationBadge/AnnotationBadge.tsx index bf696577..a7490f70 100644 --- a/clients/web/src/components/atoms/AnnotationBadge/AnnotationBadge.tsx +++ b/clients/web/src/components/atoms/AnnotationBadge/AnnotationBadge.tsx @@ -1,4 +1,4 @@ -import { Badge } from "@mantine/core"; +import { Badge, useComputedColorScheme } from "@mantine/core"; export type AnnotationVariant = | "audience" @@ -17,11 +17,11 @@ const variantMap: Record< AnnotationVariant, { color: string; variant: string } > = { - audience: { color: "gray", variant: "outline" }, - readOnly: { color: "dark", variant: "filled" }, - destructive: { color: "red", variant: "outline" }, - longRun: { color: "yellow", variant: "outline" }, - priority: { color: "orange", variant: "light" }, + audience: { color: "blue", variant: "outline" }, + readOnly: { color: "green", variant: "filled" }, + destructive: { color: "red", variant: "filled" }, + longRun: { color: "yellow", variant: "filled" }, + priority: { color: "orange", variant: "filled" }, default: { color: "gray", variant: "light" }, }; @@ -29,10 +29,13 @@ export function AnnotationBadge({ label, variant = "default", }: AnnotationBadgeProps) { + const colorScheme = useComputedColorScheme(); const { color, variant: badgeVariant } = variantMap[variant]; + const textColor = + (variant === "priority" || variant === "destructive") && colorScheme === "dark" ? "black" : undefined; return ( - + {label} ); diff --git a/clients/web/src/components/atoms/SubscribeButton/SubscribeButton.stories.tsx b/clients/web/src/components/atoms/SubscribeButton/SubscribeButton.stories.tsx new file mode 100644 index 00000000..c2bbdfdb --- /dev/null +++ b/clients/web/src/components/atoms/SubscribeButton/SubscribeButton.stories.tsx @@ -0,0 +1,26 @@ +import type { Meta, StoryObj } from "@storybook/react-vite"; +import { fn } from "storybook/test"; +import { SubscribeButton } from "./SubscribeButton"; + +const meta: Meta = { + title: "Atoms/SubscribeButton", + component: SubscribeButton, + args: { + onToggle: fn(), + }, +}; + +export default meta; +type Story = StoryObj; + +export const Subscribed: Story = { + args: { + subscribed: true, + }, +}; + +export const Unsubscribed: Story = { + args: { + subscribed: false, + }, +}; diff --git a/clients/web/src/components/atoms/SubscribeButton/SubscribeButton.tsx b/clients/web/src/components/atoms/SubscribeButton/SubscribeButton.tsx new file mode 100644 index 00000000..3b0ccc36 --- /dev/null +++ b/clients/web/src/components/atoms/SubscribeButton/SubscribeButton.tsx @@ -0,0 +1,17 @@ +import { Button } from "@mantine/core"; + +export interface SubscribeButtonProps { + subscribed: boolean; + onToggle: () => void; +} + +export function SubscribeButton({ + subscribed, + onToggle, +}: SubscribeButtonProps) { + return ( + + ); +} diff --git a/clients/web/src/components/layouts/ConnectedLayout/ConnectedLayout.stories.tsx b/clients/web/src/components/layouts/ConnectedLayout/ConnectedLayout.stories.tsx index 2980c32b..c86161b9 100644 --- a/clients/web/src/components/layouts/ConnectedLayout/ConnectedLayout.stories.tsx +++ b/clients/web/src/components/layouts/ConnectedLayout/ConnectedLayout.stories.tsx @@ -2,6 +2,9 @@ import type { Meta, StoryObj } from "@storybook/react-vite"; import { fn } from "storybook/test"; import { Text } from "@mantine/core"; import { ConnectedLayout } from "./ConnectedLayout"; +import { ToolsScreen } from "../../organisms/ToolsScreen/ToolsScreen"; +import { ResourcesScreen } from "../../organisms/ResourcesScreen/ResourcesScreen"; +import { PromptsScreen } from "../../organisms/PromptsScreen/PromptsScreen"; const allTabs = ["Tools", "Resources", "Prompts", "Logs", "Tasks", "History"]; @@ -27,14 +30,153 @@ type Story = StoryObj; export const ToolsActive: Story = { args: { activeTab: "Tools", - children: Tools screen content, + children: ( + + ), }, }; export const ResourcesActive: Story = { args: { activeTab: "Resources", - children: Resources screen content, + children: ( + + ), + }, +}; + +export const PromptsActive: Story = { + args: { + activeTab: "Prompts", + children: ( + + ), }, }; @@ -47,7 +189,7 @@ export const LimitedTabs: Story = { export const LongServerName: Story = { args: { - serverName: "my-very-long-server-name-that-might-overflow", + serverName: "my-very-long-server-name-that-might-overflow-is", children: Tools screen content, }, }; diff --git a/clients/web/src/components/layouts/ConnectedLayout/ConnectedLayout.tsx b/clients/web/src/components/layouts/ConnectedLayout/ConnectedLayout.tsx index 2417be8c..8cc850bb 100644 --- a/clients/web/src/components/layouts/ConnectedLayout/ConnectedLayout.tsx +++ b/clients/web/src/components/layouts/ConnectedLayout/ConnectedLayout.tsx @@ -1,7 +1,9 @@ import type { ReactNode } from "react"; -import { ActionIcon, AppShell, Button, Group, Tabs, Text } from "@mantine/core"; +import { ActionIcon, AppShell, Button, Group, Image, SegmentedControl, Text } from "@mantine/core"; import { useComputedColorScheme } from "@mantine/core"; import { StatusIndicator } from "../../atoms/StatusIndicator/StatusIndicator"; +import mcpLogo from "../../../theme/assets/MCP.svg"; +import mcpLogoDark from "../../../theme/assets/MCP-dark.svg"; export interface ConnectedLayoutProps { serverName: string; @@ -18,6 +20,8 @@ export interface ConnectedLayoutProps { const ServerName = Text.withProps({ fw: 600, size: "lg", + truncate: "end", + maw: "calc(100% - 40px)", }); export function ConnectedLayout({ @@ -36,35 +40,23 @@ export function ConnectedLayout({ return ( - - + + + MCP {serverName} - - value && onTabChange(value)} - variant="default" - > - - {availableTabs.map((tab) => ( - - {tab} - - ))} - - + + + - - - {colorScheme === "dark" ? "\u2600" : "\u263E"} - + + + + {colorScheme === "dark" ? "\u2600" : "\u263E"} + diff --git a/clients/web/src/components/molecules/PromptArgumentsForm/PromptArgumentsForm.tsx b/clients/web/src/components/molecules/PromptArgumentsForm/PromptArgumentsForm.tsx index 3281729f..0194f920 100644 --- a/clients/web/src/components/molecules/PromptArgumentsForm/PromptArgumentsForm.tsx +++ b/clients/web/src/components/molecules/PromptArgumentsForm/PromptArgumentsForm.tsx @@ -34,7 +34,7 @@ export function PromptArgumentsForm({ return ( - Select Prompt + Prompts