felixdivall.com / Tools / Themes

Electric Noctis

One palette,
two editors.

Dark, high-contrast themes for VS Code and Zed.
Built around semantic highlighting.

code --install-extension felixdivall.electric-indigo

The look

The same file, three ways

Every sample below is rendered from the theme files themselves, not screenshotted – and rendered twice over, because neither editor stops at the grammar. The second pass is the semantic one, and it is the reason enum members are green here rather than the color of an ordinary variable.

Two of the three are closer than they look. Electric Indigo is not a second palette: it shares every one of the 300 syntax rules with Electric Noctis and differs in the 124 colors around them – the ground, the activity bar, the panels. Same code, lighter room. The Zed build is the one that genuinely diverges, and comments are where you see it.

Electric Noctis Zed

index.ts

// Barrel file: re-exports, namespace imports, type-only exports.
export * from "./domain/enums";
export * as Types from "./domain/types";
export type { User, UserId, Result } from "./domain/types";
export { UserService, main as runDemo } from "./domain/services";
export { default as ThemeCard, ThemeProvider, useTheme } from "./ui/ThemeCard";

import { App } from "./domain/enums";

if (typeof window !== "undefined") {
  window.__THEME__ ??= App.Theme.Mode.Dark;
}

enums.ts

// ─── Numeric enum (auto-incrementing) ─────────────────────────────────────────
export enum Direction {
  Up = 1,
  Down,
  Left,
  Right,
}

// ─── String enum ──────────────────────────────────────────────────────────────
export enum LogLevel {
  Trace = "TRACE",
  Debug = "DEBUG",
  Info = "INFO",
  Warn = "WARN",
  Error = "ERROR",
}

// ─── Const enum (inlined at compile time) ─────────────────────────────────────
export const enum HttpStatus {
  Ok = 200,
  Created = 201,
  NoContent = 204,
  BadRequest = 400,
  Unauthorized = 401,
  NotFound = 404,
  Teapot = 418,
  InternalServerError = 500,
}

// ─── Bit flags with computed members ──────────────────────────────────────────
export enum Permission {
  None = 0,
  Read = 1 << 0,
  Write = 1 << 1,
  Execute = 1 << 2,
  Delete = 1 << 3,
  ReadWrite = Read | Write,
  All = Read | Write | Execute | Delete,
}
Electric Noctis VS Code

index.ts

// Barrel file: re-exports, namespace imports, type-only exports.
export * from "./domain/enums";
export * as Types from "./domain/types";
export type { User, UserId, Result } from "./domain/types";
export { UserService, main as runDemo } from "./domain/services";
export { default as ThemeCard, ThemeProvider, useTheme } from "./ui/ThemeCard";

import { App } from "./domain/enums";

if (typeof window !== "undefined") {
  window.__THEME__ ??= App.Theme.Mode.Dark;
}

enums.ts

// ─── Numeric enum (auto-incrementing) ─────────────────────────────────────────
export enum Direction {
  Up = 1,
  Down,
  Left,
  Right,
}

// ─── String enum ──────────────────────────────────────────────────────────────
export enum LogLevel {
  Trace = "TRACE",
  Debug = "DEBUG",
  Info = "INFO",
  Warn = "WARN",
  Error = "ERROR",
}

// ─── Const enum (inlined at compile time) ─────────────────────────────────────
export const enum HttpStatus {
  Ok = 200,
  Created = 201,
  NoContent = 204,
  BadRequest = 400,
  Unauthorized = 401,
  NotFound = 404,
  Teapot = 418,
  InternalServerError = 500,
}

// ─── Bit flags with computed members ──────────────────────────────────────────
export enum Permission {
  None = 0,
  Read = 1 << 0,
  Write = 1 << 1,
  Execute = 1 << 2,
  Delete = 1 << 3,
  ReadWrite = Read | Write,
  All = Read | Write | Execute | Delete,
}
Electric Indigo VS Code

index.ts

// Barrel file: re-exports, namespace imports, type-only exports.
export * from "./domain/enums";
export * as Types from "./domain/types";
export type { User, UserId, Result } from "./domain/types";
export { UserService, main as runDemo } from "./domain/services";
export { default as ThemeCard, ThemeProvider, useTheme } from "./ui/ThemeCard";

import { App } from "./domain/enums";

if (typeof window !== "undefined") {
  window.__THEME__ ??= App.Theme.Mode.Dark;
}

enums.ts

// ─── Numeric enum (auto-incrementing) ─────────────────────────────────────────
export enum Direction {
  Up = 1,
  Down,
  Left,
  Right,
}

// ─── String enum ──────────────────────────────────────────────────────────────
export enum LogLevel {
  Trace = "TRACE",
  Debug = "DEBUG",
  Info = "INFO",
  Warn = "WARN",
  Error = "ERROR",
}

// ─── Const enum (inlined at compile time) ─────────────────────────────────────
export const enum HttpStatus {
  Ok = 200,
  Created = 201,
  NoContent = 204,
  BadRequest = 400,
  Unauthorized = 401,
  NotFound = 404,
  Teapot = 418,
  InternalServerError = 500,
}

// ─── Bit flags with computed members ──────────────────────────────────────────
export enum Permission {
  None = 0,
  Read = 1 << 0,
  Write = 1 << 1,
  Execute = 1 << 2,
  Delete = 1 << 3,
  ReadWrite = Read | Write,
  All = Read | Write | Execute | Delete,
}

Enums, const enums and bit flags – where semantic tokens earn their keep. TypeScript only: it is the one language whose semantic tokens can be reproduced here exactly.

Why

A theme is only half of it

A grammar can tell a string from a number, but it cannot tell an enum member from a constant, or a type from the variable holding one – it has not read your code, only matched it. Semantic tokens come from the language server, which has, and both editors merge them over the top.

Which is why these themes lean on them, and why the Zed one needs a few lines of settings.json as well as the theme file. Without that block the colors below are still the theme, but types stop being gold and properties stop being distinct from everything else.

Zed

The same theme, outside VS Code

Electric Noctis for Zed is not on Zed's extension registry – it is a file. Put it in your themes directory and Zed picks it up, then choose it in the theme selector.

curl -o ~/.config/zed/themes/electric-noctis.json https://felixdivall.com/themes/electric-noctis.json

Then the half that lives in your settings, which is what paints types, properties, parameters and anything async:



{
  "semantic_tokens": "combined",

  "global_lsp_settings": {
    "semantic_token_rules": [
      { "token_type": "interface", "token_modifiers": ["defaultLibrary"], "style": ["type.builtin", "type.interface"] },
      { "token_type": "class", "token_modifiers": ["defaultLibrary"], "style": ["type.builtin", "type"] },
      { "token_type": "type", "token_modifiers": ["defaultLibrary"], "style": ["type.builtin", "type"] },

      { "token_type": "interface", "style": ["type.interface", "type"], "foreground_color": "#FFD700" },
      { "token_type": "class", "style": ["type.class", "type"], "foreground_color": "#FFD700" },
      { "token_type": "type", "style": ["type"], "foreground_color": "#FFD700" },

      { "token_type": "enumMember", "token_modifiers": ["readonly"], "foreground_color": "#B8FB71" },
      { "token_type": "enumMember", "style": ["constant", "property"] },

      { "token_type": "property", "foreground_color": "#FFEE80" },
      { "token_type": "parameter", "foreground_color": "#AAF5FF" },
      { "token_type": "function", "token_modifiers": ["async"], "foreground_color": "#FE9B70" },
      { "token_type": "method", "token_modifiers": ["async"], "foreground_color": "#FE9B70" },
      { "token_type": "namespace", "foreground_color": "#FFD73D" }
    ]
  }
}
      

Get it

code --install-extension felixdivall.electric-indigo