openproject-primer_view_components 0.11.0 → 0.13.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (134) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +110 -0
  3. data/app/assets/javascripts/app/components/primer/alpha/tool_tip.d.ts +1 -0
  4. data/app/assets/javascripts/app/components/primer/primer.d.ts +1 -1
  5. data/app/assets/javascripts/primer_view_components.js +1 -1
  6. data/app/assets/javascripts/primer_view_components.js.map +1 -1
  7. data/app/assets/styles/primer_view_components.css +1 -1
  8. data/app/assets/styles/primer_view_components.css.map +1 -1
  9. data/app/components/primer/alpha/action_bar/item.rb +7 -4
  10. data/app/components/primer/alpha/action_bar.rb +2 -2
  11. data/app/components/primer/alpha/action_bar_element.js +9 -4
  12. data/app/components/primer/alpha/action_bar_element.ts +9 -2
  13. data/app/components/primer/alpha/action_list/form_wrapper.html.erb +4 -2
  14. data/app/components/primer/alpha/action_list/form_wrapper.rb +20 -9
  15. data/app/components/primer/alpha/action_menu/action_menu_element.js +162 -86
  16. data/app/components/primer/alpha/action_menu/action_menu_element.ts +197 -82
  17. data/app/components/primer/alpha/action_menu/list.rb +0 -2
  18. data/app/components/primer/alpha/action_menu.rb +120 -3
  19. data/app/components/primer/alpha/check_box_group.rb +2 -0
  20. data/app/components/primer/alpha/dialog/header.rb +12 -0
  21. data/app/components/primer/alpha/dialog.rb +1 -1
  22. data/app/components/primer/alpha/modal_dialog.js +10 -13
  23. data/app/components/primer/alpha/modal_dialog.ts +10 -13
  24. data/app/components/primer/alpha/nav_list/divider.rb +2 -5
  25. data/app/components/primer/alpha/nav_list/group.rb +2 -98
  26. data/app/components/primer/alpha/nav_list/heading.rb +2 -27
  27. data/app/components/primer/alpha/nav_list/item.rb +2 -147
  28. data/app/components/primer/alpha/nav_list.rb +2 -205
  29. data/app/components/primer/alpha/overlay.css +1 -1
  30. data/app/components/primer/alpha/overlay.css.map +1 -1
  31. data/app/components/primer/alpha/overlay.pcss +1 -7
  32. data/app/components/primer/alpha/overlay.rb +6 -4
  33. data/app/components/primer/alpha/radio_button_group.rb +2 -0
  34. data/app/components/primer/alpha/segmented_control/item.html.erb +1 -8
  35. data/app/components/primer/alpha/segmented_control/item.rb +38 -4
  36. data/app/components/primer/alpha/segmented_control.css +1 -1
  37. data/app/components/primer/alpha/segmented_control.css.json +14 -13
  38. data/app/components/primer/alpha/segmented_control.css.map +1 -1
  39. data/app/components/primer/alpha/segmented_control.pcss +75 -66
  40. data/app/components/primer/alpha/segmented_control.rb +10 -0
  41. data/app/components/primer/alpha/text_field.css +1 -1
  42. data/app/components/primer/alpha/text_field.css.json +4 -1
  43. data/app/components/primer/alpha/text_field.css.map +1 -1
  44. data/app/components/primer/alpha/text_field.pcss +18 -3
  45. data/app/components/primer/alpha/tool_tip.d.ts +1 -0
  46. data/app/components/primer/alpha/tool_tip.js +26 -93
  47. data/app/components/primer/alpha/tool_tip.ts +25 -91
  48. data/app/components/primer/alpha/tooltip.rb +3 -1
  49. data/app/components/primer/beta/base_button.rb +4 -0
  50. data/app/components/primer/beta/button.css +1 -1
  51. data/app/components/primer/beta/button.css.json +2 -0
  52. data/app/components/primer/beta/button.css.map +1 -1
  53. data/app/components/primer/beta/button.pcss +17 -5
  54. data/app/components/primer/beta/icon_button.html.erb +1 -1
  55. data/app/components/primer/beta/icon_button.rb +8 -1
  56. data/app/components/primer/beta/link.css +1 -1
  57. data/app/components/primer/beta/link.css.json +1 -0
  58. data/app/components/primer/beta/link.css.map +1 -1
  59. data/app/components/primer/beta/link.pcss +5 -0
  60. data/app/components/primer/beta/link.rb +2 -2
  61. data/app/components/primer/beta/nav_list/divider.rb +14 -0
  62. data/app/components/primer/beta/nav_list/group.rb +107 -0
  63. data/app/components/primer/beta/nav_list/heading.rb +36 -0
  64. data/app/components/primer/beta/nav_list/item.rb +156 -0
  65. data/app/components/primer/beta/nav_list.rb +212 -0
  66. data/app/components/primer/focus_group.js +30 -4
  67. data/app/components/primer/focus_group.ts +29 -2
  68. data/app/components/primer/open_project/flex_layout.html.erb +23 -0
  69. data/app/components/primer/open_project/flex_layout.rb +52 -0
  70. data/app/components/primer/open_project/grid_layout/area.rb +38 -0
  71. data/app/components/primer/open_project/grid_layout.html.erb +11 -0
  72. data/app/components/primer/open_project/grid_layout.rb +34 -0
  73. data/app/components/primer/open_project/page_header.css +1 -1
  74. data/app/components/primer/open_project/page_header.css.map +1 -1
  75. data/app/components/primer/open_project/page_header.pcss +4 -0
  76. data/app/components/primer/primer.d.ts +1 -1
  77. data/app/components/primer/primer.js +1 -1
  78. data/app/components/primer/primer.ts +1 -1
  79. data/app/helpers/primer/form_helper.rb +10 -0
  80. data/lib/primer/accessibility.rb +3 -1
  81. data/lib/primer/deprecations.yml +20 -0
  82. data/lib/primer/forms/check_box_group.html.erb +3 -0
  83. data/lib/primer/forms/dsl/check_box_group_input.rb +1 -5
  84. data/lib/primer/forms/dsl/check_box_input.rb +5 -0
  85. data/lib/primer/forms/dsl/radio_button_input.rb +5 -0
  86. data/lib/primer/forms/form_control.html.erb +1 -4
  87. data/lib/primer/forms/radio_button_group.html.erb +3 -0
  88. data/lib/primer/forms/utils.rb +2 -0
  89. data/lib/primer/forms/validation_message.html.erb +4 -0
  90. data/lib/primer/forms/validation_message.rb +14 -0
  91. data/lib/primer/forms.rb +16 -0
  92. data/lib/primer/static/generate_info_arch.rb +86 -5
  93. data/lib/primer/view_components/version.rb +1 -1
  94. data/lib/primer/yard/component_manifest.rb +4 -0
  95. data/previews/primer/alpha/action_menu_preview/single_select_form_items.html.erb +31 -0
  96. data/previews/primer/alpha/action_menu_preview/with_actions.html.erb +6 -5
  97. data/previews/primer/alpha/action_menu_preview.rb +10 -1
  98. data/previews/primer/alpha/check_box_group_preview.rb +13 -0
  99. data/previews/primer/alpha/check_box_preview.rb +1 -0
  100. data/previews/primer/alpha/dialog_preview/autofocus_element.html.erb +8 -0
  101. data/previews/primer/alpha/dialog_preview/with_header.html.erb +5 -0
  102. data/previews/primer/alpha/dialog_preview.rb +22 -0
  103. data/previews/primer/alpha/overlay_preview.rb +1 -1
  104. data/previews/primer/alpha/radio_button_group_preview.rb +13 -0
  105. data/previews/primer/alpha/radio_button_preview.rb +2 -1
  106. data/previews/primer/alpha/segmented_control_preview.rb +35 -0
  107. data/previews/primer/alpha/text_field_preview/input_group_leading_action_menu.html.erb +21 -0
  108. data/previews/primer/alpha/text_field_preview/input_group_leading_button.html.erb +18 -0
  109. data/previews/primer/alpha/text_field_preview/input_group_trailing_button.html.erb +18 -0
  110. data/previews/primer/alpha/text_field_preview.rb +21 -0
  111. data/previews/primer/alpha/tooltip_preview/tooltip_with_dialog_moving_focus_to_input.html.erb +23 -0
  112. data/previews/primer/alpha/tooltip_preview.rb +6 -1
  113. data/previews/primer/beta/button_group_preview.rb +6 -6
  114. data/previews/primer/beta/button_preview.rb +21 -3
  115. data/previews/primer/beta/icon_button_preview.rb +3 -0
  116. data/previews/primer/{alpha → beta}/nav_list_preview/trailing_action.html.erb +1 -1
  117. data/previews/primer/{alpha → beta}/nav_list_preview.rb +5 -5
  118. data/previews/primer/open_project/flex_layout_preview.rb +73 -0
  119. data/previews/primer/open_project/grid_layout_preview.rb +37 -0
  120. data/static/arguments.json +278 -7
  121. data/static/audited_at.json +8 -0
  122. data/static/classes.json +15 -0
  123. data/static/constants.json +47 -1
  124. data/static/info_arch.json +1338 -632
  125. data/static/previews.json +271 -167
  126. data/static/statuses.json +13 -5
  127. metadata +33 -319
  128. /data/app/assets/javascripts/app/components/primer/{alpha → beta}/nav_list.d.ts +0 -0
  129. /data/app/components/primer/{alpha → beta}/nav_list/group.html.erb +0 -0
  130. /data/app/components/primer/{alpha → beta}/nav_list/item.html.erb +0 -0
  131. /data/app/components/primer/{alpha → beta}/nav_list.d.ts +0 -0
  132. /data/app/components/primer/{alpha → beta}/nav_list.html.erb +0 -0
  133. /data/app/components/primer/{alpha → beta}/nav_list.js +0 -0
  134. /data/app/components/primer/{alpha → beta}/nav_list.ts +0 -0
@@ -3,104 +3,8 @@
3
3
  module Primer
4
4
  module Alpha
5
5
  class NavList
6
- # A logical grouping of navigation links with an optional heading.
7
- #
8
- # See <%= link_to_component(Primer::Alpha::NavList) %> for usage examples.
9
- class Group < ActionList
10
- # A special "show more" list item that appears at the bottom of the group. Clicking
11
- # the item will fetch the next page of results from the URL passed in the `src` argument
12
- # and append the resulting chunk of HTML to the group.
13
- #
14
- # @param src [String] The URL to query for additional pages of list items.
15
- # @param pages [Integer] The total number of pages in the result set.
16
- # @param component_klass [Class] A component class to use instead of the default `Primer::Alpha::NavList::Item` class.
17
- # @param system_arguments [Hash] The arguments accepted by <%= link_to_component(Primer::Alpha::NavList::Item) %>.
18
- renders_one :show_more_item, lambda { |src:, pages:, component_klass: NavList::Item, **system_arguments|
19
- system_arguments[:classes] = class_names(
20
- @item_classes,
21
- system_arguments[:classes]
22
- )
23
- system_arguments[:tag] = :div
24
- system_arguments[:id] ||= self.class.generate_id(base_name: "item")
25
- system_arguments[:hidden] = true
26
- system_arguments[:href] = "#"
27
- system_arguments[:data] ||= {}
28
- system_arguments[:data][:target] = "nav-list.showMoreItem"
29
- system_arguments[:data][:action] = "click:nav-list#showMore"
30
- system_arguments[:data][:current_page] = "1"
31
- system_arguments[:data][:total_pages] = pages.to_s
32
- system_arguments[:label_arguments] = {
33
- **system_arguments[:label_arguments] || {},
34
- color: :accent
35
- }
36
-
37
- system_arguments[:content_arguments] = {
38
- **system_arguments[:content_arguments] || {},
39
- tag: :button
40
- }
41
-
42
- system_arguments[:content_arguments][:data] = merge_data(
43
- system_arguments[:content_arguments],
44
- data: { list_id: id }
45
- )
46
-
47
- component_klass.new(list: self, src: src, **system_arguments)
48
- }
49
-
50
- # @private
51
- def self.custom_element_name
52
- Primer::Alpha::NavList.custom_element_name
53
- end
54
-
55
- # @param selected_item_id [Symbol] The ID of the currently selected item. Used internally.
56
- # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
57
- def initialize(selected_item_id: nil, **system_arguments)
58
- @system_arguments = system_arguments
59
- @selected_item_id = selected_item_id
60
-
61
- super(**@system_arguments)
62
- end
63
-
64
- # Cause this group to show its list of sub items when rendered.
65
- # :nocov:
66
- def expand!
67
- @expanded = true
68
- end
69
- # :nocov:
70
-
71
- # @!parse
72
- # # Items.
73
- # #
74
- # # @param system_arguments [Hash] The arguments accepted by <%= link_to_component(Primer::Alpha::NavList::Item) %>.
75
- # renders_many :items
76
-
77
- # @private
78
- def build_item(component_klass: NavList::Item, **system_arguments)
79
- super(
80
- component_klass: component_klass,
81
- selected_item_id: @selected_item_id,
82
- **system_arguments
83
- )
84
- end
85
-
86
- # @private
87
- def build_avatar_item(component_klass: NavList::Item, **system_arguments)
88
- super(
89
- component_klass: component_klass,
90
- selected_item_id: @selected_item_id,
91
- **system_arguments
92
- )
93
- end
94
-
95
- def kind
96
- :group
97
- end
98
-
99
- def before_render
100
- super
101
-
102
- raise ArgumentError, "NavList groups are required to have headings" unless heading?
103
- end
6
+ class Group < Beta::NavList::Group
7
+ status :deprecated
104
8
  end
105
9
  end
106
10
  end
@@ -3,33 +3,8 @@
3
3
  module Primer
4
4
  module Alpha
5
5
  class NavList
6
- # The heading placed above a `NavList`'s items.
7
- #
8
- # See <%= link_to_component(Primer::Alpha::NavList) %> for usage examples.
9
- class Heading < Primer::Component
10
- attr_reader :title, :id, :heading_level, :system_arguments
11
-
12
- # @param title [String] The text content of the heading.
13
- # @param id [String] The value of the ID HTML attribute. Auto-generated by default.
14
- # @param heading_level [Integer] The heading level, i.e. 2 for an `<h2>`, 3 for an `<h3>`, etc.
15
- # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
16
- def initialize(title:, id: self.class.generate_id, heading_level: 2, **system_arguments)
17
- @title = title
18
- @id = id
19
- @heading_level = heading_level
20
- @system_arguments = system_arguments
21
- end
22
-
23
- def call
24
- render(
25
- Primer::BaseComponent.new(
26
- tag: :"h#{heading_level}",
27
- id: id,
28
- classes: "ActionListHeader",
29
- **system_arguments
30
- ).with_content(title)
31
- )
32
- end
6
+ class Heading < Beta::NavList::Heading
7
+ status :deprecated
33
8
  end
34
9
  end
35
10
  end
@@ -3,153 +3,8 @@
3
3
  module Primer
4
4
  module Alpha
5
5
  class NavList
6
- # Items are rendered as styled links. They can optionally include leading and/or trailing visuals,
7
- # such as icons, avatars, and counters. Items are selected by ID. IDs can be specified via the
8
- # `selected_item_ids` argument, which accepts a list of valid IDs for the item. Items can also
9
- # themselves contain sub items. Sub items are rendered collapsed by default.
10
- class Item < Primer::Alpha::ActionList::Item
11
- attr_reader :selected_by_ids, :sub_item
12
-
13
- # @param system_arguments [Hash] The arguments accepted by <%= link_to_component(Primer::Alpha::ActionList::Item) %>.
14
- renders_many :items, lambda { |**system_arguments|
15
- raise "Items can only be nested 2 levels deep" if sub_item?
16
-
17
- @list.build_item(parent: self, sub_item: true, **system_arguments).tap do |item|
18
- @list.will_add_item(item)
19
- end
20
- }
21
-
22
- # Whether or not this item is nested under a parent item.
23
- #
24
- # @return [Boolean]
25
- alias sub_item? sub_item
26
-
27
- # @param selected_item_id [Symbol] The ID of the currently selected list item. Used internally.
28
- # @param selected_by_ids [Array<Symbol>] The list of IDs that select this item. In other words, if the `selected_item_id` attribute on the parent `NavList` is set to one of these IDs, the item will appear selected.
29
- # @param expanded [Boolean] Whether this item shows (expands) or hides (collapses) its list of sub items.
30
- # @param sub_item [Boolean] Whether or not this item is nested under a parent item. Used internally.
31
- # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
32
- def initialize(selected_item_id: nil, selected_by_ids: [], sub_item: false, expanded: false, **system_arguments)
33
- @selected_item_id = selected_item_id
34
- @selected_by_ids = Array(selected_by_ids)
35
- @expanded = expanded
36
- @sub_item = sub_item
37
-
38
- system_arguments[:classes] = class_names(
39
- system_arguments[:classes],
40
- "ActionListItem--subItem" => @sub_item
41
- )
42
-
43
- @sub_list_arguments = {
44
- classes: class_names(
45
- "ActionList",
46
- "ActionList--subGroup"
47
- )
48
- }
49
-
50
- @list = system_arguments[:list]
51
-
52
- @sub_list_arguments["data-action"] = "keydown:#{@list.custom_element_name}#handleItemWithSubItemKeydown" if @list
53
-
54
- overrides = { "data-item-id": @selected_by_ids.join(" ") }
55
-
56
- super(**system_arguments, **overrides)
57
- end
58
-
59
- def active?
60
- item_active?(self) && items.empty?
61
- end
62
-
63
- # Cause this item to show its list of sub items when rendered.
64
- def expand!
65
- @expanded = true
66
- end
67
-
68
- def before_render
69
- if active_sub_item?
70
- expand!
71
-
72
- @content_arguments[:classes] = class_names(
73
- @content_arguments[:classes],
74
- "ActionListContent--hasActiveSubItem"
75
- )
76
- else
77
- @system_arguments[:classes] = class_names(
78
- @system_arguments[:classes],
79
- "ActionListItem--navActive" => active?
80
- )
81
- end
82
-
83
- @content_arguments[:"aria-current"] = "page" if active?
84
-
85
- super
86
-
87
- raise "Cannot render a trailing action for an item with subitems" if items.present? && trailing_action.present?
88
-
89
- raise "Cannot pass `selected_by_ids:` for an item with subitems, since parent items cannot be selected" if items.present? && @selected_by_ids.present?
90
-
91
- return if items.blank?
92
-
93
- @sub_list_arguments[:aria] = merge_aria(
94
- @sub_list_arguments,
95
- { aria: { labelledby: id } }
96
- )
97
-
98
- raise ArgumentError, "Items with sub-items cannot have hrefs" if href.present?
99
-
100
- @content_arguments[:tag] = :button
101
- @content_arguments[:"aria-expanded"] = @expanded.to_s
102
- @content_arguments[:"data-action"] = "
103
- click:#{@list.custom_element_name}#handleItemWithSubItemClick
104
- keydown:#{@list.custom_element_name}#handleItemWithSubItemKeydown
105
- "
106
-
107
- with_private_trailing_action_icon(:"chevron-down", classes: "ActionListItem-collapseIcon")
108
-
109
- @system_arguments[:classes] = class_names(
110
- @system_arguments[:classes],
111
- "ActionListItem--hasSubItem"
112
- )
113
- end
114
-
115
- def kind
116
- :item
117
- end
118
-
119
- private
120
-
121
- # Normally it would be easier to simply ask each item for its active status, eg.
122
- # items.any?(&:active?), but unfortunately the view context is not set on each
123
- # item until _after_ the parent's before_render, etc methods have been called.
124
- # This means helper methods like current_page? will blow up with an error, since
125
- # `helpers` is simply an alias for the view context (i.e. an instance of
126
- # ActionView::Base). Since we know the view context for the parent object must
127
- # be set before `before_render` is invoked, we can call helper methods here in
128
- # the parent and bypass the problem entirely. Maybe not the most OO approach,
129
- # but it works.
130
- def item_active?(item)
131
- if item.selected_by_ids.present?
132
- item.selected_by_ids.include?(@selected_item_id)
133
- elsif item.href
134
- current_page?(item.href)
135
- else
136
- # :nocov:
137
- false
138
- # :nocov:
139
- end
140
- end
141
-
142
- def active_sub_item?
143
- items.any? { |subitem| item_active?(subitem) }
144
- end
145
-
146
- def current_page?(url)
147
- helpers.current_page?(url)
148
- end
149
-
150
- def list_class
151
- Primer::Alpha::NavList
152
- end
6
+ class Item < Beta::NavList::Item
7
+ status :deprecated
153
8
  end
154
9
  end
155
10
  end
@@ -2,211 +2,8 @@
2
2
 
3
3
  module Primer
4
4
  module Alpha
5
- # `NavList` provides a simple way to render side navigation, i.e. navigation
6
- # that appears to the left or right side of some main content. Each group in a
7
- # nav list is a list of links.
8
- #
9
- # Nav list groups can contain sub items. Rather than navigating to a URL, groups
10
- # with sub items expand and collapse on click. To indicate this functionality, the
11
- # group will automatically render with a trailing chevron icon that changes direction
12
- # when the group expands and collapses.
13
- #
14
- # Nav list items appear visually active when selected. Each nav item must have one
15
- # or more ID values that determine which item will appear selected. Use the
16
- # `selected_item_id` argument to select the appropriate item.
17
- class NavList < Primer::Component
18
- status :alpha
19
- audited_at "2023-07-10"
20
-
21
- # @private
22
- def self.custom_element_name
23
- "nav-list"
24
- end
25
-
26
- # The heading for the list at large. Accepts the arguments accepted by <%= link_to_component(Primer::Alpha::NavList::Heading) %>.
27
- #
28
- renders_one :heading, Primer::Alpha::NavList::Heading
29
-
30
- # @!parse
31
- # # Adds an item to the list.
32
- # #
33
- # # @param component_klass [Class] The class to use instead of the default <%= link_to_component(Primer::Alpha::NavList::Item) %>
34
- # # @param system_arguments [Hash] These arguments are forwarded to <%= link_to_component(Primer::Alpha::NavList::Item) %>, or whatever class is passed as the `component_klass` argument.
35
- # def with_item(component_klass: Primer::Alpha::NavList::Item, **system_arguments, &block)
36
- # end
37
-
38
- # @!parse
39
- # # Adds an avatar item to the list. Avatar items are a convenient way to accessibly add an item with a leading avatar image.
40
- # #
41
- # # @param src [String] The source url of the avatar image.
42
- # # @param username [String] The username associated with the avatar.
43
- # # @param full_name [String] Optional. The user's full name.
44
- # # @param full_name_scheme [Symbol] Optional. How to display the user's full name. <%= one_of(Primer::Alpha::ActionList::Item::DESCRIPTION_SCHEME_OPTIONS) %>
45
- # # @param component_klass [Class] The class to use instead of the default <%= link_to_component(Primer::Alpha::NavList::Item) %>
46
- # # @param avatar_arguments [Hash] Optional. The arguments accepted by <%= link_to_component(Primer::Beta::Avatar) %>
47
- # # @param system_arguments [Hash] These arguments are forwarded to <%= link_to_component(Primer::Alpha::NavList::Item) %>, or whatever class is passed as the `component_klass` argument.
48
- # def with_avatar_item(src:, username:, full_name: nil, full_name_scheme: Primer::Alpha::ActionList::Item::DEFAULT_DESCRIPTION_SCHEME, component_klass: Primer::Alpha::NavList::Item, avatar_arguments: {}, **system_arguments, &block)
49
- # end
50
-
51
- # @!parse
52
- # # Adds a group to the list. A group is a list of links and a (required) heading.
53
- # #
54
- # # @param system_arguments [Hash] The arguments accepted by <%= link_to_component(Primer::Alpha::NavList::Group) %>.
55
- # def with_group(**system_arguments, &block)
56
- # end
57
-
58
- # @!parse
59
- # # Adds a divider to the list. Dividers visually separate items and groups.
60
- # #
61
- # # @param system_arguments [Hash] The arguments accepted by <%= link_to_component(Primer::Alpha::NavList::Divider) %>.
62
- # def with_divider(**system_arguments, &block)
63
- # end
64
-
65
- # Items. Items can be individual items, dividers, or groups. See the documentation for `#with_item`, `#with_divider`, and `#with_group` respectively for more information.
66
- #
67
- renders_many :items, types: {
68
- item: {
69
- renders: lambda { |**system_arguments, &block|
70
- build_item(**system_arguments, &block)
71
- },
72
-
73
- as: :item
74
- },
75
-
76
- avatar_item: {
77
- renders: lambda { |**system_arguments|
78
- build_avatar_item(**system_arguments)
79
- },
80
-
81
- as: :avatar_item
82
- },
83
-
84
- divider: {
85
- renders: Primer::Alpha::NavList::Divider,
86
- as: :divider
87
- },
88
-
89
- group: {
90
- renders: lambda { |**system_arguments, &block|
91
- Primer::Alpha::NavList::Group.new(
92
- selected_item_id: @selected_item_id,
93
- **system_arguments,
94
- &block
95
- )
96
- },
97
-
98
- as: :group
99
- }
100
- }
101
-
102
- # @param selected_item_id [Symbol] The ID of the currently selected item. The default is `nil`, meaning no item is selected.
103
- # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
104
- def initialize(selected_item_id: nil, **system_arguments)
105
- @system_arguments = system_arguments
106
- @selected_item_id = selected_item_id
107
- end
108
-
109
- # Builds a new item but does not add it to the list. Use this method
110
- # instead of the `#with_item` slot if you need to render an item outside
111
- # the context of a list, eg. if rendering additional items to append to
112
- # an existing list, perhaps via a separate HTTP request.
113
- #
114
- # @param component_klass [Class] The class to use instead of the default <%= link_to_component(Primer::Alpha::NavList::Item) %>
115
- # @param system_arguments [Hash] These arguments are forwarded to <%= link_to_component(Primer::Alpha::NavList::Item) %>, or whatever class is passed as the `component_klass` argument.
116
- def build_item(component_klass: Primer::Alpha::NavList::Item, **system_arguments, &block)
117
- component_klass.new(
118
- list: top_level_group,
119
- selected_item_id: @selected_item_id,
120
- **system_arguments,
121
- &block
122
- )
123
- end
124
-
125
- # Builds a new avatar item but does not add it to the list. Avatar items
126
- # are a convenient way to accessibly add an item with a leading avatar
127
- # image. Use this method instead of the `#with_avatar_item` slot if you
128
- # need to render an avatar item outside the context of a list, eg. if
129
- # rendering additional items to append to an existing list, perhaps via
130
- # a separate HTTP request.
131
- #
132
- # @param src [String] The source url of the avatar image.
133
- # @param username [String] The username associated with the avatar.
134
- # @param full_name [String] Optional. The user's full name.
135
- # @param full_name_scheme [Symbol] Optional. How to display the user's full name. <%= one_of(Primer::Alpha::ActionList::Item::DESCRIPTION_SCHEME_OPTIONS) %>
136
- # @param component_klass [Class] The class to use instead of the default <%= link_to_component(Primer::Alpha::NavList::Item) %>
137
- # @param avatar_arguments [Hash] Optional. The arguments accepted by <%= link_to_component(Primer::Beta::Avatar) %>
138
- # @param system_arguments [Hash] These arguments are forwarded to <%= link_to_component(Primer::Alpha::NavList::Item) %>, or whatever class is passed as the `component_klass` argument.
139
- def build_avatar_item(src:, username:, full_name: nil, full_name_scheme: Primer::Alpha::ActionList::Item::DEFAULT_DESCRIPTION_SCHEME, component_klass: Primer::Alpha::NavList::Item, avatar_arguments: {}, **system_arguments)
140
- component_klass.new(
141
- list: top_level_group,
142
- selected_item_id: @selected_item_id,
143
- label: username,
144
- description_scheme: full_name_scheme,
145
- **system_arguments
146
- ).tap do |item|
147
- item.with_leading_visual_raw_content do
148
- # no alt text necessary
149
- item.render(Primer::Beta::Avatar.new(src: src, **avatar_arguments, role: :presentation, size: 16))
150
- end
151
-
152
- item.with_description_content(full_name) if full_name
153
- end
154
- end
155
-
156
- private
157
-
158
- def before_render
159
- if heading?
160
- raise ArgumentError, "Please don't set an aria-label if a heading is provided" if aria(:label, @system_arguments)
161
-
162
- @system_arguments[:aria] = merge_aria(
163
- @system_arguments,
164
- { aria: { labelledby: heading.id } }
165
- )
166
- else
167
- raise ArgumentError, "When no heading is provided, an aria-label must be given" unless aria(:label, @system_arguments)
168
- end
169
- end
170
-
171
- # Lists that contain top-level items (i.e. items outside of a group) should be wrapped in a <ul>
172
- def render_outer_list?
173
- items.any? { |item| !group?(item) }
174
- end
175
-
176
- def render_divider_between?(item1, item2)
177
- return false if either_is_divider?(item1, item2)
178
-
179
- both_are_groups?(item1, item2) || heterogeneous?(item1, item2)
180
- end
181
-
182
- def both_are_groups?(item1, item2)
183
- group?(item1) && group?(item2)
184
- end
185
-
186
- def heterogeneous?(item1, item2)
187
- kind(item1) != kind(item2)
188
- end
189
-
190
- def either_is_divider?(item1, item2)
191
- divider?(item1) || divider?(item2)
192
- end
193
-
194
- def group?(item)
195
- kind(item) == :group
196
- end
197
-
198
- def divider?(item)
199
- kind(item) == :divider
200
- end
201
-
202
- def kind(item)
203
- item.respond_to?(:kind) ? item.kind : :item
204
- end
205
-
206
- def top_level_group
207
- # dummy group for the list: argument in the item slot above
208
- @top_level_group ||= Primer::Alpha::NavList::Group.new(selected_item_id: @selected_item_id)
209
- end
5
+ class NavList < Beta::NavList
6
+ status :deprecated
210
7
  end
211
8
  end
212
9
  end
@@ -1 +1 @@
1
- anchored-position[popover]{border-width:0;inset:auto;min-width:192px;overflow:visible;padding:0;position:absolute}.Overlay{display:flex}anchored-position[popover]:not(.\:popover-open){display:none}anchored-position.not-anchored::-webkit-backdrop{background-color:var(--overlay-backdrop-bgColor,var(--color-neutral-muted))}anchored-position.not-anchored::backdrop{background-color:var(--overlay-backdrop-bgColor,var(--color-neutral-muted))}@supports selector(:popover-open){anchored-position[popover]:not(.\:popover-open){display:revert}}@supports selector(:open){anchored-position[popover]:not(.\:popover-open){display:revert}}
1
+ anchored-position[popover]{background:none;border-width:0;inset:auto;min-width:192px;overflow:visible;padding:0;position:absolute}.Overlay{display:flex}anchored-position[popover]:not(.\:popover-open){display:none}anchored-position.not-anchored::-webkit-backdrop{background-color:var(--overlay-backdrop-bgColor,var(--color-neutral-muted))}anchored-position.not-anchored::backdrop{background-color:var(--overlay-backdrop-bgColor,var(--color-neutral-muted))}@supports selector(:popover-open){anchored-position[popover]:not(.\:popover-open){display:revert}}
@@ -1 +1 @@
1
- {"version":3,"sources":["overlay.pcss"],"names":[],"mappings":"AAAA,2BACE,cAAe,CAIf,UAAW,CADX,eAAgB,CAEhB,gBAAiB,CAJjB,SAAU,CACV,iBAIF,CAEA,SACE,YACF,CAEA,gDACE,YACF,CAEA,iDACE,2EACF,CAFA,yCACE,2EACF,CAGA,kCACE,gDACE,cACF,CACF,CAGA,0BACE,gDACI,cACJ,CACF","file":"overlay.css","sourcesContent":["anchored-position[popover] {\n border-width: 0;\n padding: 0;\n position: absolute;\n min-width: 192px;\n inset: auto;\n overflow: visible;\n}\n\n.Overlay {\n display: flex;\n}\n\nanchored-position[popover]:not(.\\:popover-open) {\n display: none;\n}\n\nanchored-position.not-anchored::backdrop {\n background-color: var(--overlay-backdrop-bgColor, var(--color-neutral-muted));\n}\n\n/* This reverts the declaration above for native popover, where `:popover-open` is supported */\n@supports selector(:popover-open) {\n anchored-position[popover]:not(.\\:popover-open) {\n display: revert;\n }\n}\n\n/* This reverts the declaration above for native popover, where `:open` is supported (Chrome 113, Safari TP) */\n@supports selector(:open) {\n anchored-position[popover]:not(.\\:popover-open) {\n display: revert;\n }\n}\n"]}
1
+ {"version":3,"sources":["overlay.pcss"],"names":[],"mappings":"AAAA,2BAOE,eAAgB,CANhB,cAAe,CAIf,UAAW,CADX,eAAgB,CAEhB,gBAAiB,CAJjB,SAAU,CACV,iBAKF,CAEA,SACE,YACF,CAEA,gDACE,YACF,CAEA,iDACE,2EACF,CAFA,yCACE,2EACF,CAGA,kCACE,gDACE,cACF,CACF","file":"overlay.css","sourcesContent":["anchored-position[popover] {\n border-width: 0;\n padding: 0;\n position: absolute;\n min-width: 192px;\n inset: auto;\n overflow: visible;\n background: none;\n}\n\n.Overlay {\n display: flex;\n}\n\nanchored-position[popover]:not(.\\:popover-open) {\n display: none;\n}\n\nanchored-position.not-anchored::backdrop {\n background-color: var(--overlay-backdrop-bgColor, var(--color-neutral-muted));\n}\n\n/* This reverts the declaration above for native popover, where `:popover-open` is supported */\n@supports selector(:popover-open) {\n anchored-position[popover]:not(.\\:popover-open) {\n display: revert;\n }\n}\n"]}
@@ -5,6 +5,7 @@ anchored-position[popover] {
5
5
  min-width: 192px;
6
6
  inset: auto;
7
7
  overflow: visible;
8
+ background: none;
8
9
  }
9
10
 
10
11
  .Overlay {
@@ -25,10 +26,3 @@ anchored-position.not-anchored::backdrop {
25
26
  display: revert;
26
27
  }
27
28
  }
28
-
29
- /* This reverts the declaration above for native popover, where `:open` is supported (Chrome 113, Safari TP) */
30
- @supports selector(:open) {
31
- anchored-position[popover]:not(.\:popover-open) {
32
- display: revert;
33
- }
34
- }
@@ -178,10 +178,12 @@ module Primer
178
178
  end
179
179
 
180
180
  def before_render
181
- if header?
182
- @system_arguments[:aria][:labelledby] ||= title_id
183
- else
184
- @system_arguments[:aria][:label] = @title
181
+ if @system_arguments[:role].present?
182
+ if header?
183
+ @system_arguments[:aria][:labelledby] ||= title_id
184
+ else
185
+ @system_arguments[:aria][:label] = @title
186
+ end
185
187
  end
186
188
  with_body unless body?
187
189
  end
@@ -23,6 +23,8 @@ module Primer
23
23
  # @param label [String] Label text displayed above the input.
24
24
  # @param hidden [Boolean] When set to `true`, visually hides the group.
25
25
  # @param caption [String] A string describing the field and what sorts of input it expects. Displayed below the group.
26
+ # @param invalid [Boolean] If set to `true`, the input will be marked as invalid. Implied if `validation_message` is truthy. This option is set to `true` automatically if the model object associated with the form reports that the input is invalid via Rails validations. It is provided for cases where the form does not have an associated model. If the input is invalid as determined by Rails validations, setting `invalid` to `false` will have no effect.
27
+ # @param validation_message [String] A string displayed between the caption and the input indicating the input's contents are invalid. This option is, by default, set to the first Rails validation message for the input (assuming the form is associated with a model object). Use `validation_message` to override the default or to provide a validation message in case there is no associated model object.
26
28
  # @param label_arguments [Hash] Attributes that will be passed to Rails' `builder.label` method. These can be HTML attributes or any of the other label options Rails supports. They will appear as HTML attributes on the `<label>` tag.
27
29
 
28
30
  # @!method radio_button
@@ -2,12 +2,5 @@
2
2
  "SegmentedControl-item",
3
3
  "SegmentedControl-item--selected": @selected
4
4
  ) %>" role="listitem" data-targets="segmented-control.items">
5
- <% if @hide_labels %>
6
- <%= render Primer::Beta::IconButton.new(icon: @icon, "aria-label": @label, **@system_arguments) %>
7
- <% else %>
8
- <%= render Primer::Beta::Button.new(**@system_arguments) do |button| %>
9
- <% button.with_leading_visual_icon(icon: @icon) unless @icon.nil? %>
10
- <%= @label %>
11
- <% end %>
12
- <% end %>
5
+ <%= render @button %>
13
6
  </li>
@@ -13,16 +13,50 @@ module Primer
13
13
  # @param selected [Boolean] Whether the item is selected
14
14
  # @param icon [Symbol] The icon to use
15
15
  # @param hide_labels [Symbol] Whether to only show the icon
16
- def initialize(label:, selected: false, icon: nil, hide_labels: false, **system_arguments)
17
- @icon = icon
18
- @hide_labels = hide_labels
19
- @label = label
16
+ def initialize(
17
+ label:,
18
+ selected: false,
19
+ icon: nil,
20
+ hide_labels: false,
21
+ **system_arguments
22
+ )
20
23
  @selected = selected
21
24
 
22
25
  @system_arguments = system_arguments
23
26
  @system_arguments[:"data-action"] = "click:segmented-control#select" if system_arguments[:href].nil?
24
27
  @system_arguments[:"aria-current"] = selected
25
28
  @system_arguments[:scheme] = :invisible
29
+
30
+ if hide_labels
31
+ @button = Primer::Beta::IconButton.new(
32
+ icon: icon,
33
+ "aria-label": label,
34
+ **@system_arguments
35
+ )
36
+ else
37
+ @button = Primer::Beta::Button.new(**@system_arguments)
38
+ @button.with_leading_visual_icon(icon: icon) if icon
39
+ @button.with_content(label)
40
+ end
41
+ end
42
+
43
+ # @!parse
44
+ # # Optional trailing Label
45
+ # #
46
+ # # @param system_arguments [Hash] The arguments accepted by <%= link_to_component(Primer::Beta::Button) %>'s `with_trailing_visual_label` slot.
47
+ # renders_one(:trailing_visual_label)
48
+
49
+ # Optional trailing label.
50
+ #
51
+ # @param system_arguments [Hash] The arguments accepted by <%= link_to_component(Primer::Beta::Button) %>'s `with_trailing_visual_label` slot.
52
+ def with_trailing_visual_label(**system_arguments, &block)
53
+ @button.with_trailing_visual_label(**system_arguments, &block)
54
+ end
55
+
56
+ private
57
+
58
+ def before_render
59
+ content
26
60
  end
27
61
  end
28
62
  end
@@ -1 +1 @@
1
- .SegmentedControl{background-color:var(--controlTrack-bgColor-rest,var(--color-segmented-control-bg));border-radius:var(--borderRadius-medium,.375rem);display:inline-flex;list-style:none}.SegmentedControl-item{border:var(--borderWidth-thin,max(1px,.0625rem)) solid #0000;border-radius:var(--borderRadius-medium,.375rem);display:inline-flex;padding:var(--control-xsmall-paddingInline-condensed,.25rem);position:relative}.SegmentedControl-item .Button--invisible:hover:not(:disabled){background-color:var(--controlTrack-bgColor-hover,var(--color-action-list-item-default-hover-bg))}.SegmentedControl-item .Button--invisible:active:not(:disabled){background-color:var(--controlTrack-bgColor-active,var(--color-action-list-item-default-active-bg))}.SegmentedControl-item.SegmentedControl-item--selected{background-color:var(--controlKnob-bgColor-rest,var(--color-segmented-control-button-bg));border-color:var(--controlKnob-borderColor-rest,var(--color-segmented-control-button-selected-border))}.SegmentedControl-item.SegmentedControl-item--selected .Button{font-weight:var(--base-text-weight-semibold,600)}.SegmentedControl-item.SegmentedControl-item--selected .Button:hover{background-color:initial}.SegmentedControl-item.SegmentedControl-item--selected:before{border-color:#0000!important}.SegmentedControl-item.SegmentedControl-item--selected+.SegmentedControl-item:before{border-color:#0000}.SegmentedControl-item .Button-label[data-content]:before{content:attr(data-content);display:block;font-weight:var(--base-text-weight-semibold,600);height:0;visibility:hidden}.SegmentedControl-item:not(:first-child):before{border-left:var(--borderWidth-thin,max(1px,.0625rem)) solid var(--borderColor-default,var(--color-border-default));content:"";inset:0 0 0 -1px;margin-bottom:var(--control-medium-paddingBlock,.375rem);margin-top:var(--control-medium-paddingBlock,.375rem);position:absolute}.SegmentedControl-item .Button{border:0;color:var(--button-default-fgColor-rest,var(--color-btn-text));font-weight:var(--base-text-weight-normal,400);transition:none}.SegmentedControl-item .Button:focus-visible{border-radius:calc(var(--borderRadius-medium,.375rem) - 5px);outline-offset:calc(var(--control-xsmall-paddingInline-condensed,.25rem) - var(--borderWidth-thin,max(1px, .0625rem)))}.SegmentedControl-item .Button--small{height:calc(var(--control-small-size,1.75rem) - var(--control-xsmall-paddingInline-condensed,.25rem)*2 - var(--borderWidth-thin,max(1px, .0625rem))*2);padding:0 calc(var(--control-small-paddingInline-condensed,.5rem) - var(--control-xsmall-paddingInline-condensed,.25rem))}.SegmentedControl-item .Button--small.Button--iconOnly{width:calc(var(--control-medium-size,2rem) - var(--control-xsmall-paddingInline-condensed,.25rem)*2 - var(--borderWidth-thin,max(1px, .0625rem))*2)}.SegmentedControl-item .Button--small.Button--iconOnly:before{content:"";height:100%;left:50%;min-height:var(--control-medium-size,2rem);min-width:var(--control-medium-size,2rem);position:absolute;top:50%;transform:translateX(-50%) translateY(-50%);width:100%}.SegmentedControl-item .Button--medium{height:calc(var(--control-medium-size,2rem) - var(--control-xsmall-paddingInline-condensed,.25rem)*2 - var(--borderWidth-thin,max(1px, .0625rem))*2);padding:0 calc(var(--control-medium-paddingInline-normal,.75rem) - var(--control-xsmall-paddingInline-condensed,.25rem))}.SegmentedControl-item .Button--medium.Button--iconOnly{width:calc(var(--control-medium-size,2rem) - var(--control-xsmall-paddingInline-condensed,.25rem)*2 - var(--borderWidth-thin,max(1px, .0625rem))*2)}.SegmentedControl-item .Button--medium.Button--iconOnly:before{content:"";height:100%;left:50%;min-height:var(--control-medium-size,2rem);min-width:var(--control-medium-size,2rem);position:absolute;top:50%;transform:translateX(-50%) translateY(-50%);width:100%}.SegmentedControl-item .Button--large{height:calc(var(--control-large-size,2.5rem) - var(--control-xsmall-paddingInline-condensed,.25rem)*2 - var(--borderWidth-thin,max(1px, .0625rem))*2);padding:0 calc(var(--control-large-paddingInline-spacious,1rem) - var(--control-xsmall-paddingInline-condensed,.25rem))}.SegmentedControl-item .Button--large.Button--iconOnly{width:calc(var(--control-large-size,2.5rem) - var(--control-xsmall-paddingInline-condensed,.25rem)*2 - var(--borderWidth-thin,max(1px, .0625rem))*2)}.SegmentedControl-item .Button--large.Button--iconOnly:before{content:"";height:100%;left:50%;min-height:var(--control-large-size,2.5rem);min-width:var(--control-large-size,2.5rem);position:absolute;top:50%;transform:translateX(-50%) translateY(-50%);width:100%}.SegmentedControl-item .Button--iconOnly{padding:initial}.SegmentedControl-item .Button--invisible.Button--invisible-noVisuals .Button-label{color:var(--button-default-fgColor-rest,var(--color-btn-text))}.SegmentedControl--fullWidth{display:flex}.SegmentedControl--fullWidth .SegmentedControl-item{flex:1;justify-content:center}.SegmentedControl--fullWidth .Button--iconOnly,.SegmentedControl--fullWidth .Button-withTooltip{width:100%}
1
+ .SegmentedControl{--segmentedControl-item-padding:var(--control-small-paddingBlock,0.25rem);background-color:var(--controlTrack-bgColor-rest,var(--color-segmented-control-bg));border-radius:var(--borderRadius-medium,.375rem);display:inline-flex;list-style:none}.SegmentedControl--iconOnly .Button--iconOnly.Button--large,.SegmentedControl--iconOnly .Button--iconOnly.Button--medium,.SegmentedControl--iconOnly .Button--iconOnly.Button--small{padding-inline:0!important;width:100%}.SegmentedControl--small{--segmentedControl-item-padding:var(--control-xsmall-paddingBlock,0.125rem)}.SegmentedControl--small .SegmentedControl-item{height:var(--control-small-size,1.75rem)}.SegmentedControl--small .SegmentedControl-item .Button{padding-inline:calc(var(--control-xsmall-paddingInline-normal,.5rem) - var(--segmentedControl-item-padding))}.SegmentedControl--small.SegmentedControl--iconOnly .SegmentedControl-item{width:var(--control-small-size,1.75rem)}.SegmentedControl--medium .SegmentedControl-item{height:var(--control-medium-size,2rem)}.SegmentedControl--medium.SegmentedControl--iconOnly .SegmentedControl-item{width:var(--control-medium-size,2rem)}.SegmentedControl--large .SegmentedControl-item{height:var(--control-large-size,2.5rem)}.SegmentedControl--large .SegmentedControl-item .Button{padding-inline:calc(var(--control-large-paddingInline-normal,.75rem) - var(--segmentedControl-item-padding))}.SegmentedControl--large.SegmentedControl--iconOnly .SegmentedControl-item{width:var(--control-large-size,2.5rem)}.SegmentedControl-item{border:var(--borderWidth-thin,max(1px,.0625rem)) solid #0000;border-radius:var(--borderRadius-medium,.375rem);display:inline-flex;height:var(--control-medium-size,2rem);justify-content:center;padding:var(--segmentedControl-item-padding);position:relative}.SegmentedControl-item .Button-withTooltip{width:100%}.SegmentedControl-item .Button--invisible:hover:not(:disabled){background-color:var(--controlTrack-bgColor-hover,var(--color-action-list-item-default-hover-bg))}.SegmentedControl-item .Button--invisible:active:not(:disabled){background-color:var(--controlTrack-bgColor-active,var(--color-action-list-item-default-active-bg))}.SegmentedControl-item.SegmentedControl-item--selected{background-color:var(--controlKnob-bgColor-rest,var(--color-segmented-control-button-bg));border-color:var(--controlKnob-borderColor-rest,var(--color-segmented-control-button-selected-border))}.SegmentedControl-item.SegmentedControl-item--selected .Button{font-weight:var(--base-text-weight-semibold,600)}.SegmentedControl-item.SegmentedControl-item--selected .Button:hover{background-color:initial}.SegmentedControl-item.SegmentedControl-item--selected:before{border-color:#0000!important}.SegmentedControl-item.SegmentedControl-item--selected+.SegmentedControl-item:before{border-color:#0000}.SegmentedControl-item .Button-label[data-content]:before{content:attr(data-content);display:block;font-weight:var(--base-text-weight-semibold,600);height:0;visibility:hidden}.SegmentedControl-item:not(:first-child):before{border-left:var(--borderWidth-thin,max(1px,.0625rem)) solid var(--borderColor-default,var(--color-border-default));content:"";inset:0 0 0 -1px;margin-bottom:var(--control-medium-paddingBlock,.375rem);margin-top:var(--control-medium-paddingBlock,.375rem);position:absolute}.SegmentedControl-item .Button{border:0;border-radius:calc(var(--borderRadius-medium,.375rem) - var(--segmentedControl-item-padding)/2);font-weight:var(--base-text-weight-normal,400);height:100%;padding-inline:calc(var(--control-medium-paddingInline-normal,.75rem) - var(--segmentedControl-item-padding));width:100%}.SegmentedControl-item .Button:focus-visible{border-radius:calc(var(--borderRadius-medium,.375rem) - var(--segmentedControl-item-padding)/1);outline-offset:calc(var(--segmentedControl-item-padding) - var(--borderWidth-thin,max(1px, .0625rem)))}.SegmentedControl-item .Button--invisible.Button--invisible-noVisuals .Button-label{color:var(--button-default-fgColor-rest,var(--color-btn-text))}.SegmentedControl--fullWidth{display:flex}.SegmentedControl--fullWidth .SegmentedControl-item{flex:1;justify-content:center}