Theme builder

A Harmony theme is a JSON file. It can state twenty-eight colours, or it can state three and let the rest be derived — and either way the application has an opinion about whether the result is wearable. This page runs that opinion as you type.

Start from

Harmony

Catppuccin

Appearance
Download

Nothing leaves this page unless you publish. The file you download is the file Harmony reads — drop it in your themes folder and a running copy picks it up. Published themesare listed separately, and publishing one needs an account.

What the application says about it

Nothing. Every plane is lifted off the one under it, every tier of ink clears its threshold on every surface it can land on, and the chip ladder climbs.

The specimen

Every token, in its smallest true context

Not a drawing of Harmony — a drawing of Harmony would rot every time the real sidebar moved, and it answers the wrong question. Each plate below carries the theme's own ground; the caption beside it carries the site's, so a light theme is readable here without the plate having to pretend it is dark.

background
plane.chrome
plane.content
plane.raised

Elevation

A relationship, not a scheme. Each surface has to sit above the one it is drawn on — in a light theme as well as a dark one, which is where Catppuccin's Latte breaks under the obvious mapping and why that one is refused rather than warned about.

background
plane.chrome
plane.content
plane.raised
rule.surface
  • 1Slow Tide4:12
  • 2Harbour Light3:38
  • 3Cold Room Blues5:07
  • 4Ninth Street2:54
  • 5Long Way Down6:21
  • 6Marram3:02
AlbumArtistAdded

Four states, all of them surfaces

Rows two and three are the same selection at two strengths — under the pointer, and in the list that has focus. Four and five are a run queued by hand, which is why there are two of them: the token groups rather than states, and one row cannot show grouping. The chosen segment is a segmented control because that is the only place it appears.

state.selected
13.4:1
state.active
11.4:1
state.queued
16.0:1
state.chosen
12.6:1
rule.row

Ratios are body ink against that fill, flattened onto the card first — every one of these is a weight of the ink rather than a colour, so the number is meaningless without a plane underneath.

Ink on the window

11 tracks · 47 minutes · 2019

Ink on the frame

11 tracks · 47 minutes · 2019

Ink on the card

11 tracks · 47 minutes · 2019

Ink on a popover

11 tracks · 47 minutes · 2019

Two tiers, four surfaces

Body ink has to clear 4.5:1 on every surface it can land on, and that is one of the two faults the application refuses a theme for. Quiet ink is held to 3.0:1 — WCAG's bar for large text and for things that are not text — because it is a duration and a track count, not a paragraph.

onink.bodyink.quiet
background19.0:17.8:1
plane.chrome19.0:17.8:1
plane.content17.5:17.3:1
plane.raised14.3:15.9:1
RestHoverPressed

The chip ladder

Three rungs and one label. The ladder has to climb: a hover fainter than rest reads as a button going out under the pointer, which is the one interaction where being wrong is unmistakable.

chip.rest
15.6:1
chip.hover
13.9:1
chip.pressed
11.4:1
chip.ink

Now playing

Copied to the device

Two files could not be read

Removes 47 tracks

Search the libraryAdd folder

Marks, never surfaces

The accent is a tick, a caret, a focus ring, a control that is on — never the fill behind a two-line row. That is what state.active is for, and it stays a step off the plane whatever hue the theme carries. The one place the accent becomes a background is a primary button, which is the only reason ink.on_accent exists.

accent
17.5:1
danger
6.6:1
warning
11.9:1
success
10.5:1
ink.on_accent
17.2:1

The four signal ratios are against the card. A signal that fails here is a mark nobody sees, which is a different problem from unreadable body text and is why it is a warning rather than a refusal.

Album

The Long Room

Eleven tracks cut live over four nights, with the room mic left open between takes.

PlayQueueRemove

2019 · 47 minutes · FLAC

The poster, and its own seven

The one surface a theme does not own outright: there is a picture under it. The sleeve is a fixture with its dominant colour stated — the tint below is that one number carried onto this theme's ground, because what crosses into the arithmetic from an album is never an image.

poster.ground
poster.title
15.9:1
poster.body
7.4:1
poster.quiet
4.1:1
poster.edge
poster.danger
6.0:1
poster.rim
wash_over(#b4532e)

The vocabulary

Twenty-eight, and what each one decides

A theme may state all of them or three of them. Every row says which it was, because "a file with two colours in it gets a whole coherent scheme" is either visible here or it is marketing — clear a row and watch what the rest of the palette does.

Surfaces

Three planes and the lines between them. Elevation is a relationship, not a scheme: raised sits above content sits above chrome, in a light theme as well as a dark one.

  • backgroundstated

    The extreme the scheme is built on, and the seed every plane is blended from. Not a plane itself — in a dark scheme it is plane.chrome, in a light one it is plane.raised, and in a theme that states its planes outright it is neither.

  • plane.chromederived

    The frame: sidebar, player bar, the space the card floats in.

  • plane.contentderived

    The card the library is drawn on.

  • plane.raisedderived

    Anything sitting on the card — a popover, a group box, a menu.

  • rule.surfacederived

    The hairline between two surfaces. Harmony draws exactly one itself: the card's edge.

  • rule.rowderived

    The line between two rows, which is not the line between two surfaces: it repeats thirty times down a screen, and at the weight of a panel edge it turns a track list into a spreadsheet.

Ink

Two tiers of type, and the one exception. Every wash in the scheme is a weight of ink.body, which is why it is the token to get right first.

  • ink.bodystated

    Body text, and the colour every wash in the scheme is a weight of.

  • ink.quietstated

    The second tier: a duration, a track count, a caption.

  • ink.on_accentstated

    What is legible on top of accent — the label on a primary button, not the text on a selected row. A selected row is a surface step, so ordinary body ink is correct on it by construction.

States

Four fills, all of them steps off the plane rather than hues. A saturated colour behind a two-line row is a poster, not an interface.

  • state.selectedderivedor a weight

    A row under the pointer, or selected in a list that is not focused.

  • state.queuedderivedor a weight

    The run of rows the listener queued by hand. Weaker than everything else on a row, because it groups rather than states.

  • state.chosenderivedor a weight

    The chosen segment of a segmented control.

  • state.activederivedor a weight

    The fill on a selected row in the list that has focus. A surface, not a hue.

Chips

A button in its three states, and the label on it. The ladder has to climb — a hover that is fainter than rest reads as a button going out.

  • chip.restderivedor a weight

    A button at rest.

  • chip.hoverderivedor a weight

    A button under the pointer.

  • chip.pressedderivedor a weight

    A button being pressed.

  • chip.inkderived

    The label on one.

Signals

Four colours spent on marks: a tick, a focus ring, the caret, a control that is on. None of them is ever a surface.

  • accentstated

    The theme's own colour, spent on marks rather than on surfaces. It is not the fill on a selected row — that is state.active, which stays a step off the plane whatever hue the theme carries.

  • dangerstated

    Destructive.

  • warningstated

    Something needs attention.

  • successstated

    Something went right.

Poster

The one surface a theme does not own outright. A poster is drawn over an album sleeve, so its seven are the scheme as it survives having a picture underneath it.

  • poster.groundstated

    The poster card, and what its picture fades into.

  • poster.titlestated

    The one thing on a poster at full strength.

  • poster.bodystatedor a weight

    The sentence under the title.

  • poster.quietstatedor a weight

    The footer, and the line under the title.

  • poster.edgestatedor a weight

    A pill's outline, and the edge of a field.

  • poster.dangerstated

    The one destructive pill.

  • poster.rimstatedor a weight

    A hairline around the whole card, where the card needs one. Transparent means it does not.