This guide will help you prepare a Data Center app for correct rendering in dark theme.
Theming in Data Center products is supported with the help of design tokens. Design tokens are CSS variables that represent design decisions like elevation, spacing, or — most importantly for the current purpose — colors.
Learn more about design tokens
Currently, Bitbucket 8.16 is the first and only publicly available Data Center product with full support for light and dark themes.
Support for the new themes in the first Early Access Program (EAP) releases of Jira Software 10.0 and Jira Service Management 6.0 is only partially implemented and theme switching is hidden behind a feature flag. However, we still encourage you to follow the instructions in this guide to prepare your Data Center app for the upcoming changes.
We're also working on bringing support for light and dark themes to Confluence 9.0 and Bamboo 10.0.
We assume that:
Here are some topics relevant to theming in Atlassian products. The section describing what themes should your app support is essential. You can skip the others on first reading.
Products will allow switching between three themes: Original, Light, and Dark.
Original theme has the same colors as before the conversion. Teams may want to continue to use this as they wait for all apps in their environment to transition to the design token themes. Additionally, some users are resistant to change, and this option will ease the pain of the transition. As a transitional measure, original theme will be removed at some point after the release of theming.
Light and Dark themes use design tokens. In fact, any given place uses a particular token that has one value in the Light theme and another value in the Dark theme.
The theme switcher will have the fourth option — Match system. It will enable either Light or Dark theme depending on the user’s browser reports.
Let’s consider an example:
CSS | JavaScript |
---|---|
|
|
In this example, --ds-text
and 'color.text'
represent the same token. Learn more about available tokens
Neutral1000
from the Atlassian color palette.DarkNeutral900
.black
) will be used.In short, Data Center products include the Atlassian User Interface library (AUI) which provides the CSS variable definitions for each token.
In general, the details shouldn’t matter to an app developer. What matters is that you define your UI’s colors in terms of the design tokens and have escape hatches to handle more involved scenarios. Loading the correct theme will be handled by the product.
However, if your app can be run in a standalone mode for testing, independent of a product, you might want to implement a theme switcher inside this mode.
If this is the case, you’ll have to decide which path to follow:
setGlobalTheme
from the @atlaskit/tokens
library.setGlobalTheme
for switching between Light and Dark themes.data-theme
and data-color-mode
attributes from the html
element.In Jira Software 10.0, theme switching is hidden behind the com.atlassian.jira.theme.switcher
feature flag.
Sometimes your code will need to apply different styles, most commonly, it occurs when there are two different images that represent the same thing (for example, a screenshot of a particular piece of functionality).
It's best to build for whole color modes (light
or dark
) rather than specific themes, because there can be multiple themes per color mode.
Check the data-color-mode
attribute on the html
element.
CSS | JavaScript |
---|---|
|
|
In some cases, you might also want to check the specific theme being rendered to cater for it. The data-theme
attribute on the html
element can be used. Learn more about the HTML API
In certain cases — for example, when rendering something on a Canvas or replacing an image rendered with JavaScript — you might need to track when a theme is changed.
To do this, use ThemeMutationObserver
as in this example:
1 2import { ThemeMutationObserver } from '@atlaskit/tokens'; const observer = new ThemeMutationObserver((newTheme) => { console.log(newTheme.colorMode); }); observer.observe(); observer.disconnect();
Learn more about the ThemeMutationObserver function
The process of adapting your app to Dark theme looks like this:
Depending on your app’s functionality, some steps won’t be applicable, or there might be more steps in your specific case. We trust your judgment.
Add the library to your project:
1 2npm install @atlaskit/tokens
You can skip this step if your app’s colors are defined only in CSS files. In this case, you’ll use only the direct var(--ds-text, black)
form, which doesn’t require installing the package.
If you include any Atlaskit components, make sure they are on a version published in October 2022 or later.
If you bundle any AUI components, make sure the AUI version is 9.9.0 or later. Otherwise you can use the version provided by the products (web-resource).
Each color that your app defines should have one of these forms:
var(<CSS syntax>, <fallback>)
form:1 2.info-field { color: var(--ds-text, black); }
token('<JavaScript syntax>', <fallback>)
form:1 2// Make sure you import the token function import { token } from '@atlaskit/tokens'; const infoField = css({ color: token('color.text', 'black') });
Learn more about available tokens
While it is possible to use the CSS syntax in JavaScript files (for example, const infoField = css({ color: 'var(--ds-text, black)' })
), the token()
form is preferred because it warns you if a non-existent token is passed in and gracefully handles version mismatches between @atlaskit/tokens
and AUI.
To kick-start the process, we suggest using the codemods. Learn more about the @atlaskit/codemod-cli
package
The package is a general one for all our codemod needs, but the two specific presets (css-to-design-tokens
and theme-to-design-tokens
) apply to the dark theme migration. They search for hard-coded colors and replace them with token-using expressions.
The replacements are done in place, overwriting the original files. We assume you store your app’s code in a version control system and thus can see the modifications easily and revert them if needed.
Run these commands in your app’s folder:
1 2# process the CSS-syntax files npx @atlaskit/codemod-cli -n css-to-design-tokens -e css,scss,less . # process the JavaScript-syntax files npx @atlaskit/codemod-cli -n theme-to-design-tokens -p tsx -e ts,tsx,js,jsx .
Don’t blindly trust the codemods! Some heuristics are applied to come up with the suggestions, but they don’t have enough context to be correct every time. The following are some traps to watch for.
There are tokens that have the same value but different names (for example, --ds-text
and --ds-icon-warning-inverse
are both Neutral1000
in the Light theme). Pick the one that most closely matches the intended use. When in doubt, use the Token picker. Refer to the available tokens page
What if there’s no proper token for the intended meaning?
The codemod treats any objects in JavaScript as potentially CSS-in-JS. If you have objects that happen to have CSS-like properties, such as { color: 'red' }
, but those aren’t actually passed to a CSS-in-JS compiler, the codemod will still convert the color expressions. You should revert those changes.
In rare cases, the codemod script won’t be able to propose any substitution and will put the "MISSING_TOKEN"
value in the code. In those places, you should pick the right replacement value. The Token picker can also help to make the decision.
If your app uses images, you should do some work for them to look well in both themes. Depending on the image type, the approach will differ. The following approaches are the most common ones.
Icons implemented as an icon font most likely won’t require rework. Probably, they already have associated CSS rules that are covered before in the “Migrate your app colors” step.
If you define inline SVG images in JSX files, they will also be effectively handled during the color migration. SVG images that are styled with CSS don't require rework either, because the CSS declarations are changed by codemods.
Images (PNG, JPG, SVG, and other types) stored as files are more difficult. For each of these images, you can pick an option:
Use the colors that fit the current theme. You can find more information in the "Background: What is the current theme?" section.
Use your regular procedures for testing visual changes. We assume that you’re using a version of our products with support for theming, which provide a UI toggle to switch between themes.
For example, here's what switching between themes looks like in Bitbucket Data Center:
For all the replaced colors, navigate to the corresponding pages and check if they look fine in all three themes: Original, Light, and Dark.
The following sections include specific suggestions for testing your changes.
The REST API that theme switcher uses under the hood can be reused. See the Atlassian Theme REST API
Use a browser extension (like axe DevTools) to check color contrast. If you notice an issue, make sure the replaced color is semantically correct for the place. If it is, let us know, and we will try to fix it. For details on how to contact us, check out the Get help section.
If you use AUI, you might want to use the testing theme. Check out the AUI dark theme documentation
You can enable it in the console of your browser’s developer tools, and it will replace all design tokens with a single color, making everything that’s not using them stand out. This can catch the cases that the codemods missed.
For better maintainability of your app, add these lint rules into your project to warn about colors that aren’t using a token form:
Now that your app supports theming:
If you have questions or need help, contact us at The Atlassian Developer Community.
Make sure to include the tag design-tokens
.
We’ll do our best to refine the solution based on your feedback.
Rate this page: