Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 13 additions & 6 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ A theme is a directory under `packages/jaamd/src/themes/<slug>/` plus one entry

### 1. Write `index.css`

One `:root` block of `--jaamd-*` declarations. These **seeds are required**:
A `:root` block of `--jaamd-*` declarations. A theme that has both a light and a
dark palette adds a second block on `html.dark`, and must repeat the seeds there —
otherwise one mode borrows the other's background. These **seeds are required**:

| Token | What it is |
|---|---|
Expand All @@ -38,18 +40,23 @@ Do not restate the font tokens: they are the defaults already.

### 2. Declare it

Add an entry to `src/themes/index.ts` with the directory name as `slug`, a readable
`name`, the `mode` the palette expects (`"light"` or `"dark"` — themes are not
assumed to be dark), and the `shiki` theme that pairs with it.
Add an entry to `src/themes/index.ts` with the directory name as `slug` and a
readable `name`, plus:

| `mode` | The palette is | `shiki` |
|---|---|---|
| `"light"` / `"dark"` | one palette, applying in both modes | one theme name |
| `"dual"` | two palettes, `:root` and `html.dark` | `{ light, dark }` |

### 3. Generate the dark variant

```bash
pnpm build:themes
```

`dark.css` is `index.css` under `html.dark`, generated and committed. Never edit it
by hand.
`dark.css` is `index.css` under `html.dark` — the variant for using a single-palette
theme only in dark mode. It is generated and committed; never edit it by hand. A
`dual` theme covers dark mode itself and gets no `dark.css`.

### 4. Check it

Expand Down
26 changes: 17 additions & 9 deletions packages/jaamd/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -375,14 +375,20 @@ The default set includes dark-mode overrides activated by the `dark` class on

### Theme presets

Three presets restyle all `--jaamd-*` variables to match popular editor colour
schemes:

| Preset | Import | Recommended Shiki theme |
|--------|--------|------------------------|
| Dracula | `@lancher-dev/jaamd/themes/dracula` | `dracula` |
| Nord | `@lancher-dev/jaamd/themes/nord` | `nord` |
| One Dark | `@lancher-dev/jaamd/themes/one-dark` | `one-dark-pro` |
Eight presets restyle the `--jaamd-*` palette to match popular editor colour
schemes. A **dual** preset carries a light and a dark palette and follows
`html.dark`; the others are one palette that applies in both modes.

| Preset | Import | Kind | Recommended Shiki theme |
|--------|--------|------|------------------------|
| Catppuccin | `@lancher-dev/jaamd/themes/catppuccin` | dual | `catppuccin-latte` / `catppuccin-mocha` |
| Dracula | `@lancher-dev/jaamd/themes/dracula` | dark | `dracula` |
| Gruvbox | `@lancher-dev/jaamd/themes/gruvbox` | dual | `gruvbox-light-medium` / `gruvbox-dark-medium` |
| Nord | `@lancher-dev/jaamd/themes/nord` | dark | `nord` |
| One Dark | `@lancher-dev/jaamd/themes/one-dark` | dark | `one-dark-pro` |
| Rosé Pine | `@lancher-dev/jaamd/themes/rose-pine` | dual | `rose-pine-dawn` / `rose-pine` |
| Rosé Pine Moon | `@lancher-dev/jaamd/themes/rose-pine-moon` | dual | `rose-pine-dawn` / `rose-pine-moon` |
| Tokyo Night | `@lancher-dev/jaamd/themes/tokyo-night` | dark | `tokyo-night` |

As a standalone theme, replacing the default light theme:

Expand All @@ -396,7 +402,9 @@ jaamd({ theme: "dracula" })
@import "@lancher-dev/jaamd/styles.css";
```

Scoped to `html.dark` via the `/dark` variant:
A single-palette preset can also be scoped to `html.dark` via the `/dark` variant,
to use it as the dark half of your own light theme. Dual presets already cover both
modes and have no `/dark`:

```css
@import "@lancher-dev/jaamd/themes/dracula/dark.css";
Expand Down
31 changes: 31 additions & 0 deletions packages/jaamd/src/themes/catppuccin/index.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/* JAAMD theme — Catppuccin. Latte in light, Mocha in dark. */

:root {
--jaamd-bg: #eff1f5;
--jaamd-color-fg: #4c4f69;
--jaamd-color-fg-bright: #4c4f69;
--jaamd-color-primary: #1e66f5;
--jaamd-color-success: #40a02b;
--jaamd-alert-note-color: #1e66f5;
--jaamd-alert-tip-color: #40a02b;
--jaamd-alert-important-color: #1e66f5;
--jaamd-alert-warning-color: #df8e1d;
--jaamd-alert-caution-color: #d20f39;

--jaamd-em-fg: #8839ef;
}

html.dark {
--jaamd-bg: #1e1e2e;
--jaamd-color-fg: #cdd6f4;
--jaamd-color-fg-bright: #cdd6f4;
--jaamd-color-primary: #89b4fa;
--jaamd-color-success: #a6e3a1;
--jaamd-alert-note-color: #89b4fa;
--jaamd-alert-tip-color: #a6e3a1;
--jaamd-alert-important-color: #89b4fa;
--jaamd-alert-warning-color: #f9e2af;
--jaamd-alert-caution-color: #f38ba8;

--jaamd-em-fg: #cba6f7;
}
33 changes: 33 additions & 0 deletions packages/jaamd/src/themes/gruvbox/index.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/* JAAMD theme — Gruvbox. Light and dark, following the toggle. */

:root {
--jaamd-bg: #fbf1c7;
--jaamd-color-fg: #3c3836;
--jaamd-color-fg-bright: #282828;
--jaamd-color-primary: #458588;
--jaamd-color-success: #98971a;
--jaamd-alert-note-color: #458588;
--jaamd-alert-tip-color: #98971a;
--jaamd-alert-important-color: #458588;
--jaamd-alert-warning-color: #d79921;
--jaamd-alert-caution-color: #cc241d;

--jaamd-border-strong: #d5c4a1;
--jaamd-em-fg: #b16286;
}

html.dark {
--jaamd-bg: #282828;
--jaamd-color-fg: #ebdbb2;
--jaamd-color-fg-bright: #fbf1c7;
--jaamd-color-primary: #83a598;
--jaamd-color-success: #b8bb26;
--jaamd-alert-note-color: #83a598;
--jaamd-alert-tip-color: #b8bb26;
--jaamd-alert-important-color: #83a598;
--jaamd-alert-warning-color: #fabd2f;
--jaamd-alert-caution-color: #fb4934;

--jaamd-border-strong: #665c54;
--jaamd-em-fg: #d3869b;
}
39 changes: 35 additions & 4 deletions packages/jaamd/src/themes/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,52 @@
* this instead of hardcoding a list, and `tests/unit/themes.mjs` checks that
* each entry matches a directory that honours the token contract.
*/
/**
* `light` and `dark` are single palettes that apply in both modes; `dual` carries
* both, a `:root` block and an `html.dark` one, and follows whatever decides the
* mode. A `dual` theme has no `/dark` variant — its own file already does that.
*/
export type JaamdThemeMode = "light" | "dark" | "dual";

export interface JaamdTheme {
/** Directory name, and the value a `data-jaamd-theme` attribute would carry. */
slug: string;
/** Human-readable name, for pickers. */
name: string;
/** Whether the palette expects `html.dark`. Not every theme is dark. */
mode: "light" | "dark";
/** Shiki theme that pairs with this palette. */
shiki: string;
mode: JaamdThemeMode;
/** Shiki theme that pairs with this palette, or a pair for a `dual` one. */
shiki: string | { light: string; dark: string };
}

export const themes: JaamdTheme[] = [
{
slug: "catppuccin",
name: "Catppuccin",
mode: "dual",
shiki: { light: "catppuccin-latte", dark: "catppuccin-mocha" },
},
{ slug: "dracula", name: "Dracula", mode: "dark", shiki: "dracula" },
{
slug: "gruvbox",
name: "Gruvbox",
mode: "dual",
shiki: { light: "gruvbox-light-medium", dark: "gruvbox-dark-medium" },
},
{ slug: "nord", name: "Nord", mode: "dark", shiki: "nord" },
{ slug: "one-dark", name: "One Dark", mode: "dark", shiki: "one-dark-pro" },
{
slug: "rose-pine",
name: "Rosé Pine",
mode: "dual",
shiki: { light: "rose-pine-dawn", dark: "rose-pine" },
},
{
slug: "rose-pine-moon",
name: "Rosé Pine Moon",
mode: "dual",
shiki: { light: "rose-pine-dawn", dark: "rose-pine-moon" },
},
{ slug: "tokyo-night", name: "Tokyo Night", mode: "dark", shiki: "tokyo-night" },
];

/** Seeds a theme must declare; everything else derives from them in variables.css. */
Expand Down
33 changes: 33 additions & 0 deletions packages/jaamd/src/themes/rose-pine-moon/index.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/* JAAMD theme — Rosé Pine Moon. Dawn in light, moon in dark. */

:root {
--jaamd-bg: #faf4ed;
--jaamd-color-fg: #575279;
--jaamd-color-fg-bright: #575279;
--jaamd-color-primary: #286983;
--jaamd-color-success: #286983;
--jaamd-alert-note-color: #56949f;
--jaamd-alert-tip-color: #286983;
--jaamd-alert-important-color: #286983;
--jaamd-alert-warning-color: #ea9d34;
--jaamd-alert-caution-color: #b4637a;

--jaamd-border-strong: #9893a5;
--jaamd-em-fg: #907aa9;
}

html.dark {
--jaamd-bg: #232136;
--jaamd-color-fg: #e0def4;
--jaamd-color-fg-bright: #e0def4;
--jaamd-color-primary: #9ccfd8;
--jaamd-color-success: #9ccfd8;
--jaamd-alert-note-color: #3e8fb0;
--jaamd-alert-tip-color: #9ccfd8;
--jaamd-alert-important-color: #9ccfd8;
--jaamd-alert-warning-color: #f6c177;
--jaamd-alert-caution-color: #eb6f92;

--jaamd-border-strong: #6e6a86;
--jaamd-em-fg: #c4a7e7;
}
33 changes: 33 additions & 0 deletions packages/jaamd/src/themes/rose-pine/index.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/* JAAMD theme — Rosé Pine. Dawn in light, main in dark. */

:root {
--jaamd-bg: #faf4ed;
--jaamd-color-fg: #575279;
--jaamd-color-fg-bright: #575279;
--jaamd-color-primary: #286983;
--jaamd-color-success: #286983;
--jaamd-alert-note-color: #56949f;
--jaamd-alert-tip-color: #286983;
--jaamd-alert-important-color: #286983;
--jaamd-alert-warning-color: #ea9d34;
--jaamd-alert-caution-color: #b4637a;

--jaamd-border-strong: #9893a5;
--jaamd-em-fg: #907aa9;
}

html.dark {
--jaamd-bg: #191724;
--jaamd-color-fg: #e0def4;
--jaamd-color-fg-bright: #e0def4;
--jaamd-color-primary: #9ccfd8;
--jaamd-color-success: #9ccfd8;
--jaamd-alert-note-color: #31748f;
--jaamd-alert-tip-color: #9ccfd8;
--jaamd-alert-important-color: #9ccfd8;
--jaamd-alert-warning-color: #f6c177;
--jaamd-alert-caution-color: #eb6f92;

--jaamd-border-strong: #6e6a86;
--jaamd-em-fg: #c4a7e7;
}
18 changes: 18 additions & 0 deletions packages/jaamd/src/themes/tokyo-night/dark.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/* JAAMD theme — Tokyo Night (dark mode only). A dark theme: it applies in both modes. */

html.dark {
--jaamd-bg: #1a1b26;
--jaamd-color-fg: #a9b1d6;
--jaamd-color-fg-bright: #c0caf5;
--jaamd-color-primary: #7aa2f7;
--jaamd-color-success: #9ece6a;
--jaamd-alert-note-color: #7dcfff;
--jaamd-alert-tip-color: #9ece6a;
--jaamd-alert-important-color: #7aa2f7;
--jaamd-alert-warning-color: #e0af68;
--jaamd-alert-caution-color: #f7768e;

--jaamd-border-strong: #565f89;
--jaamd-color-primary-light: #7dcfff;
--jaamd-em-fg: #bb9af7;
}
18 changes: 18 additions & 0 deletions packages/jaamd/src/themes/tokyo-night/index.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/* JAAMD theme — Tokyo Night. A dark theme: it applies in both modes. */

:root {
--jaamd-bg: #1a1b26;
--jaamd-color-fg: #a9b1d6;
--jaamd-color-fg-bright: #c0caf5;
--jaamd-color-primary: #7aa2f7;
--jaamd-color-success: #9ece6a;
--jaamd-alert-note-color: #7dcfff;
--jaamd-alert-tip-color: #9ece6a;
--jaamd-alert-important-color: #7aa2f7;
--jaamd-alert-warning-color: #e0af68;
--jaamd-alert-caution-color: #f7768e;

--jaamd-border-strong: #565f89;
--jaamd-color-primary-light: #7dcfff;
--jaamd-em-fg: #bb9af7;
}
22 changes: 19 additions & 3 deletions scripts/build-themes.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,17 @@
* `--check` verifies the committed files instead of writing them.
*/

import { readdirSync, readFileSync, writeFileSync } from "node:fs";
import { readdirSync, readFileSync, writeFileSync, rmSync, existsSync } from "node:fs";
import { join } from "node:path";
import { fileURLToPath } from "node:url";

import { themes } from "../packages/jaamd/src/themes/index.ts";

const THEMES = join(process.cwd(), "packages", "jaamd", "src", "themes");

/** A dual theme carries both palettes already; a dark-only variant is meaningless. */
const isDual = (slug) => themes.find((t) => t.slug === slug)?.mode === "dual";

/** The dark variant of a theme's source. */
export function darkVariant(source) {
return source
Expand All @@ -29,12 +34,23 @@ function run(check) {
const stale = [];

for (const slug of slugs) {
const path = join(THEMES, slug, "dark.css");

if (isDual(slug)) {
if (check) {
if (existsSync(path)) stale.push(`${slug} (dual, should have no dark.css)`);
} else if (existsSync(path)) {
rmSync(path);
console.log(`✓ ${slug}/dark.css removed (dual)`);
}
continue;
}

const source = readFileSync(join(THEMES, slug, "index.css"), "utf8");
const expected = darkVariant(source);
const path = join(THEMES, slug, "dark.css");

if (check) {
if (readFileSync(path, "utf8") !== expected) stale.push(slug);
if (!existsSync(path) || readFileSync(path, "utf8") !== expected) stale.push(slug);
continue;
}

Expand Down
Loading
Loading