From eef98c4f7a4480cc0c40a64aa4395ea250306b22 Mon Sep 17 00:00:00 2001 From: Anna Effort Date: Fri, 14 Aug 2026 17:19:01 -0700 Subject: [PATCH 1/9] style: flatten surfaces in light theme and drop shadows from controls MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The light theme is flat by design: surfaces get no elevation, and controls carry none in either theme. Tailwind inlines shadow values at build time — only the color is a variable, and --tw-shadow-color is registered inherits: false — so there is no single place to switch them off per theme. Add elevation-xs, elevation-sm and elevation-panel utilities that read a variable instead: flat in light, the values the raw Tailwind utilities used in dark, so nothing shifts there. Three rules now hold: controls no shadow in either theme. Buttons, inputs, switches, and select triggers are flat; segmented controls that used shadow-sm as their only selected-state signal get ring-1 ring-border, which reads in both themes. surfaces elevation-*. Cards, form panels, toolbars, icon chips. floating untouched. Popovers, dropdowns, dialogs, sheets and the slide-over detail panels overlay the page and need the separation in both themes. The utilities compose through --tw-shadow rather than setting box-shadow directly, because ring-* builds its outline from the same box-shadow list; setting the property outright made elevation-* win on cascade order and erased the ring on every card in light mode. Also replaces the two sidebar menu outlines drawn as shadow-[0_0_0_1px_hsl(var(--sidebar-border))] with ring utilities. Those resolved to hsl(oklch(...)) after the oklch token migration, which is invalid, so the outline they intended has not been rendering. Signed-off-by: Anna Effort --- .../dashboard/ComponentsEcosystemCard.tsx | 2 +- src/components/dashboard/MiniCard.tsx | 2 +- src/components/dashboard/SystemStatsCard.tsx | 2 +- .../dashboard/VirtualServersCard.tsx | 2 +- src/components/gateways/CreateServerForm.tsx | 4 +- .../gateways/ExposeComponentsForm.tsx | 6 +-- .../gateways/VirtualServerDetailsPanel.tsx | 2 +- src/components/layout/HeaderProfileMenu.tsx | 6 +-- src/components/mcp-servers/MCPServerForm.tsx | 4 +- src/components/plugins/PluginToolbar.tsx | 4 +- src/components/prompts/PromptDetailsPanel.tsx | 2 +- src/components/prompts/PromptForm.tsx | 2 +- src/components/resources/ResourceForm.tsx | 4 +- .../server-catalog/CatalogToolbar.tsx | 4 +- .../servers/MCPServerDetailsPanel.tsx | 2 +- .../servers/TestConnectionPanel.tsx | 2 +- src/components/teams/TeamForm.tsx | 4 +- src/components/tokens/TokenForm.tsx | 2 +- src/components/tokens/TokenIcon.tsx | 2 +- src/components/tools/ToolForm.tsx | 4 +- src/components/ui/LanguageSwitcher.tsx | 2 +- src/components/ui/button.tsx | 2 +- src/components/ui/card.tsx | 2 +- src/components/ui/input.test.tsx | 4 +- src/components/ui/input.tsx | 2 +- src/components/ui/select.tsx | 2 +- src/components/ui/sidebar.tsx | 6 +-- src/components/ui/switch.tsx | 4 +- src/components/users/UserForm.tsx | 4 +- src/index.css | 46 +++++++++++++++++++ src/pages/ForgotPassword.tsx | 2 +- src/pages/Login.tsx | 2 +- src/pages/Prompts.tsx | 2 +- src/pages/ResetPassword.tsx | 2 +- src/pages/Resources.tsx | 6 +-- src/pages/Tokens.tsx | 2 +- src/pages/Tools.tsx | 2 +- src/pages/Users.tsx | 2 +- 38 files changed, 102 insertions(+), 54 deletions(-) diff --git a/src/components/dashboard/ComponentsEcosystemCard.tsx b/src/components/dashboard/ComponentsEcosystemCard.tsx index b6de3a2..381d7d2 100644 --- a/src/components/dashboard/ComponentsEcosystemCard.tsx +++ b/src/components/dashboard/ComponentsEcosystemCard.tsx @@ -47,7 +47,7 @@ export function ComponentsEcosystemCard({ : UNAVAILABLE; return ( -
+

{intl.formatMessage({ id: "dashboard.home.system.components" })}

diff --git a/src/components/dashboard/MiniCard.tsx b/src/components/dashboard/MiniCard.tsx index 0f5ea4b..8835f84 100644 --- a/src/components/dashboard/MiniCard.tsx +++ b/src/components/dashboard/MiniCard.tsx @@ -30,7 +30,7 @@ export function MiniCard({ id, status, className }: MiniCardProps) { type="button" onClick={() => navigate(viewHref(meta.view))} className={cn( - "flex w-full flex-col gap-2 rounded-lg bg-card px-4 py-3 text-left text-sm ring-1 ring-foreground/10 shadow-xs", + "flex w-full flex-col gap-2 rounded-lg bg-card px-4 py-3 text-left text-sm ring-1 ring-foreground/10 elevation-xs", "transition-colors hover:bg-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring", className, )} diff --git a/src/components/dashboard/SystemStatsCard.tsx b/src/components/dashboard/SystemStatsCard.tsx index cd97101..b3b4630 100644 --- a/src/components/dashboard/SystemStatsCard.tsx +++ b/src/components/dashboard/SystemStatsCard.tsx @@ -20,7 +20,7 @@ export function SystemStatsCard({ stats, loading }: SystemStatsCardProps) { const intl = useIntl(); return ( -
+
+

{intl.formatMessage({ id: "dashboard.home.system.virtualServers" })}

diff --git a/src/components/gateways/CreateServerForm.tsx b/src/components/gateways/CreateServerForm.tsx index fbca0f6..a0fc0bd 100644 --- a/src/components/gateways/CreateServerForm.tsx +++ b/src/components/gateways/CreateServerForm.tsx @@ -88,7 +88,7 @@ export function CreateServerForm({ return (
@@ -146,7 +146,7 @@ export function CreateServerForm({ /> diff --git a/src/components/gateways/ExposeComponentsForm.tsx b/src/components/gateways/ExposeComponentsForm.tsx index b6a1937..8992102 100644 --- a/src/components/gateways/ExposeComponentsForm.tsx +++ b/src/components/gateways/ExposeComponentsForm.tsx @@ -277,7 +277,7 @@ export function ExposeComponentsForm({ if (isLoading) { return ( -
+
@@ -296,7 +296,7 @@ export function ExposeComponentsForm({ const somePromptsSelected = selectedPrompts.size > 0 && selectedPrompts.size < prompts.length; return ( -
+
{oauthNotification && (
-
+

diff --git a/src/components/gateways/VirtualServerDetailsPanel.tsx b/src/components/gateways/VirtualServerDetailsPanel.tsx index e97a34f..d19e6e6 100644 --- a/src/components/gateways/VirtualServerDetailsPanel.tsx +++ b/src/components/gateways/VirtualServerDetailsPanel.tsx @@ -469,7 +469,7 @@ export function VirtualServerDetailsPanel({ className={cn( "h-8 shrink-0 rounded-sm px-4 text-sm font-medium transition-colors", isSelected - ? "bg-background text-foreground shadow-sm" + ? "bg-background text-foreground ring-1 ring-border" : "text-muted-foreground hover:text-foreground", )} onClick={() => setSourceFilter(source.id)} diff --git a/src/components/layout/HeaderProfileMenu.tsx b/src/components/layout/HeaderProfileMenu.tsx index 1170caf..f940bf2 100644 --- a/src/components/layout/HeaderProfileMenu.tsx +++ b/src/components/layout/HeaderProfileMenu.tsx @@ -50,7 +50,7 @@ export function HeaderProfileMenu() { variant="ghost" size="icon-sm" onClick={() => setTheme("light")} - className={`rounded-full transition-colors ${theme === "light" ? "bg-background text-foreground shadow-sm" : "text-muted-foreground hover:text-foreground"}`} + className={`rounded-full transition-colors ${theme === "light" ? "bg-background text-foreground ring-1 ring-border" : "text-muted-foreground hover:text-foreground"}`} aria-label={intl.formatMessage({ id: "common.theme.light" })} > @@ -60,7 +60,7 @@ export function HeaderProfileMenu() { variant="ghost" size="icon-sm" onClick={() => setTheme("dark")} - className={`rounded-full transition-colors ${theme === "dark" ? "bg-background text-foreground shadow-sm" : "text-muted-foreground hover:text-foreground"}`} + className={`rounded-full transition-colors ${theme === "dark" ? "bg-background text-foreground ring-1 ring-border" : "text-muted-foreground hover:text-foreground"}`} aria-label={intl.formatMessage({ id: "common.theme.dark" })} > @@ -70,7 +70,7 @@ export function HeaderProfileMenu() { variant="ghost" size="icon-sm" onClick={() => setTheme("system")} - className={`rounded-full transition-colors ${theme === "system" ? "bg-background text-foreground shadow-sm" : "text-muted-foreground hover:text-foreground"}`} + className={`rounded-full transition-colors ${theme === "system" ? "bg-background text-foreground ring-1 ring-border" : "text-muted-foreground hover:text-foreground"}`} aria-label={intl.formatMessage({ id: "common.theme.system" })} > diff --git a/src/components/mcp-servers/MCPServerForm.tsx b/src/components/mcp-servers/MCPServerForm.tsx index 9d63516..9c8d472 100644 --- a/src/components/mcp-servers/MCPServerForm.tsx +++ b/src/components/mcp-servers/MCPServerForm.tsx @@ -146,11 +146,11 @@ export function MCPServerForm({ isOpen, onToggle, serverId, onSuccess }: MCPServ return ( <> -
+
-
+

diff --git a/src/components/plugins/PluginToolbar.tsx b/src/components/plugins/PluginToolbar.tsx index 679c436..c6680ae 100644 --- a/src/components/plugins/PluginToolbar.tsx +++ b/src/components/plugins/PluginToolbar.tsx @@ -54,7 +54,7 @@ function PluginViewToggle({ type="button" variant="ghost" aria-pressed={!enabledOnly} - className="h-8 flex-1 rounded-md font-medium aria-pressed:bg-background aria-pressed:text-foreground aria-pressed:shadow-xs" + className="h-8 flex-1 rounded-md font-medium aria-pressed:bg-background aria-pressed:text-foreground aria-pressed:ring-1 aria-pressed:ring-border" onClick={() => onChange(false)} > {intl.formatMessage({ id: "plugins.catalog.all" })} @@ -63,7 +63,7 @@ function PluginViewToggle({ type="button" variant="ghost" aria-pressed={enabledOnly} - className="h-8 flex-1 rounded-md font-medium aria-pressed:bg-background aria-pressed:text-foreground aria-pressed:shadow-xs" + className="h-8 flex-1 rounded-md font-medium aria-pressed:bg-background aria-pressed:text-foreground aria-pressed:ring-1 aria-pressed:ring-border" onClick={() => onChange(true)} > {intl.formatMessage({ id: "plugins.catalog.enabled" })} diff --git a/src/components/prompts/PromptDetailsPanel.tsx b/src/components/prompts/PromptDetailsPanel.tsx index 0f979b1..8dbcc37 100644 --- a/src/components/prompts/PromptDetailsPanel.tsx +++ b/src/components/prompts/PromptDetailsPanel.tsx @@ -21,7 +21,7 @@ import { PromptDefinitionTable } from "./PromptDefinitionTable"; // Segmented-control styling for the Try it / Definition tab triggers. const SEGMENTED_TRIGGER_CLASS = - "flex-1 rounded-sm px-3 py-1.5 font-medium data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow-sm"; + "flex-1 rounded-sm px-3 py-1.5 font-medium data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:ring-1 data-[state=active]:ring-border"; function DetailRow({ label, children }: { label: string; children: ReactNode }) { return ( diff --git a/src/components/prompts/PromptForm.tsx b/src/components/prompts/PromptForm.tsx index 0e0afda..4a56b55 100644 --- a/src/components/prompts/PromptForm.tsx +++ b/src/components/prompts/PromptForm.tsx @@ -82,7 +82,7 @@ export function PromptForm({ isOpen, onToggle, onSuccess, prompt }: PromptFormPr
-
+
diff --git a/src/components/resources/ResourceForm.tsx b/src/components/resources/ResourceForm.tsx index 394148a..bf3c7c2 100644 --- a/src/components/resources/ResourceForm.tsx +++ b/src/components/resources/ResourceForm.tsx @@ -98,11 +98,11 @@ export function ResourceForm({
-
+
-
+

onChange(false)} > {intl.formatMessage({ id: "mcpServer.catalog.all" })} @@ -82,7 +82,7 @@ function CatalogViewToggle({ type="button" variant="ghost" aria-pressed={installedOnly} - className="h-8 flex-1 rounded-md font-medium aria-pressed:bg-background aria-pressed:text-foreground aria-pressed:shadow-xs" + className="h-8 flex-1 rounded-md font-medium aria-pressed:bg-background aria-pressed:text-foreground aria-pressed:ring-1 aria-pressed:ring-border" onClick={() => onChange(true)} > {intl.formatMessage({ id: "mcpServer.catalog.connected" })} diff --git a/src/components/servers/MCPServerDetailsPanel.tsx b/src/components/servers/MCPServerDetailsPanel.tsx index 2efd6a1..b024417 100644 --- a/src/components/servers/MCPServerDetailsPanel.tsx +++ b/src/components/servers/MCPServerDetailsPanel.tsx @@ -46,7 +46,7 @@ const TABS: Array<{ value: ComponentTab; label: string }> = [ // Segmented-control styling for the Try it / Components tab triggers. const SEGMENTED_TRIGGER_CLASS = - "flex-1 rounded-sm px-3 py-1.5 font-medium data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow-sm"; + "flex-1 rounded-sm px-3 py-1.5 font-medium data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:ring-1 data-[state=active]:ring-border"; interface Tool { id: string; diff --git a/src/components/servers/TestConnectionPanel.tsx b/src/components/servers/TestConnectionPanel.tsx index 41f1514..ef9a748 100644 --- a/src/components/servers/TestConnectionPanel.tsx +++ b/src/components/servers/TestConnectionPanel.tsx @@ -277,7 +277,7 @@ export function TestConnectionPanel({ serverUrl }: TestConnectionPanelProps) { "text-muted-foreground hover:text-foreground", "focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring", "disabled:pointer-events-none disabled:opacity-50", - "data-[state=checked]:bg-background data-[state=checked]:text-foreground data-[state=checked]:shadow-sm", + "data-[state=checked]:bg-background data-[state=checked]:text-foreground data-[state=checked]:ring-1 data-[state=checked]:ring-border", )} > {m} diff --git a/src/components/teams/TeamForm.tsx b/src/components/teams/TeamForm.tsx index b1655da..e588e76 100644 --- a/src/components/teams/TeamForm.tsx +++ b/src/components/teams/TeamForm.tsx @@ -75,12 +75,12 @@ export function TeamForm({ isOpen, onToggle, onSuccess, team }: TeamFormProps) { {intl.formatMessage({ id: "common.button.back" })} -
+
{/* Header */}
-
+

-
+
diff --git a/src/components/tokens/TokenIcon.tsx b/src/components/tokens/TokenIcon.tsx index 91590aa..aae6aab 100644 --- a/src/components/tokens/TokenIcon.tsx +++ b/src/components/tokens/TokenIcon.tsx @@ -16,7 +16,7 @@ export function TokenIcon({ className }: TokenIconProps) { return (