Colors & Palettes
Diagrammo has a small, closed set of named colors — red, orange, yellow, green, blue, purple, teal, cyan, plus the neutrals gray, black, and white. Use them anywhere an element takes a color. There is no way to add a twelfth name; crimson, navy, and #3b6ea5 are all rejected on an element. Hex appears in one place only: a custom palette, which redefines what the eleven names look like (see Your own palette).
The actual shade is resolved from the active palette, so the same blue looks different in Slate than in Nord — but it’s always that palette’s considered version of the hue, never a clashing primary. black and white are theme-relative: each palette picks near-darkest / near-lightest values that stay distinct from the canvas, which means black is the strongest mark you can make on a light theme and nearly invisible on a dark one. white is the exact reverse. Neither is a fixed ink.
Where the palette comes from
The first palette source that is set wins:
- An override where the diagram is shown. On the command line this is
--palette <name>. In code it is thepaletteOverrideoption ofrender(). - The file’s own
paletteline. Most files have none. - The host’s default — the palette the page, plugin or tool asks for when it draws.
- Slate, when nothing else is set.
Whichever palette wins, each of the eleven names then resolves to that palette’s hex value, in light or dark.
The palettes that ship are slate (the default), nord, atlas, blueprint, catppuccin, tidewater, and tokyo-night. Exporting diagrams covers --palette together with the light, dark and transparent theme.
The palette line
A file can name its palette on a line of its own. The usual place is the bottom of the file, but any line works:
// a built-in, in the reader's own light or dark
palette nord
Add dark or light to pin the diagram to one mode: palette nord dark.
The line is the same on every chart type, and it never becomes a node or a row. It is lowercase only: Palette 70 stays a data row. An unknown name draws the diagram in the next source down, with a warning on that line.
In the desktop app
The app follows the same order, with Settings (⌘ + ,) as the host’s default: Editor palette for the preview, Export palette for exports. A file’s own palette line beats both. With palette nord, the preview and every export draw in Nord whatever Settings says, and the preview pane takes Nord’s background. The rest of the app keeps the Settings palette. A file with no palette line draws in Settings’ palette. A share link keeps the file’s line in the copy it sends, so the author’s choice travels with the diagram.
Choosing a color
Naming a color is easy. Deciding which one is the actual work, and the answer is almost always about how hard you want an element to push.
What advances, what recedes
Every palette is tuned so no series shouts, so the differences are smaller than in a raw RGB set — but they are consistent, and they are theme-dependent:
grayis the recede color, in every palette and both themes. It carries the least color of any hue name — measurably so; in every shipped palette, in both themes,grayis the lowest-saturation entry of the eight hues plus itself. That is why it recedes: it has no hue competing for attention, so it reads as context rather than as a category. It is not necessarily the palest color; Nord’s lightgrayis quite dark. Gray means “still here, not the point.”blue,purple, andredadvance on a light theme. In every shipped palette, the strongest-contrasting non-neutral against a light canvas is one of these three. If one element must be read first, it belongs on one of them.yellowis the weakest color on a light theme and one of the strongest on a dark one. In nearly every palette,yellowhas the lowest contrast against a light canvas of any non-neutral, and the highest against a dark one.redruns the opposite way — solid on light, and the weakest non-neutral on dark in nearly every palette. Never put your most important series onyellowif the chart might be exported light, or onredif it might be exported dark — and re-check any color-carried emphasis after switching themes, because the ranking genuinely changes.orange,green,teal, andcyanare the middle. Reliable for categories that need to be told apart, unreliable for “look here first.”
What gray is for
gray is the background voice. Use it for the elements a chart needs in order to be honest but doesn’t want to argue about:
- the comparison baseline — last year’s line, the control group, the plan you’re measuring against
- the residual bucket — “Other”, “Uncategorized”, everything below the fold
- the parts of a structure that provide context rather than carrying the message
Doing this deliberately is the single highest-leverage color decision available, because it is what makes everything else look emphasized without you having to shout.
Building emphasis
Emphasis is contrast within one chart, so it has to come from the per-element channel:
A tag group is the general-purpose tool: declare the group once, then attach a value to each element. It maps meaning to color across the whole chart and adds a labeled legend, so the emphasis is explained rather than merely applied. Where a chart type takes a bare color token on an element or a series, that works too and is quicker; tag groups are the form that works nearly everywhere. See How DGMO thinks for where each form applies.
One caution: color is a scarce resource and emphasis spends it. If three of five elements are “emphasized”, none of them are.
The limit you will hit
fill-tint, fill-solid, and fill-outline are chart-wide — they set the fill treatment for the entire diagram, not per element. That makes them a tone control, not an emphasis control. You cannot solid-fill one bar and outline the rest, so the thing emphasis actually requires — contrast within a single chart — is not available from the fill family. Build emphasis from color choice and tag groups instead.
For genuine emphasis — pushing one element back without recoloring it — two chart types ship a dim / highlight directive that fades everything else while preserving each element’s own hue (a red flow that recedes is still red). sankey has both dim <name> and highlight <name>; family has highlight <name>, which dims everyone outside one person’s bloodline. Both bake into the exported image — no hover needed. On every other chart type there is no de-emphasis directive yet, so “recede” there still means assigning gray.
Accessibility
Treat color as a secondary channel, never the only one. Palettes are tuned for a single perceived weight, which is good for looking calm and bad for telling hues apart under color-vision deficiency — blue and purple in particular sit close in hue and separate weakly under deuteranopia, and tinted fills push them closer still.
The rule that follows, stated for family and true everywhere: the legend, not the hue, is the guaranteed channel, because its entries carry text. So when accessibility matters:
- Carry the distinction on a tag group, which produces labeled legend entries, rather than on bare color tokens which may not.
- Separate important categories by lightness as well as hue — pair a light-theme strong color (
blue,purple,red) againstgray, notblueagainstteal. - Keep the number of color-carried categories small. Beyond a handful, no palette separates reliably for anyone.
- Check the chart in both light and dark, since the contrast ranking flips between them.
Your own palette
You can’t add a color name, but you can change what the eleven names look like. A custom palette gives each name its own hex value, plus twelve role colors — the canvas, the panels, the text and the accents around the shapes. There are two ways to bring one in.
In the file: an embedded palette block
Write palette and a name of your own, then an indented block. This file carries a warm light palette called Harbor:
bar Cargo by Hold
Rum 320
Silk 210
Spice 180
palette Harbor
light
bg #fbf8f1
surface #f2ede1
overlay #ebe4d4
border #d9cfba
text #2b2620
text-muted #6b6152
text-on-fill-light #ffffff
text-on-fill-dark #2b2620
primary #2f5d7c
secondary #6b6152
accent #2f7a6d
destructive #a8432f
colors
red #a8432f
orange #b8682a
yellow #a88420
green #4f7d3e
blue #2f5d7c
purple #6a4f8a
teal #2f7a6d
cyan #3a7f9e
gray #8a8170
black #2b2620
white #f2ede1The rules the block must follow:
- Sections.
light,dark, or both. A block with one section draws in that mode only. - Role keys. Each section needs all twelve:
bg surface overlay border text text-muted text-on-fill-light text-on-fill-dark primary secondary accent destructive. - Colors. A
colorssection needs all eleven names. A twelfth name is refused. - Hex only. This block is the one place DGMO accepts hex.
- Readable labels. Text on a tinted fill needs a contrast ratio of at least 4.5:1. Text on a solid fill has a floor too.
blackandwhiteare exempt. - A name of your own. You can’t reuse a built-in name such as
nord.
A block that breaks a rule is not an error. The diagram draws in the next source down, and a warning names the line at fault. The palette belongs to that file alone: it is never added to anyone’s list of palettes.
In the desktop app: the theme folder
The desktop app reads custom palettes from a theme folder, one .json file per palette:
| System | Folder |
|---|---|
| macOS | ~/.diagrammo/themes |
| Linux | ~/.config/diagrammo/themes (or $XDG_CONFIG_HOME/diagrammo/themes) |
| Windows | %APPDATA%\diagrammo\themes |
Create the folder if it is not there. A file holds an id, a name, and a block of colors per mode. The keys are the role keys in camel case (textMuted, textOnFillLight), plus colors. This is Harbor again, as a light-only theme file:
{
"id": "harbor",
"name": "Harbor",
"mode": "light",
"light": {
"bg": "#fbf8f1", "surface": "#f2ede1", "overlay": "#ebe4d4", "border": "#d9cfba",
"text": "#2b2620", "textMuted": "#6b6152",
"textOnFillLight": "#ffffff", "textOnFillDark": "#2b2620",
"primary": "#2f5d7c", "secondary": "#6b6152", "accent": "#2f7a6d", "destructive": "#a8432f",
"colors": {
"red": "#a8432f", "orange": "#b8682a", "yellow": "#a88420", "green": "#4f7d3e",
"blue": "#2f5d7c", "purple": "#6a4f8a", "teal": "#2f7a6d", "cyan": "#3a7f9e",
"gray": "#8a8170", "black": "#2b2620", "white": "#f2ede1"
}
}
}
To cover both modes, leave out mode and give a light and a dark block. The rules are the same as for an embedded block, and the id can’t be a built-in name.
- It shows up live. The app watches the folder. A saved file appears in Settings → Editor palette, under Your themes. A sun or moon beside it marks a one-mode palette, which is listed only while the app is in that mode.
- Open folder sits beside the Your themes heading once one theme has loaded.
- A broken file is named. Settings says which file was not used and why. If the file loaded before, the app keeps showing your last good version.
- Desktop only. The web editor can’t read a folder on your computer, so it has no theme folder.
Named Colors
Every name, shown across the palettes that ship:
| Name | Slate | Nord | Atlas | Blueprint | Catppuccin | Tidewater | Tokyo Night |
|---|---|---|---|---|---|---|---|
red | |||||||
orange | |||||||
yellow | |||||||
green | |||||||
blue | |||||||
purple | |||||||
teal | |||||||
cyan | |||||||
gray | |||||||
black | |||||||
white |