twenty tokens is the contract; eleven palettes prove it

Officer now ships fourteen themes. Eleven of them were written by other people, ported
unchanged, and none of them knows that panels, docks, glass, grids or scrollbars exist.

── What changed ──

`base.css` derives every surface from the standard tokens: a panel is `card` at 92%, the
header is `card` at 85%, grid lines are `border` faded, scrollbars are `muted-foreground`.
Those defaults sit on `:root`; a theme sits on `[data-theme='x']` and both land on
<html>, so a theme's own declaration simply outranks them. No machinery.

State tones are defaulted too — shadcn's vocabulary has `destructive` and nothing else,
and green-means-good is a convention rather than a palette decision. That is what drops
the required contract from 29 to 20: exactly the tokens every published shadcn palette
already ships.

So there are now three tiers, and an author picks one:

  palette   20 tokens                  Tokyo Night, Gruvbox, Nord — surfaces derived
  textured  + a few surfaces           glass, blur, radius, a wallpaper of its own
  white-label + assets                 its own logo and background

Duck is tier three and is untouched — verified by probe: it still reports
`panel=#ffffff1f`, `blur=24px` and its own grid, because its declarations outrank the
new defaults.

── Verified before committing, not assumed ──

The whole HSL-triplet design existed to make `bg-card/50` work. Tested it: Tailwind v4
emits `color-mix(in oklab, var(--card) 50%, transparent)` for a HEX token, with a
`@supports` fallback. The unwrapped triplets were never necessary, and the ported
palettes are plain hex.

Six themes probed in the browser: each derives panels from its own card colour,
including the light one (Catppuccin Latte).

── Credit ──

The eleven palettes and the idea of a small standard contract come from the owner's
`vimazing` repository, which solved this more simply than we had. What Officer adds is
the surface layer underneath, so a palette gets a textured app for free.

── One open decision ──

`--logo-src` defaults to empty, so a palette theme shows no mark at all. Correct for a
third-party theme; probably wrong for Officer, where the alternative is defaulting to
the officer.dev logo and letting a white-label theme replace it. One line either way.

tsgo clean, suite unchanged, builds.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-17 00:49:13 +00:00
co-authored by Claude Opus 5
parent 1dfadef506
commit b106f67288
14 changed files with 645 additions and 0 deletions
+118
View File
@@ -192,3 +192,121 @@
background-size: cover;
}
}
/*
DERIVED SURFACES — the defaults that make a 29-value theme a complete one.
============================================================================================
A theme is required to supply the 29 standard tokens: shadcn's 20 plus the state tones shadcn lacks
(success, warning, info, busy). Everything below is then computed from them, so a palette-only theme —
Tokyo Night, Gruvbox, anything published in the shadcn vocabulary — renders a complete application
without knowing that panels, docks, glass or scrollbars exist.
── How an override works ──
These live on `:root`; a theme lives on `[data-theme='x']`, and both land on the same <html> element. A
theme's own declaration is more specific, so it simply wins. Nothing here has to know which themes exist,
and a theme only declares what it actually cares about.
That is the difference between a contract of 29 and a contract of 84. Duck has a TEXTURE — glass over a
photograph — and declares its surfaces. Tokyo Night has a palette and declares none of them.
`color-mix` rather than opacity variants because these are complete CSS values: a surface may be a
gradient or an image in a theme that wants one, and an alpha channel cannot express that.
*/
@layer base {
:root {
/*
State tones, which shadcn's vocabulary does not have.
Defaulted rather than required, because green-means-good is a convention rather than a palette
decision, and a theme published elsewhere will never have thought about them. A theme that cares
overrides; every ported palette gets something legible for free.
This is what drops the required contract from 29 to 20 — the twenty tokens every shadcn palette
already ships.
*/
--success: #16a34a;
--success-foreground: #ffffff;
--warning: #f59e0b;
--warning-foreground: #1c1917;
--info: #6366f1;
--info-foreground: #ffffff;
--busy: #f59e0b;
--busy-foreground: #1c1917;
--busy-ink: #b45309;
/* The page */
--page-bg: var(--background);
--page-bg-src: '';
--pixel-grid-color: color-mix(in srgb, var(--border) 35%, transparent);
/* Panels — the cornerstone of the layout */
--panel-bg: color-mix(in srgb, var(--card) 92%, transparent);
--panel-border: var(--border);
--panel-border-bare: var(--border);
--panel-raised-bg: var(--card);
--panel-raised-border: var(--border);
--panel-radius: var(--radius);
--panel-blur: 0px;
--panel-header-bg: color-mix(in srgb, var(--muted) 60%, transparent);
--panel-header-fg: var(--foreground);
--panel-accent: var(--primary);
--panel-grid-color: color-mix(in srgb, var(--border) 25%, transparent);
/* The header */
--header-bg: color-mix(in srgb, var(--card) 85%, transparent);
--header-border: var(--border);
--header-fg: var(--foreground);
--header-blur: 0px;
/* Other surfaces */
--glass-bg: color-mix(in srgb, var(--card) 75%, transparent);
--glass-border: var(--border);
--dock-bg: color-mix(in srgb, var(--card) 85%, transparent);
--dock-border: var(--border);
--dock-tooltip-bg: var(--popover);
--card-bg: var(--card);
--card-grid-color: color-mix(in srgb, var(--border) 25%, transparent);
/* Chrome */
--scrollbar-thumb: color-mix(in srgb, var(--muted-foreground) 60%, transparent);
--scrollbar-thumb-hover: var(--muted-foreground);
--scrollbar-thin-thumb: color-mix(in srgb, var(--muted-foreground) 40%, transparent);
--scrollbar-thin-thumb-hover: color-mix(in srgb, var(--muted-foreground) 70%, transparent);
/* The mark. Empty is correct: a theme that ships no logo should show none rather than someone else's. */
--logo-src: '';
/* Brand slots, until the `duck-*` utilities are renamed. A palette theme should never think about these. */
--brand-primary: var(--primary);
--brand-accent: var(--accent);
--brand-warm: var(--destructive);
--brand-deep: var(--primary);
--ink: var(--foreground);
--surface-warm: var(--muted);
--duck-teal: var(--brand-primary);
--duck-dark: var(--ink);
--duck-yellow: var(--brand-accent);
--duck-forest: var(--brand-deep);
--duck-beige: var(--surface-warm);
--duck-orange: var(--brand-warm);
/* Officer leftovers, kept alive until their few call sites go. */
--cta: var(--primary);
--cta-foreground: var(--primary-foreground);
--ctahover: var(--primary);
--naturegreen: var(--success);
--naturegreen-foreground: var(--success-foreground);
--brand: var(--primary);
--brand-foreground: var(--primary-foreground);
--brand-muted: color-mix(in srgb, var(--primary) 20%, transparent);
/* Data, when a theme has not said. */
--chart-primary: var(--primary);
--chart-secondary: color-mix(in srgb, var(--primary) 50%, transparent);
--status-success: var(--success);
--status-warning: var(--warning);
--status-in-progress: var(--info);
}
}
+13
View File
@@ -17,4 +17,17 @@
@import './themes/duck-dark.css';
@import './themes/plain.css';
/* Palette themes — 20 standard tokens each, every surface derived. */
@import './themes/tokyo-night.css';
@import './themes/catppuccin-mocha.css';
@import './themes/catppuccin-latte.css';
@import './themes/everforest.css';
@import './themes/gruvbox.css';
@import './themes/kanagawa.css';
@import './themes/matte-black.css';
@import './themes/nord.css';
@import './themes/osaka-jade.css';
@import './themes/ristretto.css';
@import './themes/rose-pine.css';
@import './chrome.css';
@@ -0,0 +1,45 @@
/*
CATPPUCCIN LATTE — ported from the published palette, unchanged.
A PALETTE theme: it supplies the standard tokens and nothing else. Panels, the header, the dock, glass,
grid lines and scrollbars are all derived from these by `base.css`, so this file never mentions them.
That is the contract working as intended — a theme anyone has already written, dropped in whole. Compare
`duck-*.css`, which additionally declares a texture.
*/
[data-theme='catppuccin-latte'] {
--radius: 0.625rem;
--background: #eff1f5;
--foreground: #4c4f69;
--card: #e6e9ef;
--card-foreground: #4c4f69;
--popover: #e6e9ef;
--popover-foreground: #4c4f69;
--primary: #1e66f5;
--primary-foreground: #eff1f5;
--secondary: #ccd0da;
--secondary-foreground: #4c4f69;
--muted: #dce0e8;
--muted-foreground: #6c6f85;
--accent: #04a5e5;
--accent-foreground: #eff1f5;
--destructive: #d20f39;
--destructive-foreground: #eff1f5;
--border: #ccd0da;
--input: #ccd0da;
--ring: #1e66f5;
--chart-1: #1e66f5;
--chart-2: #df8e1d;
--chart-3: #40a02b;
--chart-4: #179299;
--chart-5: #8839ef;
--sidebar: #e6e9ef;
--sidebar-foreground: #6c6f85;
--sidebar-primary: #1e66f5;
--sidebar-primary-foreground: #eff1f5;
--sidebar-accent: #dce0e8;
--sidebar-accent-foreground: #4c4f69;
--sidebar-border: #ccd0da;
--sidebar-ring: #1e66f5;
}
@@ -0,0 +1,45 @@
/*
CATPPUCCIN MOCHA — ported from the published palette, unchanged.
A PALETTE theme: it supplies the standard tokens and nothing else. Panels, the header, the dock, glass,
grid lines and scrollbars are all derived from these by `base.css`, so this file never mentions them.
That is the contract working as intended — a theme anyone has already written, dropped in whole. Compare
`duck-*.css`, which additionally declares a texture.
*/
[data-theme='catppuccin-mocha'] {
--radius: 0.625rem;
--background: #1e1e2e;
--foreground: #cdd6f4;
--card: #181825;
--card-foreground: #cdd6f4;
--popover: #181825;
--popover-foreground: #cdd6f4;
--primary: #89b4fa;
--primary-foreground: #1e1e2e;
--secondary: #45475a;
--secondary-foreground: #cdd6f4;
--muted: #313244;
--muted-foreground: #7f849c;
--accent: #89dceb;
--accent-foreground: #1e1e2e;
--destructive: #f38ba8;
--destructive-foreground: #1e1e2e;
--border: #45475a;
--input: #45475a;
--ring: #89b4fa;
--chart-1: #89b4fa;
--chart-2: #f9e2af;
--chart-3: #a6e3a1;
--chart-4: #94e2d5;
--chart-5: #cba6f7;
--sidebar: #181825;
--sidebar-foreground: #7f849c;
--sidebar-primary: #89b4fa;
--sidebar-primary-foreground: #1e1e2e;
--sidebar-accent: #313244;
--sidebar-accent-foreground: #cdd6f4;
--sidebar-border: #45475a;
--sidebar-ring: #89b4fa;
}
@@ -0,0 +1,45 @@
/*
EVERFOREST — ported from the published palette, unchanged.
A PALETTE theme: it supplies the standard tokens and nothing else. Panels, the header, the dock, glass,
grid lines and scrollbars are all derived from these by `base.css`, so this file never mentions them.
That is the contract working as intended — a theme anyone has already written, dropped in whole. Compare
`duck-*.css`, which additionally declares a texture.
*/
[data-theme='everforest'] {
--radius: 0.625rem;
--background: #2d353b;
--foreground: #d3c6aa;
--card: #272e33;
--card-foreground: #d3c6aa;
--popover: #272e33;
--popover-foreground: #d3c6aa;
--primary: #a7c080;
--primary-foreground: #2d353b;
--secondary: #3d484d;
--secondary-foreground: #d3c6aa;
--muted: #374247;
--muted-foreground: #859289;
--accent: #83c092;
--accent-foreground: #2d353b;
--destructive: #e67e80;
--destructive-foreground: #d3c6aa;
--border: #3d484d;
--input: #3d484d;
--ring: #a7c080;
--chart-1: #a7c080;
--chart-2: #dbbc7f;
--chart-3: #83c092;
--chart-4: #7fbbb3;
--chart-5: #d699b6;
--sidebar: #272e33;
--sidebar-foreground: #859289;
--sidebar-primary: #a7c080;
--sidebar-primary-foreground: #2d353b;
--sidebar-accent: #374247;
--sidebar-accent-foreground: #d3c6aa;
--sidebar-border: #3d484d;
--sidebar-ring: #a7c080;
}
@@ -0,0 +1,45 @@
/*
GRUVBOX — ported from the published palette, unchanged.
A PALETTE theme: it supplies the standard tokens and nothing else. Panels, the header, the dock, glass,
grid lines and scrollbars are all derived from these by `base.css`, so this file never mentions them.
That is the contract working as intended — a theme anyone has already written, dropped in whole. Compare
`duck-*.css`, which additionally declares a texture.
*/
[data-theme='gruvbox'] {
--radius: 0.625rem;
--background: #282828;
--foreground: #ebdbb2;
--card: #1d2021;
--card-foreground: #ebdbb2;
--popover: #1d2021;
--popover-foreground: #ebdbb2;
--primary: #83a598;
--primary-foreground: #282828;
--secondary: #504945;
--secondary-foreground: #ebdbb2;
--muted: #3c3836;
--muted-foreground: #a89984;
--accent: #8ec07c;
--accent-foreground: #282828;
--destructive: #fb4934;
--destructive-foreground: #ebdbb2;
--border: #504945;
--input: #504945;
--ring: #83a598;
--chart-1: #83a598;
--chart-2: #fabd2f;
--chart-3: #b8bb26;
--chart-4: #8ec07c;
--chart-5: #d3869b;
--sidebar: #1d2021;
--sidebar-foreground: #a89984;
--sidebar-primary: #83a598;
--sidebar-primary-foreground: #282828;
--sidebar-accent: #3c3836;
--sidebar-accent-foreground: #ebdbb2;
--sidebar-border: #504945;
--sidebar-ring: #83a598;
}
@@ -0,0 +1,45 @@
/*
KANAGAWA — ported from the published palette, unchanged.
A PALETTE theme: it supplies the standard tokens and nothing else. Panels, the header, the dock, glass,
grid lines and scrollbars are all derived from these by `base.css`, so this file never mentions them.
That is the contract working as intended — a theme anyone has already written, dropped in whole. Compare
`duck-*.css`, which additionally declares a texture.
*/
[data-theme='kanagawa'] {
--radius: 0.625rem;
--background: #1f1f28;
--foreground: #dcd7ba;
--card: #16161d;
--card-foreground: #dcd7ba;
--popover: #16161d;
--popover-foreground: #dcd7ba;
--primary: #7e9cd8;
--primary-foreground: #1f1f28;
--secondary: #2a2a37;
--secondary-foreground: #dcd7ba;
--muted: #223249;
--muted-foreground: #727169;
--accent: #7fb4ca;
--accent-foreground: #1f1f28;
--destructive: #e82424;
--destructive-foreground: #dcd7ba;
--border: #2a2a37;
--input: #2a2a37;
--ring: #7e9cd8;
--chart-1: #7e9cd8;
--chart-2: #ffa066;
--chart-3: #98bb6c;
--chart-4: #7aa89f;
--chart-5: #957fb8;
--sidebar: #16161d;
--sidebar-foreground: #727169;
--sidebar-primary: #7e9cd8;
--sidebar-primary-foreground: #1f1f28;
--sidebar-accent: #223249;
--sidebar-accent-foreground: #dcd7ba;
--sidebar-border: #2a2a37;
--sidebar-ring: #7e9cd8;
}
@@ -0,0 +1,45 @@
/*
MATTE BLACK — ported from the published palette, unchanged.
A PALETTE theme: it supplies the standard tokens and nothing else. Panels, the header, the dock, glass,
grid lines and scrollbars are all derived from these by `base.css`, so this file never mentions them.
That is the contract working as intended — a theme anyone has already written, dropped in whole. Compare
`duck-*.css`, which additionally declares a texture.
*/
[data-theme='matte-black'] {
--radius: 0.625rem;
--background: #0a0a0a;
--foreground: #e0e0e0;
--card: #121212;
--card-foreground: #e0e0e0;
--popover: #121212;
--popover-foreground: #e0e0e0;
--primary: #ffffff;
--primary-foreground: #0a0a0a;
--secondary: #2a2a2a;
--secondary-foreground: #e0e0e0;
--muted: #1a1a1a;
--muted-foreground: #9a9a9a;
--accent: #d0d0d0;
--accent-foreground: #0a0a0a;
--destructive: #ff4444;
--destructive-foreground: #e0e0e0;
--border: #2a2a2a;
--input: #2a2a2a;
--ring: #ffffff;
--chart-1: #ffffff;
--chart-2: #cccccc;
--chart-3: #999999;
--chart-4: #666666;
--chart-5: #444444;
--sidebar: #121212;
--sidebar-foreground: #9a9a9a;
--sidebar-primary: #ffffff;
--sidebar-primary-foreground: #0a0a0a;
--sidebar-accent: #1a1a1a;
--sidebar-accent-foreground: #e0e0e0;
--sidebar-border: #2a2a2a;
--sidebar-ring: #ffffff;
}
+45
View File
@@ -0,0 +1,45 @@
/*
NORD — ported from the published palette, unchanged.
A PALETTE theme: it supplies the standard tokens and nothing else. Panels, the header, the dock, glass,
grid lines and scrollbars are all derived from these by `base.css`, so this file never mentions them.
That is the contract working as intended — a theme anyone has already written, dropped in whole. Compare
`duck-*.css`, which additionally declares a texture.
*/
[data-theme='nord'] {
--radius: 0.625rem;
--background: #2e3440;
--foreground: #eceff4;
--card: #3b4252;
--card-foreground: #eceff4;
--popover: #3b4252;
--popover-foreground: #eceff4;
--primary: #88c0d0;
--primary-foreground: #2e3440;
--secondary: #434c5e;
--secondary-foreground: #eceff4;
--muted: #3b4252;
--muted-foreground: #d8dee9;
--accent: #8fbcbb;
--accent-foreground: #2e3440;
--destructive: #bf616a;
--destructive-foreground: #eceff4;
--border: #434c5e;
--input: #434c5e;
--ring: #88c0d0;
--chart-1: #88c0d0;
--chart-2: #ebcb8b;
--chart-3: #a3be8c;
--chart-4: #8fbcbb;
--chart-5: #b48ead;
--sidebar: #3b4252;
--sidebar-foreground: #d8dee9;
--sidebar-primary: #88c0d0;
--sidebar-primary-foreground: #2e3440;
--sidebar-accent: #434c5e;
--sidebar-accent-foreground: #eceff4;
--sidebar-border: #4c566a;
--sidebar-ring: #88c0d0;
}
@@ -0,0 +1,45 @@
/*
OSAKA JADE — ported from the published palette, unchanged.
A PALETTE theme: it supplies the standard tokens and nothing else. Panels, the header, the dock, glass,
grid lines and scrollbars are all derived from these by `base.css`, so this file never mentions them.
That is the contract working as intended — a theme anyone has already written, dropped in whole. Compare
`duck-*.css`, which additionally declares a texture.
*/
[data-theme='osaka-jade'] {
--radius: 0.625rem;
--background: #1a1b26;
--foreground: #c5cdd9;
--card: #16161e;
--card-foreground: #c5cdd9;
--popover: #16161e;
--popover-foreground: #c5cdd9;
--primary: #2ac3de;
--primary-foreground: #1a1b26;
--secondary: #292e42;
--secondary-foreground: #c5cdd9;
--muted: #1f2335;
--muted-foreground: #565f89;
--accent: #0db9d7;
--accent-foreground: #1a1b26;
--destructive: #f7768e;
--destructive-foreground: #c5cdd9;
--border: #292e42;
--input: #292e42;
--ring: #2ac3de;
--chart-1: #2ac3de;
--chart-2: #e0af68;
--chart-3: #9ece6a;
--chart-4: #1abc9c;
--chart-5: #bb9af7;
--sidebar: #16161e;
--sidebar-foreground: #565f89;
--sidebar-primary: #2ac3de;
--sidebar-primary-foreground: #1a1b26;
--sidebar-accent: #1f2335;
--sidebar-accent-foreground: #c5cdd9;
--sidebar-border: #292e42;
--sidebar-ring: #2ac3de;
}
@@ -0,0 +1,45 @@
/*
RISTRETTO — ported from the published palette, unchanged.
A PALETTE theme: it supplies the standard tokens and nothing else. Panels, the header, the dock, glass,
grid lines and scrollbars are all derived from these by `base.css`, so this file never mentions them.
That is the contract working as intended — a theme anyone has already written, dropped in whole. Compare
`duck-*.css`, which additionally declares a texture.
*/
[data-theme='ristretto'] {
--radius: 0.625rem;
--background: #403d39;
--foreground: #ebe5df;
--card: #352f2a;
--card-foreground: #ebe5df;
--popover: #352f2a;
--popover-foreground: #ebe5df;
--primary: #fc9867;
--primary-foreground: #403d39;
--secondary: #5f574f;
--secondary-foreground: #ebe5df;
--muted: #4d4743;
--muted-foreground: #ada49d;
--accent: #fbb360;
--accent-foreground: #403d39;
--destructive: #d76c6c;
--destructive-foreground: #ebe5df;
--border: #5f574f;
--input: #5f574f;
--ring: #fc9867;
--chart-1: #fc9867;
--chart-2: #fbb360;
--chart-3: #8ca589;
--chart-4: #86a3a3;
--chart-5: #a38dac;
--sidebar: #352f2a;
--sidebar-foreground: #ada49d;
--sidebar-primary: #fc9867;
--sidebar-primary-foreground: #403d39;
--sidebar-accent: #4d4743;
--sidebar-accent-foreground: #ebe5df;
--sidebar-border: #5f574f;
--sidebar-ring: #fc9867;
}
@@ -0,0 +1,45 @@
/*
ROSÉ PINE — ported from the published palette, unchanged.
A PALETTE theme: it supplies the standard tokens and nothing else. Panels, the header, the dock, glass,
grid lines and scrollbars are all derived from these by `base.css`, so this file never mentions them.
That is the contract working as intended — a theme anyone has already written, dropped in whole. Compare
`duck-*.css`, which additionally declares a texture.
*/
[data-theme='rose-pine'] {
--radius: 0.625rem;
--background: #191724;
--foreground: #e0def4;
--card: #1f1d2e;
--card-foreground: #e0def4;
--popover: #1f1d2e;
--popover-foreground: #e0def4;
--primary: #c4a7e7;
--primary-foreground: #191724;
--secondary: #26233a;
--secondary-foreground: #e0def4;
--muted: #26233a;
--muted-foreground: #908caa;
--accent: #ebbcba;
--accent-foreground: #191724;
--destructive: #eb6f92;
--destructive-foreground: #e0def4;
--border: #26233a;
--input: #26233a;
--ring: #c4a7e7;
--chart-1: #c4a7e7;
--chart-2: #f6c177;
--chart-3: #9ccfd8;
--chart-4: #31748f;
--chart-5: #eb6f92;
--sidebar: #1f1d2e;
--sidebar-foreground: #908caa;
--sidebar-primary: #c4a7e7;
--sidebar-primary-foreground: #191724;
--sidebar-accent: #26233a;
--sidebar-accent-foreground: #e0def4;
--sidebar-border: #403d52;
--sidebar-ring: #c4a7e7;
}
@@ -0,0 +1,45 @@
/*
TOKYO NIGHT — ported from the published palette, unchanged.
A PALETTE theme: it supplies the standard tokens and nothing else. Panels, the header, the dock, glass,
grid lines and scrollbars are all derived from these by `base.css`, so this file never mentions them.
That is the contract working as intended — a theme anyone has already written, dropped in whole. Compare
`duck-*.css`, which additionally declares a texture.
*/
[data-theme='tokyo-night'] {
--radius: 0.625rem;
--background: #222436;
--foreground: #c8d3f5;
--card: #1e2030;
--card-foreground: #c8d3f5;
--popover: #1e2030;
--popover-foreground: #c8d3f5;
--primary: #82aaff;
--primary-foreground: #1b1d2b;
--secondary: #3b4261;
--secondary-foreground: #c8d3f5;
--muted: #2f334d;
--muted-foreground: #828bb8;
--accent: #86e1fc;
--accent-foreground: #1b1d2b;
--destructive: #c53b53;
--destructive-foreground: #c8d3f5;
--border: #3b4261;
--input: #3b4261;
--ring: #82aaff;
--chart-1: #82aaff;
--chart-2: #ffc777;
--chart-3: #c3e88d;
--chart-4: #4fd6be;
--chart-5: #c099ff;
--sidebar: #1e2030;
--sidebar-foreground: #828bb8;
--sidebar-primary: #82aaff;
--sidebar-primary-foreground: #1b1d2b;
--sidebar-accent: #2f334d;
--sidebar-accent-foreground: #c8d3f5;
--sidebar-border: #3b4261;
--sidebar-ring: #82aaff;
}
+19
View File
@@ -36,6 +36,25 @@ export const THEMES: readonly Theme[] = [
// and Plain exists to show what the app looks like without any of them.
applyDarkClass: false,
},
/*
Palette themes, ported unchanged from published colour schemes. Each supplies only the standard tokens;
`base.css` derives panels, header, dock, glass, grid and scrollbars from them.
`applyDarkClass` is set for the dark ones so the 396 `dark:` utilities still written into components
resolve. It says nothing about the theme beyond "treat this as a dark ground".
*/
{ id: 'tokyo-night', name: 'Tokyo Night', family: 'Tokyo Night', applyDarkClass: true },
{ id: 'catppuccin-mocha', name: 'Catppuccin Mocha', family: 'Catppuccin', applyDarkClass: true },
{ id: 'catppuccin-latte', name: 'Catppuccin Latte', family: 'Catppuccin', applyDarkClass: false },
{ id: 'everforest', name: 'Everforest', family: 'Everforest', applyDarkClass: true },
{ id: 'gruvbox', name: 'Gruvbox', family: 'Gruvbox', applyDarkClass: true },
{ id: 'kanagawa', name: 'Kanagawa', family: 'Kanagawa', applyDarkClass: true },
{ id: 'matte-black', name: 'Matte Black', family: 'Matte Black', applyDarkClass: true },
{ id: 'nord', name: 'Nord', family: 'Nord', applyDarkClass: true },
{ id: 'osaka-jade', name: 'Osaka Jade', family: 'Osaka Jade', applyDarkClass: true },
{ id: 'ristretto', name: 'Ristretto', family: 'Ristretto', applyDarkClass: true },
{ id: 'rose-pine', name: 'Rosé Pine', family: 'Rosé Pine', applyDarkClass: true },
] as const;
/** What the app wears when nobody has chosen — its appearance before this refactor. */