MatteoGabriele/ubik

★ 0Forks 0JavaScriptGitHub ↗Compare

README

Ubik

A warm, earthy VS Code theme in dark and light — built to sit comfortably behind mononoki, and tuned on TypeScript and Vue.

Ubik dark and light previewing a composable and a Vue SFC

The idea

Most dark themes are lit by a blue-grey moon. Ubik is lit by a low fire: umber grounds, clay and ochre accents, moss and sage for the things you read most. It is soft without being murky — every syntax colour clears 4.5:1 against its background (comments and punctuation, which are meant to recede, clear 3.5:1), so long sessions don't cost you your eyes.

Mononoki is a warm, slightly hand-cut typeface with real italics. Ubik leans on that: italics are used sparingly and deliberately — comments, this, decorators, Vue directives, export/import — never as decoration.

Install

From the Marketplace: search Ubik in the Extensions view.

Or locally:

git clone https://github.com/MatteoGabriele/ubik.git ~/.vscode/extensions/ubik

Then ⌘K ⌘T → Ubik Dark or Ubik Light.

Recommended settings

{
  "workbench.colorTheme": "Ubik Dark",
  "editor.fontFamily": "mononoki, Menlo, monospace",
  "editor.fontSize": 14,
  "editor.lineHeight": 1.7,
  "editor.letterSpacing": 0.3,
  // Ubik ships semantic colours for TS/Vue — leave this on.
  "editor.semanticHighlighting.enabled": true,
  "editor.bracketPairColorization.enabled": true,
  "terminal.integrated.fontFamily": "mononoki"
}

Get the font with brew install --cask font-mononoki-nerd-font, or from madmalik/mononoki.

Palette

Role Dark Light
Background #181410 #FBF3E3
Foreground #E6DACA #3B3227
Comment #8B7B6A #7D7059
Keyword · tag — clay #F15B22 #D22E00
Function · directive — ochre #FFB700 #956600
String — moss #92CC36 #3F7D00
Type · component — sage #00DFC1 #007C6D
Constant · number — plum #E473D9 #C000B8
Property · key — stone #A9B4D6 #45486B
Error — rust #FF473A #DE0020

Accents run at CIELAB chroma 52–83 in the dark variant and 33–93 in the light one — at or near the highest saturation sRGB can express at each hue while still clearing the contrast floor. The light ground is a warm cream rather than paper-white: pulling the field off #FFF takes the glare out and lets the accents read louder against it. Neutrals stay deliberately quiet (foreground and comments carry almost no chroma) so the accents do all the work. No two accent hues sit closer than 33°. stone is the one low-chroma colour: properties sit in the same lightness band as the foreground but at the opposite temperature, so payload.pull_request?.author_association shows where the variable ends and the object walk begins without another accent entering the picture.

On a light ground, yellow and teal are gamut-capped: ochre and sage are already at the sRGB ceiling for their hue at readable contrast, so they cannot be pushed further without dropping below AA. That is a property of the colour space, not a style choice.

Roles are consistent across languages: a type is sage whether it's a TS interface, a Vue component tag, or a generic parameter. A Vue directive (v-if, :prop, @click) reads as ochre italic so template logic separates from plain attributes at a glance.

Working on it

Both themes are generated from one palette so dark and light can never drift apart.

npm run build   # palettes.mjs → themes/*.json, plus the icon
npm run check   # WCAG contrast audit of every syntax colour
node scripts/preview.mjs   # rebuild preview/preview.html

Edit scripts/palettes.mjs for colour, and scripts/build.mjs for which scope gets which colour. Never edit themes/*.json by hand — it's generated.

npm run check fails the build on any colour that drops below its contrast floor.

Licence

MIT © Matteo Gabriele

Contributors

MatteoGabriele

Issues