Skip to main content

Theming

In this guide you will learn about theming in JUI. You will read about what a theme is, how to create and provide it, and how to use it to created your own themed components.

Theme

Styling in JUI is implemented with styled-components, and it requires an object of type Theme to be provided by styled-component's theme context. Theme class implements the interface for accessing common colors, resolving theme values, icons, etc.

ThemeProvider

Similar to styled-component's ThemeProvider, provides ThemeContext. With a few additions and nuances:

  • It also provides the default font styles (overridable via props), as well as a minimal normalization style on body. Global styles can be disabled via ThemeProviderProps#globalStyles, if needed.
  • Unlike styled-component's ThemeProvider, it doesn't merge nested themes, into a plain object. That's important, because a theme must be an instance of Theme class.

Creating a theme

Use Theme constructor to create a theme object:

import { Theme } from "@intellij-platform/core";
import darculaThemeJson from "@intellij-platform/core/themes/darcula.theme.json";

const theme = new Theme(darculaThemeJson);

Theme json

The only required arguments for creating a Theme is a plain theme object of type ThemeJson, which is usually imported from a .theme.json file. The following .theme.json files from Intellij Community are available out of the box:

You can also find many theme plugins, each containing a .theme.json file.

Nord theme example

In the example below, nord.theme.json from Nord theme's github repo is fetched and used:

Result
Loading...
Live Editor

IconResolver

Theme depends on an IconResolver implementation for resolving svg icons. By default GithubIconResolver is used, which fetches icons from Intellij Community repo. An alternative implementation can be passed to the iconResolver argument in Theme's constructor:

import { Theme, IconResolver } from "@intellij-platform/core";

class MyIconResolver implements IconResolver {
//...
}
const theme = new Theme(themeJson, new MyIconResolver());

Operating system

Properties in ThemeJson can have os-dependent values. See selectionBackground in darcula theme as an example. In order to resolve os-dependent values, a theme needs to know what the current operating system is. While the default value is detected based on the window.navigator, you can override that and set the value in Theme's constructor:

const theme = new Theme(
themeJson,
undefined /* going with the default icon resolver */,
"windows"
);

Theming your own components

Resolving values

🚧 TODO: explain .color() and more generic .value() methods. 🚧

Fallback when resolving values

🚧 TODO: explain star fallback and difference with fallback argument. 🚧

Accessing theme in components

The best way to use theme in styling your own components is to use styled components:

import { styled } from "@intellij-platform/core";

const MyComponent = styled`
background: ${({ theme }) => theme.color("Panel.background")};
`;

You can also use styled-component API for getting the theme without styled components:

import { useTheme } from "@intellij-platform/core";

function MyComponent() {
const theme = useTheme();
// ...
}
types

In order to get the right type for theme in your styled components, import styled, css or useTheme, etc. from @intellij-platform/core, instead of styled-components. They are the same as the ones from styled-components, only with the adjusted theme type. If you wish to import from styled-components, you need to create a declarations file to extend styled-component's DefaultTheme.