diff --git a/.changeset/gorgeous-keys-heal.md b/.changeset/gorgeous-keys-heal.md new file mode 100644 index 0000000000..b4d5de00b8 --- /dev/null +++ b/.changeset/gorgeous-keys-heal.md @@ -0,0 +1,5 @@ +--- +"@primer/view-components": patch +--- + +Add the ability to pass an icon to Dialog `with_show_button`, which will turn it from a Beta::Button to a Beta::IconButton. diff --git a/app/components/primer/alpha/dialog.rb b/app/components/primer/alpha/dialog.rb index b4e6741258..4dfc3f3fe7 100644 --- a/app/components/primer/alpha/dialog.rb +++ b/app/components/primer/alpha/dialog.rb @@ -53,13 +53,17 @@ class Dialog < Primer::Component # Optional button to open the dialog. # # @param system_arguments [Hash] The same arguments as <%= link_to_component(Primer::Beta::Button) %>. - renders_one :show_button, lambda { |**system_arguments| + renders_one :show_button, lambda { |icon: nil, **system_arguments| system_arguments[:classes] = class_names( system_arguments[:classes] ) system_arguments[:id] = "dialog-show-#{@system_arguments[:id]}" system_arguments[:data] = (system_arguments[:data] || {}).merge({ "show-dialog-id": @system_arguments[:id] }) - Primer::Beta::Button.new(**system_arguments) + if icon.present? + Primer::Beta::IconButton.new(icon: icon, **system_arguments) + else + Primer::Beta::Button.new(**system_arguments) + end } # Header content. diff --git a/previews/primer/alpha/dialog_preview.rb b/previews/primer/alpha/dialog_preview.rb index b0d7119b38..29629c5446 100644 --- a/previews/primer/alpha/dialog_preview.rb +++ b/previews/primer/alpha/dialog_preview.rb @@ -14,9 +14,14 @@ class DialogPreview < ViewComponent::Preview # @param visually_hide_title [Boolean] toggle # @param button_text [String] text # @param body_text [String] text - def playground(title: "Test Dialog", subtitle: nil, size: :medium, button_text: "Show Dialog", body_text: "Content", position: :center, position_narrow: :fullscreen, visually_hide_title: false) + # @param icon [Symbol] octicon + def playground(title: "Test Dialog", subtitle: nil, size: :medium, button_text: "Show Dialog", body_text: "Content", position: :center, position_narrow: :fullscreen, visually_hide_title: false, icon: nil) render(Primer::Alpha::Dialog.new(title: title, subtitle: subtitle, size: size, position: position, position_narrow: position_narrow, visually_hide_title: visually_hide_title)) do |d| - d.with_show_button { button_text } + if icon.present? && (icon != :none) + d.with_show_button(icon: icon, "aria-label": icon.to_s) + else + d.with_show_button { button_text } + end d.with_body { body_text } end end diff --git a/test/components/primer/alpha/dialog_test.rb b/test/components/primer/alpha/dialog_test.rb index 7696165ba0..578dd26876 100644 --- a/test/components/primer/alpha/dialog_test.rb +++ b/test/components/primer/alpha/dialog_test.rb @@ -2,84 +2,94 @@ require "components/test_helper" -class PrimerAlphaDialogTest < Minitest::Test - include Primer::ComponentTestHelpers - - def test_renders_title_and_body - render_inline(Primer::Alpha::Dialog.new(title: "Title")) do |component| - component.with_body { "Hello" } - end - - assert_selector("modal-dialog[role='dialog']") do - assert_selector("h1", text: "Title") - assert_selector(".Overlay-body", text: "Hello") - end - end - - def test_renders_show_button - render_inline(Primer::Alpha::Dialog.new(title: "Title")) do |component| - component.with_body { "Hello" } - component.with_show_button { "Show" } - end - - assert_selector("[data-show-dialog-id]") - end - - def test_raises_on_missing_title - error = assert_raises(ArgumentError) do - render_inline(Primer::Alpha::Dialog.new) - end - - assert_includes(error.message, "missing keyword:") - assert_includes(error.message, "title") - end - - def test_renders_provided_id - render_inline(Primer::Alpha::Dialog.new(title: "Title", id: "my-id")) do |component| - component.with_body { "content" } - end - - assert_selector("modal-dialog[id='my-id']") - end - - def test_renders_random_id - render_inline(Primer::Alpha::Dialog.new(title: "Title")) do |component| - component.with_body { "content" } - end - - assert_selector("modal-dialog[id^='dialog-']") - end - - def test_renders_title_and_subtitle_with_describedby - render_inline(Primer::Alpha::Dialog.new(title: "Title", id: "my-dialog", subtitle: "Subtitle")) do |component| - component.with_body { "content" } - end - - assert_selector("modal-dialog[id='my-dialog'][aria-describedby='my-dialog-title my-dialog-description']") do - assert_selector("h1[id='my-dialog-title']", text: "Title") - assert_selector("h2[id='my-dialog-description']", text: "Subtitle") - end - end - - def test_renders_footer_without_divider_by_default - render_inline(Primer::Alpha::Dialog.new(title: "Title", id: "my-dialog", subtitle: "Subtitle")) do |component| - component.with_body { "content" } - component.with_footer { "footer" } - end - - assert_selector("modal-dialog") do - assert_selector(".Overlay-footer:not(.Overlay-footer--divided)") - end - end - - def test_renders_footer_with_divider_if_show_divider_is_true - render_inline(Primer::Alpha::Dialog.new(title: "Title", id: "my-dialog", subtitle: "Subtitle")) do |component| - component.with_body { "content" } - component.with_footer(show_divider: true) { "footer" } - end - - assert_selector("modal-dialog") do - assert_selector(".Overlay-footer.Overlay-footer--divided") +module Primer + module Alpha + class DialogTest < Minitest::Test + include Primer::ComponentTestHelpers + + def test_renders_title_and_body + render_inline(Primer::Alpha::Dialog.new(title: "Title")) do |component| + component.with_body { "Hello" } + end + + assert_selector("modal-dialog[role='dialog']") do + assert_selector("h1", text: "Title") + assert_selector(".Overlay-body", text: "Hello") + end + end + + def test_renders_show_button + render_inline(Primer::Alpha::Dialog.new(title: "Title")) do |component| + component.with_body { "Hello" } + component.with_show_button { "Show" } + end + + assert_selector("[data-show-dialog-id]") + end + + def test_renders_icon_show_button + render_preview :playground, params: { icon: :ellipsis } + + assert_selector("button[data-show-dialog-id] svg.octicon.octicon-ellipsis") + end + + def test_raises_on_missing_title + error = assert_raises(ArgumentError) do + render_inline(Primer::Alpha::Dialog.new) + end + + assert_includes(error.message, "missing keyword:") + assert_includes(error.message, "title") + end + + def test_renders_provided_id + render_inline(Primer::Alpha::Dialog.new(title: "Title", id: "my-id")) do |component| + component.with_body { "content" } + end + + assert_selector("modal-dialog[id='my-id']") + end + + def test_renders_random_id + render_inline(Primer::Alpha::Dialog.new(title: "Title")) do |component| + component.with_body { "content" } + end + + assert_selector("modal-dialog[id^='dialog-']") + end + + def test_renders_title_and_subtitle_with_describedby + render_inline(Primer::Alpha::Dialog.new(title: "Title", id: "my-dialog", subtitle: "Subtitle")) do |component| + component.with_body { "content" } + end + + assert_selector("modal-dialog[id='my-dialog'][aria-describedby='my-dialog-title my-dialog-description']") do + assert_selector("h1[id='my-dialog-title']", text: "Title") + assert_selector("h2[id='my-dialog-description']", text: "Subtitle") + end + end + + def test_renders_footer_without_divider_by_default + render_inline(Primer::Alpha::Dialog.new(title: "Title", id: "my-dialog", subtitle: "Subtitle")) do |component| + component.with_body { "content" } + component.with_footer { "footer" } + end + + assert_selector("modal-dialog") do + assert_selector(".Overlay-footer:not(.Overlay-footer--divided)") + end + end + + def test_renders_footer_with_divider_if_show_divider_is_true + render_inline(Primer::Alpha::Dialog.new(title: "Title", id: "my-dialog", subtitle: "Subtitle")) do |component| + component.with_body { "content" } + component.with_footer(show_divider: true) { "footer" } + end + + assert_selector("modal-dialog") do + assert_selector(".Overlay-footer.Overlay-footer--divided") + end + end end end end