Skip to content

Commit

Permalink
On dismiss, allow banners to be hidden instead of removed from the DOM (
Browse files Browse the repository at this point in the history
#2186)

Co-authored-by: camertron <camertron@users.noreply.github.com>
  • Loading branch information
camertron and camertron authored Aug 2, 2023
1 parent 7d4e05e commit eab82c0
Show file tree
Hide file tree
Showing 11 changed files with 67 additions and 42 deletions.
7 changes: 7 additions & 0 deletions .changeset/twelve-rocks-design.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@primer/view-components': minor
---

On dismiss, allow banners to be hidden instead of removed from DOM

<!-- Changed components: Primer::Alpha::Banner -->
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion app/components/primer/alpha/banner.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
<%= action %>
</div>
<% end %>
<% if @dismissible %>
<% if @dismiss_scheme != :none %>
<div class="flash-close Banner-close">
<%= render(
Primer::Beta::IconButton.new(
Expand Down
22 changes: 13 additions & 9 deletions app/components/primer/alpha/banner.rb
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,13 @@ class Banner < Primer::Component
success: :"check-circle"
}.freeze

DEFAULT_DISMISS_SCHEME = :none
DISMISS_SCHEMES = [
DEFAULT_DISMISS_SCHEME,
:remove,
:hide
].freeze

# @example Schemes
# <div style="display: grid; row-gap: 15px">
# <%= render(Primer::Alpha::Banner.new) { "This is a banner message!" } %>
Expand All @@ -60,7 +67,7 @@ class Banner < Primer::Component
# <%= render(Primer::Alpha::Banner.new(full: true)) { "This is a full width banner!" } %>
#
# @example Dismissible
# <%= render(Primer::Alpha::Banner.new(dismissible: true, reappear: true)) { "This is a dismissible banner!" } %>
# <%= render(Primer::Alpha::Banner.new(dismissible: :remove)) { "This is a dismissible banner!" } %>
#
# @example Custom icon
# <%= render(Primer::Alpha::Banner.new(icon: :people)) { "This is a banner with a custom icon!" } %>
Expand All @@ -81,18 +88,16 @@ class Banner < Primer::Component
#
# @param full [Boolean] Whether the component should take up the full width of the screen.
# @param full_when_narrow [Boolean] Whether the component should take up the full width of the screen when rendered inside smaller viewports.
# @param dismissible [Boolean] Whether the component can be dismissed with an "x" button.
# @param dismiss_scheme [Symbol] Whether the component can be dismissed with an "x" button. <%= one_of(Primer::Alpha::Banner::DISMISS_SCHEMES) %>
# @param description [String] Description text rendered underneath the message.
# @param icon [Symbol] The name of an <%= link_to_octicons %> icon to use. If no icon is provided, a default one will be chosen based on the scheme.
# @param scheme [Symbol] <%= one_of(Primer::Alpha::Banner::SCHEME_MAPPINGS.keys) %>
# @param reappear [Boolean] Whether or not the flash banner should reappear after being dismissed. Only for use in test and preview environments.
# @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
def initialize(full: false, full_when_narrow: false, dismissible: false, description: nil, icon: nil, scheme: DEFAULT_SCHEME, reappear: false, **system_arguments)
def initialize(full: false, full_when_narrow: false, dismiss_scheme: DEFAULT_DISMISS_SCHEME, description: nil, icon: nil, scheme: DEFAULT_SCHEME, **system_arguments)
@scheme = fetch_or_fallback(SCHEME_MAPPINGS.keys, scheme, DEFAULT_SCHEME)
@icon = icon || DEFAULT_ICONS[@scheme]
@dismissible = dismissible
@dismiss_scheme = dismiss_scheme
@description = description
@reappear = reappear

@system_arguments = deny_tag_argument(**system_arguments)
@system_arguments[:tag] = :div
Expand All @@ -113,10 +118,9 @@ def initialize(full: false, full_when_narrow: false, dismissible: false, descrip
}

@wrapper_arguments = {
tag: custom_element_name
tag: custom_element_name,
data: { dismiss_scheme: @dismiss_scheme }
}

@wrapper_arguments[:data] = { reappear: @reappear } if @reappear
end

private
Expand Down
26 changes: 14 additions & 12 deletions app/components/primer/alpha/x_banner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,26 @@ class XBannerElement extends HTMLElement {
@target titleText: HTMLElement

dismiss() {
if (this.shouldReappear()) {
this.style.setProperty('visibility', 'hidden')

setTimeout(() => {
this.style.setProperty('visibility', 'visible')
}, 2000)
const parentElement = this.parentElement
if (!parentElement) return

return
if (this.#dismissScheme === 'remove') {
parentElement.removeChild(this)
} else {
this.hide()
}
}

const parentElement = this.parentElement
if (!parentElement) return
show() {
this.style.setProperty('display', 'initial')
}

parentElement.removeChild(this)
hide() {
this.style.setProperty('display', 'none')
}

private shouldReappear(): boolean {
return this.getAttribute('data-reappear') === 'true'
get #dismissScheme(): string {
return this.getAttribute('data-dismiss-scheme')!
}
}

Expand Down
25 changes: 11 additions & 14 deletions previews/primer/alpha/banner_preview.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,14 @@ class BannerPreview < ViewComponent::Preview
#
# @param full toggle
# @param full_when_narrow toggle
# @param dismissible toggle
# @param dismiss_scheme [Symbol] select [none, remove, hide]
# @param icon [Symbol] octicon
# @param scheme [Symbol] select [default, warning, danger, success]
# @param content text
# @param description text
# @param reappear [Boolean]
def playground(full: false, full_when_narrow: false, dismissible: false, icon: :people, scheme: Primer::Alpha::Banner::DEFAULT_SCHEME, reappear: true, content: "This is a banner!", description: nil)
def playground(full: false, full_when_narrow: false, dismiss_scheme: Primer::Alpha::Banner::DEFAULT_DISMISS_SCHEME, icon: :people, scheme: Primer::Alpha::Banner::DEFAULT_SCHEME, content: "This is a banner!", description: nil)
icon = nil if icon == :none
render(Primer::Alpha::Banner.new(full: full, full_when_narrow: full_when_narrow, dismissible: dismissible, icon: icon == :none ? nil : icon, scheme: scheme, description: description, reappear: reappear)) { content }
render(Primer::Alpha::Banner.new(full: full, full_when_narrow: full_when_narrow, dismiss_scheme: dismiss_scheme, icon: icon == :none ? nil : icon, scheme: scheme, description: description)) { content }
end

# @label Default
Expand Down Expand Up @@ -54,8 +53,8 @@ def scheme_warning

# @label Dismissable
# @snapshot
def dismissable
render(Primer::Alpha::Banner.new(dismissible: true, reappear: true)) { "This is a dismissable banner." }
def dismissible
render(Primer::Alpha::Banner.new(dismiss_scheme: :hide, reappear: true)) { "This is a dismissable banner." }
end

# @!group Full Width
Expand All @@ -76,29 +75,27 @@ def full_width_in_narrow_viewport
# @label With action button
#
# @param full toggle
# @param dismissible toggle
# @param dismiss_scheme [Symbol] select [none, remove, hide]
# @param icon [Symbol] octicon
# @param scheme [Symbol] select [default, warning, danger, success]
# @param content text
# @param reappear [Boolean]
# @snapshot
def with_action_button(full: false, dismissible: false, icon: :people, scheme: Primer::Alpha::Banner::DEFAULT_SCHEME, reappear: true, content: "This is a banner with an action!")
def with_action_button(full: false, dismiss_scheme: Primer::Alpha::Banner::DEFAULT_DISMISS_SCHEME, icon: :people, scheme: Primer::Alpha::Banner::DEFAULT_SCHEME, content: "This is a banner with an action!")
icon = nil if icon == :none
render_with_template(locals: { full: full, dismissible: dismissible, icon: icon == :none ? nil : icon, scheme: scheme, content: content, reappear: reappear })
render_with_template(locals: { full: full, dismiss_scheme: dismiss_scheme, icon: icon == :none ? nil : icon, scheme: scheme, content: content })
end

# @label With action content
#
# @param full toggle
# @param dismissible toggle
# @param dismiss_scheme [Symbol] select [none, remove, hide]
# @param icon [Symbol] octicon
# @param scheme [Symbol] select [default, warning, danger, success]
# @param content text
# @param reappear [Boolean]
# @snapshot
def with_action_content(full: false, dismissible: false, icon: :people, scheme: Primer::Alpha::Banner::DEFAULT_SCHEME, reappear: true, content: "Did you know? Comments can be edited.")
def with_action_content(full: false, dismiss_scheme: Primer::Alpha::Banner::DEFAULT_DISMISS_SCHEME, icon: :people, scheme: Primer::Alpha::Banner::DEFAULT_SCHEME, content: "Did you know? Comments can be edited.")
icon = nil if icon == :none
render_with_template(locals: { full: full, dismissible: dismissible, icon: icon == :none ? nil : icon, scheme: scheme, content: content, reappear: reappear })
render_with_template(locals: { full: full, dismiss_scheme: dismiss_scheme, icon: icon == :none ? nil : icon, scheme: scheme, content: content })
end
end
end
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<%= render(Primer::Alpha::Banner.new(full: full, dismissible: dismissible, icon: icon, scheme: scheme, reappear: reappear)) do |component| %>
<%= render(Primer::Alpha::Banner.new(full: full, dismiss_scheme: dismiss_scheme, icon: icon, scheme: scheme)) do |component| %>
<% component.with_action_button(size: :medium) { "Take action" } %>
<%= content %>
<% end %>
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<%= render(Primer::Alpha::Banner.new(full: full, dismissible: dismissible, icon: icon, scheme: scheme, reappear: reappear)) do |component| %>
<%= render(Primer::Alpha::Banner.new(full: full, dismiss_scheme: dismiss_scheme, icon: icon, scheme: scheme)) do |component| %>
<% component.with_action_content do %>
<%= render(Primer::Beta::IconButton.new(icon: :pencil, mr: 1, "aria-label": "Edit")) %>
<% end %>
Expand Down
8 changes: 7 additions & 1 deletion test/components/alpha/banner_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -101,11 +101,17 @@ def test_renders_custom_icon
end

def test_renders_dismiss_button
render_inline(Primer::Alpha::Banner.new(dismissible: true)) { "foo" }
render_inline(Primer::Alpha::Banner.new(dismiss_scheme: :remove)) { "foo" }

assert_selector(".Banner .Banner-close")
end

def test_does_not_render_dismiss_button
render_inline(Primer::Alpha::Banner.new(dismiss_scheme: :none)) { "foo" }

refute_selector(".Banner-close")
end

def test_renders_action_button_slot
render_inline(Primer::Alpha::Banner.new) do |component|
component.with_action_button { "submit" }
Expand Down
15 changes: 12 additions & 3 deletions test/system/alpha/banner_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,22 @@

module Alpha
class IntegrationBannerTest < System::TestCase
def test_dismiss_button
visit_preview(:playground, dismissible: true, reappear: false)
def test_dismiss_button_remove
visit_preview(:playground, dismiss_scheme: :remove)
assert_selector(".Banner")

find(".Banner-close button").click

refute_selector(".Banner")
refute_selector(".Banner", visible: :all)
end

def test_dismiss_button_hide
visit_preview(:playground, dismiss_scheme: :hide)
assert_selector(".Banner")

find(".Banner-close button").click

assert_selector(".Banner", visible: :hidden)
end
end
end

0 comments on commit eab82c0

Please sign in to comment.