Amplify UI

Dark Mode

Overview

Amplify UI supports color modes/schemes, like Dark Mode, through theme overrides. Amplify UI Theme Overrides let you define different theme styles in different contexts, such as color mode. You can also use plain CSS.

There are 2 ways to support light/dark mode in your application:

  1. Rely on the user's OS preference (System Preferences > General > Appearance in Mac)
  2. Place a control like a toggle button in your application that allows the user to switch color modes. With this option you could default to the OS preference or show 3 options: light, dark, system, like this site does.

Either of these approaches work with Amplify UI whether you are using the Theme Overrides or writing plain CSS.

ThemeProvider

colorMode

The ThemeProvider accepts a colorMode prop which can be light, dark, or system.

If you have multiple ThemeProviders in your application, make sure to store colorMode in the application's state or context and pass it to each ThemeProvider or else some parts of your app won't have the right color mode applied. Also, because the theme uses CSS variables which are inherited, your application can have some weird behavior with nested themes and color modes.

Multiple ThemeProviders should be avoided if possible because it is more efficient to use a selector override instead. This site uses nested ThemeProviders for demos.

Default Dark Mode

Amplify UI comes with a default dark mode that you can use.

Note: the Amplify UI theme and any overrides like dark mode are scoped to the ThemeProvider. Changing the color mode in the example will only affect the example code.

Current color mode: system

import * as React from 'react';
import {
  defaultDarkModeOverride,
  ThemeProvider,
  Card,
  Text,
  ToggleButton,
  ToggleButtonGroup,
} from '@aws-amplify/ui-react';

export const DefaultDarkMode = () => {
  const [colorMode, setColorMode] = React.useState('system');
  const theme = {
    name: 'my-theme',
    overrides: [defaultDarkModeOverride],
  };

  return (
    <ThemeProvider theme={theme} colorMode={colorMode}>
      <Card>
        <ToggleButtonGroup
          value={colorMode}
          isExclusive
          onChange={(value) => setColorMode(value)}
        >
          <ToggleButton value="light">Light</ToggleButton>
          <ToggleButton value="dark">Dark</ToggleButton>
          <ToggleButton value="system">System</ToggleButton>
        </ToggleButtonGroup>
        <Text>Current color mode: {colorMode}</Text>
      </Card>
    </ThemeProvider>
  );
};

Current color mode: system

import * as React from 'react';
import {
  defaultDarkModeOverride,
  ThemeProvider,
  ColorMode,
  Card,
  Text,
  ToggleButton,
  ToggleButtonGroup,
} from '@aws-amplify/ui-react';

export const DefaultDarkMode = () => {
  const [colorMode, setColorMode] = React.useState<ColorMode>('system');
  const theme = {
    name: 'my-theme',
    overrides: [defaultDarkModeOverride],
  };

  return (
    <ThemeProvider theme={theme} colorMode={colorMode}>
      <Card>
        <ToggleButtonGroup
          value={colorMode}
          isExclusive
          onChange={(value: ColorMode) => setColorMode(value)}
        >
          <ToggleButton value="light">Light</ToggleButton>
          <ToggleButton value="dark">Dark</ToggleButton>
          <ToggleButton value="system">System</ToggleButton>
        </ToggleButtonGroup>
        <Text>Current color mode: {colorMode}</Text>
      </Card>
    </ThemeProvider>
  );
};

System Dark Mode

If you don't want to provide a color mode control on your application, but still want to honor the user's operating system preference for color mode, you can set the colorMode on the ThemeProvider to system. Then use either the default dark mode override styling or provide your own.

Note: to see dark mode applied, change your OS preferences

Primary text

Secondary text

Tertiary text

import * as React from 'react';
import {
  defaultDarkModeOverride,
  ThemeProvider,
  Card,
  Text,
  Button,
} from '@aws-amplify/ui-react';

export const SystemDarkModeExample = () => {
  const theme = {
    name: 'my-theme',
    overrides: [defaultDarkModeOverride],
  };

  return (
    // Note: color mode overrides are scoped to the ThemeProvider
    // if you use multiple providers
    <ThemeProvider theme={theme} colorMode="system">
      <Card>
        <Button>Hello</Button>
        <Text variation="primary">Primary text</Text>
        <Text variation="secondary">Secondary text</Text>
        <Text variation="tertiary">Tertiary text</Text>
      </Card>
    </ThemeProvider>
  );
};

Custom dark mode

Current color mode: system

import * as React from 'react';
import {
  ThemeProvider,
  Card,
  Text,
  ToggleButton,
  ToggleButtonGroup,
} from '@aws-amplify/ui-react';

export const CustomDarkModeExample = () => {
  const [colorMode, setColorMode] = React.useState('system');
  const theme = {
    name: 'my-theme',
    overrides: [
      {
        colorMode: 'dark',
        tokens: {
          colors: {
            font: {
              primary: { value: '{colors.pink.100}' },
              secondary: { value: '{colors.pink.90}' },
              tertiary: { value: '{colors.pink.80}' },
            },
            background: {
              primary: { value: '{colors.purple.10}' },
              secondary: { value: '{colors.purple.20}' },
              tertiary: { value: '{colors.purple.40}' },
            },
            border: {
              primary: { value: '{colors.pink.60}' },
              secondary: { value: '{colors.pink.40}' },
              tertiary: { value: '{colors.pink.20}' },
            },
          },
        },
      },
    ],
  };

  return (
    // Note: color mode overrides are scoped to the ThemeProvider
    // if you use multiple providers
    <ThemeProvider theme={theme} colorMode={colorMode}>
      <Card>
        <ToggleButtonGroup
          value={colorMode}
          isExclusive
          onChange={(value) => setColorMode(value)}
        >
          <ToggleButton value="light">Light</ToggleButton>
          <ToggleButton value="dark">Dark</ToggleButton>
          <ToggleButton value="system">System</ToggleButton>
        </ToggleButtonGroup>
        <Text>Current color mode: {colorMode}</Text>
      </Card>
    </ThemeProvider>
  );
};

Current color mode: system

import * as React from 'react';
import {
  ThemeProvider,
  ColorMode,
  Card,
  Text,
  ToggleButton,
  ToggleButtonGroup,
  Theme,
} from '@aws-amplify/ui-react';

export const CustomDarkModeExample = () => {
  const [colorMode, setColorMode] = React.useState<ColorMode>('system');
  const theme: Theme = {
    name: 'my-theme',
    overrides: [
      {
        colorMode: 'dark',
        tokens: {
          colors: {
            font: {
              primary: { value: '{colors.pink.100}' },
              secondary: { value: '{colors.pink.90}' },
              tertiary: { value: '{colors.pink.80}' },
            },
            background: {
              primary: { value: '{colors.purple.10}' },
              secondary: { value: '{colors.purple.20}' },
              tertiary: { value: '{colors.purple.40}' },
            },
            border: {
              primary: { value: '{colors.pink.60}' },
              secondary: { value: '{colors.pink.40}' },
              tertiary: { value: '{colors.pink.20}' },
            },
          },
        },
      },
    ],
  };

  return (
    // Note: color mode overrides are scoped to the ThemeProvider
    // if you use multiple providers
    <ThemeProvider theme={theme} colorMode={colorMode}>
      <Card>
        <ToggleButtonGroup
          value={colorMode}
          isExclusive
          onChange={(value: ColorMode) => setColorMode(value)}
        >
          <ToggleButton value="light">Light</ToggleButton>
          <ToggleButton value="dark">Dark</ToggleButton>
          <ToggleButton value="system">System</ToggleButton>
        </ToggleButtonGroup>
        <Text>Current color mode: {colorMode}</Text>
      </Card>
    </ThemeProvider>
  );
};

CSS

You can also write CSS variables directly to support color modes. If you are using the colorMode prop in the ThemeProvider, you can write CSS like this to support dark mode:

/* The prefers-color-scheme media query detects the system setting */
@media (prefers-color-scheme: dark) {
  [data-amplify-color-mode='system'] {
    --amplify-colors-background-primary: black;
  }
}

[data-amplify-color-mode='dark'] {
  --amplify-colors-background-primary: black;
}

Amplify open source software, documentation and community are supported by Amazon Web Services.

© 2024 Amazon Web Services, Inc. and its affiliates. All rights reserved. View the site terms and privacy policy.

Flutter and the related logo are trademarks of Google LLC. We are not endorsed by or affiliated with Google LLC.