# frozen_string_literal: true module Ariadne # Simple toggle switch with on/off state. The logic is controlled by toggleable_controller and styles applied through # tailwind's group+data attributes: https://tailwindcss.com/docs/hover-focus-and-other-states#data-attributes class ToggleComponent < Ariadne::Component DEFAULT_TAG = :div DEFAULT_STATUS_LABEL_POSITION = :start STATUS_LABEL_POSITION_MAPPINGS = { start: "ariadne-flex-row", end: "ariadne-flex-row-reverse", }.freeze STATUS_LABEL_POSITION_OPTIONS = STATUS_LABEL_POSITION_MAPPINGS.keys.freeze DEFAULT_SIZE = :md THUMB_SIZE_MAPPINGS = { sm: "ariadne-translate-x-0 ariadne-h-3 ariadne-w-3 group-aria-checked/toggle:ariadne-translate-x-3", md: "ariadne-translate-x-0 ariadne-h-5 ariadne-w-5 group-aria-checked/toggle:ariadne-translate-x-5" }.freeze TRACK_SIZE_MAPPINGS = { sm: "ariadne-h-2 ariadne-w-4", md: "ariadne-h-4 ariadne-w-9" }.freeze BUTTON_SIZE_MAPPINGS = { sm: "ariadne-h-3 ariadne-w-6", md: "ariadne-h-5 ariadne-w-10" }.freeze LABEL_SIZE_MAPPINGS = { sm: "ariadne-text-xs", md: "ariadne-text-lg" }.freeze SIZE_OPTIONS = THUMB_SIZE_MAPPINGS.keys.freeze DEFAULT_CLASSES = { wrapper: "ariadne-group/wrapper data-[disabled=true]:ariadne-opacity-50 data-[disabled=true]:ariadne-cursor-auto", button: "ariadne-flex ariadne-justify-center ariadne-group/toggle ariadne-relative ariadne-inline-flex ariadne-flex-shrink-0 group-data-[disabled=false]/wrapper:ariadne-cursor-pointer ariadne-items-center ariadne-justify-center ariadne-rounded-full ariadne-focus:outline-none ariadne-focus:ring-2 ariadne-focus:ring-indigo-600 ariadne-focus:ring-offset-2 disabled:ariadne-cursor-auto", } DEFAULT_ATTRIBUTES = { wrapper: {}.freeze, button: { role: "switch", "data-controller": "toggleable", "data-toggleable-synced-attrs-value": '["aria-checked"]', "data-action": "click->toggleable#toggle", }, }.freeze DEFAULT_TRACK_COLOR = :indigo TRACK_COLOR_MAPPINGS = { white: "group-aria-checked/toggle:ariadne-bg-white", green: "group-aria-checked/toggle:ariadne-bg-green-600", blue: "group-aria-checked/toggle:ariadne-bg-blue-600", billy_purple: "group-aria-checked/toggle:ariadne-bg-billy-purple", indigo: "group-aria-checked/toggle:ariadne-bg-indigo-600", } TRACK_COLOR_OPTIONS = TRACK_COLOR_MAPPINGS.keys.freeze # @example Default # # <%= render(Ariadne::ToggleComponent.new) { "Example" } %> # # @param classes [String] <%= link_to_classes_docs %> # @param color [String] <%= link_to_classes_docs %> # @param checked [Boolean] <%= link_to_classes_docs %> # @param disabled [Boolean] <%= link_to_classes_docs %> # @param size [String] <%= link_to_classes_docs %> # @param label [String] <%= link_to_classes_docs %> # @param status_label_position [String] <%= link_to_classes_docs %> # @param attributes [Hash] <%= link_to_attributes_docs %> def initialize( classes: nil, checked: false, disabled: false, size: DEFAULT_SIZE, color: DEFAULT_TRACK_COLOR, status_label_position: DEFAULT_STATUS_LABEL_POSITION, attributes: {} ) @tag = DEFAULT_TAG @size = fetch_or_raise(SIZE_OPTIONS, size) @status_label_position = fetch_or_raise(STATUS_LABEL_POSITION_OPTIONS, status_label_position) @color = fetch_or_raise(TRACK_COLOR_OPTIONS, color) @classes = merge_class_names(DEFAULT_CLASSES[:wrapper], classes) @checked = checked @disabled = disabled @attributes = DEFAULT_ATTRIBUTES[:wrapper].merge({ "data-label-position": @status_label_position, "data-disabled": @disabled }).merge(attributes) @label_classes = merge_class_names(STATUS_LABEL_POSITION_MAPPINGS.fetch(@status_label_position), LABEL_SIZE_MAPPINGS.fetch(@size)) @button_classes = merge_class_names(DEFAULT_CLASSES[:button], BUTTON_SIZE_MAPPINGS.fetch(@size)) @button_attributes = DEFAULT_ATTRIBUTES[:button].merge({ "aria-checked": @checked, "data-toggleable-state-value": @checked, disabled: @disabled }) @thumb_classes = THUMB_SIZE_MAPPINGS.fetch(@size) @track_classes = merge_class_names(TRACK_SIZE_MAPPINGS.fetch(@size), TRACK_COLOR_MAPPINGS.fetch(@color)) end def on? @checked end def disabled? @disabled end end end