diff --git a/apps/mcp/src/widget/design/globals.css b/apps/mcp/src/widget/design/globals.css index e63673d5..01d31399 100644 --- a/apps/mcp/src/widget/design/globals.css +++ b/apps/mcp/src/widget/design/globals.css @@ -193,6 +193,7 @@ border: 1px solid var(--card-border); border-radius: var(--radius-lg); background: var(--card-bg); + box-shadow: var(--card-shadow); /* Hide scrollbar chrome — the framed list keeps a stable height. */ scrollbar-width: none; } diff --git a/apps/mcp/src/widget/design/tokens.css b/apps/mcp/src/widget/design/tokens.css index 221e3130..0b1a1df4 100644 --- a/apps/mcp/src/widget/design/tokens.css +++ b/apps/mcp/src/widget/design/tokens.css @@ -3,7 +3,8 @@ * The widget renders inside a host chat surface (Cursor, Claude, ChatGPT). It * should read as a native extension of the Supermemory console, whose language * is: flat cool-neutral surfaces, a signature recessed inset-shadow on inputs, - * one restrained blue accent, and DM Sans. No gradients, no glows, no grids. + * one restrained blue accent, and DM Sans. Decorative surfaces stay flat; the + * light primary action alone uses a subtle tonal CSS texture. * * The host applies `data-theme="light" | "dark"` on the document via ext-apps' * `applyDocumentTheme`; Tailwind's `dark:` variant is wired in globals.css via @@ -24,46 +25,76 @@ --accent-muted: rgba(46, 111, 230, 0.1); --accent-ring: rgba(46, 111, 230, 0.35); - /* Surfaces — cool light neutrals. The shell is the widget's own canvas; - * cards/panels sit a step brighter (white) so borders + shadow read. */ - --app-bg: #eef1f6; - --widget-shell-bg: #f5f7fa; - --widget-shell-graph-bg: #f5f7fa; + --button-primary-bg: var(--accent); + --button-primary-hover: var(--accent-hover); + --button-primary-active: #1f55bb; + --button-primary-text: #ffffff; + --button-primary-shadow: + inset 0 1px 0 rgba(255, 255, 255, 0.18), 0 1px 2px rgba(31, 85, 187, 0.2); + --button-primary-texture: + radial-gradient( + 90% 180% at 20% -40%, + rgba(255, 255, 255, 0.28) 0%, + rgba(255, 255, 255, 0) 62% + ), + radial-gradient( + 70% 150% at 62% 0%, + rgba(133, 183, 255, 0.18) 0%, + rgba(133, 183, 255, 0) 68% + ), + radial-gradient( + 85% 180% at 100% 120%, + rgba(12, 63, 165, 0.34) 0%, + rgba(12, 63, 165, 0) 64% + ); - --bg-primary: #f5f7fa; - --bg-secondary: #eef1f6; - --bg-muted: #e7ebf1; + /* Surfaces — quiet neutral layers. Depth comes from the near-white canvas, + * a soft shell, and white cards rather than a large drop shadow. */ + --app-bg: #fbfbfa; + --widget-shell-bg: #f6f6f4; + --widget-shell-graph-bg: #f6f6f4; + + --bg-primary: #f6f6f4; + --bg-secondary: #fbfbfa; + --bg-muted: #f0f0ed; --bg-elevated: #ffffff; - --bg-overlay: rgba(245, 247, 250, 0.8); + --bg-overlay: rgba(251, 251, 250, 0.82); --bg-panel: #ffffff; --bg-control: #ffffff; - --bg-control-hover: #f4f6fa; + --bg-control-hover: #f5f5f2; - --border: #e2e7ef; - --border-muted: #edf0f5; - --border-control: #dce2ea; + --border: #e3e3df; + --border-muted: #ececea; + --border-control: #d9d9d4; --border-accent: rgba(46, 111, 230, 0.45); --card-bg: #ffffff; - --card-bg-hover: #f6f8fb; - --card-border: #e2e7ef; - --card-border-hover: #d2dae5; - --card-active-bg: rgba(46, 111, 230, 0.06); + --card-bg-hover: #fafaf8; + --card-border: #e1e1dd; + --card-border-hover: #d2d2cd; + --card-active-bg: #f3f3f0; --card-active-border: rgba(46, 111, 230, 0.4); + --card-shadow: + inset 0 1px 0 rgba(255, 255, 255, 0.9), 0 1px 2px rgba(23, 23, 23, 0.04), + 0 5px 14px rgba(23, 23, 23, 0.025); + --card-shadow-hover: + inset 0 1px 0 rgba(255, 255, 255, 0.95), 0 1px 2px rgba(23, 23, 23, 0.05), + 0 7px 18px rgba(23, 23, 23, 0.04); --panel-bg: #ffffff; - --panel-border: #e2e7ef; + --panel-border: #dfdfdb; --panel-shadow: - 0 1px 2px rgba(15, 23, 42, 0.04), 0 10px 26px rgba(15, 23, 42, 0.05); + inset 0 1px 0 rgba(255, 255, 255, 0.9), 0 1px 2px rgba(23, 23, 23, 0.04), + 0 6px 16px rgba(23, 23, 23, 0.03); /* Signature recessed shadow — subtle in light so fields read as inset * without going muddy. */ - --shadow-inset: inset 0 1px 2px rgba(15, 23, 42, 0.06); - --shadow-inset-strong: inset 1px 1px 3px rgba(15, 23, 42, 0.08); + --shadow-inset: inset 0 1px 2px rgba(23, 23, 23, 0.055); + --shadow-inset-strong: inset 1px 1px 3px rgba(23, 23, 23, 0.075); - --text-primary: #0f1729; - --text-secondary: #55617a; - --text-muted: #8b95a7; + --text-primary: #171717; + --text-secondary: #5f5f5f; + --text-muted: #737373; --text-inverse: #ffffff; --success: #15935a; @@ -142,9 +173,11 @@ --page-title-mt: var(--space-4); /* Panel shadow family (also exposed to Tailwind as shadow-sm/md/lg). */ - --shadow-sm: 0 1px 2px rgba(15, 23, 42, 0.06); - --shadow-md: 0 6px 18px rgba(15, 23, 42, 0.08); - --shadow-lg: 0 18px 40px rgba(15, 23, 42, 0.12); + --shadow-sm: 0 1px 2px rgba(23, 23, 23, 0.05); + --shadow-md: + 0 1px 2px rgba(23, 23, 23, 0.04), 0 6px 16px rgba(23, 23, 23, 0.045); + --shadow-lg: + 0 2px 6px rgba(23, 23, 23, 0.06), 0 14px 32px rgba(23, 23, 23, 0.08); /* Host-provided iframe dimensions; fallback for standalone dev. */ --host-height: 100vh; @@ -153,31 +186,31 @@ /* Memory graph canvas — read by @supermemory/memory-graph's theme. * Neutral fills, one accent, semantic (not decorative) relation edges. */ --graph-bg: transparent; - --graph-doc-fill: #f2f5f9; - --graph-doc-stroke: #dce2ea; + --graph-doc-fill: #f3f3f0; + --graph-doc-stroke: #d9d9d4; --graph-doc-inner: #ffffff; - --graph-mem-fill: #eaf1fc; - --graph-mem-fill-hover: #dde9fb; + --graph-mem-fill: #edf3fc; + --graph-mem-fill-hover: #e2ecfb; --graph-mem-stroke: #2e6fe6; --graph-accent: #2e6fe6; - --graph-text-primary: #0f1729; - --graph-text-secondary: #55617a; - --graph-text-muted: #8b95a7; - --graph-edge-derives: #b0b7c3; + --graph-text-primary: #171717; + --graph-text-secondary: #5f5f5f; + --graph-text-muted: #737373; + --graph-edge-derives: #b8b8b3; --graph-edge-updates: #2e6fe6; --graph-edge-extends: #0e9488; --graph-mem-border-forgotten: #d64545; --graph-mem-border-expiring: #b7791f; --graph-mem-border-recent: #15935a; --graph-glow: rgba(46, 111, 230, 0.35); - --graph-icon: #8b95a7; + --graph-icon: #737373; --graph-popover-bg: #ffffff; - --graph-popover-border: #e2e7ef; - --graph-popover-text-primary: #0f1729; - --graph-popover-text-secondary: #55617a; - --graph-popover-text-muted: #8b95a7; + --graph-popover-border: #e1e1dd; + --graph-popover-text-primary: #171717; + --graph-popover-text-secondary: #5f5f5f; + --graph-popover-text-muted: #737373; --graph-control-bg: #ffffff; - --graph-control-border: #e2e7ef; + --graph-control-border: #e1e1dd; } /* ── Dark ─────────────────────────────────────────────────────────────────── */ @@ -190,6 +223,14 @@ --accent-muted: rgba(75, 160, 250, 0.14); --accent-ring: rgba(75, 160, 250, 0.4); + --button-primary-bg: #0d121a; + --button-primary-hover: #121820; + --button-primary-active: #0a0e14; + --button-primary-text: #fafafa; + --button-primary-shadow: + inset 0 2px 4px rgba(0, 0, 0, 0.3), inset 0 1px 2px rgba(0, 0, 0, 0.1); + --button-primary-texture: none; + --app-bg: #080c11; --widget-shell-bg: #0b1119; --widget-shell-graph-bg: #0b1119; @@ -214,6 +255,8 @@ --card-border-hover: #2b3a4e; --card-active-bg: rgba(75, 160, 250, 0.1); --card-active-border: rgba(75, 160, 250, 0.45); + --card-shadow: none; + --card-shadow-hover: none; --panel-bg: #101822; --panel-border: #1f2b3b; @@ -283,6 +326,14 @@ --accent-muted: rgba(75, 160, 250, 0.14); --accent-ring: rgba(75, 160, 250, 0.4); + --button-primary-bg: #0d121a; + --button-primary-hover: #121820; + --button-primary-active: #0a0e14; + --button-primary-text: #fafafa; + --button-primary-shadow: + inset 0 2px 4px rgba(0, 0, 0, 0.3), inset 0 1px 2px rgba(0, 0, 0, 0.1); + --button-primary-texture: none; + --app-bg: #080c11; --widget-shell-bg: #0b1119; --widget-shell-graph-bg: #0b1119; @@ -307,6 +358,8 @@ --card-border-hover: #2b3a4e; --card-active-bg: rgba(75, 160, 250, 0.1); --card-active-border: rgba(75, 160, 250, 0.45); + --card-shadow: none; + --card-shadow-hover: none; --panel-bg: #101822; --panel-border: #1f2b3b; diff --git a/apps/mcp/src/widget/design/ui/Button.tsx b/apps/mcp/src/widget/design/ui/Button.tsx index d1a42fc7..80883617 100644 --- a/apps/mcp/src/widget/design/ui/Button.tsx +++ b/apps/mcp/src/widget/design/ui/Button.tsx @@ -3,9 +3,9 @@ import { type ButtonHTMLAttributes, forwardRef, type ReactNode } from "react" import { Loader2 } from "../../lib/icons" import { cn } from "../lib/cn" -// Token-driven, theme-aware pill controls. Primary is a high-contrast slab that -// inverts per theme (dark-on-light / light-on-dark); secondary is a neutral, -// input-like surface so it never reads as a heavy block on light backgrounds. +// Token-driven, theme-aware pill controls. Primary stays high contrast while +// matching each theme's surface family; secondary remains a neutral, +// input-like surface. const buttonVariants = cva( [ "inline-flex items-center justify-center gap-2", @@ -19,13 +19,11 @@ const buttonVariants = cva( { variants: { variant: { - // Nova's "insideOut" primary button: a near-black pill with the - // shadow-inside-out recessed inset. Same in both themes, exactly as - // the console renders it. primary: [ - "bg-[#0D121A] text-[#FAFAFA]", - "shadow-[inset_0_2px_4px_rgba(0,0,0,0.3),inset_0_1px_2px_rgba(0,0,0,0.1)]", - "hover:bg-[#121820] active:bg-[#0A0E14]", + "bg-[var(--button-primary-bg)] text-[var(--button-primary-text)]", + "[background-image:var(--button-primary-texture)]", + "shadow-[var(--button-primary-shadow)]", + "hover:bg-[var(--button-primary-hover)] active:bg-[var(--button-primary-active)]", ].join(" "), secondary: [ "bg-[var(--bg-control)] text-[var(--text-primary)]", diff --git a/apps/mcp/src/widget/design/ui/Card.tsx b/apps/mcp/src/widget/design/ui/Card.tsx index edcb9d95..20d578d7 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 text-left", - "rounded-xl border border-[var(--card-border)] bg-[var(--card-bg)] p-4", + "rounded-xl border border-[var(--card-border)] bg-[var(--card-bg)] p-4 shadow-[var(--card-shadow)]", "transition-colors duration-150", ].join(" "), { @@ -17,7 +17,7 @@ const cardStyles = cva( variant: { default: "", interactive: - "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/30 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)] hover:shadow-[var(--card-shadow-hover)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent/30 focus-visible:ring-offset-2 focus-visible:ring-offset-bg-primary", active: "cursor-pointer border-[var(--card-active-border)] bg-[var(--card-active-bg)] hover:border-[var(--card-active-border)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent/30 focus-visible:ring-offset-2 focus-visible:ring-offset-bg-primary", },