diff --git a/app/components/polaris/button_component.html.erb b/app/components/polaris/button_component.html.erb index 466fd3da..d940e20b 100644 --- a/app/components/polaris/button_component.html.erb +++ b/app/components/polaris/button_component.html.erb @@ -1,4 +1,4 @@ -<%= render Polaris::BaseComponent.new(tag: @tag, **dynamic_arguments) do %> +<%= render Polaris::BaseComponent.new(tag: @tag, **system_arguments) do %> <% if @loading %> diff --git a/app/components/polaris/button_component.rb b/app/components/polaris/button_component.rb index 932afbff..09fe2d8c 100644 --- a/app/components/polaris/button_component.rb +++ b/app/components/polaris/button_component.rb @@ -1,90 +1,6 @@ # frozen_string_literal: true module Polaris - class ButtonComponent < Polaris::NewComponent - SIZE_DEFAULT = :medium - SIZE_MAPPINGS = { - SIZE_DEFAULT => "", - :slim => "Polaris-Button--sizeSlim", - :large => "Polaris-Button--sizeLarge", - } - SIZE_OPTIONS = SIZE_MAPPINGS.keys - - TEXT_ALIGN_DEFAULT = :default - TEXT_ALIGN_MAPPINGS = { - TEXT_ALIGN_DEFAULT => "", - :left => "Polaris-Button--textAlignLeft", - :center => "Polaris-Button--textAlignCenter", - :right => "Polaris-Button--textAlignRight", - } - TEXT_ALIGN_OPTIONS = TEXT_ALIGN_MAPPINGS.keys - - renders_one :icon, IconComponent - - def initialize( - url: nil, - outline: false, - plain: false, - primary: false, - pressed: false, - monochrome: false, - loading: false, - destructive: false, - disabled: false, - external: false, - full_width: false, - submit: false, - remove_underline: false, - size: SIZE_DEFAULT, - text_align: TEXT_ALIGN_DEFAULT, - **system_arguments - ) - @tag = url.present? ? 'a' : 'button' - @text_classes = class_names( - "Polaris-Button__Text", - "Polaris-Button--removeUnderline": plain && monochrome && remove_underline - ) - @loading = loading - - @system_arguments = system_arguments - @system_arguments[:type] = submit ? 'submit' : 'button' - if loading - @system_arguments[:disabled] = true - end - if url.present? - @system_arguments.delete(:type) - @system_arguments[:href] = url - @system_arguments[:target] = "_blank" if external - end - if disabled - @system_arguments[:disabled] = disabled - end - @system_arguments[:classes] = class_names( - @system_arguments[:classes], - "Polaris-Button", - SIZE_MAPPINGS[fetch_or_fallback(SIZE_OPTIONS, size, SIZE_DEFAULT)], - TEXT_ALIGN_MAPPINGS[fetch_or_fallback(TEXT_ALIGN_OPTIONS, text_align, TEXT_ALIGN_DEFAULT)], - "Polaris-Button--destructive": destructive, - "Polaris-Button--disabled": disabled || loading, - "Polaris-Button--loading": loading, - "Polaris-Button--fullWidth": full_width, - "Polaris-Button--monochrome": monochrome, - "Polaris-Button--outline": outline, - "Polaris-Button--plain": plain, - "Polaris-Button--primary": primary, - "Polaris-Button--pressed": pressed, - "Polaris-Button--removeUnderline": (plain && monochrome && remove_underline) - ) - end - - private - - def dynamic_arguments - @system_arguments[:classes] = class_names( - @system_arguments[:classes], - "Polaris-Button--iconOnly": icon.present? && content.blank?, - ) - @system_arguments - end + class ButtonComponent < HeadlessButton end end diff --git a/app/components/polaris/headless_button.html.erb b/app/components/polaris/headless_button.html.erb new file mode 100644 index 00000000..55443a05 --- /dev/null +++ b/app/components/polaris/headless_button.html.erb @@ -0,0 +1,22 @@ + + <% if @loading %> + + <%= polaris_spinner(size: :small) %> + + <% end %> + + <% if icon.present? %> +
+ <%= icon %> +
+ <% if content.present? %> +   + <% end %> + <% end %> + + <% if content.present? %> +
+ <%= content %> +
+ <% end %> +
diff --git a/app/components/polaris/headless_button.rb b/app/components/polaris/headless_button.rb new file mode 100644 index 00000000..41a4c84a --- /dev/null +++ b/app/components/polaris/headless_button.rb @@ -0,0 +1,95 @@ +# frozen_string_literal: true + +module Polaris + class HeadlessButton < Polaris::NewComponent + SIZE_DEFAULT = :medium + SIZE_MAPPINGS = { + SIZE_DEFAULT => "", + :slim => "Polaris-Button--sizeSlim", + :large => "Polaris-Button--sizeLarge", + } + SIZE_OPTIONS = SIZE_MAPPINGS.keys + + TEXT_ALIGN_DEFAULT = :default + TEXT_ALIGN_MAPPINGS = { + TEXT_ALIGN_DEFAULT => "", + :left => "Polaris-Button--textAlignLeft", + :center => "Polaris-Button--textAlignCenter", + :right => "Polaris-Button--textAlignRight", + } + TEXT_ALIGN_OPTIONS = TEXT_ALIGN_MAPPINGS.keys + + renders_one :icon, IconComponent + + def initialize( + url: nil, + outline: false, + plain: false, + primary: false, + pressed: false, + monochrome: false, + loading: false, + destructive: false, + disabled: false, + external: false, + full_width: false, + submit: false, + remove_underline: false, + size: SIZE_DEFAULT, + text_align: TEXT_ALIGN_DEFAULT, + **system_arguments + ) + @tag = url.present? ? 'a' : 'button' + @text_classes = class_names( + "Polaris-Button__Text", + "Polaris-Button--removeUnderline": plain && monochrome && remove_underline + ) + @loading = loading + + @system_arguments = system_arguments + @system_arguments[:type] = submit ? 'submit' : 'button' + if loading + @system_arguments[:disabled] = true + end + if url.present? + @system_arguments.delete(:type) + @system_arguments[:href] = url + @system_arguments[:target] = "_blank" if external + end + if disabled + @system_arguments[:disabled] = disabled + end + @system_arguments[:classes] = class_names( + @system_arguments[:classes], + "Polaris-Button", + SIZE_MAPPINGS[fetch_or_fallback(SIZE_OPTIONS, size, SIZE_DEFAULT)], + TEXT_ALIGN_MAPPINGS[fetch_or_fallback(TEXT_ALIGN_OPTIONS, text_align, TEXT_ALIGN_DEFAULT)], + "Polaris-Button--destructive": destructive, + "Polaris-Button--disabled": disabled || loading, + "Polaris-Button--loading": loading, + "Polaris-Button--fullWidth": full_width, + "Polaris-Button--monochrome": monochrome, + "Polaris-Button--outline": outline, + "Polaris-Button--plain": plain, + "Polaris-Button--primary": primary, + "Polaris-Button--pressed": pressed, + "Polaris-Button--removeUnderline": (plain && monochrome && remove_underline) + ) + end + + def system_arguments + @system_arguments[:classes] = class_names( + @system_arguments[:classes], + "Polaris-Button--iconOnly": icon.present? && content.blank?, + ) + @system_arguments + end + + def html_options + options = system_arguments + options[:class] = options[:classes] + options.delete(:classes) + options + end + end +end diff --git a/app/helpers/polaris/url_helper.rb b/app/helpers/polaris/url_helper.rb new file mode 100644 index 00000000..d28f6925 --- /dev/null +++ b/app/helpers/polaris/url_helper.rb @@ -0,0 +1,19 @@ +module Polaris + module UrlHelper + def polaris_button_to(name = nil, options = nil, html_options = nil, &block) + html_options, options = options, name if block_given? + options ||= {} + html_options ||= {} + html_options[:classes] = html_options[:class] + html_options.delete(:class) + + button = Polaris::HeadlessButton.new(submit: true, **html_options) + button = button.with_content(name) unless block_given? + content = render(button, &block) + + button_to(options, button.html_options) do + content + end + end + end +end diff --git a/demo/app/javascript/packs/application.js b/demo/app/javascript/packs/application.js index 72ef077f..5931f46a 100644 --- a/demo/app/javascript/packs/application.js +++ b/demo/app/javascript/packs/application.js @@ -1 +1,4 @@ +import Rails from "@rails/ujs" +Rails.start() + import "controllers" diff --git a/demo/package.json b/demo/package.json index ce3ff0ba..63959c5f 100644 --- a/demo/package.json +++ b/demo/package.json @@ -2,6 +2,7 @@ "name": "demo", "private": true, "dependencies": { + "@rails/ujs": "^6.1.4", "@rails/webpacker": "5.4.0", "polaris-view-components": "^0.1.0", "stimulus": "^2.0.0", diff --git a/demo/test/components/previews/rails/helpers_component_preview.rb b/demo/test/components/previews/rails/helpers_component_preview.rb new file mode 100644 index 00000000..5565a132 --- /dev/null +++ b/demo/test/components/previews/rails/helpers_component_preview.rb @@ -0,0 +1,4 @@ +class Rails::HelpersComponentPreview < ViewComponent::Preview + def button_to + end +end diff --git a/demo/test/components/previews/rails/helpers_component_preview/button_to.html.erb b/demo/test/components/previews/rails/helpers_component_preview/button_to.html.erb new file mode 100644 index 00000000..16a153e4 --- /dev/null +++ b/demo/test/components/previews/rails/helpers_component_preview/button_to.html.erb @@ -0,0 +1,18 @@ +<%= polaris_button_to("Delete", products_path, + method: :delete, + destructive: true, + data: { + confirm: "Are you sure?", + } +) %> + +
+ +<%= polaris_button_to(products_path, + method: :delete, + data: { + confirm: "Are you sure?", + } +) do |button| %> + <% button.icon(name: "DeleteMinor") %> +<% end %> diff --git a/demo/yarn.lock b/demo/yarn.lock index 8e98524a..b2baf507 100644 --- a/demo/yarn.lock +++ b/demo/yarn.lock @@ -893,6 +893,11 @@ mkdirp "^1.0.4" rimraf "^3.0.2" +"@rails/ujs@^6.1.4": + version "6.1.4" + resolved "https://registry.yarnpkg.com/@rails/ujs/-/ujs-6.1.4.tgz#093d5341595a02089ed309dec40f3c37da7b1b10" + integrity sha512-O3lEzL5DYbxppMdsFSw36e4BHIlfz/xusynwXGv3l2lhSlvah41qviRpsoAlKXxl37nZAqK+UUF5cnGGK45Mfw== + "@rails/webpacker@5.4.0": version "5.4.0" resolved "https://registry.yarnpkg.com/@rails/webpacker/-/webpacker-5.4.0.tgz#2c64a9ea7e85d2a33e50e86319fe6751df0c47e8" diff --git a/lib/polaris/view_components/engine.rb b/lib/polaris/view_components/engine.rb index 6390de45..1ddb064e 100644 --- a/lib/polaris/view_components/engine.rb +++ b/lib/polaris/view_components/engine.rb @@ -20,6 +20,7 @@ class Engine < ::Rails::Engine initializer "polaris_view_components.helpers" do ActiveSupport.on_load(:action_controller_base) do helper Polaris::ViewHelper + helper Polaris::UrlHelper helper Polaris::ActionHelper helper Polaris::ConditionalHelper end diff --git a/test/helpers/polaris/url_helper_test.rb b/test/helpers/polaris/url_helper_test.rb new file mode 100644 index 00000000..d16f8bcb --- /dev/null +++ b/test/helpers/polaris/url_helper_test.rb @@ -0,0 +1,17 @@ +require "test_helper" + +class Polaris::UrlHelperTest < ActionView::TestCase + test "polaris_button_to helper with name" do + assert_dom_equal( + %(
), + polaris_button_to("Name", "/url", plain: true, data: { controller: "test" }) + ) + end + + test "polaris_button_to helper with block" do + assert_dom_equal( + %(
), + polaris_button_to("/url", class: "TestClass") { |b| b.icon(name: "DeleteMinor") } + ) + end +end