fix(ui): restore the purple dark sidebar from v4.5.0

- Bring back the #120e1a sidebar with its brand wash, lavender tiles, edges,
  Search, section labels, and account menu in the default dark theme.
- Keep the neutral sidebar rules for custom themes.
- Set the Coolify preset sidebar to #1a0f2d, the color the dark sidebar shows.
- Update DESIGN.md to match.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Andras Bacsai
2026-10-24 10:13:00 +02:00
co-authored by Claude Opus 5.5
parent 029827db9e
commit 73b1ad1587
3 changed files with 91 additions and 31 deletions
+24 -21
View File
@@ -36,10 +36,10 @@ change.
pure neutral gray.
- **One accent.** Coolify purple in both themes (`#6b16ed`, hover `#7317ff`,
pressed `#5a12c7`, depth `#4a0fa3`, light text and icons `#a391ff`). Yellow
is only for real warnings. The dark sidebar, including the logo cell, is
quiet neutral near-black (`#0d0d0d`), so the content keeps the focus; only
the current item's tile is purple. The dark command palette has a
light purple tint. The page canvas stays neutral.
is only for real warnings. In the default dark theme the sidebar, including
the logo cell, is purple-black (`#120e1a`) with a faint brand wash. Users
who want a neutral sidebar can pick a custom theme. The dark command palette
has a light purple tint. The page canvas stays neutral.
- **Quiet text.** Sentence case. A clear text ladder: primary, dim, faint.
No em dashes in UI copy.
@@ -127,7 +127,7 @@ follow the theme.
--ui-accent-edge: #4a0fa3;
--ui-accent-fg: #ffffff;
--ui-accent-light: #a391ff;
--ui-sidebar: #0d0d0d;
--ui-sidebar: #120e1a;
--ui-card: #121212;
--ui-success: oklch(72.27% 0.192 149.58);
--ui-warning: oklch(88.13% 0.1507 91.7);
@@ -144,8 +144,9 @@ Rules for the tokens:
- Floating surfaces (menus, popovers, tooltips, modals) must be opaque. Use
`--ui-menu-bg`, never a translucent value, or the content behind shows
through.
- Keep the page canvas, cards, menus, logs, and the sidebar pure neutral
(chroma 0). The dark command palette is the only tinted surface.
- Keep the page canvas, cards, menus, and logs pure neutral (chroma 0). The
default dark sidebar, the logo cell above it, and the dark command palette
are the tinted surfaces.
- **Dark lightness level.** The canvas is at 14.48% and the header panel at
19.13%. To
change the level, move every dark surface and border token by the same
@@ -220,11 +221,12 @@ Class names below are examples. Keep the values and structure.
well is `--ui-panel` (`#121212`). Tables use the same pair: the darker mix
for the header row and `--ui-panel` for the rows.
- In light mode the sidebar is the canvas color and has a 1px
`--ui-chrome-border` right edge. In dark mode the sidebar column, including
the logo cell, is a flat neutral `#0d0d0d` (one step above the `#0a0a0a`
canvas) with a faint `rgb(255 255 255 / 0.06)` right edge. Do not add a
brand tint or wash to the sidebar: a colored sidebar competes with the
content for attention.
`--ui-chrome-border` right edge. In the default dark theme the sidebar
column, including the logo cell, is `#120e1a` with a faint lavender right
edge (`rgb(163 145 255 / 0.10)`). The nav has a brand-purple wash that
starts at 9% and fades out; the logo cell has a flat 9% wash, so the two
read as one surface. A custom theme gets the neutral sidebar rules and its
own sidebar color.
- The top bar matches the canvas. It has no bottom border at rest. After the
page scrolls under it, dark mode draws a neutral hairline
(`rgb(255 255 255 / 0.06)`), a translucent bar, blur, and a soft shadow.
@@ -679,12 +681,13 @@ lift off the content:
mode, top-level card wells and table rows use `--color-card` (`#121212`),
not the top bar.
- **Desktop sidebar and the topbar brand block** (Coolify name and version)
use the canvas color in light mode. In dark mode they use `--color-sidebar`
(`#0d0d0d`), flat and neutral, with a `rgb(255 255 255 / 0.06)` right edge.
Inactive icon tiles, Search, the account button in the footer, and section
labels (10.5px uppercase mono, `--color-nav-muted`) are neutral gray. Only
the current item's tile uses the brand purple, so the sidebar does not
compete with the content. Chevrons are hidden until the row is hovered,
use the canvas color in light mode. In the default dark theme they use
`--color-sidebar` (`#120e1a`): a vertical brand wash on the nav, a flat 9%
wash on the logo cell, and a lavender right edge. Inactive icon tiles,
Search, the account button, and section labels (10.5px uppercase mono) are
lavender. The Admin icon stays neutral. These purple rules use
`html.dark:not([data-theme="custom"])`; a custom theme keeps neutral tiles,
Search, and account button. Chevrons are hidden until the row is hovered,
focused, or current. Do not use `dark:border-white/[0.06]` on these chrome
edges; a global rule forces that utility to the solid hairline grey.
@@ -695,9 +698,9 @@ value. The dark ladder is `--color-app` 10, `--color-panel` 20,
`--coollabs-recessed` 34 (sRGB, r=g=b), which reads as distinct surfaces.
Temperature: the page canvas, cards, menus, listboxes, modals, and logs stay
**pure neutral gray** (r=g=b). Do not tint those. The dark sidebar
(`--color-sidebar`, `#0d0d0d`) is neutral too. The dark command palette is the
only exception: it carries a faint brand-purple wash. A custom theme derives all
**pure neutral gray** (r=g=b). Do not tint those. The exceptions are the
default dark sidebar (`--color-sidebar`, `#120e1a`, with a brand-purple wash)
and the dark command palette (a faint brand-purple wash). A custom theme derives all
of these surfaces from its background and sidebar colors (see the token rules in P2). The light page canvas uses `bg-neutral-50` (not
`bg-gray-50`, which is faintly cool) so it matches the neutral cards and chrome.
The only intentional color is the purple brand accent. Yellow is for warnings.
+64 -8
View File
@@ -1319,7 +1319,7 @@ html:not(.dark) .application-console-shell[data-console-theme="system"] .termina
/* Cards sit one step above the #0a0a0a canvas. The top bar uses the canvas,
not this color. The sidebar uses --color-sidebar. */
--color-card: #121212;
--color-sidebar: #0d0d0d;
--color-sidebar: #120e1a;
/* Dark surface ladder in hex (sRGB), not oklch: oklch lightness compresses
to near-black below ~15%, so oklch(15%) rendered as sRGB 11 and cards
could not lift off the content canvas (sRGB 10). These give clear,
@@ -6250,9 +6250,9 @@ html.dark .canvas-zoom-max {
}
}
/* Brand shell (dark): black canvas and top bar, quiet neutral sidebar, scroll hairline.
The sidebar stays neutral so the content keeps the focus; only the current item
uses the brand purple. Light mode keeps the neutral shell. Floating navigation
/* Brand shell (dark): black canvas and top bar, sidebar, scroll hairline.
The default dark theme tints the sidebar purple (below); a custom theme gets
these neutral rules. Light mode keeps the neutral shell. Floating navigation
keeps its own frame. */
html.dark .app-sidebar nav.sidebar-nav,
html.dark .mobile-sidebar-sheet [role="dialog"] {
@@ -6279,20 +6279,20 @@ html.dark :is(.app-sidebar, .mobile-sidebar-sheet) .menu-search {
box-shadow: inset 0 0 0 1px rgb(255 255 255 / 0.06) !important;
}
/* The account button is a .button, which is purple in dark mode; keep it neutral in the sidebar. */
html.dark :is(.app-sidebar, .mobile-sidebar-sheet) .sidebar-footer .button:not(.button-highlighted):not(.button-error):not([isHighlighted]):not(:disabled) {
/* The account button is a .button, which is purple in dark mode; keep it neutral in a custom theme sidebar. */
html.dark[data-theme="custom"] :is(.app-sidebar, .mobile-sidebar-sheet) .sidebar-footer .button:not(.button-highlighted):not(.button-error):not([isHighlighted]):not(:disabled) {
--button-depth-color: rgb(255 255 255 / 0.05);
background-color: rgb(255 255 255 / 0.04);
border-color: rgb(255 255 255 / 0.08);
color: var(--color-nav-text);
}
html.dark :is(.app-sidebar, .mobile-sidebar-sheet) .sidebar-footer .button:not(.button-highlighted):not(.button-error):not([isHighlighted]):not(:disabled):hover {
html.dark[data-theme="custom"] :is(.app-sidebar, .mobile-sidebar-sheet) .sidebar-footer .button:not(.button-highlighted):not(.button-error):not([isHighlighted]):not(:disabled):hover {
background-color: rgb(255 255 255 / 0.07);
border-color: rgb(255 255 255 / 0.12);
}
html.dark :is(.app-sidebar, .mobile-sidebar-sheet) .sidebar-footer .button:not(.button-highlighted):not(.button-error):not([isHighlighted]):not(:disabled) svg {
html.dark[data-theme="custom"] :is(.app-sidebar, .mobile-sidebar-sheet) .sidebar-footer .button:not(.button-highlighted):not(.button-error):not([isHighlighted]):not(:disabled) svg {
color: var(--color-nav-muted);
}
@@ -6327,6 +6327,62 @@ html.dark .app-sidebar .menu-item:not(:hover):not(:focus-visible):not(.menu-item
opacity: 0;
}
/* Default dark theme sidebar: purple-black with a faint brand wash and lavender
tiles, text, and edges. A custom theme keeps the neutral rules above. */
html.dark:not([data-theme="custom"]) .app-sidebar nav.sidebar-nav,
html.dark:not([data-theme="custom"]) .mobile-sidebar-sheet [role="dialog"] {
background-image: linear-gradient(180deg, rgb(107 22 237 / 0.09), transparent 520px);
border-right-color: rgb(163 145 255 / 0.10);
--color-nav-text: oklch(80% 0.02 300);
--color-nav-muted: oklch(58% 0.04 300);
}
/* Same color as the top of the sidebar gradient, so the brand and sidebar read as one surface. */
html.dark:not([data-theme="custom"]) .app-topbar-brand {
background-image: linear-gradient(rgb(107 22 237 / 0.09), rgb(107 22 237 / 0.09));
border-right-color: rgb(163 145 255 / 0.10);
}
html.dark:not([data-theme="custom"]) :is(.app-sidebar, .mobile-sidebar-sheet) .menu-search {
background-color: rgb(163 145 255 / 0.06) !important;
box-shadow: inset 0 0 0 1px rgb(163 145 255 / 0.10) !important;
}
html.dark:not([data-theme="custom"]) :is(.app-sidebar, .mobile-sidebar-sheet) .menu-search:hover {
background-color: rgb(163 145 255 / 0.10) !important;
}
html.dark:not([data-theme="custom"]) :is(.app-sidebar, .mobile-sidebar-sheet) .menu-search kbd {
border-color: rgb(163 145 255 / 0.18) !important;
}
/* Group dividers use the lavender sidebar edge: the neutral hairline looks olive on the purple-black sidebar. */
html.dark:not([data-theme="custom"]) :is(.app-sidebar, .mobile-sidebar-sheet) .sidebar-nav :is([class~="dark:border-white/[0.06]"], [class~="dark:border-white/[0.07]"], [class~="dark:border-white/[0.08]"]) {
border-color: rgb(163 145 255 / 0.10) !important;
}
/* Admin keeps the neutral tile unless it is the current page. */
html.dark:not([data-theme="custom"]):where(:not([data-nav-items="flat"])) :is(.app-sidebar, .mobile-sidebar-sheet) :is(.menu-item, .menu-subitem):not(.sidebar-toggle):not(.menu-search):not(.nav-admin):not(.menu-item-active):not(.menu-subitem-active) .menu-item-icon,
html.dark:not([data-theme="custom"]):where(:not([data-nav-items="flat"])) .app-sidebar nav.sidebar-collapsed .menu-search.menu-item .menu-item-icon {
border-color: rgb(163 145 255 / 0.13);
background: rgb(107 22 237 / 0.07);
color: #b9adff;
}
html.dark:not([data-theme="custom"]) :is(.app-sidebar, .mobile-sidebar-sheet) nav:not(.sidebar-collapsed) .nav-section {
color: rgb(163 145 255 / 0.55);
}
/* Sidebar account menu: the purple tint of the sidebar it opens from. */
html.dark:not([data-theme="custom"]) .listbox-panel.top-user-menu-panel-sidebar {
background: color-mix(in oklab, #6b16ed 10%, var(--coollabs-elevated));
border-color: rgb(163 145 255 / 0.22);
}
html.dark:not([data-theme="custom"]) .top-user-menu-panel-sidebar .listbox-option:hover {
background: rgb(163 145 255 / 0.10);
}
/* Custom theme sidebar. These rules come after the dark sidebar rules above, so they win. */
/* !important: the light custom theme maps bg-neutral-50 to the canvas with !important. */
html[data-theme="custom"] :is(.app-sidebar nav.sidebar-nav, .app-topbar-brand, .mobile-sidebar-sheet [role="dialog"]) {
+3 -2
View File
@@ -76,8 +76,9 @@
: { sidebar: mixHex('#0c0c0e', accent, 0.1), selected: mixHex('#1c1c1f', accent, 0.3), accent, background: mixHex('#0f0f11', accent, 0.12) };
};
window.customThemePresets = [
// The built-in Dark theme, not a custom theme. Its colors start the fields when the user edits it.
{ name: 'Coolify', theme: null, swatch: { sidebar: '#0d0d0d', selected: '#1c1c1c', accent: '#6b16ed', background: '#0a0a0a' } },
// The built-in Dark theme, not a custom theme. Its colors start the fields when the user edits it. The sidebar is
// the color that the Dark sidebar shows: #120e1a with its 9% purple wash.
{ name: 'Coolify', theme: null, swatch: { sidebar: '#1a0f2d', selected: '#1c1c1c', accent: '#6b16ed', background: '#0a0a0a' } },
{ name: 'Midnight', theme: { sidebar: '#0f172a', selected: '#2e4a7d', accent: '#f2458f', background: '#1a2338' } },
{ name: 'Forest', theme: { sidebar: '#12342b', selected: '#2c6e57', accent: '#f4b860', background: '#1b2a25' } },
{ name: 'Ember', theme: { sidebar: '#3b1410', selected: '#8f2d1f', accent: '#ffb86b', background: '#241816' } },