Candela

The theme that
does the math.

Candela is a warm, low-fatigue theme for Zed where every color is derived, not picked — uniform in OKLCH, verified against WCAG. Beautiful and legible, not one at the cost of the other.

◆ Dark + Light ◆ WCAG AAA body ◆ OKLCH-uniform accents ◆ Colorblind-aware ◆ MIT
Get it on GitHub Install in 30s

The problem

Most themes optimize one axis. Candela does both.

There are two ways to judge a color theme, and they usually fight each other:

🎨

Axis 1 — Perceptual coherence

Colors that feel like one family: same weight, evenly spaced, none screaming louder than the rest. Solarized, Nord and Dracula nail this — but many are hard to read.

📐

Axis 2 — Measured contrast

Legibility you can prove with a number (WCAG ratio). GitHub Primer and IBM Carbon are legible — but their palettes are assembled ad-hoc, so colors clash.

Candela is engineered to pass both: accents are generated in OKLCH at a fixed lightness and chroma so they're perceptually uniform, and the result is checked with WCAG math before a single line ships.

See it

Same rules, every language.
1// color = identifier, gray = operator
2import { readFile } from "node:fs/promises";
3
4interface Theme {
5  name: string;
6  contrast: number;
7}
8
9async function load(path: string): Promise<Theme> {
10  const raw = await readFile(path, "utf8");
11  if (JSON.parse(raw).contrast < 7)
12    throw new Error(`below AAA: ${path}`);
13  return JSON.parse(raw);
14}

Why you'll keep it

Details that add up over a long day.
🔵

Color = identifier, gray = operator

Variables, props and params are colored; operators and punctuation fade to neutral gray. Your eye lands on the content, not the syntax noise.

🌡️

Warm base, cool structure

Warm background eases eye strain; cool accents mark structure (functions, types), warm accents mark values (numbers, strings). Calm to read, easy to scan.

👁️

Colorblind-aware by design

Meaning never depends on red vs green. Red is reserved for errors and always paired with a background and border, so status reads in any vision type.

🌗

Dark and light, one system

Both variants share the same OKLCH construction and role mapping — switch by time of day without relearning your colors.

🖥️

Terminal included

Full 16-color ANSI palette derived from the same accents, plus bright/dim variants. Your integrated terminal matches the editor.

🔥

No pure black, no pure white

Avoids halation and glare. Backgrounds and text sit just inside the extremes, which is gentler on OLED and in dim rooms.

The receipts

Where classic themes land on the two axes.
ThemePerceptual coherenceMeasured contrast
Solarized / Nord / Dracula✓ strong✗ often fails AA
GitHub Primer / IBM Carbon✗ ad-hoc✓ passes
Candela✓ OKLCH-uniform✓ AAA / AA+

Palette — dark

8 hues, one lightness (L=0.80), one chroma (C=0.115).
variable#8ac1ff
function#d5bd62
type#4dd4db
keyword#c9adfd
number#f4ac6f
string#86d396
special#f39fcf
error#ffa098

Contrast, verified

Dark · vs #1c1915
RoleRatioGrade
Body14:1AAA
Variable9.0:1AAA
Function9.4:1AAA
Type9.6:1AAA
String9.8:1AAA
Number8.9:1AAA
Light · vs #faf9f6
RoleRatioGrade
Body13:1AAA
Variable6.1:1AA+
Function5.6:1AA+
Type5.1:1AA+
String5.4:1AA+
Number5.8:1AA+

Install

Two ways in under a minute.

From the Zed store

Command palette → zed: extensions → search Candela → Install.

Then Ctrl+K Ctrl+T and pick Candela Dark or Candela Light.

Manual (local)

Drop themes/candela.json into:

Windows %APPDATA%\Zed\themes\
macOS / Linux ~/.config/zed/themes/

FAQ

What is OKLCH and why does it matter?

OKLCH is a perceptually uniform color space. Fixing lightness and chroma while rotating hue gives colors that truly feel equally bright and equally vivid — something HSL and hex-picking can't guarantee. That's what stops one accent from screaming over the others.

Is it really WCAG AAA?

Body text is AAA (≥7:1) in both dark and light. Accents are AAA in dark and AA+ (≥4.5:1, most ≥5:1) in light — a deliberate trade so light-mode colors stay saturated enough to tell apart. Every value is computed, not estimated.

Does it work with my language?

Yes. Zed uses Tree-sitter, so highlighting is grammar-based and consistent across languages. The role mapping (identifier = color, operator = gray) applies everywhere; the samples above are the same theme, unedited.

Dark or light — do I have to choose?

No. Both ship in one extension and share the same construction, so switching keeps every role in the same color family.

License?

MIT. Fork it, tweak it, ship your own spin.