Theme Switcher

Pick a color palette and light/dark mode. Persists in localStorage. You'll see it live in the top-right of this page.

Installation

bin/rails g shadcnrb:component theme_switcher

Usage

Put sui.theme_class on <html> so the server renders the saved choice, then place the switcher anywhere. The choice lives in the shadcnrb_theme and shadcnrb_mode cookies.

# In your layout — the saved theme is rendered, nothing flashes
<html class="<%= sui.theme_class %>">

# Anywhere in your UI
<%= sui.theme_switcher %>

Try it

The switcher in the header above is live. Change the theme, reload the page — your choice persists. Dark mode toggles independently.

<%= sui.theme_switcher %>

How it works

Each theme is a CSS class like .sui-theme-blue that overrides --color-primary / --color-primary-foreground / --color-ring on <html>. Dark mode is the same mechanism, just a .dark class. The two combine: <html class="sui-theme-blue dark"> gives you blue-accented dark. Because every component uses semantic tokens (no inline bg-blue-500), components pick up the new values automatically.

Shipped themes

  • default — neutral zinc (the base palette)
  • blue
  • green
  • rose
  • violet
  • orange

All six ship in app/assets/tailwind/shadcnrb_themes.css, which application.css pulls in via @import "./shadcnrb_themes.css". Don't want presets? Delete the import line and ship only the neutral palette.

Adding your own theme

  1. Open app/assets/tailwind/shadcnrb_themes.css.
  2. Add a .sui-theme-<name> rule and a .dark.sui-theme-<name> pair.
  3. Pass the name to the switcher via themes: — or skip that and use the class directly.
/* app/assets/tailwind/shadcnrb_themes.css */
.sui-theme-brand {
  --color-primary: oklch(0.6 0.2 320);
  --color-primary-foreground: oklch(0.985 0 0);
  --color-ring: oklch(0.6 0.2 320);
}
.dark.sui-theme-brand {
  --color-primary: oklch(0.75 0.18 320);
  --color-primary-foreground: oklch(0.145 0 0);
  --color-ring: oklch(0.75 0.18 320);
}
<%= sui.theme_switcher themes: %w[default blue green brand] %>

Themes only override --color-primary, --color-primary-foreground, and --color-ring. Keep it to those three so backgrounds/borders stay neutral and theme swaps don't touch surface colors. If you want broader recolors, edit the base application.css tokens instead.

Persisting on the server

The cookie is the default store. To keep the choice with the user's account, pass the stored value to the helper and listen for the change event — see State persistence.

API

MethodArgsDescription
theme_switcherthemes:, **optsDropdown with theme swatches + light/dark toggle
theme_classtheme:, mode:Classes for <html> from the theme and mode cookies (sui-theme-blue dark). Arguments win over the cookies; nil falls through.