Theming
TL;DR: 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 themes
Set configuration.theme to one of these names:
default- uses config-supplied colors merged with stock defaultslightStock- light mode with stock JBrowse palettelightMinimal- light mode with greyscale chromedarkStock- dark mode with stock palettedarkMinimal- dark mode with greyscale chrome
Custom palette properties
These 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 codon |
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 |
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 |
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 |
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 rather than palette members. 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 is what 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
is fixed instead.
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 carries 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) is what 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, which is why the export path resolves its own rather than 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.