@adea-ai/themes

中文文档
0.11.6发布于 2026/11/03Apache-2.0TypeScriptES Module零依赖近 30 天下载 4.9万

The Adea theme catalogue: first-party and imported semantic OKLCH themes, with Base24, terminal, CSS and syntax adapters.

原始使用文档
文档目录9 节
  1. The catalogue
  2. Using it
  3. The design, in four decisions
  4. Base24 is a bridge, not the schema
  5. Adapters
  6. Working on it
  7. Composing a theme from two palettes
  8. Adding a theme
  9. Licence

@adea-ai/themes

The Adea theme catalogue. Thirty-four themes — every one an OKLCH theme with the full set of semantic surface roles, sixteen ANSI colours, a cursor and a selection — including first-party Adea palettes and mature upstream palettes normalized through the same adapters.

bun add @adea-ai/themes

The catalogue

FamilyVariants
AdeaDark, Dark Colorblind, Dark High Contrast, Light, Light Colorblind, Light High Contrast
AardvarkInk, Blue
CatppuccinLatte, Frappé, Macchiato, Mocha
Tokyo NightDay, Storm, Night
Rosé PineDawn, Moon, Main
GruvboxLight, Dark
EverforestLight, Dark
AyuLight, Mirage, Dark
SolarizedLight, Dark
MonokaiClassic
NordNord, Light
Dracula, One Dark, Kanagawa, Vesperone each

The six Adea variants are the managed family — two appearances × three accessibility variants — and all of them are composed from upstream palettes rather than authored or copied:

Variantcanvashuesaccent
Adea DarkGitHub Dark Default, re-greyedGitHub Dark Defaultits violet
Adea Dark Colorblindsame re-greyed canvasGitHub Dark Colorblindits violet
Adea Dark High ContrastGitHub Dark High Contrast, re-greyedGitHub Dark High Contrastits violet
Adea LightGitHub Light Default #ffffffGitHub Dark Default, transposedits violet
Adea Light ColorblindGitHub Light Colorblind #ffffffGitHub Dark Colorblind, transposedits violet
Adea Light High ContrastGitHub Light High ContrastGitHub Dark High Contrast, transposedits violet

The re-greying is the one family-wide customisation: GitHub's dark greyscale is cut blue (h≈258), so its chroma is halved and the hue rotated to violet-grey — the ground the family's violet accent is meant to read on. The hue slots are untouched (GitHub's dark palette stays GitHub's), the accessibility variants are compositions of GitHub's own accessibility variants, and every light variant is its dark counterpart's hues transposed onto paper, so a red is the same red in both modes of a variant and switching appearance changes lightness and nothing else. tests/provenance.test.ts asserts the partnership — identical hue and chroma for every chromatic role across a variant's two appearances, the re-tinted canvases, and the violet accent on all six.

The other themes reproduce somebody else's palette from a named revision and are credited in NOTICE.

Using it

For an application that needs one palette, import its generated module directly:

import theme from '@adea-ai/themes/themes/adea-dark'
import { toXtermTheme } from '@adea-ai/themes/adapters/xterm'

terminal.options.theme = toXtermTheme(theme)

This entry point does not load the catalogue, other palettes, or normalization. @adea-ai/themes/metadata exports themeMetadata, a picker catalogue containing identity, family, appearance, description, tags, and provenance, without palette values. Load a selected palette through a static map of dynamic imports so the application bundler can create separate chunks. The full catalogue API below remains available when every palette is needed.

All JavaScript exports use native ESM with explicit relative file extensions. The shadcn adapter is available at @adea-ai/themes/adapters/shadcn. tests/package.test.ts builds and packs the actual archive, resolves its public exports in Node, and checks that a single-theme browser bundle excludes other palettes and catalogue tooling. Its 16 KiB uncompressed ceiling leaves headroom for one record and the terminal adapter while detecting catalogue inclusion. This package still has no runtime dependencies.

import { getTheme, themeFamilies, resolveTheme } from '@adea-ai/themes'
import { themeCssVariables } from '@adea-ai/themes/adapters/css'
import { toXtermTheme } from '@adea-ai/themes/adapters/xterm'
import { toShikiTheme } from '@adea-ai/themes/adapters/shiki'

// Apply a theme to the document.
const theme = resolveTheme('catppuccin-mocha', 'dark')
for (const [name, value] of Object.entries(themeCssVariables(theme))) {
  document.documentElement.style.setProperty(name, value)
}

// Colour a terminal.
terminal.options.theme = toXtermTheme(theme)

// Register a syntax theme.
const highlighter = await createHighlighter({ themes: [toShikiTheme(theme)], langs: [...] })

syntaxRolesHex(theme) keeps comments at the catalogue's intentionally quiet default. For editor palettes where comments and diff markers are small content text, editorRolesHex(theme) returns the editor roles with every rounded hex value checked against a 4.5:1 contrast floor. The source syntax palette remains unchanged.

Every exported theme value is an oklch() string, which means the browser does the colour work and a consumer can compose — color-mix(in oklch, var(--adea-accent), transparent 20%) — and get a predictable result. The adapters that need hex (xterm, Shiki) convert, gamut-mapping rather than clipping.

The design, in four decisions

Adea owns the schema and the transformation. The seventeen surface roles in src/schema.ts are the contract. No upstream project is asked to satisfy it. palettes/ holds Base24 schemes reproduced from a pinned revision; and src/normalize.ts is the single place an input becomes a canonical application theme. Adding a theme is a line in src/sources.ts plus a rebuild.

A theme may also be composed from two donors — one supplying the structure, another the hues — which is how all six of Adea's own themes are built. The composition is a slot map in COMPOSED_SOURCES, so both parents stay named and freshening either one is a one-line diff rather than a re-transcription. A composition can also declare hueTranspose, which moves a borrowed hue set onto a different kind of canvas as a group: hue and chroma intact, every relative brightness preserved.

OKLCH is the representation. Perceptually uniform lightness is what makes a surface ladder buildable by adding fixed steps, a contrast failure repairable by moving one axis, and a theme re-hueable without re-deriving its ramp by eye.

Contrast is measured, not assumed. Nothing enters the catalogue without clearing the floors defined in src/policy.ts and checked by src/validate.ts, and bun run catalogue:build fails if a theme cannot be repaired within budget. The pipeline caught real defects that a hand-authored catalogue would have shipped:

  • Solarized Light's body text measures 4.28:1 on its own background — under WCAG AA.
  • Tokyo Night's black is 1.17:1 against its canvas, and Gruvbox Light's white was resolving to a near-black, both from light schemes that invert Base24's greyscale ramp.
  • Everforest Light contains no colour above 2.6:1 on its own canvas, so its status and accent roles have to be deepened rather than used as published.

Derived colours are derived. Syntax roles, chart series and status fills are functions of the roles a theme does hold (src/derive.ts), so two consumers cannot disagree about what colour a keyword is.

Base24 is a bridge, not the schema

Base24 is an excellent interchange format and a poor application schema: it has a slot for the colour of a deprecated API and nothing that means "the surface one step above the card". So Base24 is how values get in and how they get out:

import { toBase24, formatBase24Scheme, parseBase24Scheme } from '@adea-ai/themes'
import { getBase24Scheme } from '@adea-ai/themes'

formatBase24Scheme(toBase24(getTheme('nord')!)) // a Base24 scheme
getBase24Scheme('nord') // the vendored original, untouched

toBase24 re-derives Base24's orange and brown slots, because Adea's schema has no role for them; getBase24Scheme returns the artefact as reproduced, for callers that need it byte-for-byte. The mapping is documented in src/adapters/base24.ts.

Adapters

ImportForOutput
adapters/cssthe applicationCSS custom properties in OKLCH
adapters/tailwindthe applicationa Tailwind v4 @theme inline block
adapters/shadcnthis org's componentsthe shadcn vocabulary, bridged from the same source
adapters/xtermshellsxterm.js's hex-only ITheme
adapters/shikicode viewsa Shiki theme registration
adapters/base24interopBase24, both directions

The shadcn bridge is worth knowing about before you read the code: Adea's accent becomes shadcn's primary, because in shadcn --primary is the action colour and --accent is a hover wash. Mapping it the other way turns every primary button grey. The mapping is in src/adapters/shadcn.ts.

Working on it

bun install
bun run verify          # formatting, typecheck, lint, catalogue freshness, tests, build
bun run catalogue:build # regenerate src/generated from palettes/ and sources.ts
bun run catalogue:check # fail if the committed catalogue is stale
bun run vendor          # refresh palettes/ from the pinned upstream revision

The generated catalogue is committed, and catalogue:check fails when it and its inputs disagree. A palette change is therefore a reviewable diff rather than an invisible drift.

palettes/ is regenerated by bun run vendor, which reproduces Base24 schemes from a revision pinned in src/sources.ts. To adopt a newer upstream, change CATALOGUE_REVISION, run vendor, then catalogue:build and read the diff — the build prints every value it repaired and why.

Composing a theme from two palettes

Add an entry to COMPOSED_SOURCES in src/sources.ts naming both donor slugs, the slot map, and the slots to synthesise; list the greyscale roles to pin to the structure donor; set hueTranspose if the hues are being borrowed for a different kind of canvas; then bun run vendor && bun run catalogue:build. The vendor step asserts the two maps cover every Base24 slot, so a composition cannot be half-specified. Assert each half against its donor in tests/provenance.test.ts.

Adding a theme

  1. Add its Base24 scheme to palettes/ (or let vendor fetch it: add the slug to VENDORED_SOURCES in src/sources.ts first).
  2. Record its family's project, URL and licence in FAMILY_PROVENANCE, and its entry in VENDORED_SOURCES — id, labels, description, appearance, tags.
  3. Declare accentSlot if the family's identity is not in its blue slot. Everforest is green, Rosé Pine is iris, Monokai is magenta.
  4. Add a fidelity assertion to tests/provenance.test.ts. The suite fails without one — a theme cannot be added without recording where its colours come from.
  5. bun run catalogue:build && bun run verify.

If the build reports a role it could not repair within budget, the answer is a decision rather than a tweak: either the palette genuinely cannot express that role, in which case say so in the entry's description, or the floor is wrong, in which case change it in CONTRAST_FLOORS and justify it there.

Licence

Apache-2.0. The palettes are not: see NOTICE for each project and its terms.

版本与发布记录

@adea-ai/themes 共发布 67 个版本,首次发布于 2026/09/26;过去 12 个月发布了 67 个版本。

版本发布日期距今
0.11.6latest2026/11/033 天前
0.11.52026/10/315 天前
0.11.42026/10/316 天前
0.11.32026/10/306 天前
0.11.22026/10/307 天前
0.11.12026/10/307 天前

关于 @adea-ai/themes 的常见问题

@adea-ai/themes 是什么?

The Adea theme catalogue: first-party and imported semantic OKLCH themes, with Base24, terminal, CSS and syntax adapters.

如何安装 @adea-ai/themes?

在项目目录运行 npm install @adea-ai/themes,或使用 pnpm add / yarn add / bun add。

@adea-ai/themes 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@adea-ai/themes 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@adea-ai/themes 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js 24.22.2。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@adea-ai/themes 可以商用吗?

@adea-ai/themes 使用 Apache-2.0 许可。宽松许可:允许商业使用、修改和再分发,并附带明确的专利授权;分发时需保留许可与 NOTICE 文件,修改过的文件要注明改动。以上为概括,不构成法律意见,请以许可原文为准。

@adea-ai/themes 的下载量有多少?

根据 npm 官方下载统计,@adea-ai/themes 在 2026/10/05 – 2026/11/03 这 30 天内被下载 48,883 次,日均约 1,629 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@adea-ai/themes 还在维护吗?

最新版本 0.11.6 发布于 2026/11/03(3 天前);至今共发布 67 个版本,其中过去 12 个月发布了 67 个;首次发布于 2026/09/26。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。