From 021df16a3e153cdafaeb2fd3981fd0cb43405c92 Mon Sep 17 00:00:00 2001 From: Sirius Date: Sun, 15 Feb 2026 04:05:20 +0100 Subject: [PATCH] chore: remove stale unified-sidebar wireframe study MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The unified sidebar wireframe (studies/unified-sidebar-wireframe.tsx) was a design artifact for TASK-026. PR #156 has been merged and the feature is shipped — the wireframe is no longer needed. Removes 1,066 lines of dead code and the empty studies/ directory. --- studies/unified-sidebar-wireframe.tsx | 1065 ------------------------- 1 file changed, 1065 deletions(-) delete mode 100644 studies/unified-sidebar-wireframe.tsx diff --git a/studies/unified-sidebar-wireframe.tsx b/studies/unified-sidebar-wireframe.tsx deleted file mode 100644 index 4d59b961..00000000 --- a/studies/unified-sidebar-wireframe.tsx +++ /dev/null @@ -1,1065 +0,0 @@ -import { useState, useEffect } from "react"; - -/* - WIREFRAME — zero visual design. - Only structural layout: borders, spacing, text hierarchy. - Purpose: validate information architecture before skinning. - - Reference for TASK-026: Unified Sidebar — Servers, Primitives & Connection Form -*/ - -const B = "1px solid #ccc"; -const BL = "1px solid #ddd"; - -const MOCK_TOOL_RESULT = { - content: [ - { - type: "text", - text: "# Weekly Sync Notes\n\nAttendees: @alice, @bob\n\n## Updates\n- Project Alpha: on track\n- Project Beta: blocked on API review", - }, - ], - structuredContent: { - page: { - id: "a1b2c3d4", - title: "Weekly Sync Notes", - type: "page", - properties: { Status: "Active", Tags: ["meetings", "weekly"] }, - }, - }, - _meta: { requestId: "req_8f3a2b1c", serverName: "notion-mcp", duration_ms: 243, cached: false }, -}; - -const MOCK_RESOURCE_RESULT = { - contents: [ - { - uri: "notion://docs/enhanced-markdown-spec", - mimeType: "text/markdown", - text: "# Enhanced Markdown Spec v2.1\n\n## Callouts\nUse > [!type] syntax\n\n## Toggle Blocks\nWrapped in
tags\n\n## Synced Blocks\nReferenced via {{sync:block_id}}", - }, - ], - _meta: { requestId: "req_4d7e9f2a", serverName: "notion-mcp", duration_ms: 87, cached: true }, -}; - -const MOCK_PROMPT_RESULT = { - messages: [ - { - role: "user", - content: - "Please summarize the following Notion page.\n\nPage URL: https://notion.so/workspace/Page-a1b2c3d4\nStyle: brief", - }, - ], - _meta: { requestId: "req_1c5b8e3d", serverName: "notion-mcp", promptName: "summarize-page" }, -}; - -const SERVERS = [ - { - name: "Notion", - tools: [ - { - kind: "tool", - name: "notion-fetch", - summary: "Retrieves details about a Notion entity by URL or ID.", - description: - "Provide URL or ID in `id` parameter. Make multiple calls to fetch multiple entities.", - examples: [ - { label: "By URL", value: '{"id": "https://notion.so/workspace/Page-a1b2c3d4"}' }, - { label: "By ID", value: '{"id": "12345678-90ab-cdef-1234-567890abcdef"}' }, - ], - parameters: [ - { - name: "id", - type: "string", - required: true, - description: "The ID or URL of the Notion page to fetch", - }, - { name: "include_transcript", type: "boolean", required: false, description: null }, - ], - annotations: { - readOnlyHint: true, - destructiveHint: false, - idempotentHint: true, - openWorldHint: false, - }, - }, - { - kind: "tool", - name: "notion-update", - summary: "Update properties or content of a Notion page.", - description: "Modifies page properties or appends content blocks.", - examples: [], - parameters: [ - { name: "page_id", type: "string", required: true, description: "The page ID to update" }, - { - name: "properties", - type: "object", - required: true, - description: "Properties to update (JSON)", - }, - ], - annotations: { - readOnlyHint: false, - destructiveHint: true, - idempotentHint: false, - openWorldHint: false, - }, - }, - ], - resources: [ - { - kind: "resource", - name: "enhanced-markdown-spec", - uri: "notion://docs/enhanced-markdown-spec", - summary: "Complete spec for Notion's enhanced Markdown format.", - description: "Describes all custom Markdown extensions.", - mimeType: "text/markdown", - }, - { - kind: "resource", - name: "workspace-members", - uri: "notion://workspace/members", - summary: "List of all workspace members and roles.", - description: "Returns JSON array of members.", - mimeType: "application/json", - }, - ], - prompts: [ - { - kind: "prompt", - name: "summarize-page", - summary: "Generate a concise summary of a Notion page.", - description: "Creates a structured summary with key points and action items.", - arguments: [ - { name: "page_url", required: true, description: "URL of the Notion page to summarize" }, - { name: "style", required: false, description: "'brief', 'detailed', or 'bullets'" }, - ], - }, - ], - }, - { - name: "Slack", - tools: [ - { - kind: "tool", - name: "slack-post", - summary: "Post a message to a Slack channel.", - description: "Sends a message using the bot token.", - examples: [], - parameters: [ - { name: "channel", type: "string", required: true, description: "Channel name or ID" }, - { name: "text", type: "string", required: true, description: "Message content" }, - ], - annotations: { - readOnlyHint: false, - destructiveHint: false, - idempotentHint: false, - openWorldHint: true, - }, - }, - ], - resources: [ - { - kind: "resource", - name: "channel-list", - uri: "slack://channels", - summary: "List of all accessible Slack channels.", - description: "Returns channel names, IDs, topics.", - mimeType: "application/json", - }, - ], - prompts: [ - { - kind: "prompt", - name: "draft-announcement", - summary: "Draft a team announcement message.", - description: "Creates a formatted announcement.", - arguments: [ - { name: "topic", required: true, description: "What the announcement is about" }, - { name: "tone", required: false, description: "'formal', 'casual', or 'celebratory'" }, - ], - }, - ], - }, -]; - -/* ═══════════════════════════════════════════ - Primitives - ═══════════════════════════════════════════ */ - -function WireCollapsible({ label, defaultOpen = false, children }) { - const [open, setOpen] = useState(defaultOpen); - return ( -
-
setOpen(!open)} - style={{ cursor: "pointer", padding: "4px 0", fontSize: 13, userSelect: "none" }} - > - {open ? "▾" : "▸"} {label} -
- {open &&
{children}
} -
- ); -} - -function WireTag({ children }) { - return ( - - {children} - - ); -} - -/* ═══════════════════════════════════════════ - Sidebar - ═══════════════════════════════════════════ */ - -function Sidebar({ servers, active, onSelect, collapsed, onToggle, search, onSearch }) { - return ( -
-
- - {collapsed ? "☰" : "✕"} - - {!collapsed && MCP Explorer} -
- - {!collapsed && ( - <> -
- onSearch(e.target.value)} - style={{ - flex: 1, - padding: "4px 6px", - fontSize: 12, - border: B, - boxSizing: "border-box", - }} - /> - -
-
- {servers.map((server) => { - const all = [...server.tools, ...server.resources, ...server.prompts]; - const q = search.toLowerCase(); - const filtered = q ? all.filter((i) => i.name.toLowerCase().includes(q)) : all; - if (q && filtered.length === 0) return null; - - const groups = {}; - filtered.forEach((i) => { - if (!groups[i.kind]) groups[i.kind] = []; - groups[i.kind].push(i); - }); - - return ( - - ); - })} -
- - )} -
- ); -} - -/* ═══════════════════════════════════════════ - Server Block (sidebar) - ═══════════════════════════════════════════ */ - -function ServerBlock({ server, groups, active, onSelect }) { - const [running, setRunning] = useState(true); - const [showInfo, setShowInfo] = useState(false); - - return ( -
- {/* Server header with start/stop */} -
- - {server.name} - - -
- - {/* Server info */} -
-
setShowInfo(!showInfo)} - style={{ cursor: "pointer", fontSize: 10, color: "#999", padding: "2px 0" }} - > - {showInfo ? "▾" : "▸"} server info -
- {showInfo && ( -
-
Status: {running ? "running" : "stopped"}
-
Transport: stdio
-
Version: 1.2.0
-
Capabilities: tools, resources, prompts
-
- )} -
- - {/* Items grouped by kind */} - {running && - ["tool", "resource", "prompt"].map((kind) => { - const items = groups[kind]; - if (!items) return null; - return ( -
-
- {kind}s -
- {items.map((item) => { - const isActive = active?.name === item.name && active?.kind === item.kind; - return ( -
onSelect(item)} - style={{ - padding: "4px 8px 4px 12px", - cursor: "pointer", - fontSize: 12, - background: isActive ? "#eee" : "transparent", - borderLeft: isActive ? "2px solid #333" : "2px solid transparent", - display: "flex", - alignItems: "center", - gap: 6, - }} - > - {item.name} -
- ); - })} -
- ); - })} - - {!running && ( -
- Server stopped -
- )} -
- ); -} - -/* ═══════════════════════════════════════════ - Response Panel - ═══════════════════════════════════════════ */ - -function ResponsePanel({ result }) { - if (!result) return null; - const hasContent = result.content || result.contents || result.messages; - const hasStructured = result.structuredContent; - const hasMeta = result._meta; - - return ( -
-
- Response -
-
- {/* Status */} -
- - {result.ok ? "Success" : "Error"} - {result._meta?.duration_ms && ( - - {result._meta.duration_ms}ms - - )} -
- - {/* content */} - {hasContent && ( - - {result.content?.map((block, i) => ( -
0 ? 8 : 0 }}> - {block.type} -
-                  {block.text}
-                
-
- ))} - {result.contents?.map((item, i) => ( -
0 ? 8 : 0 }}> - {item.mimeType} -
{item.uri}
-
-                  {item.text}
-                
-
- ))} - {result.messages?.map((msg, i) => ( -
0 ? 8 : 0 }}> - {msg.role} -
-                  {typeof msg.content === "string"
-                    ? msg.content
-                    : JSON.stringify(msg.content, null, 2)}
-                
-
- ))} -
- )} - - {/* structuredContent */} - {hasStructured && ( - -
-              {JSON.stringify(result.structuredContent, null, 2)}
-            
-
- )} - - {/* _meta */} - {hasMeta && ( - - {Object.entries(result._meta).map(([k, v]) => ( -
- {k} - {typeof v === "object" ? JSON.stringify(v) : String(v)} -
- ))} -
- )} -
-
- ); -} - -function WireResponseSection({ label, defaultOpen, children }) { - const [open, setOpen] = useState(defaultOpen); - return ( -
-
setOpen(!open)} - style={{ - padding: "6px 10px", - cursor: "pointer", - fontSize: 12, - display: "flex", - alignItems: "center", - gap: 6, - }} - > - {open ? "▾" : "▸"} - {label} - - {open ? "collapse" : "expand"} - -
- {open &&
{children}
} -
- ); -} - -/* ═══════════════════════════════════════════ - Action Forms - ═══════════════════════════════════════════ */ - -function ToolRunForm({ item, onClose }) { - const [values, setValues] = useState(() => { - const o = {}; - item.parameters.forEach((p) => { - o[p.name] = p.type === "boolean" ? false : ""; - }); - return o; - }); - const [running, setRunning] = useState(false); - const [result, setResult] = useState(null); - const set = (n, v) => setValues((p) => ({ ...p, [n]: v })); - const ready = item.parameters - .filter((p) => p.required) - .every((p) => values[p.name] !== "" && values[p.name] !== undefined); - - return ( -
- {item.parameters.map((p) => ( -
-
- {p.name} - {p.type} - {p.required ? "required" : "optional"} -
- {p.description && ( -
{p.description}
- )} - {p.type === "boolean" ? ( - - ) : p.type === "object" ? ( -