From f1e3ea5bd93367ff71200f7d59449d3c7176c1bb Mon Sep 17 00:00:00 2001
From: Matthew Meszaros
Date: Sat, 3 Oct 2026 08:49:37 -0700
Subject: [PATCH 1/2] feat: add a Linear-style dark theme to the dashboard
(web/) with Light, Dark and System options in the user menu, Settings >
Profile > Appearance and the command palette, light by default, and an
Appearance guide in docs
---
docs/content/docs/guides/appearance.mdx | 26 +
docs/content/docs/guides/meta.json | 1 +
web/index.html | 20 +
.../api-keys/_components/CreateKeyModal.tsx | 2 +-
web/src/app/app/api-keys/page.tsx | 2 +-
web/src/app/app/crm/tasks/page.tsx | 3 +-
web/src/app/app/emails/page.tsx | 3 +-
.../_components/ProviderGlyph.tsx | 4 +-
.../settings/_components/RoleMultiSelect.tsx | 3 +-
.../app/settings/_components/SectionShell.tsx | 2 +-
web/src/app/app/settings/profile/page.tsx | 10 +-
web/src/app/auth/_components/AuthShowcase.tsx | 2 +-
web/src/app/auth/layout.tsx | 2 +-
web/src/app/cli/page.tsx | 6 +-
web/src/app/connect/page.tsx | 6 +-
web/src/app/invite/page.tsx | 3 +-
web/src/app/layout.tsx | 9 +-
web/src/app/select-org/page.tsx | 2 +-
.../app/analytics/StatsShareCard.tsx | 2 +
.../app/automations/AutomationFlow.tsx | 12 +-
.../campaigns/preferences/SenderSelector.tsx | 3 +-
.../app/campaigns/sequences/CampaignFlow.tsx | 36 +-
.../sequences/nodes/FormLinkNode.tsx | 6 +-
.../app/contacts/AddFromContactsDialog.tsx | 4 +-
.../app/contacts/CategoryPicker.tsx | 3 +-
.../app/contacts/contact-edit/OverviewTab.tsx | 3 +-
.../app/emails/add/AddBoxStepButton.tsx | 2 +-
.../app/modals/PasskeyEnrollPrompt.tsx | 2 +-
.../app/placement/PlacementCharts.tsx | 4 +-
.../app/popup/select/TagSelector.tsx | 3 +-
web/src/components/app/theme/ThemePicker.tsx | 170 +++
web/src/components/app/theme/themeOptions.ts | 16 +
.../app/unibox/ConversationItem.tsx | 6 +-
web/src/components/app/unibox/EmailBody.tsx | 36 +-
web/src/components/app/unibox/ScopeRail.tsx | 2 +-
web/src/components/auth/button.tsx | 2 +-
web/src/components/layout/AppHeader.tsx | 2 +-
web/src/components/layout/AppLayout.tsx | 11 +-
web/src/components/layout/AppNav.tsx | 2 +-
web/src/components/layout/AppShell.tsx | 6 +-
web/src/components/layout/OrgSwitcher.tsx | 4 +-
web/src/components/layout/Page.tsx | 2 +-
web/src/components/layout/SkyChrome.tsx | 12 +-
web/src/components/layout/ThemeProvider.tsx | 25 +-
web/src/components/layout/UpdateDialog.tsx | 2 +-
web/src/components/layout/UpgradeDialog.tsx | 2 +-
web/src/components/layout/UserNav.tsx | 6 +
web/src/components/shared/BrandMark.tsx | 6 +-
web/src/components/shared/CommandPalette.tsx | 20 +
web/src/components/svg.tsx | 18 +-
web/src/components/ui/dither.tsx | 44 +-
web/src/global.css | 81 +-
web/src/lib/theme.ts | 116 ++
web/src/lib/utils.ts | 7 +
web/src/stores/slices/uiSlice.ts | 41 +-
web/src/stores/useAppStore.ts | 4 +-
web/src/styles/theme-dark.css | 1235 +++++++++++++++++
57 files changed, 1892 insertions(+), 172 deletions(-)
create mode 100644 docs/content/docs/guides/appearance.mdx
create mode 100644 web/src/components/app/theme/ThemePicker.tsx
create mode 100644 web/src/components/app/theme/themeOptions.ts
create mode 100644 web/src/lib/theme.ts
create mode 100644 web/src/styles/theme-dark.css
diff --git a/docs/content/docs/guides/appearance.mdx b/docs/content/docs/guides/appearance.mdx
new file mode 100644
index 000000000..c9035876d
--- /dev/null
+++ b/docs/content/docs/guides/appearance.mdx
@@ -0,0 +1,26 @@
+---
+title: "Appearance"
+description: "Light, dark, or matching your device: how the dashboard theme is chosen and what it changes."
+---
+
+The dashboard comes in a light and a dark theme. **Light** is the default. **System** follows your device's light or dark setting and switches with it, so a laptop that goes dark at sunset takes the dashboard along without a reload.
+
+## Changing the theme
+
+There are three places to pick one, and they all do the same thing:
+
+- **User menu.** Open the menu under your name at the bottom of the sidebar and use the three-way switch next to **Theme**.
+- **Settings.** **Settings > Profile > Appearance** shows a preview of each option.
+- **Command palette.** Press **⌘K** (**Ctrl K** on Windows and Linux) and type `dark`, `light` or `system`.
+
+The choice is saved in this browser, so a work laptop and a phone can each keep their own. Every open tab of the dashboard switches together.
+
+## What the dark theme leaves light
+
+A few things are shown the way someone else will see them, whatever theme you use:
+
+- **Designed email.** In the unibox, a plain reply is drawn in the dashboard's dark colours. A message that brings its own colours or backgrounds (a newsletter, a branded signature, most mail written in Outlook) sits on a white sheet instead, so it looks the way its sender designed it.
+- **Forms.** The form builder previews your form with its own design, as visitors will see it on the published page.
+- **Shared images.** An analytics card exported as an image always uses the light design.
+
+Mail you send is not affected by your theme. Recipients see exactly what you wrote.
diff --git a/docs/content/docs/guides/meta.json b/docs/content/docs/guides/meta.json
index 65717bf11..c9564bd62 100644
--- a/docs/content/docs/guides/meta.json
+++ b/docs/content/docs/guides/meta.json
@@ -46,6 +46,7 @@
"billing",
"analytics",
"notifications",
+ "appearance",
"security",
"workspace-export-import",
"team-roles",
diff --git a/web/index.html b/web/index.html
index 5e1715c5b..7ba5cbab3 100644
--- a/web/index.html
+++ b/web/index.html
@@ -10,17 +10,37 @@
+
Warmbly
+
+
diff --git a/web/src/app/app/api-keys/_components/CreateKeyModal.tsx b/web/src/app/app/api-keys/_components/CreateKeyModal.tsx
index 329f6b323..99333680f 100644
--- a/web/src/app/app/api-keys/_components/CreateKeyModal.tsx
+++ b/web/src/app/app/api-keys/_components/CreateKeyModal.tsx
@@ -338,7 +338,7 @@ function RevealStep({ apiKey, onClose }: { apiKey: APIKeyWithSecret; onClose: ()
Copy the secret now. We hash it on the server and can never show it again.