# ThemeToggle

> Cherry ThemeToggle component - a pill-shaped sun and moon switch for light and dark mode.

Source: https://cherry.al/code/theme-toggle

> For the complete documentation index, see [llms.txt](https://cherry.al/llms.txt).

# ThemeToggle

<iframe className="light-only" src="https://demo.cherry.al/preview/theme-toggle?theme=light" title="Theme toggle" loading="lazy" style={{ width: "100%", height: "320px", border: "1px solid var(--color-grayLight)", borderRadius: "12px" }} />
<iframe className="dark-only" src="https://demo.cherry.al/preview/theme-toggle?theme=dark" title="Theme toggle" loading="lazy" style={{ width: "100%", height: "320px", border: "1px solid var(--color-grayLight)", borderRadius: "12px" }} />

The ThemeToggle is a pill-shaped switch for light and dark mode. It shows a sun and a moon side by side, with a soft circular highlight that slides over the active icon when the theme changes.

ThemeToggle works with the providers described on the [Dark Mode](/code/dark-mode) page.

It works out of the box inside `CherryThemeProvider` or `ClientThemeProvider`: clicking it flips the current theme, persists the choice (to the `theme` cookie and `localStorage` under `ClientThemeProvider`, to `localStorage` under `CherryThemeProvider`), and keeps the `dark` class on the `<html>` element in sync. No wiring is needed. See [Dark Mode](/code/dark-mode) for the flash-free SSR setup.

Keep in mind that the `<button>` element inherently includes native browser properties like `onClick`. Cherry UI components introduce custom properties that always begin with a `$` to distinguish them from native props.

```jsx
import React from "react";
import { ThemeToggle } from "cherry-styled-components";

export default function Page() {
  return <ThemeToggle />;
}
```

A custom `onClick` runs after the theme switch, which is handy for analytics:

```html
<ThemeToggle onClick={() => trackEvent("theme toggled")} />
```

Hide it (for example while the theme is still resolving on the server) with the `$hidden` prop:

```html
<ThemeToggle $hidden={!mounted} />
```

## Keyboard Shortcut

Bind the <kbd>Command</kbd> + <kbd>Shift</kbd> + <kbd>L</kbd> (<kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>L</kbd> on Windows) shortcut with the `$shortcut` prop. While the toggle is mounted, pressing it flips the theme without a click:

```html
<ThemeToggle $shortcut />
```

The shortcut listens on `window`, is removed when the toggle unmounts, and calls the same `toggleTheme` as a click, so the choice is persisted the same way. It requires Shift and ignores Alt so it stays clear of the browser's Cmd/Ctrl+L address-bar shortcut. Like clicking, it does nothing until a `themeDark` is passed to the provider.

<Callout type="note">
  ThemeToggle requires a `themeDark` to be passed to the theme provider. Without
  it there is nothing to switch to, and clicking the button does nothing.
</Callout>

## Properties

<Field value="$hidden" type="boolean">
  Hides the toggle with `display: none`, for example while the theme is still
  resolving on the server.
</Field>

<Field value="$shortcut" type="boolean">
  Binds the <kbd>Command</kbd> + <kbd>Shift</kbd> + <kbd>L</kbd> (<kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>L</kbd> on Windows) keyboard
  shortcut while the toggle is mounted, flipping the theme without a click. Off
  by default.
</Field>

<Button href="https://github.com/cherry-design-system/styled-components/blob/main/src/lib/theme-toggle.tsx" icon="code" iconPosition="left">
  View Source
</Button>
