import { ArgTypes, Story, Canvas, Meta } from '@storybook/addon-docs/blocks';
import * as ThemeStories from './Theme.stories';
import { stackblitzPrefillConfig } from '../../../previewer/codePreviewer';

<Meta isTemplate />

# Theme

[Source code](https://github.com/carbon-design-system/carbon/tree/main/packages/react/src/components/Theme)

{/* prettier-ignore-start */}

{/* <!-- START doctoc generated TOC please keep comment here to allow auto update --> <!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --> */}

## Table of Contents

- [Overview](#overview)
- [Setting the global theme](#setting-the-global-theme)
- [Setting an inline theme](#setting-an-inline-theme)
- [Getting the current theme in a component](#getting-the-current-theme-in-a-component)
- [Component API](#component-api)
  - [Theme as](#theme-as)
- [Feedback](#feedback)

{/* <!-- END doctoc generated TOC please keep comment here to allow auto update --> */}

{/* prettier-ignore-end */}

## Overview

The `GlobalTheme` and `Theme` components allow you to specify the theme for a
page, or for a part of a page, respectively. `Theme` is most often used to
implement inline theming where you can style a portion of your page with a
particular theme.

In order for the styles of `Theme` to be correctly applied in your project, you
need to make sure that you have included `@carbon/react/scss/zone` in your Sass
files by writing:

```scss
@use '@carbon/react/scss/zone';
```

You also get this file when you import `@carbon/react` directly in your Sass.

<Canvas
  of={ThemeStories.Default}
  additionalActions={[
    {
      title: 'Open in Stackblitz',
      onClick: () => stackblitzPrefillConfig(ThemeStories.Default),
    },
  ]}
/>

## Setting the global theme

To the set the theme for your entire project, the `GlobalTheme` component can be
used.

Please note that in contrast to `Theme` this does not apply any styles on its
own but rather sets the context's theme according to the value you pass to its
`theme` prop.

This is due to the various options of applying global css custom properties
which differ from application to application. Depending on your architecture you
may want to apply a class to the `<body>` or add a custom data attribute to your
`<html>` element:

```jsx
import { useEffect } from 'react';
import { GlobalTheme } from '@carbon/react';

function App() {
  const theme = 'g100'; // ← your implementation, e.g. fetching user settings

  useEffect(() => {
    document.documentElement.dataset.carbonTheme = theme;
  }, [theme]);

  return (
    <GlobalTheme theme={theme}>
      <YourApp />
    </GlobalTheme>;
  );
}
```

```scss
@use '@carbon/styles/scss/theme';
@use '@carbon/styles/scss/themes';

:root[data-carbon-theme='g10'] {
  @include theme.theme(themes.$g10);
}

:root[data-carbon-theme='g100'] {
  @include theme.theme(themes.$g100);
}
```

This way, the `GlobalTheme` component is used to "synchronize" the state of the
application's context and your scss, so that other components and hooks like
useTheme can work properly. For this reason, the component should be used as a
wrapper of the root of your application.

By default, the global theme is set to `white`.

## Setting an inline theme

Use the `Theme` component to set an inline theme for a part of the UI in your
project. All components that you render as `children` of `Theme` will now use
the design token values from that theme.

```jsx
import { Theme } from '@carbon/react';

function ExamplePage() {
  return (
    <GlobalTheme theme="white">
      <h1>Page title</h1>
      <p>Display in the white theme</p>
      <Theme theme="g100">
        <p>Display in the g100 theme</p>
      </Theme>
    <GlobalTheme>
  );
}
```

<Canvas of={ThemeStories.Default} />

## Getting the current theme in a component

The `useTheme` hook provides the current theme for a component. This can be
helpful if you need to conditionally render items based on the current theme.

```jsx
import { useTheme } from '@carbon/react';

function ExampleComponent() {
  const { theme } = useTheme();

  // Use the current theme in your component
}
```

<Canvas of={ThemeStories.UseTheme} />

## Component API

<ArgTypes />

### Theme as

You can configure the base element rendered by `Theme` using the `as` prop. For
example, if you would like the `Theme` component to render as a `section` you
could write the following:

```jsx
<Theme as="section" theme="g100">
  <ChildComponent />
</Theme>
```

Similarly, you can provide any custom component to the `as` prop which the
`Theme` component will use.

## Feedback

Help us improve this component by providing feedback, asking questions on Slack,
or updating this file on
[GitHub](https://github.com/carbon-design-system/carbon/edit/main/packages/carbon-react/src/components/Theme/Theme.mdx).
