From 46d701bfaf505b944ec9b51b40bead543d10ee83 Mon Sep 17 00:00:00 2001 From: Taha Tariq Date: Thu, 24 Sep 2026 12:46:37 +0000 Subject: [PATCH 1/7] Dark mode: switch to the neutral grey palette from the Figma frames Replaces the warm charcoal ladder (#231F20 / #2C2829 / #353132 / #3F3A3B) with neutral greys measured from the Figma dark-mode designs: - bg/base #1A1A1A: background, card, sidebar, chat top bar, composer - bg/level1 #232323: message hover, popovers/menus - bg/level2 #2C2C2C: selected sidebar row, muted/secondary/accent fills - borders/subtle #242424: dividers, search, composer, sidebar border - borders/default #4A4A4A: border-strong (link-preview card, message action toolbar); form inputs keep #4A4A4A so fields stay visible on dialogs Text tokens and the #DE5D83 brand pink are unchanged (the Figma text greys are the existing tokens at reduced opacity). Light mode untouched. Because the sidebar now shares bg/base, active sidebar rows add dark:bg-sidebar-accent (they used bg-background, which would vanish). Boot splash and iOS theme-color updated to #1A1A1A. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01MUFbG57m3Ha4mL9uYrUfPu --- index.html | 4 +- src/components/chat/MessageItem.tsx | 2 +- src/components/chat/UnfurlCard.tsx | 2 +- src/components/layout/ChannelRow.tsx | 2 +- src/components/layout/ConversationRow.tsx | 2 +- src/components/layout/Sidebar.tsx | 10 ++-- src/index.css | 60 ++++++++++++----------- 7 files changed, 42 insertions(+), 40 deletions(-) diff --git a/index.html b/index.html index 4af7f94e..2b0a0f53 100644 --- a/index.html +++ b/index.html @@ -11,7 +11,7 @@ black in dark mode, which produces a hard seam against the composer's bg-background. --> - + ex @@ -53,7 +53,7 @@ font-family: system-ui, -apple-system, sans-serif; z-index: 9999; } - html.dark #boot-splash { background: #2c2829; } + html.dark #boot-splash { background: #1a1a1a; } #boot-splash .boot-spinner { width: 20px; height: 20px; diff --git a/src/components/chat/MessageItem.tsx b/src/components/chat/MessageItem.tsx index 7a9c542c..06c458cd 100644 --- a/src/components/chat/MessageItem.tsx +++ b/src/components/chat/MessageItem.tsx @@ -1129,7 +1129,7 @@ function MessageItemImpl({ {!isEditing && !message.deleted && (
{/* Stretched link covering the whole card → navigates to the message. */} `relative flex flex-1 min-w-0 items-center gap-2 rounded-md py-1.5 pl-2 pr-12 text-sm transition-colors touch:pr-16 mobile:h-12 mobile:py-0 mobile:pl-3 mobile:pr-20 mobile:text-base ${ isActive - ? 'bg-background text-white font-semibold before:absolute before:inset-y-1 before:left-0 before:w-[3px] before:rounded-full before:bg-sidebar-foreground before:content-[""]' + ? 'bg-background dark:bg-sidebar-accent text-white font-semibold before:absolute before:inset-y-1 before:left-0 before:w-[3px] before:rounded-full before:bg-sidebar-foreground before:content-[""]' : hasUnread ? 'font-bold text-white hover:bg-white/10' : 'text-gray-300 hover:bg-white/10 hover:text-white' diff --git a/src/components/layout/ConversationRow.tsx b/src/components/layout/ConversationRow.tsx index ba19cad7..3c8cf7f8 100644 --- a/src/components/layout/ConversationRow.tsx +++ b/src/components/layout/ConversationRow.tsx @@ -119,7 +119,7 @@ export function ConversationRow({ className={({ isActive }) => `relative flex flex-1 min-w-0 items-center gap-2 rounded-md py-1.5 pl-2 pr-12 text-sm transition-colors touch:pr-16 mobile:h-12 mobile:py-0 mobile:pl-3 mobile:pr-20 mobile:text-base ${ isActive - ? 'bg-background text-white font-semibold before:absolute before:inset-y-1 before:left-0 before:w-[3px] before:rounded-full before:bg-sidebar-foreground before:content-[""]' + ? 'bg-background dark:bg-sidebar-accent text-white font-semibold before:absolute before:inset-y-1 before:left-0 before:w-[3px] before:rounded-full before:bg-sidebar-foreground before:content-[""]' : hasUnread ? 'font-bold text-white hover:bg-white/10' : 'text-gray-300 hover:bg-white/10 hover:text-white' diff --git a/src/components/layout/Sidebar.tsx b/src/components/layout/Sidebar.tsx index a704ee0a..844cc084 100644 --- a/src/components/layout/Sidebar.tsx +++ b/src/components/layout/Sidebar.tsx @@ -947,7 +947,7 @@ export function Sidebar({ onClose }: SidebarProps) { className={({ isActive }) => `relative flex items-center gap-2 rounded-md px-2 py-1.5 text-sm transition-colors mobile:h-12 mobile:px-3 mobile:py-0 mobile:text-base ${ isActive - ? 'bg-background text-white font-semibold before:absolute before:inset-y-1 before:left-0 before:w-[3px] before:rounded-full before:bg-sidebar-foreground before:content-[""]' + ? 'bg-background dark:bg-sidebar-accent text-white font-semibold before:absolute before:inset-y-1 before:left-0 before:w-[3px] before:rounded-full before:bg-sidebar-foreground before:content-[""]' : 'text-gray-300 hover:bg-white/10 hover:text-white' }` } @@ -974,7 +974,7 @@ export function Sidebar({ onClose }: SidebarProps) { className={({ isActive }) => `relative flex items-center gap-2 rounded-md px-2 py-1.5 text-sm transition-colors mobile:h-12 mobile:px-3 mobile:py-0 mobile:text-base ${ isActive - ? 'bg-background text-white font-semibold before:absolute before:inset-y-1 before:left-0 before:w-[3px] before:rounded-full before:bg-sidebar-foreground before:content-[""]' + ? 'bg-background dark:bg-sidebar-accent text-white font-semibold before:absolute before:inset-y-1 before:left-0 before:w-[3px] before:rounded-full before:bg-sidebar-foreground before:content-[""]' : 'text-gray-300 hover:bg-white/10 hover:text-white' }` } @@ -998,7 +998,7 @@ export function Sidebar({ onClose }: SidebarProps) { className={() => `relative flex items-center gap-2 rounded-md px-2 py-1.5 text-sm transition-colors mobile:h-12 mobile:px-3 mobile:py-0 mobile:text-base ${ directoryActive - ? 'bg-background text-white font-semibold before:absolute before:inset-y-1 before:left-0 before:w-[3px] before:rounded-full before:bg-sidebar-foreground before:content-[""]' + ? 'bg-background dark:bg-sidebar-accent text-white font-semibold before:absolute before:inset-y-1 before:left-0 before:w-[3px] before:rounded-full before:bg-sidebar-foreground before:content-[""]' : 'text-gray-300 hover:bg-white/10 hover:text-white' }` } @@ -1013,7 +1013,7 @@ export function Sidebar({ onClose }: SidebarProps) { className={({ isActive }) => `relative flex items-center gap-2 rounded-md px-2 py-1.5 text-sm transition-colors mobile:h-12 mobile:px-3 mobile:py-0 mobile:text-base ${ isActive - ? 'bg-background text-white font-semibold before:absolute before:inset-y-1 before:left-0 before:w-[3px] before:rounded-full before:bg-sidebar-foreground before:content-[""]' + ? 'bg-background dark:bg-sidebar-accent text-white font-semibold before:absolute before:inset-y-1 before:left-0 before:w-[3px] before:rounded-full before:bg-sidebar-foreground before:content-[""]' : 'text-gray-300 hover:bg-white/10 hover:text-white' }` } @@ -1035,7 +1035,7 @@ export function Sidebar({ onClose }: SidebarProps) { aria-current={aiHubActive ? 'page' : undefined} className={`relative flex items-center gap-2 rounded-md px-2 py-1.5 text-sm transition-colors mobile:h-12 mobile:px-3 mobile:py-0 mobile:text-base ${ aiHubActive - ? 'bg-background text-white font-semibold before:absolute before:inset-y-1 before:left-0 before:w-[3px] before:rounded-full before:bg-sidebar-foreground before:content-[""]' + ? 'bg-background dark:bg-sidebar-accent text-white font-semibold before:absolute before:inset-y-1 before:left-0 before:w-[3px] before:rounded-full before:bg-sidebar-foreground before:content-[""]' : 'text-gray-300 hover:bg-white/10 hover:text-white' }`} > diff --git a/src/index.css b/src/index.css index 2c656201..0b0380ed 100644 --- a/src/index.css +++ b/src/index.css @@ -297,12 +297,16 @@ @layer base { html.dark { - /* Dark theme — design system tokens - * bg/base #231F20 · bg/level1 (sidebar) #2C2829 - * bg/level2 (chat top bar) #353132 · bg/level3 #3F3A3B + /* Dark theme — design system tokens (neutral greys, per the Figma + * dark-mode frames; replaces the earlier warm charcoal #231F20 ladder) + * bg/base #1A1A1A · bg/level1 (hover, floating) #232323 + * bg/level2 (selected, fills) #2C2C2C * text/primary #FFFFFF · text/secondary #D3D2D2 · text/muted #A7A5A6 · text/disabled #7B7979 - * borders/default #A7A5A6 · borders/subtle #4A4A4A + * borders/subtle (dividers, fields, composer) #242424 + * borders/default (cards, toolbars, form inputs) #4A4A4A * primary/CTA #FFFFFF (neutral, inverted) · badges/highlights #DE5D83 + * Sidebar, chat area, top bar and composer all sit on bg/base — the + * Figma frames separate them with #242424 dividers, not fill steps. * * IMPORTANT: `primary` is the NEUTRAL action colour (near-black in * light, white in dark) — it is NOT pink. Pink (#DE5D83) lives @@ -312,38 +316,39 @@ * `primary` drives every default button, focus accent, avatar * fallback and mention pill, so making it pink floods the whole UI. */ - --color-background: #231F20; + --color-background: #1A1A1A; --color-foreground: #FFFFFF; - /* Cards = bg/base in dark. The previous level2 #353132 made every + /* Cards = bg/base in dark. A lighter card level made every * card-backed surface (thread cards + their messages, admin/drafts/ * directory/search panels) read noticeably LIGHTER than the chat, so a * message inside a thread card looked brighter than the same message in * its channel. Anchoring `card` to base makes those surfaces match the * chat; their borders still delineate them. This is the single * fundamental knob — fix it here, not per component. */ - --color-card: #231F20; + --color-card: #1A1A1A; --color-card-foreground: #FFFFFF; /* Floating surfaces (menus, dialogs, hover cards, tooltips) keep a - * subtle one-step elevation above base — but level1 #2C2829, not the - * glaring level2 #353132 they used before. */ - --color-popover: #2C2829; + * subtle one-step elevation above base (level1). */ + --color-popover: #232323; --color-popover-foreground: #FFFFFF; --color-primary: #FFFFFF; - --color-primary-foreground: #231F20; + --color-primary-foreground: #1A1A1A; --color-primary-hover: #D3D2D2; --color-link: #93C5FD; - --color-secondary: #3F3A3B; + --color-secondary: #2C2C2C; /* text/secondary per spec sheet (lower-emphasis body text) — #D3D2D2, not pure white, so secondary text reads a step below primary. */ --color-secondary-foreground: #D3D2D2; - --color-muted: #3F3A3B; + --color-muted: #2C2C2C; --color-muted-foreground: #A7A5A6; - --color-accent: #3F3A3B; + --color-accent: #2C2C2C; --color-accent-foreground: #FFFFFF; --color-destructive: #F87171; --color-destructive-foreground: #FFFFFF; - --color-border: #4A4A4A; - --color-border-strong: #A7A5A6; + --color-border: #242424; + --color-border-strong: #4A4A4A; + /* Form inputs keep borders/default so fields stay visible on the + #232323 dialog/popover surface (#242424 would vanish there). */ --color-input: #4A4A4A; --color-ring: #A7A5A6; --color-brand: #DE5D83; @@ -357,7 +362,7 @@ --color-caution: #3B2F12; --color-caution-foreground: #FCD34D; /* Dark notification banner: a warm near-black distinct from the app's - * #231F20 base (so it reads as a floating card, never white, never blended) + * #1A1A1A base (so it reads as a floating card, never white, never blended) * with warm amber text + edge to keep the "alert" identity. */ --color-notification-toast: #17120F; --color-notification-toast-foreground: #FDE68A; @@ -367,23 +372,20 @@ --color-chart-3: #D3D2D2; --color-chart-4: #7B7979; --color-chart-5: #FFFFFF; - --color-sidebar: #2C2829; + --color-sidebar: #1A1A1A; --color-sidebar-foreground: #FFFFFF; --color-sidebar-primary: #FFFFFF; - --color-sidebar-primary-foreground: #231F20; - --color-sidebar-accent: #3F3A3B; + --color-sidebar-primary-foreground: #1A1A1A; + --color-sidebar-accent: #2C2C2C; --color-sidebar-accent-foreground: #FFFFFF; - --color-sidebar-border: #4A4A4A; + --color-sidebar-border: #242424; --color-sidebar-ring: #A7A5A6; - --color-chat-top: #353132; + --color-chat-top: #1A1A1A; /* Chat message-row hover = bg/level1, mirroring the light spec (where - "chat hover" is level1 #F5F5F5). Was #353132 (level2), a step too - light vs the reference screenshots. */ - --color-chat-hover: #2C2829; - /* Composer / typing field. The reference dark screenshot shows it at - bg/base #231F20 (not the lighter level3 #3F3A3B the token sheet - labels) — a #3F3A3B field read as a washed-out light box in dark. */ - --color-typing-field: #231F20; + "chat hover" is level1 #F5F5F5). */ + --color-chat-hover: #232323; + /* Composer / typing field sits on bg/base, outlined by borders/subtle. */ + --color-typing-field: #1A1A1A; } } From 432305abb8ac6303c11bf1cc1c653581980e0a69 Mon Sep 17 00:00:00 2001 From: Taha Tariq Date: Thu, 24 Sep 2026 13:49:17 +0000 Subject: [PATCH 2/7] Dark mode: add #242424 divider between sidebar and chat area The sidebar now shares the #1A1A1A base with the chat, so the fill step that used to separate them is gone; the Figma frames use a 1px borders/subtle line instead. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01MUFbG57m3Ha4mL9uYrUfPu --- src/components/layout/AppLayout.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/layout/AppLayout.tsx b/src/components/layout/AppLayout.tsx index c3b4efd6..39cad27d 100644 --- a/src/components/layout/AppLayout.tsx +++ b/src/components/layout/AppLayout.tsx @@ -259,7 +259,7 @@ export function AppLayout({ children }: AppLayoutProps) {