diff --git a/apps/mcp/src/widget/App.tsx b/apps/mcp/src/widget/App.tsx index 736b9a65..0d9f552a 100644 --- a/apps/mcp/src/widget/App.tsx +++ b/apps/mcp/src/widget/App.tsx @@ -69,26 +69,24 @@ export function WidgetShell({ return (
- {immersive ? null : ( -
- - - - - supermemory - MCP - -
- )} +
+ + + + + supermemory + MCP + +
{children}
) diff --git a/apps/mcp/src/widget/components/PermissionBadge.tsx b/apps/mcp/src/widget/components/PermissionBadge.tsx index 3b1739ec..3ce84b9a 100644 --- a/apps/mcp/src/widget/components/PermissionBadge.tsx +++ b/apps/mcp/src/widget/components/PermissionBadge.tsx @@ -6,7 +6,7 @@ export function PermissionBadge({ permission }: Props) { const isWrite = permission === "write" return ( {isWrite ? "Read/write" : "Read only"} diff --git a/apps/mcp/src/widget/components/WorkspaceCard.tsx b/apps/mcp/src/widget/components/WorkspaceCard.tsx index 490add1a..6e6ebbb7 100644 --- a/apps/mcp/src/widget/components/WorkspaceCard.tsx +++ b/apps/mcp/src/widget/components/WorkspaceCard.tsx @@ -1,6 +1,7 @@ import type { ContainerTag, ContainerTagAccess } from "../../shared/types" -import { Card, Stack } from "../design/ui" +import { Card } from "../design/ui" import { Check } from "../lib/icons" +import { formatTagLabel } from "../lib/formatTag" import { PermissionBadge } from "./PermissionBadge" interface Props { @@ -16,46 +17,53 @@ export function WorkspaceCard({ access, onClick, }: Props) { - const name = containerTag.name || containerTag.containerTag + const name = containerTag.name || formatTagLabel(containerTag.containerTag) return ( onClick(containerTag.containerTag)} variant={active ? "active" : "interactive"} > -
- {access ? : null} -
- {active ? ( - - ) : null} - - - - {name} - - -
- {containerTag.containerTag} -
- {(containerTag.documentCount > 0 || containerTag.memoryCount > 0) && ( -
- - {containerTag.documentCount} doc - {containerTag.documentCount === 1 ? "" : "s"} - - · - - {containerTag.memoryCount}{" "} - {containerTag.memoryCount === 1 ? "memory" : "memories"} +
+
+
+ + {name} + {active ? ( + + ) : null}
- )} - + {(containerTag.documentCount > 0 || + containerTag.memoryCount > 0) && ( +
+ + {containerTag.documentCount} doc + {containerTag.documentCount === 1 ? "" : "s"} + + + · + + + {containerTag.memoryCount}{" "} + {containerTag.memoryCount === 1 ? "memory" : "memories"} + +
+ )} +
+ {access ? ( +
+ +
+ ) : null} +
) } diff --git a/apps/mcp/src/widget/design/globals.css b/apps/mcp/src/widget/design/globals.css index 30973ba4..dfc24bde 100644 --- a/apps/mcp/src/widget/design/globals.css +++ b/apps/mcp/src/widget/design/globals.css @@ -88,14 +88,7 @@ } body { - background: - radial-gradient( - ellipse at 50% 112%, - rgba(75, 160, 250, 0.34) 0%, - rgba(20, 16, 255, 0.22) 28%, - rgba(11, 17, 25, 0) 62% - ), - linear-gradient(180deg, #0b1119 0%, #070b11 100%); + background: var(--app-bg); color: var(--text-primary); font-family: var(--font-sans); letter-spacing: -0.01em; @@ -123,26 +116,13 @@ isolation: isolate; min-height: 280px; overflow: hidden; - background: - linear-gradient(rgba(75, 160, 250, 0.04) 1px, transparent 1px), - linear-gradient(90deg, rgba(75, 160, 250, 0.04) 1px, transparent 1px), - radial-gradient( - circle at 50% 108%, - rgba(75, 160, 250, 0.18), - transparent 42% - ), - linear-gradient(180deg, #0b1119 0%, #070b11 100%); - background-size: - 36px 36px, - 36px 36px, - 100% 100%, - 100% 100%; + background: var(--widget-shell-bg); color: var(--text-primary); } .mcp-widget-shell-graph { min-height: 420px; - background: #05080d; + background: var(--widget-shell-graph-bg); } .mcp-widget-shell-graph::before, @@ -177,24 +157,379 @@ .mcp-widget-glow { position: absolute; - right: -18%; - bottom: -42%; - left: -18%; + right: -16%; + bottom: -44%; + left: -16%; z-index: -1; - height: 70%; + height: 68%; pointer-events: none; background: radial-gradient( - ellipse at 50% 48%, - rgba(255, 255, 255, 0.22) 0%, - rgba(71, 168, 253, 0.3) 12%, - rgba(0, 153, 255, 0.22) 28%, - rgba(20, 16, 255, 0.18) 48%, + ellipse at 50% 42%, + var(--widget-glow-inner) 0%, + var(--widget-glow-mid) 22%, + var(--widget-glow-outer) 46%, transparent 74% ); - filter: blur(20px); - opacity: 0.78; + filter: blur(18px); + opacity: 0.82; } + +/* Studio-only visual variants. Production widgets do not set this attribute. */ +[data-widget-version="v1"] .mcp-widget-shell { + --brand-accent: var(--accent); + --brand-opacity: 0.86; + --widget-glow-inner: rgba(255, 255, 255, 0.22); + --widget-glow-mid: rgba(71, 168, 253, 0.3); + --widget-glow-outer: rgba(20, 16, 255, 0.18); + background: + linear-gradient(rgba(75, 160, 250, 0.045) 1px, transparent 1px), + linear-gradient(90deg, rgba(75, 160, 250, 0.045) 1px, transparent 1px), + radial-gradient( + circle at 50% 108%, + rgba(75, 160, 250, 0.16), + transparent 42% + ), + var(--widget-shell-bg); + background-size: + 36px 36px, + 36px 36px, + 100% 100%, + 100% 100%; +} + +[data-widget-version="v1"] .super-loader, +[data-widget-version="v1"] .spinner { + color: var(--accent); +} + +[data-widget-version="v1"] .spinner { + border-top-color: var(--accent); + box-shadow: 0 0 20px rgba(75, 160, 250, 0.42); +} +[data-widget-version="v2"] .mcp-widget-shell { + --brand-accent: var(--accent); + --brand-opacity: 1; + --widget-shell-bg: color-mix(in srgb, var(--widget-shell-bg) 86%, var(--bg-muted)); + --card-bg: color-mix(in srgb, var(--card-bg) 88%, var(--bg-muted)); + --panel-bg: color-mix(in srgb, var(--panel-bg) 88%, var(--bg-muted)); + --widget-glow-mid: color-mix(in srgb, var(--widget-glow-mid) 70%, transparent); + --widget-glow-outer: color-mix(in srgb, var(--widget-glow-outer) 70%, transparent); +} + +[data-widget-version="v2"] .mcp-widget-shell-graph::before { + background-image: + linear-gradient(rgba(105, 167, 240, 0.12) 1px, transparent 1px), + linear-gradient(90deg, rgba(105, 167, 240, 0.12) 1px, transparent 1px); + background-size: 32px 32px; + mask-image: radial-gradient(ellipse at center, black 60%, transparent 100%); +} + +[data-theme="light"] [data-widget-version="v2"] .mcp-widget-shell-graph::before, +:root:not([data-theme="dark"]) [data-widget-version="v2"] .mcp-widget-shell-graph::before { + background-image: + linear-gradient(rgba(75, 160, 250, 0.045) 1px, transparent 1px), + linear-gradient(90deg, rgba(75, 160, 250, 0.045) 1px, transparent 1px); +} + +[data-theme="light"] [data-widget-version="v2"] .mcp-widget-shell-graph::after, +:root:not([data-theme="dark"]) [data-widget-version="v2"] .mcp-widget-shell-graph::after { + content: none; +} + +[data-theme="light"] [data-widget-version="v2"] .mcp-soft-button, +:root:not([data-theme="dark"]) [data-widget-version="v2"] .mcp-soft-button { + background: var(--button-secondary-bg); + color: var(--button-secondary-text); + border: 1px solid var(--button-secondary-border); + box-shadow: var(--shadow-sm); +} + +[data-theme="light"] [data-widget-version="v2"] .mcp-soft-button:hover, +:root:not([data-theme="dark"]) [data-widget-version="v2"] .mcp-soft-button:hover { + background: var(--button-secondary-hover); +} + +/* Card/panel glow — hidden by default, activated by v3/v4. */ +.card-glow, +.panel-glow { + display: none; +} + +.mcp-panel { + position: relative; + overflow: hidden; +} + +.mcp-panel > :not(.panel-glow) { + position: relative; + z-index: 1; +} + +/* Workspace picker cards — grid layout (default). */ +.workspace-card { + min-height: 104px; +} + +.workspace-card-inner { + position: relative; + display: flex; + flex-direction: column; + height: 100%; + min-height: 56px; +} + +.workspace-card-main { + display: flex; + flex-direction: column; + gap: var(--space-1); + min-width: 0; + padding-right: 72px; +} + +.workspace-card-heading { + display: flex; + align-items: center; + gap: var(--space-2); + min-width: 0; +} + +.workspace-card-title { + flex: 1; + min-width: 0; +} + +.workspace-card-trailing { + position: absolute; + top: 0; + right: 0; + font-size: 11px; + font-weight: 500; + line-height: 1; +} + +/* v3 — Bold inner glow on cards/panels (web-app BgGrad-inspired), plain shell background. */ +[data-widget-version="v3"] .mcp-widget-shell { + --brand-accent: var(--accent); + --brand-opacity: 1; + background: var(--widget-shell-bg); +} + +[data-widget-version="v3"] .mcp-widget-glow { + display: none; +} + +[data-widget-version="v3"] .card-glow, +[data-widget-version="v3"] .panel-glow { + display: block; + position: absolute; + inset: 0; + z-index: 0; + pointer-events: none; + background: + radial-gradient( + ellipse 80% 50% at 50% 100%, + rgba(20, 16, 255, 0.12) 0%, + rgba(0, 144, 255, 0.08) 30%, + transparent 70% + ), + radial-gradient( + ellipse 60% 40% at 30% 90%, + rgba(71, 168, 253, 0.10) 0%, + transparent 60% + ), + radial-gradient( + ellipse 60% 40% at 70% 90%, + rgba(75, 160, 250, 0.10) 0%, + transparent 60% + ); +} + +/* v4 — Fully refined for white/light + proper dark mode support. */ +[data-widget-version="v4"] .mcp-widget-shell { + --brand-accent: var(--accent); + --brand-opacity: 1; + display: flex; + flex-direction: column; + background: var(--widget-shell-bg); +} + +[data-widget-version="v4"] .mcp-widget-glow { + display: none; +} + +[data-theme="light"] [data-widget-version="v4"] .mcp-widget-shell, +:root:not([data-theme="dark"]) [data-widget-version="v4"] .mcp-widget-shell { + --widget-shell-bg: #faf9f7; + --card-bg: #ffffff; + --card-border: rgba(0, 0, 0, 0.06); + --card-border-hover: rgba(0, 0, 0, 0.10); + --card-active-border: rgba(63, 126, 232, 0.32); + --card-active-bg: #fafcff; + --panel-bg: #ffffff; + --panel-border: rgba(0, 0, 0, 0.06); + --panel-shadow: 0 1px 3px rgba(0, 0, 0, 0.04), 0 6px 16px rgba(0, 0, 0, 0.03); + --bg-control: #fafafa; + --bg-control-hover: #f5f5f5; + --border-control: rgba(0, 0, 0, 0.08); + --text-secondary: #6b7280; + --text-muted: #9ca3af; +} + +[data-theme="dark"] [data-widget-version="v4"] .mcp-widget-shell { + --widget-shell-bg: #111518; + --card-bg: #181d22; + --card-border: rgba(255, 255, 255, 0.06); + --card-border-hover: rgba(255, 255, 255, 0.10); + --card-active-border: rgba(106, 166, 248, 0.36); + --card-active-bg: #161c24; + --panel-bg: #181d22; + --panel-border: rgba(255, 255, 255, 0.06); + --panel-shadow: 0 1px 3px rgba(0, 0, 0, 0.16), 0 6px 16px rgba(0, 0, 0, 0.14); + --bg-control: #14191f; + --bg-control-hover: #1b222a; + --border-control: rgba(255, 255, 255, 0.08); + --text-secondary: #a0a8b4; + --text-muted: #6b7580; +} + +[data-widget-version="v4"] .card-glow, +[data-widget-version="v4"] .panel-glow { + display: block; + position: absolute; + inset: 0; + z-index: 0; + pointer-events: none; + background: radial-gradient( + ellipse 80% 50% at 50% 100%, + rgba(20, 16, 255, 0.07) 0%, + rgba(0, 144, 255, 0.04) 30%, + transparent 70% + ); +} + +/* v4 — Compact inline wordmark: logo + supermemory, no MCP subtitle. */ +[data-widget-version="v4"] .mcp-widget-brand { + display: flex; + align-items: center; + gap: var(--space-2); + margin: var(--space-3) var(--page-header-px) 0; + padding-bottom: var(--space-3); + border-bottom: 1px solid var(--border-muted); + opacity: 1; +} + +[data-widget-version="v4"] .mcp-widget-brand-mark { + width: 18px; + height: 18px; +} + +[data-widget-version="v4"] .mcp-widget-brand-mark svg { + width: 15px; + height: 12px; +} + +[data-widget-version="v4"] .mcp-widget-brand-copy { + flex-direction: row; + align-items: center; +} + +[data-widget-version="v4"] .mcp-widget-brand-name { + font-family: var(--font-brand); + font-size: 13px; + font-weight: 600; + letter-spacing: -0.02em; + line-height: 1; +} + +[data-widget-version="v4"] .mcp-widget-brand-mode { + display: none; +} + +/* v4 — Vertically center loading in the shell below the header. */ +[data-widget-version="v4"] .mcp-widget-content:has(.mcp-widget-loading) { + flex: 1; + display: flex; + flex-direction: column; + min-height: 0; +} + +[data-widget-version="v4"] .mcp-widget-loading { + flex: 1; + min-height: 180px; + padding: 0; +} + +/* v4 — Workspace picker as compact list rows. */ +[data-widget-version="v4"] .workspace-picker-grid { + display: flex; + flex-direction: column; + gap: 0; + overflow: hidden; + border: 1px solid var(--card-border); + border-radius: var(--radius-lg); + background: var(--card-bg); +} + +[data-widget-version="v4"] .workspace-card { + min-height: 0; + padding: var(--space-2) var(--space-3); + border: 0; + border-radius: 0; + background: transparent; + box-shadow: none; +} + +[data-widget-version="v4"] .workspace-card:not(:last-child) { + border-bottom: 1px solid var(--card-border); +} + +[data-widget-version="v4"] .workspace-card:hover { + background: var(--card-bg-hover); +} + +[data-widget-version="v4"] .workspace-card .card-glow { + display: none; +} + +[data-widget-version="v4"] .workspace-card-inner { + flex-direction: row; + align-items: center; + justify-content: space-between; + gap: var(--space-3); + height: auto; + min-height: 0; +} + +[data-widget-version="v4"] .workspace-card-main { + flex: 1; + flex-direction: row; + flex-wrap: nowrap; + align-items: center; + gap: var(--space-3); + min-width: 0; + padding-right: 0; + overflow: hidden; +} + +[data-widget-version="v4"] .workspace-card-heading { + flex: 1; + min-width: 0; +} + +[data-widget-version="v4"] .workspace-card-title { + min-width: 0; +} + +[data-widget-version="v4"] .workspace-card-meta { + flex-shrink: 0; + white-space: nowrap; +} + +[data-widget-version="v4"] .workspace-card-trailing { + position: static; + flex-shrink: 0; +} .mcp-widget-shell-graph .mcp-widget-glow { display: none; } @@ -203,12 +538,14 @@ display: inline-flex; align-items: center; gap: var(--space-2); + position: relative; + z-index: 1; margin: var(--space-4) var(--page-header-px) 0; padding: 0; border: 0; background: transparent; box-shadow: none; - opacity: 0.86; + opacity: var(--brand-opacity); } .mcp-widget-brand-mark { @@ -216,7 +553,7 @@ width: 20px; height: 20px; place-items: center; - color: var(--accent); + color: var(--brand-accent); } .mcp-widget-brand-mark svg { @@ -265,7 +602,7 @@ width: 24px; height: 24px; border: 2px solid rgba(255, 255, 255, 0.12); - border-top-color: var(--accent); + border-top-color: var(--brand-accent); border-radius: 50%; animation: spin 0.8s linear infinite; box-shadow: 0 0 20px rgba(75, 160, 250, 0.42); @@ -282,7 +619,7 @@ min-width: calc(var(--super-loader-size, 42px) + 10px); align-items: center; gap: var(--space-2); - color: var(--accent); + color: var(--brand-accent); } .super-loader-mark { diff --git a/apps/mcp/src/widget/design/tokens.css b/apps/mcp/src/widget/design/tokens.css index 78848e42..8610ca00 100644 --- a/apps/mcp/src/widget/design/tokens.css +++ b/apps/mcp/src/widget/design/tokens.css @@ -33,7 +33,7 @@ --bg-primary: #faf9f4; --bg-secondary: #f3f1ec; --bg-muted: #e8e5e0; - --bg-elevated: #ffffff; + --bg-elevated: #f8f7f3; --bg-overlay: rgba(250, 249, 244, 0.7); /* Borders */ @@ -276,100 +276,231 @@ } } -/* Nova widget theme +/* Cursor MCP widget theme * - * PR-1120's widget screens run inside agent cells, so the light/dark host - * theme can vary independently from the Supermemory product theme. Force the - * MCP app surfaces onto Nova's dark product palette so all widget tools match - * apps/web: DM Sans, dark cards, soft borders, and the #4ba0fa accent. + * The web app palette is a useful reference, but these widgets live inside + * Cursor's chat surface. Keep the brand typography, then soften both themes so + * the widget feels embedded instead of like a separate high-contrast app frame. */ :root, -[data-theme="light"], -[data-theme="dark"] { - color-scheme: dark; +[data-theme="light"] { + color-scheme: light; - --accent-start: #369bfd; - --accent-mid: #4ba0fa; - --accent-end: #36fdfd; - --accent-gradient: linear-gradient( - 94deg, - var(--accent-start), - var(--accent-end) - ); - - --accent: #4ba0fa; + --accent-start: #4f8df7; + --accent-mid: #4f8df7; + --accent-end: #8ec8ff; + --accent-gradient: linear-gradient(94deg, var(--accent-start), var(--accent-end)); + --accent: #3f7ee8; --accent-foreground: #ffffff; - --accent-hover: #369bfd; - --accent-muted: rgba(75, 160, 250, 0.12); + --accent-hover: #2f6fd8; + --accent-muted: rgba(63, 126, 232, 0.1); - --bg-primary: #0b1119; - --bg-secondary: #101822; - --bg-muted: #131b28; - --bg-elevated: #080b0f; - --bg-overlay: rgba(13, 18, 26, 0.78); - --bg-panel: #101822; - --bg-control: #080b0f; - --bg-control-hover: #0d121a; + --app-bg: #f3f1ec; + --widget-shell-bg: #f6f4ef; + --widget-shell-graph-bg: #f4f2ec; + --brand-accent: #78746c; + --brand-opacity: 0.66; + --widget-glow-inner: rgba(255, 255, 255, 0.62); + --widget-glow-mid: rgba(110, 154, 220, 0.2); + --widget-glow-outer: rgba(63, 126, 232, 0.08); - --border: #263348; - --border-muted: #161f2c; - --border-control: #263348; - --border-accent: rgba(75, 160, 250, 0.5); + --bg-primary: #f6f4ef; + --bg-secondary: #efede7; + --bg-muted: #e7e3da; + --bg-elevated: #f8f7f3; + --bg-overlay: rgba(246, 244, 239, 0.74); + --bg-panel: #f1efe8; + --bg-control: #fbfaf7; + --bg-control-hover: #f4f2ec; - --text-primary: #fafafa; - --text-secondary: #d0dae7; - --text-muted: #8b8b8b; - --text-inverse: #0b1119; + --border: #ddd8ce; + --border-muted: #e9e5dc; + --border-control: #dcd6ca; + --border-accent: rgba(63, 126, 232, 0.42); - --success: #4ade80; - --success-muted: rgba(74, 222, 128, 0.14); - --error: #fb7185; - --error-muted: rgba(251, 113, 133, 0.14); - --warning: #fbbf24; - --warning-muted: rgba(251, 191, 36, 0.14); - --info: #60a5fa; - --info-muted: rgba(96, 165, 250, 0.14); - --danger: #ef4444; + --card-bg: #f8f7f3; + --card-bg-hover: #f3f1eb; + --card-border: #ddd8ce; + --card-border-hover: #cfc7b8; + --card-active-bg: #f8f7f3; + --card-active-border: rgba(63, 126, 232, 0.42); - --font-sans: - "DM Sans", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif; - --font-display: - "DM Sans", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif; - --font-brand: - "DM Sans", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif; + --panel-bg: #f1efe8; + --panel-border: #ddd8ce; + --panel-shadow: 0 10px 24px rgba(74, 68, 58, 0.08); + + --button-primary-bg: #111827; + --button-primary-hover: #1f2937; + --button-primary-active: #0b1120; + --button-primary-text: #ffffff; + --button-secondary-bg: #f8f7f3; + --button-secondary-hover: #f1eee7; + --button-secondary-text: #111827; + --button-secondary-border: #dcd6ca; + --button-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.22), 0 1px 2px rgba(15, 23, 42, 0.1); + + --text-primary: #111827; + --text-secondary: #4b5563; + --text-muted: #8a94a3; + --text-inverse: #ffffff; + + --success: #16a34a; + --success-muted: rgba(22, 163, 74, 0.1); + --error: #dc2626; + --error-muted: rgba(220, 38, 38, 0.1); + --warning: #d97706; + --warning-muted: rgba(217, 119, 6, 0.12); + --info: #2563eb; + --info-muted: rgba(37, 99, 235, 0.1); + --danger: #dc2626; + + --font-sans: "DM Sans", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif; + --font-display: "DM Sans", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif; + --font-brand: "DM Sans", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif; --radius-sm: 4px; --radius-md: 6px; --radius-lg: 8px; - --shadow-sm: 0 2px 12px rgba(0, 0, 0, 0.2); - --shadow-md: 0 12px 34px rgba(0, 0, 0, 0.28); - --shadow-lg: 0 20px 54px rgba(0, 0, 0, 0.38); + --shadow-sm: 0 1px 2px rgba(15, 23, 42, 0.06); + --shadow-md: 0 12px 28px rgba(15, 23, 42, 0.09); + --shadow-lg: 0 20px 44px rgba(15, 23, 42, 0.12); - --graph-bg: #0b1119; - --graph-doc-fill: #1b1f24; - --graph-doc-stroke: rgba(255, 255, 255, 0.12); - --graph-doc-inner: #0d121a; - --graph-mem-fill: #0d2034; - --graph-mem-fill-hover: #112840; - --graph-mem-stroke: #4ba0fa; - --graph-accent: #4ba0fa; - --graph-text-primary: #fafafa; - --graph-text-secondary: #d0dae7; - --graph-text-muted: #a0aec4; - --graph-edge-derives: #fbbf24; - --graph-edge-updates: #4ba0fa; - --graph-edge-extends: #36fdfd; - --graph-mem-border-forgotten: #ef4444; - --graph-mem-border-expiring: #f59e0b; - --graph-mem-border-recent: #10b981; - --graph-glow: #4ba0fa; - --graph-icon: #4ba0fa; - --graph-popover-bg: rgba(27, 31, 36, 0.94); - --graph-popover-border: rgba(255, 255, 255, 0.12); - --graph-popover-text-primary: #fafafa; - --graph-popover-text-secondary: #d0dae7; - --graph-popover-text-muted: #a0aec4; - --graph-control-bg: rgba(13, 18, 26, 0.78); - --graph-control-border: rgba(255, 255, 255, 0.12); + --graph-bg: #f3f1ec; + --graph-doc-fill: #f8f7f3; + --graph-doc-stroke: #ddd8ce; + --graph-doc-inner: #efede7; + --graph-mem-fill: #edf2f7; + --graph-mem-fill-hover: #e3ebf3; + --graph-mem-stroke: #6aa6f8; + --graph-accent: #3f7ee8; + --graph-text-primary: #111827; + --graph-text-secondary: #4b5563; + --graph-text-muted: #8a94a3; + --graph-edge-derives: #c08403; + --graph-edge-updates: #3f7ee8; + --graph-edge-extends: #0891b2; + --graph-mem-border-forgotten: #dc2626; + --graph-mem-border-expiring: #d97706; + --graph-mem-border-recent: #16a34a; + --graph-glow: #6aa6f8; + --graph-icon: #6b7280; + --graph-popover-bg: #f8f7f3; + --graph-popover-border: #ddd8ce; + --graph-popover-text-primary: #111827; + --graph-popover-text-secondary: #4b5563; + --graph-popover-text-muted: #8a94a3; + --graph-control-bg: #f8f7f3; + --graph-control-border: #ddd8ce; +} + +[data-theme="dark"] { + color-scheme: dark; + + --accent-start: #6aa6f8; + --accent-mid: #6aa6f8; + --accent-end: #8bd4ff; + --accent-gradient: linear-gradient(94deg, var(--accent-start), var(--accent-end)); + --accent: #6aa6f8; + --accent-foreground: #0f141a; + --accent-hover: #82b7ff; + --accent-muted: rgba(106, 166, 248, 0.12); + + --app-bg: #12161b; + --widget-shell-bg: #151a20; + --widget-shell-graph-bg: #11161c; + --brand-accent: #7f8996; + --brand-opacity: 0.56; + --widget-glow-inner: rgba(255, 255, 255, 0.12); + --widget-glow-mid: rgba(106, 166, 248, 0.16); + --widget-glow-outer: rgba(106, 166, 248, 0.08); + + --bg-primary: #151a20; + --bg-secondary: #181e25; + --bg-muted: #20262e; + --bg-elevated: #1a2027; + --bg-overlay: rgba(21, 26, 32, 0.72); + --bg-panel: #1d232b; + --bg-control: #14191f; + --bg-control-hover: #1b222a; + + --border: #2b333d; + --border-muted: #232a33; + --border-control: #303946; + --border-accent: rgba(106, 166, 248, 0.38); + + --card-bg: #1a2026; + --card-bg-hover: #202731; + --card-border: #2b333d; + --card-border-hover: #3a4654; + --card-active-bg: #1b222b; + --card-active-border: rgba(106, 166, 248, 0.44); + + --panel-bg: #1c222a; + --panel-border: #2b333d; + --panel-shadow: 0 14px 34px rgba(0, 0, 0, 0.22), inset 0 1px 0 rgba(255, 255, 255, 0.035); + + --button-primary-bg: #eef4ff; + --button-primary-hover: #ffffff; + --button-primary-active: #dceaff; + --button-primary-text: #101820; + --button-secondary-bg: #202731; + --button-secondary-hover: #27303b; + --button-secondary-text: #eef2f7; + --button-secondary-border: #34404d; + --button-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.08), 0 1px 2px rgba(0, 0, 0, 0.22); + + --text-primary: #f4f6f8; + --text-secondary: #c1c9d2; + --text-muted: #87909c; + --text-inverse: #111827; + + --success: #4ade80; + --success-muted: rgba(74, 222, 128, 0.12); + --error: #fb7185; + --error-muted: rgba(251, 113, 133, 0.12); + --warning: #fbbf24; + --warning-muted: rgba(251, 191, 36, 0.12); + --info: #8bbcff; + --info-muted: rgba(139, 188, 255, 0.12); + --danger: #fb7185; + + --font-sans: "DM Sans", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif; + --font-display: "DM Sans", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif; + --font-brand: "DM Sans", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif; + + --radius-sm: 4px; + --radius-md: 6px; + --radius-lg: 8px; + + --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.18); + --shadow-md: 0 12px 30px rgba(0, 0, 0, 0.22); + --shadow-lg: 0 20px 48px rgba(0, 0, 0, 0.28); + + --graph-bg: #151a20; + --graph-doc-fill: #202731; + --graph-doc-stroke: #35404c; + --graph-doc-inner: #171d24; + --graph-mem-fill: #172536; + --graph-mem-fill-hover: #1b2d42; + --graph-mem-stroke: #6aa6f8; + --graph-accent: #6aa6f8; + --graph-text-primary: #f4f6f8; + --graph-text-secondary: #c1c9d2; + --graph-text-muted: #87909c; + --graph-edge-derives: #fbbf24; + --graph-edge-updates: #6aa6f8; + --graph-edge-extends: #67e8f9; + --graph-mem-border-forgotten: #fb7185; + --graph-mem-border-expiring: #f59e0b; + --graph-mem-border-recent: #4ade80; + --graph-glow: #6aa6f8; + --graph-icon: #7ab2ff; + --graph-popover-bg: #1c222a; + --graph-popover-border: #34404d; + --graph-popover-text-primary: #f4f6f8; + --graph-popover-text-secondary: #c1c9d2; + --graph-popover-text-muted: #87909c; + --graph-control-bg: #1c222a; + --graph-control-border: #34404d; } diff --git a/apps/mcp/src/widget/design/ui/Card.tsx b/apps/mcp/src/widget/design/ui/Card.tsx index 6c52dd9f..07028c5e 100644 --- a/apps/mcp/src/widget/design/ui/Card.tsx +++ b/apps/mcp/src/widget/design/ui/Card.tsx @@ -9,7 +9,7 @@ import { cn } from "../lib/cn" const cardStyles = cva( [ "group relative overflow-hidden text-left", - "rounded-lg border border-[#0D121A] bg-bg-elevated p-4", + "rounded-lg border border-[var(--card-border)] bg-[var(--card-bg)] p-4", "transition-all duration-200", ].join(" "), { @@ -17,9 +17,9 @@ const cardStyles = cva( variant: { default: "", interactive: - "cursor-pointer hover:border-[#3A4455] hover:bg-bg-control-hover focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent/20 focus-visible:ring-offset-2 focus-visible:ring-offset-bg-primary", + "cursor-pointer hover:border-[var(--card-border-hover)] hover:bg-[var(--card-bg-hover)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent/20 focus-visible:ring-offset-2 focus-visible:ring-offset-bg-primary", active: - "cursor-pointer border-[#263348] bg-bg-elevated hover:border-[#3A4455] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent/20 focus-visible:ring-offset-2 focus-visible:ring-offset-bg-primary", + "cursor-pointer border-[var(--card-active-border)] bg-[var(--card-active-bg)] hover:border-[var(--card-border-hover)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent/20 focus-visible:ring-offset-2 focus-visible:ring-offset-bg-primary", }, }, defaultVariants: { variant: "default" }, @@ -37,8 +37,14 @@ type ButtonElementProps = ButtonHTMLAttributes & export type CardProps = DivProps | ButtonElementProps export const Card = forwardRef( - ({ className, variant, as = "div", ...props }, ref) => { + ({ className, variant, as = "div", children, ...props }, ref) => { const cls = cn(cardStyles({ variant }), className) + const inner = ( + <> +
+ {children} + + ) if (as === "button") { return ( ) } return ( @@ -54,7 +62,9 @@ export const Card = forwardRef( className={cls} ref={ref as React.Ref} {...(props as HTMLAttributes)} - /> + > + {inner} +
) }, ) diff --git a/apps/mcp/src/widget/design/ui/Chip.tsx b/apps/mcp/src/widget/design/ui/Chip.tsx index a25a809a..89e5d811 100644 --- a/apps/mcp/src/widget/design/ui/Chip.tsx +++ b/apps/mcp/src/widget/design/ui/Chip.tsx @@ -9,7 +9,7 @@ const chipStyles = cva( selected: { true: "bg-accent-muted border-accent text-accent", false: - "bg-bg-elevated border-[#0D121A] text-text-secondary hover:border-[#3A4455] hover:bg-bg-control-hover", + "bg-bg-elevated border-[var(--card-border)] text-text-secondary hover:border-[var(--card-border-hover)] hover:bg-bg-control-hover", }, }, defaultVariants: { selected: false }, diff --git a/apps/mcp/src/widget/design/ui/FileUpload.tsx b/apps/mcp/src/widget/design/ui/FileUpload.tsx index f32da50a..fb97e2d5 100644 --- a/apps/mcp/src/widget/design/ui/FileUpload.tsx +++ b/apps/mcp/src/widget/design/ui/FileUpload.tsx @@ -61,7 +61,7 @@ export function FileUpload({ "bg-[var(--bg-control)] cursor-pointer shadow-sm transition-all", dragOver ? "border-accent bg-accent-muted" - : "border-[var(--border-control)] hover:border-[#3A4455] hover:bg-[var(--bg-control-hover)]", + : "border-[var(--border-control)] hover:border-[var(--card-border-hover)] hover:bg-[var(--bg-control-hover)]", disabled && "pointer-events-none opacity-50", className, )} diff --git a/apps/mcp/src/widget/design/ui/WorkspaceSelect.tsx b/apps/mcp/src/widget/design/ui/WorkspaceSelect.tsx index 06c9261c..168b7e7c 100644 --- a/apps/mcp/src/widget/design/ui/WorkspaceSelect.tsx +++ b/apps/mcp/src/widget/design/ui/WorkspaceSelect.tsx @@ -1,5 +1,5 @@ import { type ReactNode, useEffect, useMemo, useState } from "react" -import { Check, ChevronDown, Package, Search } from "../../lib/icons" +import { Check, ChevronDown, Search } from "../../lib/icons" import { cn } from "../lib/cn" import { Button } from "./Button" import { Popover, PopoverContent, PopoverTrigger } from "./Popover" @@ -63,13 +63,12 @@ export function WorkspaceSelect({
+
+ + Version + + setVersion("v1")} selected={version === "v1"}> + v1 + + setVersion("v2")} selected={version === "v2"}> + v2 + + setVersion("v3")} selected={version === "v3"}> + v3 + + setVersion("v4")} selected={version === "v4"}> + v4 + +
Width @@ -235,7 +254,7 @@ export function Studio() {
Selected Unselected - sm_project_marketing + Marketing
@@ -346,7 +365,7 @@ export function Studio() { description="The same widget shell Cursor renders, with mock MCP tool data." title="Cursor widgets" > -
+
+
Active workspace set
- {containerTag} + {formatTagLabel(containerTag)}

All subsequent saves and recalls will use this workspace until you diff --git a/apps/mcp/src/widget/views/Error.tsx b/apps/mcp/src/widget/views/Error.tsx index fc6fa120..5dfb5f40 100644 --- a/apps/mcp/src/widget/views/Error.tsx +++ b/apps/mcp/src/widget/views/Error.tsx @@ -9,7 +9,7 @@ export function ErrorView({ message }: Props) { return ( diff --git a/apps/mcp/src/widget/views/Loading.tsx b/apps/mcp/src/widget/views/Loading.tsx index 499451dc..513498ab 100644 --- a/apps/mcp/src/widget/views/Loading.tsx +++ b/apps/mcp/src/widget/views/Loading.tsx @@ -1,6 +1,6 @@ export function Loading() { return ( -

+
- +
{count >= SEARCH_THRESHOLD ? (
@@ -87,7 +88,7 @@ export function Picker({ No workspaces match “{query}”.

) : ( -
+
{filtered.map((tag) => { const access = assignedTags?.find( (t) => t.containerTag === tag.containerTag, @@ -108,7 +109,7 @@ export function Picker({ {pending ? (

- Setting workspace to {pending}… + Setting workspace to {formatTagLabel(pending)}…

) : null}
diff --git a/apps/mcp/src/widget/views/Save.tsx b/apps/mcp/src/widget/views/Save.tsx index d12e70fd..10e2683b 100644 --- a/apps/mcp/src/widget/views/Save.tsx +++ b/apps/mcp/src/widget/views/Save.tsx @@ -11,6 +11,7 @@ import { } from "../design/ui" import { useApp } from "../hooks/useApp" import { useLog } from "../hooks/useLog" +import { formatTagLabel } from "../lib/formatTag" interface Props { activeTag?: string | null @@ -42,7 +43,12 @@ export function Save({ }, [selectedTag, writableTags]) const options = useMemo( - () => writableTags.map((tag) => ({ value: tag, label: tag })), + () => + writableTags.map((tag) => ({ + value: tag, + label: formatTagLabel(tag), + description: tag, + })), [writableTags], ) @@ -73,7 +79,8 @@ export function Save({ title="Add Memory" />
-
+
+