Skip to main content
  1. Index

Theming

Many applications aim to provide multiple themes, especially light and dark modes to support user preferences. GoJS provides functionality to define and manage themes to achieve this goal.

Getting started with themes

Various GoJS templates are themed, such as the default node, group and link template, tool adornments, background grid, and more. This makes it easy to quickly change the way certain objects appear. For example, you can change the selection adornment color/thickness without providing a Part.selectionAdornmentTemplate, or change the temporary link color when drawing a new link without providing a LinkingBaseTool.temporaryLink.

The default theme objects group properties into category objects by property type. The category for a given binding is inferred from the target property. For example, Shape.fill and Shape.stroke are grouped in the colors object, while Shape.strokeWidth is grouped in numbers. The predefined templates and tool archetypes use the following categories:

Category Used for Example keys
colors brush-valued properties such as Shape.fill and Shape.stroke selection, tempLink, link, text
fonts font strings for TextBlock.font normal, bold
numbers numeric properties such as Shape.strokeWidth selection, group
margins Margin-valued properties such as Panel.padding group
arrowheads arrowhead names for Shape.toArrow and Shape.fromArrow toArrow

For a complete list of themed properties on predefined templates, see Templates.js in the extensionsJSM directory.

Basic theming

The simplest way to theme your diagram is to use the predefined Themes available and call GraphObject.theme or create a new ThemeBinding when constructing templates. By default, both a light and a dark theme are provided in the ThemeManager. These are the Themes.Light and Themes.Dark objects, respectively.

To change themes, simply set ThemeManager.currentTheme to a theme name. Note that the special value 'system' will pick either the 'light' or 'dark' theme depending on the end user's browser preference.

Creating or modifying themes

In most scenarios, you'll want custom themes, either by modifying the predefined themes or creating your own. This can be done by calling ThemeManager.set, passing a theme name and a partial (or complete) Theme object. Passing an empty string as the theme name will modify the ThemeManager.defaultTheme, which is initially 'light'.

If the theme name exists in the ThemeManager.themeMap, that theme will be updated by merging the partial theme object into it. If the theme name does not exist, the theme will be added to the theme map.

Using CSS variables for theming

If you're using CSS variables to style other parts of your application, you can use ThemeManager.readsCssVariables to reuse those variables in your GoJS themes.

NOTE: The syntax to reference a CSS variable in a theme is 'var(<varname>)'. Only a single variable may be referenced, and any fallbacks should be defined either on the template or in the referenced CSS variable. The CSS variable's value will be read before any Binding.themeConverter functions have run.

In some cases, your CSS variables may already handle light and dark mode. If that's the case, you have the option to use a single theme which references those variables. Rather than changing the theme, you'll update your page as normal and call ThemeManager.updateDiagrams, reflecting any changes in CSS variables in the ThemeManager's associated diagrams.

When using a single theme, you'll need to make sure you define any properties used by default templates such as colors.selection or colors.link if you haven't overridden those templates.

Theme binding sources

The typical case for theming a GraphObject will be getting a value directly from a Theme. It is also possible to use values from other sources, such as a bound data object, a GraphObject in the binding Panel, or the shared model data object.

These different sources are specified by calling GraphObject.themeData, GraphObject.themeObject, or GraphObject.themeModel. In addition to specifying the source, the Binding.converter function can be used to convert from some value to a theme property name. In the following example, a themeObject binding is used on the node's text to get a color variable from the theme when the node is selected:

Converting theme values

In addition to a conversion function to determine the theme property name, a Binding.themeConverter can be provided as the fifth argument to GraphObject.themeData to perform a conversion on the resulting theme value before assigning it to the target property.

Other themable types

Discussion on this page has focused on colors, but theming can also be used for fonts, stroke widths, sizes, or any other property type. You must ensure that the returned theme value matches the type of the target property.

To access an arbitrary property value in your theme, you can use a '.' separated path, like 'colors.primary' or 'icons.mode'.

Theming builder objects

To keep the builder objects ("Button", "ToolTip", "ContextMenu", etc) simple, they are not themed by default.

Creating themed versions of these objects is relatively simple given the predefined definitions available at Buttons.js. Here we demonstrate theming the "Button" and "ToolTip" builders.

See the learn pages on buttons, tooltips, and context menus to change appearances without theming.