Icon Theme Toggle
Animate between sun and moon icons while changing the UI theme.
Preview
Examples
Theme transition
A slide transition declared on this control. Duration is 500 milliseconds. Other controls keep their own settings.
Shadow borders
Use a prominent ambient shadow and inset edge in place of a solid border.
Slide icons
Sun and moon exchange places with a short sideways movement.
Blur icons
A brief blur and crossfade joins the two states.
When to use
- Use a compact light/dark action in a header or toolbar.
- Use a short icon animation to make the changed state clear.
When not to use
- People need to choose the system preference. Use Theme Switcher or Theme Selector.
- The control changes a palette. Use Color Theme Selector.
Installation
Set up uitheme-web in an existing Tailwind app. Then install the component.
The CLI copies Icon Theme Toggle and its Theme Toggle dependency. Both reuse the shared cn utility.
Usage
Use the control inside your theme provider. Import it from your app’s component directory.
API reference
These props belong to the installed control. Its page transition settings override the provider for this action only.
| Prop | Type | Behavior |
|---|---|---|
label | string | Override the readable accessible label. |
borderStyle | 'solid' | 'shadow' | Use the default solid border or prominent shadow borders. Both use the same space and theme tokens. |
class | string | Extend the root styles. Your classes replace default classes through the local merge helper. |
classes | object | Style the root and trigger parts. |
disabled | boolean | Disable interaction. Preference controls also wait for the provider to mount. |
animationType | ThemeAnimationType | Override the UI theme transition for this control. Defaults to the provider setting. |
duration | number | UI theme transition duration in milliseconds. Defaults to the provider setting. |
slideDirection | SlideDirection | Valid only with animationType set to ThemeAnimationType.SLIDE. Other animation types do not accept this prop. |
effect | 'rotate' | 'slide' | 'blur' | Icon motion only. Defaults to rotate and is separate from the page transition. |
Keyboard
| Key | Action |
|---|---|
| Enter / Space | Toggle the resolved light/dark theme. Keyboard activation changes state without icon movement. |
Accessibility
- Keep the accessible label when changing the visible content. Icons are decorative.
- The control stays disabled until the theme provider mounts.
- Reduced motion removes travel and rotation. Icon state keeps a short opacity change. The selection surface changes position without travel.
- Keyboard activation changes the theme without the pointer animation.
Theme behavior
The sun represents resolved light mode. The moon represents resolved dark mode. Activation replaces a system preference with the opposite resolved theme. The clicked button sets the page transition origin.
AI Agent notes
- Use
uitheme-web/reactfor React oruitheme-web/vuefor Vue. Keep the theme provider around the control. - Keep page transitions in the control’s
animationTypeanddurationprops. Do not add a standalone transition-settings control. - Keep input labels, focus styles, selected state, disabled state, and reduced-motion behavior when editing source.
- Use the shared theme tokens. Do not hardcode a palette or radius.
Source
The CLI reuses your shared cn utility. If it is missing, installation creates it
at the configured utils path. Existing utilities are checked before a replacement
is offered.
These are the files the CLI installs. The control installs one main component file.
Dependencies: @lucide/vue
Customization
Use borderStyle="shadow" in React or border-style="shadow" in Vue for prominent shadow borders. The default is solid.
Use slideDirection only when animationType is ThemeAnimationType.SLIDE. Set both props on the control when you need a slide direction override.
Use effect="rotate" (default), effect="slide", or effect="blur" for the icon exchange. Icon motion lasts 200ms and retargets from its current state on another pointer activation. Use animationType, duration, and slideDirection for the separate UI theme transition. Use native button props, label, and classes to customize the control.

