refactor(design): migrate hardcoded colors to kami tokens

Purge remaining hardcoded color values from the component layer and main
process so every surface flows through the kami token system.

src/main/desktop-shell-window.ts
  - BrowserWindow.backgroundColor no longer paints pure white before the
    renderer mounts. It now picks kami parchment (#F5F4ED) or deep-dark
    (#141413) based on nativeTheme.shouldUseDarkColors so the startup
    flash respects the user's OS theme preference.

src/shared/constants.ts
  - DEPARTMENT_COLORS collapses 12 unrelated hex brand colors (violet,
    red, green, cyan, pink, ...) into six kami tokens: var(--primary),
    var(--kami-ink), var(--kami-dark-warm), var(--kami-charcoal),
    var(--kami-olive), var(--kami-stone). Departments are distinguished
    by warm-neutral ramp + ink-blue, never by second chromatic hue.

src/renderer/components/communication/{MessageItem,SearchResults}.tsx
  - Replace the string-concat tint pattern `${color}18` with
    color-mix(in oklab, ${color}, transparent 91%). The old pattern
    produced invalid CSS (e.g. `var(--primary)18`) whenever `color`
    was a CSS custom property, silently falling back to no background.
    color-mix works for both hex and var() inputs, eliminating the
    latent bug at the source.

src/renderer/components/ui/ActionButton.tsx
  - Replace hand-rolled rgba(74,93,122,0.35) and rgba(220,53,69,0.3)
    drop shadows with kami ring shadows routed through color-mix over
    var(--primary) and var(--destructive).

src/renderer/views/CommandPaletteView.tsx
  - Replace rgba(15,23,42,0.08) cold-slate shadow with a kami whisper
    shadow driven by color-mix over var(--foreground).

src/renderer/components/skills/SkillAgentToggles.tsx
src/renderer/components/execution/ModelManagementShared.tsx
  - Toggle thumbs switch from bg-white to bg-background so they
    inherit parchment in light mode and deep-dark in dark mode,
    removing the last pure-white surfaces from the renderer.

Third-party brand hex values in src/renderer/components/social/
social-config.ts are retained: they represent external brand identity
(Twitter blue, YouTube red, ...), not kami chrome, and collapsing them
to one hue would destroy recognition.

Typecheck clean. No business-logic signatures changed.
This commit is contained in:
ZacharyZhang-NY committed 2026-04-21 13:38:06 -04:00
1 parent 5113abacc7
commit 95c4b0ae48
8 files changed
+21 -20

No files matched your search

+2 -1
View File
@@ -7,6 +7,7 @@ import {
BrowserWindow,
dialog,
nativeImage,
nativeTheme,
net,
protocol,
session,
@@ -266,7 +267,7 @@ export function createDesktopShellWindow(deps: DesktopShellWindowDependencies) {
y: savedWindowState.bounds.y,
minWidth: 1180,
minHeight: 760,
backgroundColor: "#ffffff",
backgroundColor: nativeTheme.shouldUseDarkColors ? "#141413" : "#F5F4ED",
frame: process.platform === "darwin",
titleBarStyle: process.platform === "darwin" ? "hiddenInset" : "default",
...(isWindows || isLinux ? { titleBarOverlay: false } : {}),
@@ -45,7 +45,7 @@ export const AgentAvatar = memo(function AgentAvatar({
return (
<div
className={`flex shrink-0 items-center justify-center rounded-full font-bold ${sizeClass}`}
style={{ backgroundColor: `${color}18`, color }}
style={{ backgroundColor: `color-mix(in oklab, ${color}, transparent 91%)`, color }}
>
{initials}
</div>
@@ -158,7 +158,7 @@ export function SearchResults({ results, query, loading, agents, onNavigateToRes
</span>
<span
className="inline-flex shrink-0 items-center gap-1 rounded-full px-1.5 py-0.5 text-[11px] font-medium"
style={{ backgroundColor: `${config.color}18`, color: config.color }}
style={{ backgroundColor: `color-mix(in oklab, ${config.color}, transparent 91%)`, color: config.color }}
>
<ChannelIcon size={10} weight="bold" />
{t(config.labelKey)}
@@ -77,7 +77,7 @@ export function ToggleSwitch({ checked, onChange, label }: { checked: boolean; o
aria-label={label}
>
<span
className={`inline-block h-3.5 w-3.5 rounded-full bg-white shadow-sm transition-transform ${checked ? "translate-x-[18px]" : "translate-x-[3px]"}`}
className={`inline-block h-3.5 w-3.5 rounded-full bg-background shadow-sm transition-transform ${checked ? "translate-x-[18px]" : "translate-x-[3px]"}`}
/>
</button>
);
@@ -90,7 +90,7 @@ export function SkillAgentToggles(props: SkillAgentTogglesProps) {
}`}
>
<span
className={`block h-[14px] w-[14px] rounded-full bg-white shadow-sm transition-transform ${
className={`block h-[14px] w-[14px] rounded-full bg-background shadow-sm transition-transform ${
isAssigned ? "translate-x-[14px]" : "translate-x-0"
}`}
/>
+2 -2
View File
@@ -25,9 +25,9 @@ export function ActionButton({
const isDisabled = loading || disabled;
const toneClass =
tone === "accent"
? "border-transparent bg-primary text-primary-foreground shadow-[0_1px_3px_rgba(74,93,122,0.35)] hover:bg-primary/90"
? "border-transparent bg-primary text-primary-foreground shadow-[0_0_0_1px_color-mix(in_oklab,var(--primary)_40%,transparent)] hover:bg-primary/90"
: tone === "danger"
? "border-transparent bg-destructive text-primary-foreground shadow-[0_1px_3px_rgba(220,53,69,0.3)] hover:brightness-90"
? "border-transparent bg-destructive text-primary-foreground shadow-[0_0_0_1px_color-mix(in_oklab,var(--destructive)_40%,transparent)] hover:brightness-90"
: "border-border bg-card text-foreground hover:bg-muted";
const sizing = iconOnly
+1 -1
View File
@@ -140,7 +140,7 @@ export function CommandPaletteView({
animate={{ opacity: 1, y: 0, scale: 1 }}
exit={{ opacity: 0, y: 10, scale: 0.98 }}
transition={panelTransition}
className="w-full max-w-[560px] rounded-lg border border-border bg-card px-5 py-4 shadow-[0_18px_40px_rgba(15,23,42,0.08)]"
className="w-full max-w-[560px] rounded-lg border border-border bg-card px-5 py-4 shadow-[0_4px_24px_color-mix(in_oklab,var(--foreground)_5%,transparent)]"
onClick={(event) => event.stopPropagation()}
>
<div className="mb-3 flex items-center gap-3">
+12 -12
View File
@@ -21,16 +21,16 @@ export const DEPARTMENT_OPTIONS: Array<{ value: DepartmentId | ""; label: string
];
export const DEPARTMENT_COLORS: Record<DepartmentId, string> = {
executive: "#8b5cf6",
engineering: "#3b82f6",
product: "#f59e0b",
marketing: "#ec4899",
sales: "#10b981",
hr: "#6366f1",
finance: "#14b8a6",
legal: "#a78bfa",
operations: "#f97316",
customer_support: "#06b6d4",
research: "#0ea5e9",
design: "#f43f5e",
executive: "var(--primary)",
engineering: "var(--kami-ink)",
product: "var(--kami-dark-warm)",
marketing: "var(--kami-olive)",
sales: "var(--kami-olive)",
hr: "var(--kami-charcoal)",
finance: "var(--kami-charcoal)",
legal: "var(--kami-stone)",
operations: "var(--kami-dark-warm)",
customer_support: "var(--kami-stone)",
research: "var(--kami-ink)",
design: "var(--primary)",
};