primer_view_components 0.0.14 → 0.0.19

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +82 -0
  3. data/app/components/primer/avatar_component.rb +24 -6
  4. data/app/components/primer/avatar_stack_component.html.erb +10 -0
  5. data/app/components/primer/avatar_stack_component.rb +81 -0
  6. data/app/components/primer/base_component.rb +63 -15
  7. data/app/components/primer/blankslate_component.html.erb +4 -4
  8. data/app/components/primer/blankslate_component.rb +34 -8
  9. data/app/components/primer/border_box_component.rb +29 -13
  10. data/app/components/primer/box_component.rb +10 -0
  11. data/app/components/primer/breadcrumb_component.rb +3 -2
  12. data/app/components/primer/button_component.rb +3 -3
  13. data/app/components/primer/button_group_component.html.erb +5 -0
  14. data/app/components/primer/button_group_component.rb +37 -0
  15. data/app/components/primer/button_marketing_component.rb +73 -0
  16. data/app/components/primer/component.rb +13 -0
  17. data/app/components/primer/counter_component.rb +21 -13
  18. data/app/components/primer/details_component.rb +10 -6
  19. data/app/components/primer/dropdown/menu_component.html.erb +12 -0
  20. data/app/components/primer/dropdown/menu_component.rb +48 -0
  21. data/app/components/primer/dropdown_component.html.erb +9 -0
  22. data/app/components/primer/dropdown_component.rb +77 -0
  23. data/app/components/primer/dropdown_menu_component.rb +35 -3
  24. data/app/components/primer/flash_component.rb +10 -7
  25. data/app/components/primer/flex_component.rb +47 -9
  26. data/app/components/primer/flex_item_component.rb +16 -1
  27. data/app/components/primer/heading_component.rb +7 -0
  28. data/app/components/primer/label_component.rb +6 -6
  29. data/app/components/primer/layout_component.rb +2 -2
  30. data/app/components/primer/link_component.rb +7 -3
  31. data/app/components/primer/markdown_component.rb +293 -0
  32. data/app/components/primer/menu_component.html.erb +6 -0
  33. data/app/components/primer/menu_component.rb +71 -0
  34. data/app/components/primer/octicon_component.rb +11 -6
  35. data/app/components/primer/popover_component.rb +6 -4
  36. data/app/components/primer/progress_bar_component.rb +9 -9
  37. data/app/components/primer/slot.rb +1 -0
  38. data/app/components/primer/spinner_component.rb +10 -7
  39. data/app/components/primer/state_component.rb +6 -6
  40. data/app/components/primer/subhead_component.rb +6 -3
  41. data/app/components/primer/text_component.rb +1 -1
  42. data/app/components/primer/timeline_item_component.rb +4 -1
  43. data/app/components/primer/tooltip_component.rb +88 -0
  44. data/app/components/primer/truncate_component.rb +41 -0
  45. data/app/components/primer/underline_nav_component.rb +26 -1
  46. data/app/components/primer/view_components.rb +9 -0
  47. data/lib/primer/class_name_helper.rb +1 -0
  48. data/lib/primer/classify.rb +141 -106
  49. data/lib/primer/classify/cache.rb +125 -0
  50. data/lib/primer/fetch_or_fallback_helper.rb +9 -0
  51. data/lib/primer/join_style_arguments_helper.rb +14 -0
  52. data/lib/primer/view_components.rb +32 -0
  53. data/lib/primer/view_components/engine.rb +1 -0
  54. data/lib/primer/view_components/version.rb +1 -1
  55. data/lib/yard/renders_many_handler.rb +19 -0
  56. data/lib/yard/renders_one_handler.rb +19 -0
  57. data/static/statuses.json +1 -0
  58. metadata +80 -19
@@ -10,30 +10,43 @@ module Primer
10
10
  with_slot :footer, class_name: "Footer"
11
11
  with_slot :row, collection: true, class_name: "Row"
12
12
 
13
- # @example 350|Header, body, rows, and footer
14
- # <%= render(Primer::BorderBoxComponent.new) do |component|
15
- # component.slot(:header) { "Header" }
16
- # component.slot(:body) { "Body" }
17
- # component.slot(:row) { "Row one" }
18
- # component.slot(:row) { "Row two" }
19
- # component.slot(:row) { "Row three" }
20
- # component.slot(:footer) { "Footer" }
21
- # end %>
13
+ # @example auto|Header, body, rows, and footer
14
+ # <%= render(Primer::BorderBoxComponent.new) do |component| %>
15
+ # <% component.slot(:header) do %>
16
+ # Header
17
+ # <% end %>
18
+ # <% component.slot(:body) do %>
19
+ # Body
20
+ # <% end %>
21
+ # <% component.slot(:row) do %>
22
+ # <% if true %>
23
+ # Row one
24
+ # <% end %>
25
+ # <% end %>
26
+ # <% component.slot(:row) do %>
27
+ # Row two
28
+ # <% end %>
29
+ # <% component.slot(:footer) do %>
30
+ # Footer
31
+ # <% end %>
32
+ # <% end %>
22
33
  #
23
34
  # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
24
35
  def initialize(**system_arguments)
25
36
  @system_arguments = system_arguments
26
37
  @system_arguments[:tag] = :div
27
- @system_arguments[:classes] = class_names(
28
- "Box",
29
- system_arguments[:classes]
30
- )
38
+ @system_arguments[:classes] = class_names("Box", system_arguments[:classes])
31
39
  end
32
40
 
33
41
  def render?
34
42
  rows.any? || header.present? || body.present? || footer.present?
35
43
  end
36
44
 
45
+ def self.status
46
+ Primer::Component::STATUSES[:beta]
47
+ end
48
+
49
+ # :nodoc:
37
50
  class Header < Primer::Slot
38
51
  attr_reader :system_arguments
39
52
  # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
@@ -47,6 +60,7 @@ module Primer
47
60
  end
48
61
  end
49
62
 
63
+ # :nodoc:
50
64
  class Body < Primer::Slot
51
65
  attr_reader :system_arguments
52
66
  # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
@@ -60,6 +74,7 @@ module Primer
60
74
  end
61
75
  end
62
76
 
77
+ # :nodoc:
63
78
  class Footer < Primer::Slot
64
79
  attr_reader :system_arguments
65
80
  # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
@@ -73,6 +88,7 @@ module Primer
73
88
  end
74
89
  end
75
90
 
91
+ # :nodoc:
76
92
  class Row < Primer::Slot
77
93
  attr_reader :system_arguments
78
94
  # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
@@ -3,6 +3,12 @@
3
3
  module Primer
4
4
  # A basic wrapper component for most layout related needs.
5
5
  class BoxComponent < Primer::Component
6
+ # @example auto|Default
7
+ # <%= render(Primer::BoxComponent.new) { "Your content here" } %>
8
+ #
9
+ # @example auto|Color and padding
10
+ # <%= render(Primer::BoxComponent.new(bg: :gray, p: 3)) { "Hello world" } %>
11
+ #
6
12
  # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
7
13
  def initialize(**system_arguments)
8
14
  @system_arguments = system_arguments
@@ -12,5 +18,9 @@ module Primer
12
18
  def call
13
19
  render(Primer::BaseComponent.new(**@system_arguments)) { content }
14
20
  end
21
+
22
+ def self.status
23
+ Primer::Component::STATUSES[:stable]
24
+ end
15
25
  end
16
26
  end
@@ -7,7 +7,7 @@ module Primer
7
7
 
8
8
  with_slot :item, collection: true, class_name: "BreadcrumbItem"
9
9
 
10
- # @example 40|Basic
10
+ # @example auto|Basic
11
11
  # <%= render(Primer::BreadcrumbComponent.new) do |component| %>
12
12
  # <% component.slot(:item, href: "/") do %>Home<% end %>
13
13
  # <% component.slot(:item, href: "/about") do %>About<% end %>
@@ -33,7 +33,8 @@ module Primer
33
33
  # @param selected [Boolean] Whether or not the item is selected and not rendered as a link.
34
34
  # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
35
35
  def initialize(href: nil, selected: false, **system_arguments)
36
- @href, @system_arguments = href, system_arguments
36
+ @href = href
37
+ @system_arguments = system_arguments
37
38
 
38
39
  @href = nil if selected
39
40
  @system_arguments[:tag] = :li
@@ -16,7 +16,7 @@ module Primer
16
16
  VARIANT_MAPPINGS = {
17
17
  :small => "btn-sm",
18
18
  DEFAULT_VARIANT => "",
19
- :large => "btn-large",
19
+ :large => "btn-large"
20
20
  }.freeze
21
21
  VARIANT_OPTIONS = VARIANT_MAPPINGS.keys
22
22
 
@@ -26,13 +26,13 @@ module Primer
26
26
  DEFAULT_TYPE = :button
27
27
  TYPE_OPTIONS = [DEFAULT_TYPE, :reset, :submit].freeze
28
28
 
29
- # @example 50|Button types
29
+ # @example auto|Button types
30
30
  # <%= render(Primer::ButtonComponent.new) { "Default" } %>
31
31
  # <%= render(Primer::ButtonComponent.new(button_type: :primary)) { "Primary" } %>
32
32
  # <%= render(Primer::ButtonComponent.new(button_type: :danger)) { "Danger" } %>
33
33
  # <%= render(Primer::ButtonComponent.new(button_type: :outline)) { "Outline" } %>
34
34
  #
35
- # @example 50|Variants
35
+ # @example auto|Variants
36
36
  # <%= render(Primer::ButtonComponent.new(variant: :small)) { "Small" } %>
37
37
  # <%= render(Primer::ButtonComponent.new(variant: :medium)) { "Medium" } %>
38
38
  # <%= render(Primer::ButtonComponent.new(variant: :large)) { "Large" } %>
@@ -0,0 +1,5 @@
1
+ <%= render Primer::BaseComponent.new(**@system_arguments) do %>
2
+ <% buttons.each do |button| %>
3
+ <%= button %>
4
+ <% end %>
5
+ <% end %>
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Primer
4
+ # Use ButtonGroupComponent to render a series of buttons.
5
+ class ButtonGroupComponent < Primer::Component
6
+ include ViewComponent::SlotableV2
7
+
8
+ # Required list of buttons to be rendered.
9
+ #
10
+ # @param kwargs [Hash] The same arguments as <%= link_to_component(Primer::ButtonComponent) %>.
11
+ renders_many :buttons, ->(**kwargs) { Primer::ButtonComponent.new(group_item: true, **kwargs) }
12
+
13
+ # @example auto|Default
14
+ # <%= render(Primer::ButtonGroupComponent.new) do |component|
15
+ # component.button { "Default" }
16
+ # component.button(button_type: :primary) { "Primary" }
17
+ # component.button(button_type: :danger) { "Danger" }
18
+ # component.button(button_type: :outline) { "Outline" }
19
+ # component.button(classes: "my-class") { "Custom class" }
20
+ # end %>
21
+ #
22
+ # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
23
+ def initialize(**system_arguments)
24
+ @system_arguments = system_arguments
25
+ @system_arguments[:tag] ||= :div
26
+
27
+ @system_arguments[:classes] = class_names(
28
+ "BtnGroup",
29
+ system_arguments[:classes]
30
+ )
31
+ end
32
+
33
+ def render?
34
+ buttons.any?
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,73 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Primer
4
+ # Use buttons for actions (e.g. in forms). Use links for destinations, or moving from one page to another.
5
+ class ButtonMarketingComponent < Primer::Component
6
+ DEFAULT_BUTTON_TYPE = :default
7
+ BUTTON_TYPE_MAPPINGS = {
8
+ DEFAULT_BUTTON_TYPE => "",
9
+ :primary => "btn-primary-mktg",
10
+ :outline => "btn-outline-mktg",
11
+ :transparent => "btn-transparent"
12
+ }.freeze
13
+ BUTTON_TYPE_OPTIONS = BUTTON_TYPE_MAPPINGS.keys
14
+
15
+ DEFAULT_VARIANT = :default
16
+ VARIANT_MAPPINGS = {
17
+ DEFAULT_VARIANT => "",
18
+ :large => "btn-large-mktg"
19
+ }.freeze
20
+ VARIANT_OPTIONS = VARIANT_MAPPINGS.keys
21
+
22
+ DEFAULT_TAG = :button
23
+ TAG_OPTIONS = [DEFAULT_TAG, :a].freeze
24
+
25
+ DEFAULT_TYPE = :button
26
+ TYPE_OPTIONS = [DEFAULT_TYPE, :submit].freeze
27
+
28
+ # @example auto|Button types
29
+ # <%= render(Primer::ButtonMarketingComponent.new(mr: 2)) { "Default" } %>
30
+ # <%= render(Primer::ButtonMarketingComponent.new(button_type: :primary, mr: 2)) { "Primary" } %>
31
+ # <%= render(Primer::ButtonMarketingComponent.new(button_type: :outline)) { "Outline" } %>
32
+ # <div class="bg-gray-dark">
33
+ # <%= render(Primer::ButtonMarketingComponent.new(button_type: :transparent)) { "Transparent" } %>
34
+ # </div>
35
+ #
36
+ # @example auto|Sizes
37
+ # <%= render(Primer::ButtonMarketingComponent.new(mr: 2)) { "Default" } %>
38
+ # <%= render(Primer::ButtonMarketingComponent.new(variant: :large)) { "Large" } %>
39
+ #
40
+ # @param button_type [Symbol] <%= one_of(Primer::ButtonMarketingComponent::BUTTON_TYPE_OPTIONS) %>
41
+ # @param variant [Symbol] <%= one_of(Primer::ButtonMarketingComponent::VARIANT_OPTIONS) %>
42
+ # @param tag [Symbol] <%= one_of(Primer::ButtonMarketingComponent::TAG_OPTIONS) %>
43
+ # @param type [Symbol] <%= one_of(Primer::ButtonMarketingComponent::TYPE_OPTIONS) %>
44
+ # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
45
+ def initialize(
46
+ button_type: DEFAULT_BUTTON_TYPE,
47
+ variant: DEFAULT_VARIANT,
48
+ tag: DEFAULT_TAG,
49
+ type: DEFAULT_TYPE,
50
+ **system_arguments
51
+ )
52
+ @system_arguments = system_arguments
53
+ @system_arguments[:tag] = fetch_or_fallback(TAG_OPTIONS, tag, DEFAULT_TAG)
54
+
55
+ if @system_arguments[:tag] == :a
56
+ @system_arguments[:role] = :button
57
+ else
58
+ @system_arguments[:type] = fetch_or_fallback(TYPE_OPTIONS, type, DEFAULT_TYPE)
59
+ end
60
+
61
+ @system_arguments[:classes] = class_names(
62
+ "btn-mktg",
63
+ BUTTON_TYPE_MAPPINGS[fetch_or_fallback(BUTTON_TYPE_OPTIONS, button_type, DEFAULT_BUTTON_TYPE)],
64
+ VARIANT_MAPPINGS[fetch_or_fallback(VARIANT_OPTIONS, variant, DEFAULT_VARIANT)],
65
+ system_arguments[:classes]
66
+ )
67
+ end
68
+
69
+ def call
70
+ render(Primer::BaseComponent.new(**@system_arguments)) { content }
71
+ end
72
+ end
73
+ end
@@ -6,5 +6,18 @@ module Primer
6
6
  include ClassNameHelper
7
7
  include FetchOrFallbackHelper
8
8
  include OcticonsHelper
9
+ include JoinStyleArgumentsHelper
10
+
11
+ # sourced from https://primer.style/doctocat/usage/front-matter#status
12
+ STATUSES = {
13
+ alpha: :alpha,
14
+ beta: :beta,
15
+ stable: :stable,
16
+ deprecated: :deprecated
17
+ }.freeze
18
+
19
+ def self.status
20
+ STATUSES[:alpha]
21
+ end
9
22
  end
10
23
  end
@@ -7,16 +7,16 @@ module Primer
7
7
  SCHEME_MAPPINGS = {
8
8
  DEFAULT_SCHEME => "Counter",
9
9
  :gray => "Counter Counter--gray",
10
- :light_gray => "Counter Counter--gray-light",
10
+ :light_gray => "Counter Counter--gray-light"
11
11
  }.freeze
12
12
 
13
13
  #
14
- # @example 34|Default
14
+ # @example auto|Default
15
15
  # <%= render(Primer::CounterComponent.new(count: 25)) %>
16
16
  #
17
17
  # @param count [Integer, Float::INFINITY, nil] The number to be displayed (e.x. # of issues, pull requests)
18
18
  # @param scheme [Symbol] Color scheme. One of `SCHEME_MAPPINGS.keys`.
19
- # @param limit [Integer] Maximum value to display. (e.x. if count == 6,000 and limit == 5000, counter will display "5,000+")
19
+ # @param limit [Integer, nil] Maximum value to display. Pass `nil` for no limit. (e.x. if `count` == 6,000 and `limit` == 5000, counter will display "5,000+")
20
20
  # @param hide_if_zero [Boolean] If true, a `hidden` attribute is added to the counter if `count` is zero.
21
21
  # @param text [String] Text to display instead of count.
22
22
  # @param round [Boolean] Whether to apply our standard rounding logic to value.
@@ -30,23 +30,31 @@ module Primer
30
30
  round: false,
31
31
  **system_arguments
32
32
  )
33
- @count, @limit, @hide_if_zero, @text, @round, @system_arguments = count, limit, hide_if_zero, text, round, system_arguments
33
+ @count = count
34
+ @limit = limit
35
+ @hide_if_zero = hide_if_zero
36
+ @text = text
37
+ @round = round
38
+ @system_arguments = system_arguments
34
39
 
40
+ @has_limit = !@limit.nil?
35
41
  @system_arguments[:title] = title
36
42
  @system_arguments[:tag] = :span
37
43
  @system_arguments[:classes] = class_names(
38
44
  @system_arguments[:classes],
39
45
  SCHEME_MAPPINGS[fetch_or_fallback(SCHEME_MAPPINGS.keys, scheme, DEFAULT_SCHEME)]
40
46
  )
41
- if count == 0 && hide_if_zero
42
- @system_arguments[:hidden] = true
43
- end
47
+ @system_arguments[:hidden] = true if count == 0 && hide_if_zero # rubocop:disable Style/NumericPredicate
44
48
  end
45
49
 
46
50
  def call
47
51
  render(Primer::BaseComponent.new(**@system_arguments)) { value }
48
52
  end
49
53
 
54
+ def self.status
55
+ Primer::Component::STATUSES[:beta]
56
+ end
57
+
50
58
  private
51
59
 
52
60
  def title
@@ -58,8 +66,8 @@ module Primer
58
66
  "Infinity"
59
67
  else
60
68
  count = @count.to_i
61
- str = number_with_delimiter([count, @limit].min)
62
- str += "+" if count > @limit
69
+ str = number_with_delimiter(@has_limit ? [count, @limit].min : count)
70
+ str += "+" if @has_limit && count > @limit
63
71
  str
64
72
  end
65
73
  end
@@ -73,16 +81,16 @@ module Primer
73
81
  "∞"
74
82
  else
75
83
  if @round
76
- count = [@count.to_i, @limit].min
84
+ count = @has_limit ? [@count.to_i, @limit].min : @count.to_i
77
85
  precision = count.between?(100_000, 999_999) ? 0 : 1
78
- units = {thousand: "k", million: "m", billion: "b"}
86
+ units = { thousand: "k", million: "m", billion: "b" }
79
87
  str = number_to_human(count, precision: precision, significant: false, units: units, format: "%n%u")
80
88
  else
81
89
  @count = @count.to_i
82
- str = number_with_delimiter([@count, @limit].min)
90
+ str = number_with_delimiter(@has_limit ? [@count, @limit].min : @count)
83
91
  end
84
92
 
85
- str += "+" if @count.to_i > @limit
93
+ str += "+" if @has_limit && @count.to_i > @limit
86
94
  str
87
95
  end
88
96
  end
@@ -1,11 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Primer
4
- #
5
- # overlay - options are `none`, `default` and `dark`. Dictates the type of overlay to render with.
6
- # button - options are `default` and `reset`. default will make the target a default primer ``.btn`
7
- # reset will remove all styles from the <summary> element.
8
- #
4
+ # Use DetailsComponent to reveal content after clicking a button.
9
5
  class DetailsComponent < Primer::Component
10
6
  include ViewComponent::Slotable
11
7
 
@@ -13,12 +9,15 @@ module Primer
13
9
  OVERLAY_MAPPINGS = {
14
10
  NO_OVERLAY => "",
15
11
  :default => "details-overlay",
16
- :dark => "details-overlay details-overlay-dark",
12
+ :dark => "details-overlay details-overlay-dark"
17
13
  }.freeze
18
14
 
19
15
  with_slot :body, class_name: "Body"
20
16
  with_slot :summary, class_name: "Summary"
21
17
 
18
+ # @param overlay [Symbol] Dictates the type of overlay to render with. <%= one_of(Primer::DetailsComponent::OVERLAY_MAPPINGS.keys) %>
19
+ # @param reset [Boolean] Defatuls to false. If set to true, it will remove the default caret and remove style from the summary element
20
+ # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
22
21
  def initialize(overlay: NO_OVERLAY, reset: false, **system_arguments)
23
22
  @system_arguments = system_arguments
24
23
  @system_arguments[:tag] = :details
@@ -33,7 +32,10 @@ module Primer
33
32
  summary.present? && body.present?
34
33
  end
35
34
 
35
+ # Use the Summary slot as a trigger to reveal the content.
36
36
  class Summary < Primer::Slot
37
+ # @param button [Boolean] Whether to render the Summary as a button or not.
38
+ # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
37
39
  def initialize(button: true, **system_arguments)
38
40
  @button = button
39
41
 
@@ -49,7 +51,9 @@ module Primer
49
51
  end
50
52
  end
51
53
 
54
+ # Use the Body slot as the main content to be shown when triggered by the Summary.
52
55
  class Body < Primer::Slot
56
+ # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
53
57
  def initialize(**system_arguments)
54
58
  @system_arguments = system_arguments
55
59
  @system_arguments[:tag] ||= :div
@@ -0,0 +1,12 @@
1
+ <%= render Primer::BaseComponent.new(**@system_arguments) do %>
2
+ <% if @header.present? %>
3
+ <div class="dropdown-header">
4
+ <%= @header %>
5
+ </div>
6
+ <% end %>
7
+ <ul>
8
+ <% items.each do |item| %>
9
+ <%= item %>
10
+ <% end %>
11
+ </ul>
12
+ <% end %>
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Primer
4
+ module Dropdown
5
+ # This component is part of `Primer::DropdownComponent` and should not be
6
+ # used as a standalone component.
7
+ class MenuComponent < Primer::Component
8
+ include ViewComponent::SlotableV2
9
+
10
+ SCHEME_DEFAULT = :default
11
+ SCHEME_MAPPINGS = {
12
+ SCHEME_DEFAULT => "",
13
+ :dark => "dropdown-menu-dark"
14
+ }.freeze
15
+
16
+ DIRECTION_DEFAULT = :se
17
+ DIRECTION_OPTIONS = [DIRECTION_DEFAULT, :sw, :w, :e, :ne, :s].freeze
18
+
19
+ renders_many :items, lambda { |divider: false, **system_arguments|
20
+ system_arguments[:tag] = :li
21
+ system_arguments[:role] = :none if divider
22
+ system_arguments[:classes] = class_names(
23
+ system_arguments[:classes],
24
+ "dropdown-item" => !divider,
25
+ "dropdown-divider" => divider
26
+ )
27
+
28
+ Primer::BaseComponent.new(**system_arguments)
29
+ }
30
+
31
+ def initialize(direction: DIRECTION_DEFAULT, scheme: SCHEME_DEFAULT, header: nil, **system_arguments)
32
+ @header = header
33
+ @direction = direction
34
+ @system_arguments = system_arguments
35
+
36
+ @system_arguments[:tag] = "details-menu"
37
+ @system_arguments[:role] = "menu"
38
+
39
+ @system_arguments[:classes] = class_names(
40
+ @system_arguments[:classes],
41
+ "dropdown-menu",
42
+ "dropdown-menu-#{fetch_or_fallback(DIRECTION_OPTIONS, direction, DIRECTION_DEFAULT)}",
43
+ SCHEME_MAPPINGS[fetch_or_fallback(SCHEME_MAPPINGS.keys, scheme, SCHEME_DEFAULT)]
44
+ )
45
+ end
46
+ end
47
+ end
48
+ end