The Theme Controller component provides a plethora of pre-built sub-components that can be used to build a custom theme switcher.
The ThemeController component is a Builder component rather than
your standard Slotable ViewComponent.
This means that instead of the component providing slots, and handling where your custom components are inserted, the developer utilizes helper methods on the component to choose where the sub-components are rendered.
In the examples below, we use the HAML = syntax to output the rendered
sub-components, whereas typical components use the HAML - syntax to
"pass" the component to a slot.
To prevent a flash of content when the page loads with a non-default
theme, add = theme_preload_script to your layout's <head> section.
This inline script runs before the page renders to set the theme from
localStorage.
See GitHub Issue #49 and the ThemeHelper API Docs for more details.
One of the most basic sub-components is the theme preview icon. It shows a
visual representation of the theme using the base, primary,
secondary, and accent colors as little dots inside of a rounded
square.
= daisy_theme_controller do |theme_controller|
.flex.flex-col.sm:flex-row.gap-4.items-start.sm:items-center
- theme_controller.themes.each do |theme|
.flex.flex-row.gap-2.items-center
= theme_controller.build_theme_preview(theme)
= theme.humanize
When a theme radio input is selected, the page's theme will change to the value of the input.
You do not need to wire up any setTheme action. The
ThemeController automatically watches its inputs for change events,
saves the selection to localStorage, and keeps every other theme
selector on the page (including the header switcher) in sync.
We provide a custom name of docs-radio-theme so these inputs form
their own radio group, but selecting one still syncs everywhere.
build_radio_input accepts a block, which it forwards to the radio. That
lets you drop a preview swatch and label inside the radio's own label
(its end slot), so the whole row is a single clickable control — no
separate wrapping <label> needed.
= daisy_theme_controller do |theme_controller|
.flex.flex-col.gap-2.items-start
- theme_controller.themes.each do |theme|
= theme_controller.build_radio_input(theme, name: "docs-inline-theme") do |radio|
- radio.with_end do
= theme_controller.build_theme_preview(theme)
%span.capitalize= theme.humanize
build_switcher_dropdown renders a complete, working theme switcher in one
line — a trigger button plus a menu with a color preview, name, and a
checkmark on the active theme for every theme, all wired to the
loco-theme controller. Pass label:, icon:, clear:, or a placement
via css: to customize it. (Everything below is hand-rolled from the
sub-components for comparison.)
.flex.gap-6.items-start
= daisy_theme_controller(themes: %w[light dark synthwave retro]) do |theme_controller|
= theme_controller.build_switcher_dropdown(css: "dropdown-start", name: "docs-switcher")
= daisy_theme_controller(themes: %w[light dark synthwave retro]) do |theme_controller|
= theme_controller.build_switcher_dropdown(label: "Theme", clear: true, css: "dropdown-start", name: "docs-switcher-labeled")
You can also build a custom switcher by using all of the sub-components in combination.
Note that the daisy_theme_controller may need to be the parent of
your custom switcher to ensure that it appropriately sets up the
Stimulus controller.
In the example below, the dropdown doesn't render custom content when
using the with_item helper, so the Stimulus controller wouldn't be
applied if the order were switched.
= daisy_theme_controller do |tc|
= daisy_dropdown do |dropdown|
- dropdown.with_button(css: "btn-error", icon: "swatch", title: "Themes", right_icon: "chevron-down")
- tc.themes.each do |theme|
- dropdown.with_item do
= daisy_link(href: "#", css: "no-underline", html: { data: { action: "click->loco-theme#setTheme" } }) do
= tc.build_radio_input(theme, name: "docs-custom-theme", css: "hidden peer")
= tc.build_theme_preview(theme)
= theme.humanize
= hero_icon "check", css: "size-4 invisible peer-checked:visible"
Create virtual credit / debit cards to keep your real info safe.
Get $5 when you sign up — free to start!
Everything you need to grow your business with confidence!
CRM, Lead Generation, Project Management, Contracts, Online Payments, and more!
The ads above are affiliate links to products I regularly use and highly
recommend.
I may receive a commission if you decide to purchase.