Theming
JBrowse extends
MUI theming with custom
palette properties, set via the configuration.theme field. For an end-user
walkthrough of colors, dark mode, the logo, and sizing, see the
Coloring/theming config guide.
Built-in palettes
default- config-supplied colors merged with the stock defaultsstock- the stock JBrowse paletteminimal- greyscale chrome
Light and dark are not palettes but a mode each of these resolves along, so a
palette states its colors once and, where a brand cannot survive the flip, a
dark delta for the slots that change. minimal is the only built-in needing
one, a lighter primary.
A user picks a palette and a mode separately in the Preferences dialog. Read
session.themeName for the palette, session.themeMode for the raw choice
(light, dark or system) and session.effectiveThemeMode for that choice
with system resolved against prefers-color-scheme. session.themeIsDark
answers off the resolved palette, so a palette pinned to one mode answers for
itself. setThemeMode moves the mode without touching the palette.
The names from before the axis — lightStock, darkStock, lightMinimal,
darkMinimal — still resolve to the palette and mode they meant, wherever one
is stored or passed.
Custom palette properties
The custom palette properties extend MUI's standard
primary/secondary/error/etc. Every key below is optional in a config
theme; anything you don't set keeps its preset value.
| Key | Type | Used for |
|---|---|---|
stopCodon | string | Stop codon in gene/CDS tracks |
startCodon | string | Start codon in gene/CDS tracks |
codonNonsynonymous | string | MAF codon view: the species' amino acid differs from the reference |
codonSynonymous | string | MAF codon view: the codon differs but the amino acid does not |
codonStop | string | MAF codon view: a stop the reference codon is not |
coverage | string | Coverage histogram fill |
insertion | string | Insertion markers in alignments |
softclip | string | Soft-clipped bases (clipped bases retained in the read) |
skip | string | Skipped regions, such as introns in RNA-seq reads |
hardclip | string | Hard-clipped bases (clipped bases removed from the read) |
deletion | string | Deletion markers in alignments |
mafGap | string | MAF alignment-gap cells, where a species has no base |
readOverlap | string | Span where two segments of one molecule both align (view-as-pairs / chains) |
modificationFwd | string | Base modifications on the forward strand |
modificationRev | string | Base modifications on the reverse strand |
mutedSnpBase | string | SNP bases muted when show-modifications coloring is on |
missingData | string | MAF bridged-row fill where a species has no alignment |
gridlineMinor | string | Minor vertical gridlines behind the genome |
gridlineMajor | string | Major vertical gridlines behind the genome |
plotGridlineMinor | string | Minor coordinate gridlines inside a plot area, e.g. the dotplot's. Lighter than the genome gridlines above: a 2D grid crosses itself, so it lays down far more ink at the same alpha than one running behind a linear genome |
plotGridlineMajor | string | Major coordinate gridlines inside a plot area. See plotGridlineMinor |
regionBoundary | string | Line marking a chromosome or region boundary, well above both plot gridline weights: it is the landmark the coordinates hang off, so it has to stay readable as a boundary on a plot that also draws a full grid |
regionSeparator | string | Opaque bar between two displayed regions of a linear genome view. Opaque because it paints over track data on both sides and has to mask it |
tableBorder | string | Cell and header rules in JBrowse's own tables, e.g. the faceted track selector |
featureHover | string | Hover shading over a single feature |
featureHoverStrong | string | Hover shading over a feature group, e.g. a linked-read chain |
featureSelected | string | Border accent around the click-selected feature |
featureDescription | string | Feature description labels, e.g. gene descriptions |
featureConnector | string | Intron lines, strand chevrons and strand arrows in feature tracks |
accent | string | The primary color where it marks something on the page's own ground, such as a checked box or a selected row. primary.main in light mode, and the secondary text color in dark mode, where a midnight primary vanishes |
tertiary | PaletteColor | Accordion headers and some toolbar chrome |
quaternary | PaletteColor | Secondary floating-action-button background |
highlight | PaletteColor | Selection highlights |
textHighlight | PaletteColor | Text-match highlight behind search hits |
bases | object | Per-base colors for sequence and SNP rendering |
bases.A | PaletteColor | Adenine |
bases.C | PaletteColor | Cytosine |
bases.G | PaletteColor | Guanine |
bases.T | PaletteColor | Thymine |
bases.N | PaletteColor | N / ambiguous base |
frames | Frames | Reading-frame coloring outside CDS, indexed 1..3 and -1..-3 |
framesCDS | Frames | Reading-frame coloring within CDS, indexed 1..3 and -1..-3 |
alignmentFill | AlignmentFill | Read fill by pair orientation, when coloring alignments by pair |
The frames / framesCDS tuples are indexed by reading frame — 1/2/3
forward and -1/-2/-3 reverse, which is why slot 0 is unused.
Defaults for the string-valued feature colors, generated from the
#color-tagged definitions in packages/core/src/ui/palette.ts (the
insertion/softclip/hardclip indicators are tagged under a separate
alignments-indicators group):
| Color | Name | Value | Description |
|---|---|---|---|
| Feature (default) | goldenrod | A feature with no color of its own — no color slot, no BED itemRgb | |
| UTR (default) | #357089 | The untranslated ends of a gene glyph when no utrColor slot is set | |
| Stop codon | #e22 | Stop codon in gene/CDS tracks | |
| Start codon | #3e3 | Start codon in gene/CDS tracks | |
| Deletion | #808080 | Deletion markers in alignments | |
| Skip (intron) | #009a8a | Skipped regions such as introns in RNA-seq reads | |
| Base modification (fwd) | #c8c8c8 | Base modifications on the forward strand | |
| Base modification (rev) | #c8dcc8 | Base modifications on the reverse strand | |
| Muted SNP base | #888 | SNP bases muted when show-modifications coloring is on |
Exported color constants
A few colors are plain const strings outside the palette. The methylation
colors are the worked case: the RPC worker packs them to ABGR per modified base
and returns them inside its vertex data, and the legend on the main thread
labels those same pixels.
Where the color is applied decides which mechanism it uses. modificationFwd
and modificationRev sit right beside these and are palette members, because
the renderer sets them as shader uniforms, so a theme switch recomputes a getter
and redraws. A color the worker has already baked into vertex data would need a
theme switch to invalidate the alignments fetch, so it stays a fixed const.
Import them from @jbrowse/core/ui/palette, which has no toolkit in its module
graph, or from @jbrowse/core/ui/theme, which re-exports the same values
alongside Material UI.
| Color | Name | Value | Description |
|---|---|---|---|
| methylated5mC | #ff0000 | 5-methylcytosine, methylated | |
| unmethylated5mC | #0000ff | 5-methylcytosine, unmethylated | |
| methylated5hmC | #ffc0cb | 5-hydroxymethylcytosine, methylated |
The palette has no such key, so the worker, the legend and an SVG export all read the same constant.
Example config
{
"configuration": {
"theme": {
"palette": {
"primary": { "main": "#311b92" },
"secondary": { "main": "#0097a7" },
"tertiary": { "main": "#f57c00" },
"quaternary": { "main": "#d4ac0d" }
}
}
}
}primary/secondary/tertiary/quaternary/highlight accept either a full
MUI PaletteColorOptions object or just { "main": "<hex>" }. Light/dark
variants are derived automatically.
Reading colors from a display
session.palette and session.theme are both on the session and both resolve
from the same resolvePalette call, so they can't disagree. They are for
different consumers, and one of them is the rendering input:
session.palette(JBrowsePalette) holds the colors rendering reads. Plain color strings, no toolkit, serializable — so it crosses the RPC boundary as itself and works with no browser at all.session.themeis the resolved MUITheme, for components that are MUI.
Derive a display's colors in a model getter over session.palette, and read
that getter from renderState or whatever you hand the renderer. MAF's is the
worked case:
get colorPalette(): MafColorPalette {
return getMafColorPalette(getPaletteHost(self).palette)
},Do not stage them in a volatile that a React useEffect pushes in with a
setColorPalette action. The effect only runs on mount, and two consumers have
no component at all — SVG export and the RPC worker — so both would see a null
palette and render blank. As a getter the value is always present, and MobX
recomputes it only when the theme changes.
SVG export deliberately overrides the palette with the export theme, so the export path resolves its own palette instead of reading the session's.
Adding theme colors in plugins
Colors the main thread applies, whether in a React component or as a shader
uniform the renderer sets, belong in the Palette / PaletteOptions module
augmentation. Follow the existing modificationFwd / modificationRev pattern:
- Declare the field on
StringColorsinpalette.ts. - Tag it with
#color <group> | <label> | <description>so it surfaces as a swatch row in these guides. - Give it a value in
lightStringColors, plusdarkStringColorsif dark mode needs a different one — aPartial<StringColors>overlay on the light set rather than a second full table.
A color a worker bakes into its output goes the other way: declare it as a plain
const in palette.ts and leave it off StringColors, for the reason in
Exported color constants. Worker code imports those
from @jbrowse/core/ui/palette, which keeps Material UI out of its bundle.
See also
- Config guide: coloring/theming
- Developer guide: Writing a plugin