# frozen_string_literal: true # A button/link can have the following settings: # style: primary/secondary/ternary # size: :xs :sm, :md, :lg class Avo::ButtonComponent < ViewComponent::Base def initialize(path = nil, size: :md, style: :outline, color: :gray, icon: nil, icon_class: "", is_link: false, rounded: true, compact: false, **args) # Main settings @size = size @style = style @color = color # Other things that appear in the button @path = path @icon = icon @icon_class = icon_class @rounded = rounded @compact = compact # Other settings @class = args[:class] @is_link = is_link @args = args || {} end def args if @args[:spinner] @args[:"data-controller"] = "loading-button" end @args[:class] = button_classes @args end def button_classes classes = "button-component inline-flex flex-grow-0 items-center text-sm font-semibold leading-6 fill-current whitespace-nowrap transition duration-100 transform transition duration-100 cursor-pointer disabled:cursor-not-allowed disabled:opacity-30 border justify-center active:outline active:outline-1 #{@class}" classes += " rounded" if @rounded.present? classes += style_classes classes += @compact ? " px-1" : " px-4" # Same horizontal padding on all sizes classes += spacing_classes classes end def is_link? @is_link end def full_content result = "" icon_classes = @icon_class icon_classes += full_content_icon_classes result += helpers.svg(@icon, class: icon_classes) if @icon.present? result += " " if content.present? result += "#{content}" end result.html_safe end def output if is_link? output_link else output_button end end def output_link link_to @path, **args do full_content end end def output_button if @args[:method].present? button_to @args[:url], **args do full_content end else button_tag(**args) do full_content end end end private def spacing_classes case @size.to_sym when :xs " py-0" when :sm " py-1" when :md " py-2" when :lg " py-3" else "" end end def style_classes case @style when :primary " bg-primary-500 text-white border-primary-500 hover:bg-primary-600 hover:border-primary-600 active:border-primary-700 active:outline-primary-700 active:bg-primary-600" when :outline " bg-white text-#{@color}-500 border-#{@color}-500 hover:bg-#{@color}-100 active:bg-#{@color}-100 active:border-#{@color}-500 active:outline-#{@color}-500" else "" end end def full_content_icon_classes icon_classes = "" case @size when :xs icon_classes += " h-4" # When icon is solo we need to add an offset icon_classes += " my-1" if content.blank? when :sm icon_classes += " h-4" # When icon is solo we need to add an offset icon_classes += " my-1" if content.blank? when :md icon_classes += " h-5" # When icon is solo we need to add an offset icon_classes += " my-0.5" if content.blank? when :lg icon_classes += " h-6" end icon_classes end end