diff --git a/Gemfile b/Gemfile index ea39aa78..41b2b41c 100644 --- a/Gemfile +++ b/Gemfile @@ -49,6 +49,8 @@ gem 'omniauth-rails_csrf_protection', '~> 1.0' gem 'cancancan', '~> 3.6' +gem 'view_component', '~> 3.13' + # Use Sass to process CSS # gem "sassc-rails" diff --git a/app/assets/stylesheets/components/_button_primary.css b/app/assets/stylesheets/components/_button_component.css similarity index 65% rename from app/assets/stylesheets/components/_button_primary.css rename to app/assets/stylesheets/components/_button_component.css index 2678c0ff..50c1fb9c 100644 --- a/app/assets/stylesheets/components/_button_primary.css +++ b/app/assets/stylesheets/components/_button_component.css @@ -1,11 +1,8 @@ -.button-primary { - background-color: var(--primary-600); - color: var(--primary-50); +.button { border-radius: var(--rounded-lg); letter-spacing: var(--spacing-lg); font-size: var(--text-sm); text-transform: uppercase; - border: none; font-weight: var(--font-bold); padding: var(--padding-xs) var(--padding-md); margin-bottom: var(--padding-md); @@ -13,7 +10,30 @@ align-items: center; } -.button-primary svg { +.button svg { padding-left: var(--padding-sm); +} + + + +/* Primary Button */ +.button-primary { + background-color: var(--primary-600); + color: var(--primary-50); + border: none; +} + +.button-primary svg { fill: var(--primary-300); } + +/* Secondary Button */ +.button-secondary { + background-color: transparent; + color: var(--primary-100); + border: 2px solid var(--primary-100); +} + +.button-secondary svg { + fill: var(--primary-500); +} diff --git a/app/assets/stylesheets/components/_button_secondary.css b/app/assets/stylesheets/components/_button_secondary.css deleted file mode 100644 index 52957e9c..00000000 --- a/app/assets/stylesheets/components/_button_secondary.css +++ /dev/null @@ -1,19 +0,0 @@ -.button-secondary { - background-color: transparent; - color: var(--primary-600); - border-radius: var(--rounded-lg); - letter-spacing: var(--spacing-lg); - font-size: var(--text-sm); - text-transform: uppercase; - border: 2px solid var(--primary-600); - font-weight: var(--font-bold); - padding: var(--padding-xs) var(--padding-md); - margin-bottom: var(--padding-md); - display: flex; - align-items: center; -} - -.button-secondary svg { - padding-left: var(--padding-sm); - fill: var(--primary-500); -} diff --git a/app/assets/stylesheets/layouts/_header.css b/app/assets/stylesheets/layouts/_header.css index 720aa6e0..adf94c23 100644 --- a/app/assets/stylesheets/layouts/_header.css +++ b/app/assets/stylesheets/layouts/_header.css @@ -27,29 +27,4 @@ nav a { .logo { font-weight: var(--font-bold); margin-right: calc(2 * var(--padding-md)); -} - -.login_button { - background-color: var(--primary-600); - color: var(--primary-200); - border-radius: var(--rounded-lg); - letter-spacing: var(--spacing-lg); - font-size: var(--text-sm); - text-transform: uppercase; - border: none; - font-weight: var(--font-bold); - padding: var(--padding-xs) var(--padding-md); -} - -.logout_button { - background-color: transparent; - color: var(--primary-200); - border-radius: var(--rounded-lg); - letter-spacing: var(--spacing-lg); - font-size: var(--text-sm); - text-transform: uppercase; - border: none; - box-shadow: inset 0px 0px 0px 2px var(--primary-200); - font-weight: var(--font-bold); - padding: var(--padding-xs) var(--padding-md); -} +} \ No newline at end of file diff --git a/app/components/button_component.rb b/app/components/button_component.rb new file mode 100644 index 00000000..44b8ad55 --- /dev/null +++ b/app/components/button_component.rb @@ -0,0 +1,69 @@ +# frozen_string_literal: true + +class ButtonComponent < ViewComponent::Base + include ApplicationHelper + + erb_template <<-ERB + <%= button_to( + @path, + method: @method, + class: button_class, + 'aria-label': @aria_label, + data: @data, + form: @form, + ) do %> + <%= @label %> + <% if @action %> + <%= svg_icon_tag button_action_icon %> + <% end %> + <% end %> + ERB + + def initialize( + label:, + path:, + method: :get, + class_name: '', + aria_label: nil, + data: { turbo: false }, + form: {}, + button_type: :primary, + action: nil + ) + @label = label + @path = path + @method = method + @class_name = class_name + @aria_label = aria_label || label + @data = data + @form = form + @button_type = button_type + @action = action + end + + def button_class + base_class = 'button' + type_class = case @button_type + when :primary + 'button-primary' + when :secondary + 'button-secondary' + else + '' + end + [base_class, type_class, @class_name].compact.join(' ') + end + + def button_action_icon + case @action + when :add + 'icon_plus' + when :edit + 'icon_edit' + when :delete + 'icon_delete' + else + '' + end + end +end diff --git a/test/components/button_component_test.rb b/test/components/button_component_test.rb new file mode 100644 index 00000000..bf544fdb --- /dev/null +++ b/test/components/button_component_test.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +require 'test_helper' + +class ButtonComponentTest < ViewComponent::TestCase + def test_component_renders_something_useful + # assert_equal( + # %(Hello, components!), + # render_inline(ButtonComponent.new(message: "Hello, components!")).css("span").to_html + # ) + end +end