Class: Daisy::Actions::ThemeControllerComponent

Inherits:
LocoMotion::BaseComponent show all
Defined in:
app/components/daisy/actions/theme_controller_component.rb

Overview

The ThemeController is the foundation for theme switching. For a complete, ready-made switcher, use the #build_switcher_dropdown builder; to build a custom switcher, compose the lower-level builders (#build_theme_preview, #build_radio_input) yourself. Either way it wires up the loco-theme Stimulus controller for you.

Constant Summary collapse

SOME_THEMES =

Default list of themes to display in the controller

%w[light dark synthwave retro cyberpunk wireframe].freeze

Constants inherited from LocoMotion::BaseComponent

LocoMotion::BaseComponent::EMPTY_PART_IGNORED_TAGS, LocoMotion::BaseComponent::SELF_CLOSING_TAGS

Instance Attribute Summary collapse

Attributes inherited from LocoMotion::BaseComponent

#config, #loco_parent

Instance Method Summary collapse

Methods inherited from LocoMotion::BaseComponent

build, #component_ref, #config_option, #cssify, define_modifier, define_modifiers, define_part, define_parts, define_size, define_sizes, #empty_part_content, #inspect, #part, register_component_initializer, register_component_setup, #rendered_css, #rendered_data, #rendered_html, #rendered_stimulus_controllers, #rendered_tag_name, renders_many, renders_one, set_component_name, #set_loco_parent, #strip_spaces

Methods included from LocoMotion::Concerns::InspectableComponent

#build_inspect_string

Constructor Details

#initialize(**kws, &block) ⇒ ThemeControllerComponent

Creates a new instance of the ThemeControllerComponent.

Parameters:

  • kws (Hash) —

    The keyword arguments for the component.

Options Hash (**kws):

  • themes (Array<String>) —

    List of DaisyUI theme names to include in the controller. Defaults to SOME_THEMES.



38
39
40
41
42
# File 'app/components/daisy/actions/theme_controller_component.rb', line 38

def initialize(**kws, &block)
  super

  @themes = config_option(:themes, SOME_THEMES)
end

Instance Attribute Details

#themes ⇒ Array<String> (readonly)

Returns The DaisyUI theme names available in this controller.

Returns:

  • (Array<String>) —

    The DaisyUI theme names available in this controller.



28
29
30
# File 'app/components/daisy/actions/theme_controller_component.rb', line 28

def themes
  @themes
end

Instance Method Details

#before_render ⇒ Object

Sets up the component with theme Stimulus controller.



47
48
49
# File 'app/components/daisy/actions/theme_controller_component.rb', line 47

def before_render
  add_stimulus_controller(:component, "loco-theme")
end

#build_night_toggle(title: "Night mode", name: "theme-night", css: "") ⇒ String

Builder method that renders a "Night mode" toggle wired to the loco-theme controller. Checking it pins the dark scheme — the saved night theme applies immediately, letting users try night mode without touching their OS settings — and unchecking pins light. Either direction is an explicit choice, so it leaves system mode. The toggle's checked state tracks the scheme actually showing, so it reads correctly in system mode too.

Parameters:

  • title (String) (defaults to: "Night mode") —

    The label text shown after the toggle. Defaults to "Night mode".

  • name (String) (defaults to: "theme-night") —

    The name (and default id) for the toggle's checkbox. Defaults to "theme-night".

  • css (String) (defaults to: "") —

    Extra CSS classes for the toggle input. Defaults to "".

Returns:

  • (String) —

    The rendered toggle.



223
224
225
226
227
228
229
# File 'app/components/daisy/actions/theme_controller_component.rb', line 223

def build_night_toggle(title: "Night mode", name: "theme-night", css: "")
  render(Daisy::DataInput::ToggleComponent.new(
           name: name, id: name, css: css, trailing: title,
           html: { data: { "loco-theme-night-toggle": true,
                           action: "change->loco-theme#toggleNightMode" } }
         ))
end

#build_radio_input(theme, scheme: nil, **options) {|radio| ... } ⇒ String

Builder method to create a radio input for use in selecting themes.

Parameters:

  • theme (String) —

    The name of the theme that the input controls.

  • scheme (Symbol, String, nil) (defaults to: nil) —

    Bind the radio to one preference slot (:light / :dark) for day / night picker UIs. Slot radios omit the theme-controller class (so a checked-but-inactive pick can't force its theme onto the page via DaisyUI's CSS) and sync their checked state to the slot's saved preference instead of the active theme. Defaults to nil.

  • options (Hash) —

    Additional options to pass to the component.

Yields:

  • (radio) —

    An optional block forwarded to the radio so you can fill its leading / trailing slots (e.g. drop a preview swatch or label inside the radio's label and make the whole row one clickable control).

Returns:

  • (String) —

    The rendered HTML for the radio input.



87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'app/components/daisy/actions/theme_controller_component.rb', line 87

def build_radio_input(theme, scheme: nil, **options, &block)
  # Scheme-scoped radios deliberately OMIT the `theme-controller`
  # class: DaisyUI's own CSS applies a theme whenever any checked
  # `.theme-controller` input carries its name, and a scheme picker's
  # radio stays checked even while the OTHER scheme is active — the
  # class would force its theme onto the page. The data attribute
  # tells the Stimulus controller to sync it to the scheme's saved
  # slot instead of the active theme.
  if scheme
    options[:html] = { data: { "loco-theme-scheme": scheme } }.deep_merge(options[:html] || {})
  else
    options[:css] = "#{options[:css]} theme-controller".lstrip
  end

  # Namespace the id by the input name so multiple theme controllers can
  # coexist on the same page without generating duplicate ids.
  name = options[:name] || "theme"
  default_options = { name: name, id: "#{name}-#{theme}", value: theme }

  render(Daisy::DataInput::RadioButtonComponent.new(**default_options.deep_merge(options)), &block)
end

#build_switcher_dropdown(icon: "swatch", label: nil, clear: false, scheme: nil, name: "theme", css: "dropdown-end") ⇒ String

Builder method that renders a complete, ready-to-use theme switcher dropdown: a trigger button and a menu with one row per theme (a color preview, the theme name, and a checkmark on the active theme), all wired to the loco-theme controller. Because it is rendered inside this component, it inherits the loco-theme Stimulus controller, so no extra setup is required.

Parameters:

  • icon (String) (defaults to: "swatch") —

    The icon name for the trigger button. Defaults to "swatch".

  • label (String, nil) (defaults to: nil) —

    Optional text shown beside the trigger icon. When omitted, the trigger is an icon-only circle button.

  • clear (Boolean) (defaults to: false) —

    Whether to append a "Clear Theme" row that resets to the default theme. Defaults to false.

  • scheme (Symbol, String, nil) (defaults to: nil) —

    Bind this dropdown to one preference slot (:light for the day slot, :dark for night), turning it into a "Day theme" / "Night theme" picker. Show ALL your themes in both pickers — either slot may hold any theme (some people prefer a dark theme during the day; the dark: variant follows the displayed theme's own scheme regardless). Picking applies immediately like any switcher and saves into the picker's slot; the checkmark tracks the slot's saved preference rather than the page's active theme. Pair two of these with #build_night_toggle and #build_system_toggle for a GitHub-style appearance picker. Defaults to nil (a classic switcher).

  • name (String) (defaults to: "theme") —

    The shared name for the theme radios. Defaults to "theme".

  • css (String) (defaults to: "dropdown-end") —

    Extra CSS classes for the dropdown (e.g. a placement modifier like "dropdown-end"). Defaults to "dropdown-end".

Returns:

  • (String) —

    The rendered dropdown.



184
185
186
187
188
189
190
191
192
193
194
195
196
197
# File 'app/components/daisy/actions/theme_controller_component.rb', line 184

def build_switcher_dropdown(icon: "swatch", label: nil, clear: false, scheme: nil, name: "theme", css: "dropdown-end")
  button_css = label ? "btn-ghost" : "btn-ghost btn-circle"

  render(Daisy::Actions::DropdownComponent.new(css: css)) do |dropdown|
    dropdown.with_button(icon: icon, title: label, css: button_css,
                         html: { title: "Switch theme", "aria-label": "Switch theme" })

    dropdown.with_item { clear_row(name) } if clear

    themes.each do |theme|
      dropdown.with_item { switcher_row(theme, name, scheme: scheme) }
    end
  end
end

#build_system_toggle(title: "Match system appearance", name: "theme-mode", css: "") ⇒ String

Builder method that renders a "Match system appearance" toggle wired to the loco-theme controller. Checking it enters system mode — the active theme follows the OS color scheme live, swapping between the saved light and dark preferences — and unchecking it pins the currently-visible scheme, so the page doesn't change when sync turns off. The controller keeps the toggle's checked state in sync with the saved mode across every switcher on the page.

Parameters:

  • title (String) (defaults to: "Match system appearance") —

    The label text shown after the toggle. Defaults to "Match system appearance".

  • name (String) (defaults to: "theme-mode") —

    The name (and default id) for the toggle's checkbox. Defaults to "theme-mode".

  • css (String) (defaults to: "") —

    Extra CSS classes for the toggle input. Defaults to "".

Returns:

  • (String) —

    The rendered toggle.



256
257
258
259
260
261
262
# File 'app/components/daisy/actions/theme_controller_component.rb', line 256

def build_system_toggle(title: "Match system appearance", name: "theme-mode", css: "")
  render(Daisy::DataInput::ToggleComponent.new(
           name: name, id: name, css: css, trailing: title,
           html: { data: { "loco-theme-mode-toggle": true,
                           action: "change->loco-theme#toggleSystemMode" } }
         ))
end

#build_theme_preview(theme, **options) ⇒ String

Builder method to create a theme preview showing the theme's colors in a 2x2 grid.

Parameters:

  • theme (String) —

    The theme name to preview.

  • options (Hash) —

    a customizable set of options

Options Hash (**options):

  • css (String) —

    Additional CSS classes.

Returns:

  • (String) —

    The rendered HTML for the theme preview.



119
120
121
122
123
124
# File 'app/components/daisy/actions/theme_controller_component.rb', line 119

def build_theme_preview(theme, **options)
  render Daisy::Actions::ThemePreviewComponent.new(
    theme: theme,
    **options
  )
end

#call ⇒ Object

Renders the component and its content.



54
55
56
# File 'app/components/daisy/actions/theme_controller_component.rb', line 54

def call
  part(:component) { content }
end