diff --git a/lib/phlexy_ui/theme_controller.rb b/lib/phlexy_ui/theme_controller.rb new file mode 100644 index 0000000..14a716d --- /dev/null +++ b/lib/phlexy_ui/theme_controller.rb @@ -0,0 +1,73 @@ +# frozen_string_literal: true + +module PhlexyUI + # @component html class="theme-controller" + # Theme controller changes the theme when checkbox/radio is checked + # Supports common patterns: swap, toggle, dropdown, radio buttons + class ThemeController < Base + register_modifiers( + # "sm:swap" + # "md:swap" + # "lg:swap" + swap: "swap", + # "sm:swap sm:swap-rotate" + # "md:swap md:swap-rotate" + # "lg:swap lg:swap-rotate" + swap_rotate: "swap swap-rotate", + # "sm:swap sm:swap-flip" + # "md:swap md:swap-flip" + # "lg:swap lg:swap-flip" + swap_flip: "swap swap-flip", + # "sm:toggle" + # "md:toggle" + # "lg:toggle" + toggle: "toggle" + ) + + def initialize(*, theme_value: nil, checked: false, as: :input, **) + super(*, **) + @theme_value = theme_value + @checked = checked + @as = as + end + + def view_template(&block) + input_classes = generate_classes!( + # "theme-controller" + component_html_class: :"theme-controller", + modifiers_map: {}, + base_modifiers: [], + options: {} + ) + + attrs = {type: :checkbox, class: input_classes} + attrs[:value] = theme_value if theme_value + attrs[:checked] = true if checked + attrs.merge!(options) + + if block + # If block given, wrap in label with modifier classes (swap, toggle, etc.) + wrapper_classes = generate_classes!( + component_html_class: nil, + modifiers_map: modifiers, + base_modifiers:, + options: {} + ) + + label(class: wrapper_classes) do + public_send(as, **attrs) + whitespace + block.call + whitespace + end + else + # Just render the input + public_send(as, **attrs) + end + end + + private + + attr_reader :theme_value, :checked + end +end diff --git a/spec/lib/phlexy_ui/theme_controller_spec.rb b/spec/lib/phlexy_ui/theme_controller_spec.rb new file mode 100644 index 0000000..dd6a446 --- /dev/null +++ b/spec/lib/phlexy_ui/theme_controller_spec.rb @@ -0,0 +1,74 @@ +require "spec_helper" + +describe PhlexyUI::ThemeController do + subject(:output) { render described_class.new } + + it "is expected to match the formatted HTML" do + expected_html = html <<~HTML + + HTML + + is_expected.to eq(expected_html) + end + + describe "with theme_value" do + subject(:output) do + render described_class.new(theme_value: "dark") + end + + it "renders with value attribute" do + expected_html = html <<~HTML + + HTML + + expect(output).to eq(expected_html) + end + end + + describe "with checked" do + subject(:output) do + render described_class.new(theme_value: "dark", checked: true) + end + + it "renders as checked" do + expected_html = html <<~HTML + + HTML + + expect(output).to eq(expected_html) + end + end + + describe "with block for swap pattern" do + subject(:output) do + render described_class.new(:swap_rotate, theme_value: "dark") do + "🌞 🌙" + end + end + + it "wraps in label with icons" do + expected_html = html <<~HTML + + HTML + + expect(output).to eq(expected_html) + end + end + + describe "data" do + subject(:output) do + render described_class.new(data: {foo: "bar"}) + end + + it "renders it correctly" do + expected_html = html <<~HTML + + HTML + + expect(output).to eq(expected_html) + end + end +end