Menu

Switch

render Switch.new

Installation

Add the component to your project

CLI

Run the following command in your terminal

bundle exec essence add switch
Manually

Add the following code and libraries into your project

components/switch.rb
# frozen_string_literal: true

# A switch component that can be toggled on and off.
#
# ==== Examples
#
#    render Switch.new
#
# ==== Documentation
#
# https://essence.primevise.com/components/switch
#
class Components::Switch < Components::Essence
  attr_reader :checked

  def initialize(checked: false, **attributes)
    @checked = checked
    super(**attributes)
  end

  def view_template(&)
    button(**attributes) do
      span(class: "sr-only") { "Use setting" }
      lever
      yield if block_given?
    end
  end

  def lever(**mattributes) = span(**m(**mattributes))
  def hidden_input(**mattributes) = input(**m(**mattributes))

  private

  def component_classes
    {
      _: {
        _: "relative inline-flex h-6 w-10 shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:ring-2 focus:ring-gray-950/5 focus:outline-hidden"
      },
      lever: {
        _: "pointer-events-none inline-block size-5 translate-x-0 transform rounded-full bg-white ring-0 transition duration-200 ease-in-out"
      }
    }.freeze
  end

  def component_attributes
    {
      _: {
        type: "button",
        role: "switch",
        aria_checked: false,
        data: {
          controller: "essence--switch",
          action: "click->essence--switch#toggle",
          essence__switch_checked_value: checked.to_s,
          essence__switch_active_class: "bg-emerald-500",
          essence__switch_inactive_class: "bg-gray-950/10",
          essence__switch_active_lever_class: "translate-x-4",
          essence__switch_inactive_lever_class: "translate-x-0"
        }
      },
      lever: {
        aria_hidden: "true",
        data: { essence__switch_target: "lever" }
      },
      hidden_input: {
        type: "hidden",
        name: "enabled",
        value: false,
        data: { essence__switch_target: "input" }

      }
    }.freeze
  end
end
essence/switch_controller.js
import { Controller } from "@hotwired/stimulus";

export default class extends Controller {
  static targets = ["input", "lever"];

  static classes = ["active", "inactive", "activeLever", "inactiveLever"];

  static values = {
    checked: {
      type: Boolean,
      default: false,
    },
  };

  toggle = () => (this.checkedValue = !this.checkedValue);

  checkedValueChanged(state, _) {
    this.element.ariaChecked = this.element.ariaChecked == state;
    if (this.hasInputTarget) this.inputTarget.value = state;

    this.element.classList.toggle(...this.activeClasses, state);
    this.element.classList.toggle(...this.inactiveClasses, !state);

    this.leverTarget.classList.toggle(...this.activeLeverClasses, state);
    this.leverTarget.classList.toggle(...this.inactiveLeverClasses, !state);
  }
}