Skip to Content

ThemeProvider

ThemeProvider must be used as an ancestor of all iTwinUI components. It provides theming and other necessary information to all components within the tree.

<ThemeProvider>
<>{/* Your components go here. */}</>
</ThemeProvider>

It is important to note that this component is not just a context provider, but also renders an actual DOM element. This is necessary for the theme to be scoped within the tree.

Theming

The theme prop can be set to either "light" or "dark". This will automatically and performantly update the theme for the entire tree, by changing the values of CSS variables.

<ThemeProvider theme='dark'>…</ThemeProvider>

This theme affects all components that use iTwinUI’s CSS variables, including custom components and components from other packages.

If you want to set the theme based on the user’s operating system, you can use the "os" value. This relies on the prefers-color-scheme query to be executed within client-side JavaScript, so it may cause a flash of incorrect theme when using server-side rendering.

<ThemeProvider theme='os'>…</ThemeProvider>

If a theme value is not specified, it will default to "inherit", which will inherit the theme from its ancestors and fall back to "light".

High contrast mode

To enable higher contrast versions of light and dark themes, themeOptions.highContrast can be used. By default, the prefers-contrast query will be used to automatically enable high contrast themes if the user has a specified a preference for it in their operating system.

<ThemeProvider
theme='dark'
themeOptions={{
highContrast: true,
}}
/>

Background

By default, only the topmost ThemeProvider in the tree will set the background-color to var(--iui-color-background-backdrop), which is the recommended value for page background.

If you want to explicitly control whether or not the background is applied, you can override this behavior using themeOptions.applyBackground.

  • If false, the background will not be applied even if this is the topmost ThemeProvider in the tree.
  • If true, the background will be applied even if this is not the topmost ThemeProvider in the tree.
<ThemeProvider
themeOptions={{
applyBackground: false, // or true
}}
/>

Scoping and nesting

By default, ThemeProvider will only apply its theme to its descendants, i.e. components outside of the provider’s subtree will not be affected.

This is useful if you want to have multiple themes in your application, or if you want to use iTwinUI for only a portion of your application.

ThemeProviders can also be nested if you want to use a different theme for a portion of your application.

<ThemeProvider theme='light'>
<Text>Uses light theme!</Text>
<ThemeProvider theme='dark'>
<Text>Uses dark theme!</Text>
</ThemeProvider>
</ThemeProvider>

Inheritance

When using theme="inherit" (which is also the default value), ThemeProvider will inherit the theme from its ancestors, e.g. from the nearest ThemeProvider higher up in the tree.

The inherited theme can also come from an older version of iTwinUI or from standalone usage of variables. If no parent theme is found, it will fall back to "light".

This behavior is useful for packages that want to use iTwinUI components but don’t want to force a theme on their users. The application using the package can then wrap its entire tree in a ThemeProvider to apply a theme, which will be inherited by the package’s components.

const PackageComponent = () => {
return (
<ThemeProvider>
<Text>Uses theme from application!</Text>
</ThemeProvider>
);
};
const Application = () => {
return (
<ThemeProvider theme='dark'>
<PackageComponent />
</ThemeProvider>
);
};

Portals

By default, ThemeProvider will use an element at the end of <body> as the portal target for floating elements (e.g. Tooltip, Toast, DropdownMenu, Dialog, etc).

If you want to specify a different element as the portal target for all components within a tree, the portalContainer prop can be used.

When passing an element to this prop, it is recommended to use state. For example:

const [myPortal, setMyPortal] = React.useState(null);
<div ref={setMyPortal} />
<ThemeProvider portalContainer={myPortal}>
</ThemeProvider>

CSS

Starting with v3, applications are advised to manually import styles.css in their entrypoint:

import '@itwin/itwinui-react/styles.css';

This works well for applications that already use iTwinUI v3, but it can be tricky if the application is still using an older version of iTwinUI and wants to consume a package that uses v3.

To make this easier, ThemeProvider can automatically import styles.css if it is not already imported. By default, this is enabled when using theme='inherit'.

If you want to override this behavior, you can use the includeCss prop:

<ThemeProvider includeCss={false}>…</ThemeProvider>