Add new components, typography, badge contrast, and screen layout refactors
New element components: - ListToggle: expand/collapse button using react-icons (RiExpandVerticalLine/RiCollapseVerticalLine) - LogLevelBadge: extracted from LogEntry, handles all 8 log levels with filled variant and dark/light text contrast New group components: - ViewHeader: shared header bar for ConnectedView and UnconnectedView with discriminated union on `connected` prop; MCP logo links to modelcontextprotocol.io - ServerListControls: combines ListToggle and AddServerMenu, hides toggle when no servers - LogStreamPanel: extracted from LoggingScreen with scroll containment, filtering by visible levels and search text - HistoryControls: vertical sidebar with search, method filter, export, and clear - HistoryListPanel: extracted from HistoryScreen with ListToggle compact mode, filtering by method and search text Badge contrast improvements: - AnnotationBadge: filled variant for both dark/light modes; black text in dark, white text in light - LogLevelBadge: same contrast approach; bold weight for alert/emergency levels - Badge theme default weight reduced from 700 to 600 Typography: - Added Fredoka (300-700) as body and heading font - Added Roboto Mono as monospace font - Google Fonts loaded in index.html and Storybook previewHead - Heading weight set to 600 Screen layout refactors: - LoggingScreen: owns filterText and visibleLevels state; passes to LogControls and LogStreamPanel; removed controls prop in favor of flat props - HistoryScreen: owns searchText and methodFilter state; passes to HistoryControls and HistoryListPanel for filtering - Both screens use new ScreenLayout (Flex variant="screen") and Sidebar subcomponents - Added Flex theme with "screen" variant (overflow: hidden) - Added Paper theme "panel" variant (flex column, overflow hidden) Component enhancements: - ServerCard: added compact prop showing only header row - HistoryEntry: renamed isExpanded to isListExpanded; internal useState syncs via useEffect; individual entries toggle independently - LogControls: Select All / Deselect All toggle for level checkboxes; nowrap on level selector group - ConnectionToggle: LoadingOverlay with rounded corners for connecting state - ConnectedView: ThemeToggle ActionIcon matched to DisconnectButton height (36px) and border color (outline variant) - Storybook preview: fullscreen layout wrapper with 100vh overflow hidden New stories: - UnconnectedView: Connecting and ManyServers (12 servers for scroll testing) - ServerCard: CompactConnected and CompactDisconnected - All new components have corresponding stories Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
dd46acba87
commit
961dc283fc
1 changed files with 1602 additions and 790 deletions
|
|
@ -0,0 +1,259 @@
|
|||
import type { Meta, StoryObj } from "@storybook/react-vite";
|
||||
import { fn } from "storybook/test";
|
||||
import { UnconnectedView } from "./UnconnectedView.js";
|
||||
import { ServerListScreen } from "../../screens/ServerListScreen/ServerListScreen";
|
||||
import type { ServerCardProps } from "../../groups/ServerCard/ServerCard";
|
||||
|
||||
const meta: Meta<typeof UnconnectedView> = {
|
||||
title: "Views/UnconnectedView",
|
||||
component: UnconnectedView,
|
||||
parameters: { layout: "fullscreen" },
|
||||
args: {
|
||||
onToggleTheme: fn(),
|
||||
},
|
||||
};
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof UnconnectedView>;
|
||||
|
||||
function makeServerCallbacks(): Pick<
|
||||
ServerCardProps,
|
||||
| "onToggleConnection"
|
||||
| "onServerInfo"
|
||||
| "onSettings"
|
||||
| "onEdit"
|
||||
| "onClone"
|
||||
| "onRemove"
|
||||
> {
|
||||
return {
|
||||
onToggleConnection: fn(),
|
||||
onServerInfo: fn(),
|
||||
onSettings: fn(),
|
||||
onEdit: fn(),
|
||||
onClone: fn(),
|
||||
onRemove: fn(),
|
||||
};
|
||||
}
|
||||
|
||||
export const Empty: Story = {
|
||||
args: {
|
||||
children: (
|
||||
<ServerListScreen
|
||||
servers={[]}
|
||||
onAddManually={fn()}
|
||||
onImportConfig={fn()}
|
||||
onImportServerJson={fn()}
|
||||
/>
|
||||
),
|
||||
},
|
||||
};
|
||||
|
||||
export const WithServers: Story = {
|
||||
args: {
|
||||
children: (
|
||||
<ServerListScreen
|
||||
servers={[
|
||||
{
|
||||
name: "everything-server",
|
||||
version: "1.0.0",
|
||||
transport: "stdio",
|
||||
connectionMode: "Via Proxy",
|
||||
command: "npx -y @modelcontextprotocol/server-everything",
|
||||
status: "connected",
|
||||
canTestClientFeatures: true,
|
||||
...makeServerCallbacks(),
|
||||
},
|
||||
{
|
||||
name: "filesystem-server",
|
||||
version: "0.6.2",
|
||||
transport: "stdio",
|
||||
connectionMode: "Via Proxy",
|
||||
command:
|
||||
"npx -y @modelcontextprotocol/server-filesystem /home/user",
|
||||
status: "disconnected",
|
||||
canTestClientFeatures: false,
|
||||
...makeServerCallbacks(),
|
||||
},
|
||||
{
|
||||
name: "remote-server",
|
||||
version: "2.1.0",
|
||||
transport: "http",
|
||||
connectionMode: "Direct",
|
||||
command: "https://api.example.com/mcp",
|
||||
status: "failed",
|
||||
retryCount: 3,
|
||||
error: { message: "Connection timeout after 20s" },
|
||||
canTestClientFeatures: false,
|
||||
...makeServerCallbacks(),
|
||||
},
|
||||
]}
|
||||
onAddManually={fn()}
|
||||
onImportConfig={fn()}
|
||||
onImportServerJson={fn()}
|
||||
/>
|
||||
),
|
||||
},
|
||||
};
|
||||
|
||||
export const ManyServers: Story = {
|
||||
args: {
|
||||
children: (
|
||||
<ServerListScreen
|
||||
servers={[
|
||||
{
|
||||
name: "everything-server",
|
||||
version: "1.0.0",
|
||||
transport: "stdio",
|
||||
connectionMode: "Via Proxy",
|
||||
command: "npx -y @modelcontextprotocol/server-everything",
|
||||
status: "connected",
|
||||
canTestClientFeatures: true,
|
||||
...makeServerCallbacks(),
|
||||
},
|
||||
{
|
||||
name: "filesystem-server",
|
||||
version: "0.6.2",
|
||||
transport: "stdio",
|
||||
connectionMode: "Via Proxy",
|
||||
command:
|
||||
"npx -y @modelcontextprotocol/server-filesystem /home/user",
|
||||
status: "disconnected",
|
||||
canTestClientFeatures: false,
|
||||
...makeServerCallbacks(),
|
||||
},
|
||||
{
|
||||
name: "remote-api-server",
|
||||
version: "2.1.0",
|
||||
transport: "http",
|
||||
connectionMode: "Direct",
|
||||
command: "https://api.example.com/mcp",
|
||||
status: "connected",
|
||||
canTestClientFeatures: true,
|
||||
...makeServerCallbacks(),
|
||||
},
|
||||
{
|
||||
name: "postgres-server",
|
||||
version: "1.3.0",
|
||||
transport: "stdio",
|
||||
connectionMode: "Via Proxy",
|
||||
command: "npx -y @modelcontextprotocol/server-postgres",
|
||||
status: "connecting",
|
||||
canTestClientFeatures: false,
|
||||
...makeServerCallbacks(),
|
||||
},
|
||||
{
|
||||
name: "github-server",
|
||||
version: "0.9.1",
|
||||
transport: "stdio",
|
||||
connectionMode: "Via Proxy",
|
||||
command: "npx -y @modelcontextprotocol/server-github",
|
||||
status: "connected",
|
||||
canTestClientFeatures: true,
|
||||
...makeServerCallbacks(),
|
||||
},
|
||||
{
|
||||
name: "slack-server",
|
||||
version: "1.1.0",
|
||||
transport: "http",
|
||||
connectionMode: "Direct",
|
||||
command: "https://slack-mcp.example.com/mcp",
|
||||
status: "failed",
|
||||
retryCount: 5,
|
||||
error: { message: "Authentication failed" },
|
||||
canTestClientFeatures: false,
|
||||
...makeServerCallbacks(),
|
||||
},
|
||||
{
|
||||
name: "memory-server",
|
||||
version: "0.2.0",
|
||||
transport: "stdio",
|
||||
connectionMode: "Via Proxy",
|
||||
command: "npx -y @modelcontextprotocol/server-memory",
|
||||
status: "connected",
|
||||
canTestClientFeatures: false,
|
||||
...makeServerCallbacks(),
|
||||
},
|
||||
{
|
||||
name: "puppeteer-server",
|
||||
version: "1.0.3",
|
||||
transport: "stdio",
|
||||
connectionMode: "Via Proxy",
|
||||
command: "npx -y @modelcontextprotocol/server-puppeteer",
|
||||
status: "disconnected",
|
||||
canTestClientFeatures: false,
|
||||
...makeServerCallbacks(),
|
||||
},
|
||||
{
|
||||
name: "sqlite-server",
|
||||
version: "0.5.1",
|
||||
transport: "stdio",
|
||||
connectionMode: "Via Proxy",
|
||||
command: "npx -y @modelcontextprotocol/server-sqlite ./data.db",
|
||||
status: "connected",
|
||||
canTestClientFeatures: true,
|
||||
...makeServerCallbacks(),
|
||||
},
|
||||
{
|
||||
name: "brave-search-server",
|
||||
version: "1.2.0",
|
||||
transport: "stdio",
|
||||
connectionMode: "Via Proxy",
|
||||
command: "npx -y @modelcontextprotocol/server-brave-search",
|
||||
status: "failed",
|
||||
retryCount: 2,
|
||||
error: { message: "API key expired" },
|
||||
canTestClientFeatures: false,
|
||||
...makeServerCallbacks(),
|
||||
},
|
||||
{
|
||||
name: "google-maps-server",
|
||||
version: "0.8.0",
|
||||
transport: "http",
|
||||
connectionMode: "Direct",
|
||||
command: "https://maps-mcp.example.com/mcp",
|
||||
status: "disconnected",
|
||||
canTestClientFeatures: false,
|
||||
...makeServerCallbacks(),
|
||||
},
|
||||
{
|
||||
name: "sequential-thinking-server",
|
||||
version: "1.4.2",
|
||||
transport: "stdio",
|
||||
connectionMode: "Via Proxy",
|
||||
command: "npx -y @modelcontextprotocol/server-sequential-thinking",
|
||||
status: "connecting",
|
||||
canTestClientFeatures: false,
|
||||
...makeServerCallbacks(),
|
||||
},
|
||||
]}
|
||||
onAddManually={fn()}
|
||||
onImportConfig={fn()}
|
||||
onImportServerJson={fn()}
|
||||
/>
|
||||
),
|
||||
},
|
||||
};
|
||||
|
||||
export const Connecting: Story = {
|
||||
args: {
|
||||
children: (
|
||||
<ServerListScreen
|
||||
servers={[
|
||||
{
|
||||
name: "everything-server",
|
||||
version: "1.0.0",
|
||||
transport: "stdio",
|
||||
connectionMode: "Via Proxy",
|
||||
command: "npx -y @modelcontextprotocol/server-everything",
|
||||
status: "connecting",
|
||||
canTestClientFeatures: false,
|
||||
...makeServerCallbacks(),
|
||||
},
|
||||
]}
|
||||
onAddManually={fn()}
|
||||
onImportConfig={fn()}
|
||||
onImportServerJson={fn()}
|
||||
/>
|
||||
),
|
||||
},
|
||||
};
|
||||
Loading…
Reference in a new issue