primer_view_components 0.1.0 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +40 -0
  3. data/app/assets/javascripts/primer_view_components.js +1 -1
  4. data/app/assets/javascripts/primer_view_components.js.map +1 -1
  5. data/app/assets/styles/primer_view_components.css +1 -1
  6. data/app/assets/styles/primer_view_components.css.map +1 -1
  7. data/app/components/primer/alpha/action_list/divider.rb +2 -2
  8. data/app/components/primer/alpha/action_list/heading.html.erb +1 -1
  9. data/app/components/primer/alpha/action_list/heading.rb +11 -5
  10. data/app/components/primer/alpha/action_list/item.rb +19 -15
  11. data/app/components/primer/alpha/action_list.html.erb +7 -8
  12. data/app/components/primer/alpha/action_list.rb +16 -11
  13. data/app/components/primer/alpha/nav_list/{section.rb → group.rb} +5 -5
  14. data/app/components/primer/alpha/nav_list/item.html.erb +1 -1
  15. data/app/components/primer/alpha/nav_list/item.rb +15 -1
  16. data/app/components/primer/alpha/nav_list.d.ts +1 -0
  17. data/app/components/primer/alpha/nav_list.html.erb +8 -8
  18. data/app/components/primer/alpha/nav_list.js +21 -0
  19. data/app/components/primer/alpha/nav_list.rb +30 -34
  20. data/app/components/primer/alpha/nav_list.ts +23 -0
  21. data/app/components/primer/alpha/navigation/tab.rb +168 -0
  22. data/app/components/primer/alpha/overlay/header.html.erb +2 -2
  23. data/app/components/primer/alpha/overlay.rb +29 -9
  24. data/app/components/primer/alpha/tab_nav.rb +10 -3
  25. data/app/components/primer/alpha/tab_panels.rb +2 -2
  26. data/app/components/primer/alpha/underline_nav.css +1 -1
  27. data/app/components/primer/alpha/underline_nav.css.map +1 -1
  28. data/app/components/primer/alpha/underline_nav.pcss +1 -0
  29. data/app/components/primer/alpha/underline_nav.rb +2 -2
  30. data/app/components/primer/alpha/underline_panels.rb +2 -2
  31. data/app/components/primer/beta/button.html.erb +1 -1
  32. data/app/components/primer/beta/button.rb +2 -1
  33. data/app/components/primer/component.rb +34 -0
  34. data/app/components/primer/navigation/tab_component.rb +3 -157
  35. data/app/components/primer/truncate.rb +1 -1
  36. data/lib/primer/deprecations.yml +9 -0
  37. data/lib/primer/forms/dsl/text_field_input.rb +1 -1
  38. data/lib/primer/forms/primer_text_field.js +17 -6
  39. data/lib/primer/forms/primer_text_field.ts +15 -7
  40. data/lib/primer/forms/text_field.html.erb +3 -3
  41. data/lib/primer/view_components/version.rb +1 -1
  42. data/lib/primer/yard/component_manifest.rb +2 -1
  43. data/lib/tasks/docs.rake +1 -1
  44. data/previews/primer/alpha/action_list_preview.rb +41 -29
  45. data/previews/primer/alpha/nav_list_preview/trailing_action.html.erb +19 -0
  46. data/previews/primer/alpha/nav_list_preview.rb +19 -30
  47. data/previews/primer/alpha/overlay_preview.rb +34 -4
  48. data/previews/primer/alpha/tab_nav_preview/with_extra.html.erb +8 -0
  49. data/previews/primer/alpha/tab_nav_preview.rb +5 -0
  50. data/previews/primer/alpha/tab_panels_preview/with_extra.html.erb +17 -0
  51. data/previews/primer/alpha/tab_panels_preview.rb +5 -0
  52. data/static/arguments.json +64 -8
  53. data/static/audited_at.json +2 -1
  54. data/static/constants.json +20 -8
  55. data/static/previews.json +20 -5
  56. data/static/statuses.json +4 -3
  57. metadata +10 -8
  58. data/app/components/primer/alpha/nav_list/section.html.erb +0 -3
  59. data/previews/primer/alpha/action_list_preview/heading.html.erb +0 -4
  60. /data/app/components/primer/{navigation/tab_component.html.erb → alpha/navigation/tab.html.erb} +0 -0
@@ -0,0 +1,168 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Primer
4
+ module Alpha
5
+ module Navigation
6
+ # This component is part of navigation components such as `Primer::Alpha::TabNav`
7
+ # and `Primer::Alpha::UnderlineNav` and should not be used by itself.
8
+ #
9
+ # @accessibility
10
+ # `Tab` renders the selected anchor tab with `aria-current="page"` by default.
11
+ # When the selected tab does not correspond to the current page, such as in a nested inner tab, make sure to use aria-current="true"
12
+ class Tab < Primer::Component
13
+ status :alpha
14
+
15
+ DEFAULT_ARIA_CURRENT_FOR_ANCHOR = :page
16
+ ARIA_CURRENT_OPTIONS_FOR_ANCHOR = [true, DEFAULT_ARIA_CURRENT_FOR_ANCHOR].freeze
17
+ # Panel controlled by the Tab. This will not render anything in the tab itself.
18
+ # It will provide a accessor for the Tab's parent to call and render the panel
19
+ # content in the appropriate place.
20
+ # Refer to `UnderlineNav` and `TabNav` implementations for examples.
21
+ #
22
+ # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
23
+ renders_one :panel, lambda { |**system_arguments|
24
+ return unless @with_panel
25
+
26
+ deny_tag_argument(**system_arguments)
27
+ system_arguments[:id] = @panel_id
28
+ system_arguments[:tag] = :div
29
+ system_arguments[:role] ||= :tabpanel
30
+ system_arguments[:tabindex] = 0
31
+ system_arguments[:hidden] = true unless @selected
32
+
33
+ label_present = aria("label", system_arguments) || aria("labelledby", system_arguments)
34
+ unless label_present
35
+ if @id.present?
36
+ system_arguments[:"aria-labelledby"] = @id
37
+ elsif !Rails.env.production?
38
+ raise ArgumentError, "Panels must be labelled. Either set a unique `id` on the tab, or set an `aria-label` directly on the panel"
39
+ end
40
+ end
41
+
42
+ Primer::BaseComponent.new(**system_arguments)
43
+ }
44
+
45
+ # Icon to be rendered in the Tab left.
46
+ #
47
+ # @param kwargs [Hash] The same arguments as <%= link_to_component(Primer::Beta::Octicon) %>.
48
+ renders_one :icon, lambda { |icon = nil, **system_arguments|
49
+ system_arguments[:classes] = class_names(
50
+ @icon_classes,
51
+ system_arguments[:classes]
52
+ )
53
+ Primer::Beta::Octicon.new(icon, **system_arguments)
54
+ }
55
+
56
+ # The Tab's text.
57
+ #
58
+ # @param kwargs [Hash] The same arguments as <%= link_to_component(Primer::Beta::Text) %>.
59
+ renders_one :text, Primer::Beta::Text
60
+
61
+ # Counter to be rendered in the Tab right.
62
+ #
63
+ # @param kwargs [Hash] The same arguments as <%= link_to_component(Primer::Beta::Counter) %>.
64
+ renders_one :counter, Primer::Beta::Counter
65
+
66
+ attr_reader :selected
67
+
68
+ # @example Default
69
+ # <%= render(Primer::Alpha::Navigation::Tab.new(selected: true)) do |component| %>
70
+ # <% component.with_text { "Selected" } %>
71
+ # <% end %>
72
+ # <%= render(Primer::Alpha::Navigation::Tab.new) do |component| %>
73
+ # <% component.with_text { "Not selected" } %>
74
+ # <% end %>
75
+ #
76
+ # @example With icons and counters
77
+ # <%= render(Primer::Alpha::Navigation::Tab.new) do |component| %>
78
+ # <% component.with_icon(:star) %>
79
+ # <% component.with_text { "Tab" } %>
80
+ # <% end %>
81
+ # <%= render(Primer::Alpha::Navigation::Tab.new) do |component| %>
82
+ # <% component.with_icon(:star) %>
83
+ # <% component.with_text { "Tab" } %>
84
+ # <% component.with_counter(count: 10) %>
85
+ # <% end %>
86
+ # <%= render(Primer::Alpha::Navigation::Tab.new) do |component| %>
87
+ # <% component.with_text { "Tab" } %>
88
+ # <% component.with_counter(count: 10) %>
89
+ # <% end %>
90
+ #
91
+ # @example Inside a list
92
+ # <%= render(Primer::Alpha::Navigation::Tab.new(list: true)) do |component| %>
93
+ # <% component.with_text { "Tab" } %>
94
+ # <% end %>
95
+ #
96
+ # @example With custom HTML
97
+ # <%= render(Primer::Alpha::Navigation::Tab.new) do %>
98
+ # <div>
99
+ # This is my <strong>custom HTML</strong>
100
+ # </div>
101
+ # <% end %>
102
+ #
103
+ # @param list [Boolean] Whether the Tab is an item in a `<ul>` list.
104
+ # @param selected [Boolean] Whether the Tab is selected or not.
105
+ # @param with_panel [Boolean] Whether the Tab has an associated panel.
106
+ # @param panel_id [String] Only applies if `with_panel` is `true`. Unique id of panel.
107
+ # @param icon_classes [Boolean] Classes that must always be applied to icons.
108
+ # @param wrapper_arguments [Hash] <%= link_to_system_arguments_docs %> to be used in the `<li>` wrapper when the tab is an item in a list.
109
+ # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
110
+ def initialize(list: false, selected: false, with_panel: false, panel_id: "", icon_classes: "", wrapper_arguments: {}, **system_arguments)
111
+ @selected = selected
112
+ @icon_classes = icon_classes
113
+ @list = list
114
+ @with_panel = with_panel
115
+
116
+ @system_arguments = system_arguments
117
+ @id = @system_arguments[:id]
118
+ @wrapper_arguments = wrapper_arguments
119
+
120
+ if with_panel || @system_arguments[:tag] == :button
121
+ @system_arguments[:tag] = :button
122
+ @system_arguments[:type] = :button
123
+ @system_arguments[:role] = :tab
124
+ panel_id(panel_id)
125
+ # https://www.w3.org/TR/wai-aria-practices/#presentation_role
126
+ @wrapper_arguments[:role] = :presentation
127
+ else
128
+ @system_arguments[:tag] = :a
129
+ end
130
+
131
+ @wrapper_arguments[:tag] = :li
132
+ @wrapper_arguments[:display] ||= :inline_flex
133
+
134
+ return unless @selected
135
+
136
+ if @system_arguments[:tag] == :a
137
+ aria_current = aria("current", system_arguments) || DEFAULT_ARIA_CURRENT_FOR_ANCHOR
138
+ @system_arguments[:"aria-current"] = fetch_or_fallback(ARIA_CURRENT_OPTIONS_FOR_ANCHOR, aria_current, DEFAULT_ARIA_CURRENT_FOR_ANCHOR)
139
+ else
140
+ @system_arguments[:"aria-selected"] = true
141
+ end
142
+ end
143
+
144
+ def wrapper
145
+ unless @list
146
+ yield
147
+ return # returning `yield` caused a double render
148
+ end
149
+
150
+ render(Primer::BaseComponent.new(**@wrapper_arguments)) do
151
+ yield if block_given?
152
+ end
153
+ end
154
+
155
+ private
156
+
157
+ def panel_id(panel_id)
158
+ if panel_id.blank?
159
+ raise ArgumentError, "`panel_id` is required" unless Rails.env.production?
160
+ else
161
+ @panel_id = panel_id
162
+ @system_arguments[:"aria-controls"] = @panel_id
163
+ end
164
+ end
165
+ end
166
+ end
167
+ end
168
+ end
@@ -1,11 +1,11 @@
1
1
  <%= render Primer::BaseComponent.new(**@system_arguments) do %>
2
2
  <div class="Overlay-headerContentWrap">
3
3
  <div class="Overlay-titleWrap">
4
- <h1 class="Overlay-title <% if @visually_hide_title || content.present? %>sr-only<% end %>"><%= @title %></h1>
4
+ <h1 id="<%= @id %>" class="Overlay-title <% if @visually_hide_title || content.present? %>sr-only<% end %>"><%= @title %></h1>
5
5
  <% if content.present? %>
6
6
  <%= content %>
7
7
  <% elsif @subtitle.present? %>
8
- <h2 id="<%= @id %>-description" class="Overlay-description"><%= @subtitle %></h2>
8
+ <h2 class="Overlay-description"><%= @subtitle %></h2>
9
9
  <% end %>
10
10
  </div>
11
11
  <div class="Overlay-actionWrap">
@@ -68,14 +68,18 @@ module Primer
68
68
  # Optional button to open the Overlay.
69
69
  #
70
70
  # @param system_arguments [Hash] The same arguments as <%= link_to_component(Primer::ButtonComponent) %>.
71
- renders_one :show_button, lambda { |**system_arguments|
71
+ renders_one :show_button, lambda { |icon: nil, **system_arguments|
72
72
  system_arguments[:classes] = class_names(
73
73
  system_arguments[:classes]
74
74
  )
75
- system_arguments[:id] = "overlay-show-#{@system_arguments[:id]}"
76
- system_arguments["popovertoggletarget"] = @system_arguments[:id]
77
- system_arguments[:data] = (system_arguments[:data] || {}).merge({ "show-dialog-id": @system_arguments[:id] })
78
- Primer::Beta::Button.new(**system_arguments)
75
+ system_arguments[:id] = show_button_id
76
+ system_arguments["popovertoggletarget"] = overlay_id
77
+ system_arguments[:aria] = (system_arguments[:aria] || {}).merge({ controls: overlay_id, haspopup: "true" })
78
+ if icon.present?
79
+ Primer::Beta::IconButton.new(icon: icon, **system_arguments)
80
+ else
81
+ Primer::Beta::Button.new(**system_arguments)
82
+ end
79
83
  }
80
84
 
81
85
  # Header content.
@@ -85,7 +89,7 @@ module Primer
85
89
  # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
86
90
  renders_one :header, lambda { |divider: false, size: :medium, visually_hide_title: @visually_hide_title, **system_arguments|
87
91
  Primer::Alpha::Overlay::Header.new(
88
- id: @id,
92
+ id: title_id,
89
93
  title: @title,
90
94
  subtitle: @subtitle,
91
95
  size: size,
@@ -165,7 +169,6 @@ module Primer
165
169
  @system_arguments[:classes] = class_names(
166
170
  "Overlay",
167
171
  SIZE_MAPPINGS[fetch_or_fallback(SIZE_OPTIONS, size, DEFAULT_SIZE)],
168
- "Overlay--motion-scaleFade",
169
172
  system_arguments[:classes]
170
173
  )
171
174
  @system_arguments[:tag] = "anchored-position"
@@ -182,13 +185,30 @@ module Primer
182
185
 
183
186
  @system_arguments[:popover] = popover
184
187
  @system_arguments[:aria] ||= {}
185
- @system_arguments[:aria][:describedby] ||= "#{@id}-description"
186
188
  end
187
189
 
188
190
  def before_render
189
- with_header unless header?
191
+ if header?
192
+ @system_arguments[:aria][:labelledby] ||= title_id
193
+ else
194
+ @system_arguments[:aria][:label] = @title
195
+ end
190
196
  with_body unless body?
191
197
  end
198
+
199
+ private
200
+
201
+ def overlay_id
202
+ @system_arguments[:id]
203
+ end
204
+
205
+ def title_id
206
+ "overlay-title-#{overlay_id}"
207
+ end
208
+
209
+ def show_button_id
210
+ "overlay-show-#{overlay_id}"
211
+ end
192
212
  end
193
213
  end
194
214
  end
@@ -9,7 +9,7 @@ module Primer
9
9
  # - By default, `TabNav` renders links within a `<nav>` element. `<nav>` has an
10
10
  # implicit landmark role of `navigation` which should be reserved for main links.
11
11
  # For all other set of links, set tag to `:div`.
12
- # - See <%= link_to_component(Primer::Navigation::TabComponent) %> for additional
12
+ # - See <%= link_to_component(Primer::Alpha::Navigation::Tab) %> for additional
13
13
  # accessibility considerations.
14
14
  class TabNav < Primer::Component
15
15
  include Primer::TabbedComponentHelper
@@ -22,13 +22,13 @@ module Primer
22
22
  TAG_DEFAULT = :nav
23
23
  TAG_OPTIONS = [TAG_DEFAULT, :div].freeze
24
24
 
25
- # Tabs to be rendered. For more information, refer to <%= link_to_component(Primer::Navigation::TabComponent) %>.
25
+ # Tabs to be rendered. For more information, refer to <%= link_to_component(Primer::Alpha::Navigation::Tab) %>.
26
26
  #
27
27
  # @param selected [Boolean] Whether the tab is selected.
28
28
  # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
29
29
  renders_many :tabs, lambda { |selected: false, **system_arguments|
30
30
  system_arguments[:classes] = tab_nav_tab_classes(system_arguments[:classes])
31
- Primer::Navigation::TabComponent.new(
31
+ Primer::Alpha::Navigation::Tab.new(
32
32
  list: true,
33
33
  selected: selected,
34
34
  **system_arguments
@@ -124,6 +124,13 @@ module Primer
124
124
 
125
125
  aria_label_for_page_nav(label)
126
126
  end
127
+
128
+ def before_render
129
+ # Eagerly evaluate content to avoid https://github.com/primer/view_components/issues/1790
130
+ content
131
+
132
+ super
133
+ end
127
134
  end
128
135
  end
129
136
  end
@@ -14,7 +14,7 @@ module Primer
14
14
  TAG_DEFAULT = :nav
15
15
  TAG_OPTIONS = [TAG_DEFAULT, :div].freeze
16
16
 
17
- # Tabs to be rendered. For more information, refer to <%= link_to_component(Primer::Navigation::TabComponent) %>.
17
+ # Tabs to be rendered. For more information, refer to <%= link_to_component(Primer::Alpha::Navigation::Tab) %>.
18
18
  #
19
19
  # @param id [String] Unique ID of tab.
20
20
  # @param selected [Boolean] Whether the tab is selected.
@@ -23,7 +23,7 @@ module Primer
23
23
  system_arguments[:id] = id
24
24
  system_arguments[:classes] = tab_nav_tab_classes(system_arguments[:classes])
25
25
 
26
- Primer::Navigation::TabComponent.new(
26
+ Primer::Alpha::Navigation::Tab.new(
27
27
  selected: selected,
28
28
  with_panel: true,
29
29
  list: true,
@@ -1 +1 @@
1
- .UnderlineNav{-webkit-overflow-scrolling:auto;box-shadow:inset 0 -1px 0 var(--color-border-muted);display:flex;justify-content:space-between;min-height:var(--base-size-48,48px);overflow-x:auto;overflow-y:hidden}.UnderlineNav .Counter{background-color:var(--color-neutral-muted);color:var(--color-fg-default);margin-left:var(--primer-control-medium-gap,8px)}.UnderlineNav .Counter--primary{background-color:var(--color-neutral-emphasis);color:var(--color-fg-on-emphasis)}.UnderlineNav-body{align-items:center;display:flex;gap:var(--primer-control-medium-gap,8px);list-style:none}.UnderlineNav-item{align-items:center;background-color:initial;border:0;border-radius:var(--primer-borderRadius-medium,6px);color:var(--color-fg-default);cursor:pointer;display:flex;font-size:var(--primer-text-body-size-medium,14px);line-height:30px;padding:0 var(--primer-control-medium-paddingInline-condensed,8px);position:relative;text-align:center;white-space:nowrap}.UnderlineNav-item:focus,.UnderlineNav-item:focus-visible,.UnderlineNav-item:hover{border-bottom-color:var(--color-neutral-muted);color:var(--color-fg-default);outline-offset:-2px;text-decoration:none;transition:border-bottom-color .12s ease-out}.UnderlineNav-item [data-content]:before{content:attr(data-content);display:block;font-weight:var(--base-text-weight-semibold,600);height:0;visibility:hidden}.UnderlineNav-item:before{content:"";height:100%;left:50%;min-height:48px;position:absolute;top:50%;transform:translateX(-50%) translateY(-50%);width:100%}@media (pointer:fine){.UnderlineNav-item:hover{background:var(--color-action-list-item-default-hover-bg);color:var(--color-fg-default);text-decoration:none;transition:background .12s ease-out}}.UnderlineNav-item.selected,.UnderlineNav-item[aria-current]:not([aria-current=false]),.UnderlineNav-item[role=tab][aria-selected=true]{border-bottom-color:var(--color-primer-border-active);color:var(--color-fg-default);font-weight:var(--base-text-weight-semibold,600)}.UnderlineNav-item.selected:after,.UnderlineNav-item[aria-current]:not([aria-current=false]):after,.UnderlineNav-item[role=tab][aria-selected=true]:after{background:var(--color-primer-border-active);border-radius:var(--primer-borderRadius-medium,6px);bottom:calc(50% - 25px);content:"";height:2px;position:absolute;right:50%;transform:translate(50%,-50%);width:100%}.UnderlineNav--right{justify-content:flex-end}.UnderlineNav--right .UnderlineNav-actions{flex:1 1 auto}.UnderlineNav-actions{align-self:center}.UnderlineNav--full{display:block}.UnderlineNav--full .UnderlineNav-body{min-height:var(--base-size-48,48px)}.UnderlineNav-octicon{fill:var(--color-fg-muted);color:var(--color-fg-muted);display:inline!important;margin-right:var(--primer-control-medium-gap,8px)}.UnderlineNav-container{display:flex;justify-content:space-between}
1
+ .UnderlineNav{-webkit-overflow-scrolling:auto;box-shadow:inset 0 -1px 0 var(--color-border-muted);display:flex;justify-content:space-between;min-height:var(--base-size-48,48px);overflow-x:auto;overflow-y:hidden}.UnderlineNav .Counter{background-color:var(--color-neutral-muted);color:var(--color-fg-default);margin-left:var(--primer-control-medium-gap,8px)}.UnderlineNav .Counter--primary{background-color:var(--color-neutral-emphasis);color:var(--color-fg-on-emphasis)}.UnderlineNav-body{align-items:center;display:flex;gap:var(--primer-control-medium-gap,8px);list-style:none}.UnderlineNav-item{align-items:center;background-color:initial;border:0;border-radius:var(--primer-borderRadius-medium,6px);color:var(--color-fg-default);cursor:pointer;display:flex;font-size:var(--primer-text-body-size-medium,14px);line-height:30px;padding:0 var(--primer-control-medium-paddingInline-condensed,8px);position:relative;text-align:center;white-space:nowrap}.UnderlineNav-item:focus,.UnderlineNav-item:focus-visible,.UnderlineNav-item:hover{border-bottom-color:var(--color-neutral-muted);color:var(--color-fg-default);outline-offset:-2px;text-decoration:none;transition:border-bottom-color .12s ease-out}.UnderlineNav-item [data-content]:before{content:attr(data-content);display:block;font-weight:var(--base-text-weight-semibold,600);height:0;visibility:hidden}.UnderlineNav-item:before{content:"";height:100%;left:50%;min-height:48px;position:absolute;top:50%;transform:translateX(-50%) translateY(-50%);width:100%}@media (pointer:fine){.UnderlineNav-item:hover{background:var(--color-action-list-item-default-hover-bg);color:var(--color-fg-default);text-decoration:none;transition:background .12s ease-out}}.UnderlineNav-item.selected,.UnderlineNav-item[aria-current]:not([aria-current=false]),.UnderlineNav-item[role=tab][aria-selected=true]{border-bottom-color:var(--color-primer-border-active);color:var(--color-fg-default);font-weight:var(--base-text-weight-semibold,600)}.UnderlineNav-item.selected:after,.UnderlineNav-item[aria-current]:not([aria-current=false]):after,.UnderlineNav-item[role=tab][aria-selected=true]:after{background:var(--color-primer-border-active);border-radius:var(--primer-borderRadius-medium,6px);bottom:calc(50% - 25px);content:"";height:2px;position:absolute;right:50%;transform:translate(50%,-50%);width:100%;z-index:1}.UnderlineNav--right{justify-content:flex-end}.UnderlineNav--right .UnderlineNav-actions{flex:1 1 auto}.UnderlineNav-actions{align-self:center}.UnderlineNav--full{display:block}.UnderlineNav--full .UnderlineNav-body{min-height:var(--base-size-48,48px)}.UnderlineNav-octicon{fill:var(--color-fg-muted);color:var(--color-fg-muted);display:inline!important;margin-right:var(--primer-control-medium-gap,8px)}.UnderlineNav-container{display:flex;justify-content:space-between}
@@ -1 +1 @@
1
- {"version":3,"sources":["underline_nav.pcss","<no source>"],"names":[],"mappings":"AAEA,cAME,+BAAgC,CADhC,mDAAoD,CAJpD,YAAa,CAMb,6BAA8B,CAL9B,mCAAqC,CACrC,eAAgB,CAChB,iBAeF,CAVE,uBAGE,2CAA4C,CAD5C,6BAA8B,CAD9B,gDAGF,CAEA,gCAEE,8CAA+C,CAD/C,iCAEF,CAGF,mBAEE,kBAAmB,CADnB,YAAa,CAEb,wCAA0C,CAC1C,eACF,CAEA,mBAaE,kBAAmB,CAHnB,wBAA6B,CAC7B,QAAS,CACT,mDAAqD,CANrD,6BAA8B,CAG9B,cAAe,CAPf,YAAa,CAEb,kDAAoD,CACpD,gBAAiB,CAFjB,kEAAoE,CAFpE,iBAAkB,CAMlB,iBAAkB,CAClB,kBA6DF,CAtDE,mFAKE,8CAA+C,CAF/C,6BAA8B,CAG9B,mBAAoB,CAFpB,oBAAqB,CAGrB,4CACF,CAGA,yCAKE,0BAA2B,CAJ3B,aAAc,CAEd,gDAAkD,CADlD,QAAS,CAET,iBAEF,CAIE,0BClEJ,WAAA,YAAA,SAAA,gBAAA,kBAAA,QAAA,4CAAA,UDkE8B,CAI5B,sBACE,yBAGE,yDAA0D,CAF1D,6BAA8B,CAC9B,oBAAqB,CAErB,mCACF,CACF,CAEA,wIAKE,qDAAsD,CADtD,6BAA8B,CAD9B,gDAgBF,CAXE,0JAOE,4CAA6C,CAC7C,mDAAqD,CALrD,uBAAwB,CAGxB,UAAW,CADX,UAAW,CAJX,iBAAkB,CAClB,SAAU,CAOV,6BAA+B,CAL/B,UAMF,CAIJ,qBACE,wBAKF,CAHE,2CACE,aACF,CAGF,sBACE,iBACF,CAEA,oBACE,aAMF,CAHE,uCACE,mCACF,CAGF,sBAIE,0BAA2B,CAD3B,2BAA4B,CAF5B,wBAA0B,CAC1B,iDAGF,CAEA,wBACE,YAAa,CACb,6BACF","file":"underline_nav.css","sourcesContent":["/* UnderlineNav */\n\n.UnderlineNav {\n display: flex;\n min-height: var(--base-size-48, 48px);\n overflow-x: auto;\n overflow-y: hidden;\n box-shadow: inset 0 -1px 0 var(--color-border-muted);\n -webkit-overflow-scrolling: auto;\n justify-content: space-between;\n\n & .Counter {\n margin-left: var(--primer-control-medium-gap, 8px);\n color: var(--color-fg-default);\n background-color: var(--color-neutral-muted);\n }\n\n & .Counter--primary {\n color: var(--color-fg-on-emphasis);\n background-color: var(--color-neutral-emphasis);\n }\n}\n\n.UnderlineNav-body {\n display: flex;\n align-items: center;\n gap: var(--primer-control-medium-gap, 8px);\n list-style: none;\n}\n\n.UnderlineNav-item {\n position: relative;\n display: flex;\n padding: 0 var(--primer-control-medium-paddingInline-condensed, 8px);\n font-size: var(--primer-text-body-size-medium, 14px);\n line-height: 30px;\n color: var(--color-fg-default);\n text-align: center;\n white-space: nowrap;\n cursor: pointer;\n background-color: transparent;\n border: 0;\n border-radius: var(--primer-borderRadius-medium, 6px);\n align-items: center;\n\n &:hover,\n &:focus,\n &:focus-visible {\n color: var(--color-fg-default);\n text-decoration: none;\n border-bottom-color: var(--color-neutral-muted);\n outline-offset: -2px;\n transition: border-bottom-color 0.12s ease-out;\n }\n\n /* renders a visibly hidden \"copy\" of the label in bold, reserving box space for when label becomes bold on selected */\n & [data-content]::before {\n display: block;\n height: 0;\n font-weight: var(--base-text-weight-semibold, 600);\n visibility: hidden;\n content: attr(data-content);\n }\n\n /* increase touch target area */\n &::before {\n @mixin minTouchTarget 48px;\n }\n\n /* hover state was \"sticking\" on mobile after click */\n @media (pointer: fine) {\n &:hover {\n color: var(--color-fg-default);\n text-decoration: none;\n background: var(--color-action-list-item-default-hover-bg);\n transition: background 0.12s ease-out;\n }\n }\n\n &.selected,\n &[role='tab'][aria-selected='true'],\n &[aria-current]:not([aria-current='false']) {\n font-weight: var(--base-text-weight-semibold, 600);\n color: var(--color-fg-default);\n border-bottom-color: var(--color-primer-border-active);\n\n /* current/selected underline */\n &::after {\n position: absolute;\n right: 50%;\n bottom: calc(50% - 25px); /* 48px total height / 2 (24px) + 1px */\n width: 100%;\n height: 2px;\n content: '';\n background: var(--color-primer-border-active);\n border-radius: var(--primer-borderRadius-medium, 6px);\n transform: translate(50%, -50%);\n }\n }\n}\n\n.UnderlineNav--right {\n justify-content: flex-end;\n\n & .UnderlineNav-actions {\n flex: 1 1 auto;\n }\n}\n\n.UnderlineNav-actions {\n align-self: center;\n}\n\n.UnderlineNav--full {\n display: block;\n\n /* required for underline to align with additional wrapper element */\n & .UnderlineNav-body {\n min-height: var(--base-size-48, 48px);\n }\n}\n\n.UnderlineNav-octicon {\n display: inline !important;\n margin-right: var(--primer-control-medium-gap, 8px);\n color: var(--color-fg-muted);\n fill: var(--color-fg-muted);\n}\n\n.UnderlineNav-container {\n display: flex;\n justify-content: space-between;\n}\n",null]}
1
+ {"version":3,"sources":["underline_nav.pcss","<no source>"],"names":[],"mappings":"AAEA,cAME,+BAAgC,CADhC,mDAAoD,CAJpD,YAAa,CAMb,6BAA8B,CAL9B,mCAAqC,CACrC,eAAgB,CAChB,iBAeF,CAVE,uBAGE,2CAA4C,CAD5C,6BAA8B,CAD9B,gDAGF,CAEA,gCAEE,8CAA+C,CAD/C,iCAEF,CAGF,mBAEE,kBAAmB,CADnB,YAAa,CAEb,wCAA0C,CAC1C,eACF,CAEA,mBAaE,kBAAmB,CAHnB,wBAA6B,CAC7B,QAAS,CACT,mDAAqD,CANrD,6BAA8B,CAG9B,cAAe,CAPf,YAAa,CAEb,kDAAoD,CACpD,gBAAiB,CAFjB,kEAAoE,CAFpE,iBAAkB,CAMlB,iBAAkB,CAClB,kBA8DF,CAvDE,mFAKE,8CAA+C,CAF/C,6BAA8B,CAG9B,mBAAoB,CAFpB,oBAAqB,CAGrB,4CACF,CAGA,yCAKE,0BAA2B,CAJ3B,aAAc,CAEd,gDAAkD,CADlD,QAAS,CAET,iBAEF,CAIE,0BClEJ,WAAA,YAAA,SAAA,gBAAA,kBAAA,QAAA,4CAAA,UDkE8B,CAI5B,sBACE,yBAGE,yDAA0D,CAF1D,6BAA8B,CAC9B,oBAAqB,CAErB,mCACF,CACF,CAEA,wIAKE,qDAAsD,CADtD,6BAA8B,CAD9B,gDAiBF,CAZE,0JAQE,4CAA6C,CAC7C,mDAAqD,CALrD,uBAAwB,CAGxB,UAAW,CADX,UAAW,CALX,iBAAkB,CAElB,SAAU,CAOV,6BAA+B,CAL/B,UAAW,CAHX,SASF,CAIJ,qBACE,wBAKF,CAHE,2CACE,aACF,CAGF,sBACE,iBACF,CAEA,oBACE,aAMF,CAHE,uCACE,mCACF,CAGF,sBAIE,0BAA2B,CAD3B,2BAA4B,CAF5B,wBAA0B,CAC1B,iDAGF,CAEA,wBACE,YAAa,CACb,6BACF","file":"underline_nav.css","sourcesContent":["/* UnderlineNav */\n\n.UnderlineNav {\n display: flex;\n min-height: var(--base-size-48, 48px);\n overflow-x: auto;\n overflow-y: hidden;\n box-shadow: inset 0 -1px 0 var(--color-border-muted);\n -webkit-overflow-scrolling: auto;\n justify-content: space-between;\n\n & .Counter {\n margin-left: var(--primer-control-medium-gap, 8px);\n color: var(--color-fg-default);\n background-color: var(--color-neutral-muted);\n }\n\n & .Counter--primary {\n color: var(--color-fg-on-emphasis);\n background-color: var(--color-neutral-emphasis);\n }\n}\n\n.UnderlineNav-body {\n display: flex;\n align-items: center;\n gap: var(--primer-control-medium-gap, 8px);\n list-style: none;\n}\n\n.UnderlineNav-item {\n position: relative;\n display: flex;\n padding: 0 var(--primer-control-medium-paddingInline-condensed, 8px);\n font-size: var(--primer-text-body-size-medium, 14px);\n line-height: 30px;\n color: var(--color-fg-default);\n text-align: center;\n white-space: nowrap;\n cursor: pointer;\n background-color: transparent;\n border: 0;\n border-radius: var(--primer-borderRadius-medium, 6px);\n align-items: center;\n\n &:hover,\n &:focus,\n &:focus-visible {\n color: var(--color-fg-default);\n text-decoration: none;\n border-bottom-color: var(--color-neutral-muted);\n outline-offset: -2px;\n transition: border-bottom-color 0.12s ease-out;\n }\n\n /* renders a visibly hidden \"copy\" of the label in bold, reserving box space for when label becomes bold on selected */\n & [data-content]::before {\n display: block;\n height: 0;\n font-weight: var(--base-text-weight-semibold, 600);\n visibility: hidden;\n content: attr(data-content);\n }\n\n /* increase touch target area */\n &::before {\n @mixin minTouchTarget 48px;\n }\n\n /* hover state was \"sticking\" on mobile after click */\n @media (pointer: fine) {\n &:hover {\n color: var(--color-fg-default);\n text-decoration: none;\n background: var(--color-action-list-item-default-hover-bg);\n transition: background 0.12s ease-out;\n }\n }\n\n &.selected,\n &[role='tab'][aria-selected='true'],\n &[aria-current]:not([aria-current='false']) {\n font-weight: var(--base-text-weight-semibold, 600);\n color: var(--color-fg-default);\n border-bottom-color: var(--color-primer-border-active);\n\n /* current/selected underline */\n &::after {\n position: absolute;\n z-index: 1; /* raise above full-width flash banner */\n right: 50%;\n bottom: calc(50% - 25px); /* 48px total height / 2 (24px) + 1px */\n width: 100%;\n height: 2px;\n content: '';\n background: var(--color-primer-border-active);\n border-radius: var(--primer-borderRadius-medium, 6px);\n transform: translate(50%, -50%);\n }\n }\n}\n\n.UnderlineNav--right {\n justify-content: flex-end;\n\n & .UnderlineNav-actions {\n flex: 1 1 auto;\n }\n}\n\n.UnderlineNav-actions {\n align-self: center;\n}\n\n.UnderlineNav--full {\n display: block;\n\n /* required for underline to align with additional wrapper element */\n & .UnderlineNav-body {\n min-height: var(--base-size-48, 48px);\n }\n}\n\n.UnderlineNav-octicon {\n display: inline !important;\n margin-right: var(--primer-control-medium-gap, 8px);\n color: var(--color-fg-muted);\n fill: var(--color-fg-muted);\n}\n\n.UnderlineNav-container {\n display: flex;\n justify-content: space-between;\n}\n",null]}
@@ -87,6 +87,7 @@
87
87
  /* current/selected underline */
88
88
  &::after {
89
89
  position: absolute;
90
+ z-index: 1; /* raise above full-width flash banner */
90
91
  right: 50%;
91
92
  bottom: calc(50% - 25px); /* 48px total height / 2 (24px) + 1px */
92
93
  width: 100%;
@@ -12,7 +12,7 @@ module Primer
12
12
  # - By default, `UnderlineNav` renders links within a `<nav>` element. `<nav>` has an
13
13
  # implicit landmark role of `navigation` which should be reserved for main links.
14
14
  # For all other set of links, set tag to `:div`.
15
- # - See <%= link_to_component(Primer::Navigation::TabComponent) %> for additional
15
+ # - See <%= link_to_component(Primer::Alpha::Navigation::Tab) %> for additional
16
16
  # accessibility considerations.
17
17
  class UnderlineNav < Primer::Component
18
18
  include Primer::TabbedComponentHelper
@@ -29,7 +29,7 @@ module Primer
29
29
  # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
30
30
  renders_many :tabs, lambda { |selected: false, **system_arguments|
31
31
  system_arguments[:classes] = underline_nav_tab_classes(system_arguments[:classes])
32
- Primer::Navigation::TabComponent.new(
32
+ Primer::Alpha::Navigation::Tab.new(
33
33
  list: true,
34
34
  selected: selected,
35
35
  icon_classes: "UnderlineNav-octicon",
@@ -6,7 +6,7 @@ module Primer
6
6
  class UnderlinePanels < Primer::Component
7
7
  include Primer::TabbedComponentHelper
8
8
  include Primer::UnderlineNavHelper
9
- # Use to render a button and an associated panel slot. See the example below or refer to <%= link_to_component(Primer::Navigation::TabComponent) %>.
9
+ # Use to render a button and an associated panel slot. See the example below or refer to <%= link_to_component(Primer::Alpha::Navigation::Tab) %>.
10
10
  #
11
11
  # @param id [String] Unique ID of tab.
12
12
  # @param selected [Boolean] Whether the tab is selected.
@@ -15,7 +15,7 @@ module Primer
15
15
  system_arguments[:id] = id
16
16
  system_arguments[:classes] = underline_nav_tab_classes(system_arguments[:classes])
17
17
 
18
- Primer::Navigation::TabComponent.new(
18
+ Primer::Alpha::Navigation::Tab.new(
19
19
  selected: selected,
20
20
  with_panel: true,
21
21
  list: true,
@@ -1,4 +1,4 @@
1
- <%= render Primer::ConditionalWrapper.new(condition: tooltip.present?, tag: :div, classes: "Button-withTooltip") do -%>
1
+ <%= render Primer::ConditionalWrapper.new(condition: tooltip.present?, tag: :div, display: (:block if @block), classes: "Button-withTooltip") do -%>
2
2
  <%= render Primer::Beta::BaseButton.new(**@system_arguments) do -%>
3
3
  <span class="<%= @align_content_classes %>">
4
4
  <% if leading_visual %>
@@ -144,6 +144,7 @@ module Primer
144
144
  **system_arguments
145
145
  )
146
146
  @scheme = scheme
147
+ @block = block
147
148
 
148
149
  @system_arguments = system_arguments
149
150
 
@@ -162,7 +163,7 @@ module Primer
162
163
  SCHEME_MAPPINGS[fetch_or_fallback(SCHEME_OPTIONS, scheme, DEFAULT_SCHEME)],
163
164
  SIZE_MAPPINGS[fetch_or_fallback(SIZE_OPTIONS, size, DEFAULT_SIZE)],
164
165
  "Button",
165
- "Button--fullWidth" => block
166
+ "Button--fullWidth" => @block
166
167
  )
167
168
  end
168
169
 
@@ -58,6 +58,40 @@ module Primer
58
58
  system_arguments[:"aria-#{val}"] || system_arguments.dig(:aria, val.to_sym)
59
59
  end
60
60
 
61
+ # Merges hashes that contain "aria-*" keys and nested aria: hashes. Removes keys from
62
+ # each hash and returns them in the new hash.
63
+ #
64
+ # Eg. merge_aria({ "aria-disabled": "true" }, { aria: { invalid: "true" } })
65
+ # => { disabled: "true", invalid: "true" }
66
+ #
67
+ # It's designed to be used to normalize and merge aria information from system_arguments
68
+ # hashes. Consider using this pattern in component initializers:
69
+ #
70
+ # @system_arguments[:aria] = merge_aria(
71
+ # @system_arguments,
72
+ # { aria: { labelled_by: id } }
73
+ # )
74
+ def merge_aria(*hashes)
75
+ {}.tap do |result|
76
+ hashes.each do |hash|
77
+ next unless hash
78
+
79
+ result.merge!(hash.delete(:aria) || {})
80
+
81
+ hash.delete_if do |key, val|
82
+ key_s = key.to_s
83
+
84
+ if key.start_with?("aria-")
85
+ result[key_s.sub("aria-", "").to_sym] = val
86
+ true
87
+ else
88
+ false
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end
94
+
61
95
  def validate_aria_label
62
96
  aria_label = aria("label", @system_arguments)
63
97
  aria_labelledby = aria("labelledby", @system_arguments)
@@ -2,163 +2,9 @@
2
2
 
3
3
  module Primer
4
4
  module Navigation
5
- # This component is part of navigation components such as `Primer::Alpha::TabNav`
6
- # and `Primer::Alpha::UnderlineNav` and should not be used by itself.
7
- #
8
- # @accessibility
9
- # `TabComponent` renders the selected anchor tab with `aria-current="page"` by default.
10
- # When the selected tab does not correspond to the current page, such as in a nested inner tab, make sure to use aria-current="true"
11
- class TabComponent < Primer::Component
12
- DEFAULT_ARIA_CURRENT_FOR_ANCHOR = :page
13
- ARIA_CURRENT_OPTIONS_FOR_ANCHOR = [true, DEFAULT_ARIA_CURRENT_FOR_ANCHOR].freeze
14
- # Panel controlled by the Tab. This will not render anything in the tab itself.
15
- # It will provide a accessor for the Tab's parent to call and render the panel
16
- # content in the appropriate place.
17
- # Refer to `UnderlineNav` and `TabNav` implementations for examples.
18
- #
19
- # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
20
- renders_one :panel, lambda { |**system_arguments|
21
- return unless @with_panel
22
-
23
- deny_tag_argument(**system_arguments)
24
- system_arguments[:id] = @panel_id
25
- system_arguments[:tag] = :div
26
- system_arguments[:role] ||= :tabpanel
27
- system_arguments[:tabindex] = 0
28
- system_arguments[:hidden] = true unless @selected
29
-
30
- label_present = aria("label", system_arguments) || aria("labelledby", system_arguments)
31
- unless label_present
32
- if @id.present?
33
- system_arguments[:"aria-labelledby"] = @id
34
- elsif !Rails.env.production?
35
- raise ArgumentError, "Panels must be labelled. Either set a unique `id` on the tab, or set an `aria-label` directly on the panel"
36
- end
37
- end
38
-
39
- Primer::BaseComponent.new(**system_arguments)
40
- }
41
-
42
- # Icon to be rendered in the Tab left.
43
- #
44
- # @param kwargs [Hash] The same arguments as <%= link_to_component(Primer::Beta::Octicon) %>.
45
- renders_one :icon, lambda { |icon = nil, **system_arguments|
46
- system_arguments[:classes] = class_names(
47
- @icon_classes,
48
- system_arguments[:classes]
49
- )
50
- Primer::Beta::Octicon.new(icon, **system_arguments)
51
- }
52
-
53
- # The Tab's text.
54
- #
55
- # @param kwargs [Hash] The same arguments as <%= link_to_component(Primer::Beta::Text) %>.
56
- renders_one :text, Primer::Beta::Text
57
-
58
- # Counter to be rendered in the Tab right.
59
- #
60
- # @param kwargs [Hash] The same arguments as <%= link_to_component(Primer::Beta::Counter) %>.
61
- renders_one :counter, Primer::Beta::Counter
62
-
63
- attr_reader :selected
64
-
65
- # @example Default
66
- # <%= render(Primer::Navigation::TabComponent.new(selected: true)) do |component| %>
67
- # <% component.with_text { "Selected" } %>
68
- # <% end %>
69
- # <%= render(Primer::Navigation::TabComponent.new) do |component| %>
70
- # <% component.with_text { "Not selected" } %>
71
- # <% end %>
72
- #
73
- # @example With icons and counters
74
- # <%= render(Primer::Navigation::TabComponent.new) do |component| %>
75
- # <% component.with_icon(:star) %>
76
- # <% component.with_text { "Tab" } %>
77
- # <% end %>
78
- # <%= render(Primer::Navigation::TabComponent.new) do |component| %>
79
- # <% component.with_icon(:star) %>
80
- # <% component.with_text { "Tab" } %>
81
- # <% component.with_counter(count: 10) %>
82
- # <% end %>
83
- # <%= render(Primer::Navigation::TabComponent.new) do |component| %>
84
- # <% component.with_text { "Tab" } %>
85
- # <% component.with_counter(count: 10) %>
86
- # <% end %>
87
- #
88
- # @example Inside a list
89
- # <%= render(Primer::Navigation::TabComponent.new(list: true)) do |component| %>
90
- # <% component.with_text { "Tab" } %>
91
- # <% end %>
92
- #
93
- # @example With custom HTML
94
- # <%= render(Primer::Navigation::TabComponent.new) do %>
95
- # <div>
96
- # This is my <strong>custom HTML</strong>
97
- # </div>
98
- # <% end %>
99
- #
100
- # @param list [Boolean] Whether the Tab is an item in a `<ul>` list.
101
- # @param selected [Boolean] Whether the Tab is selected or not.
102
- # @param with_panel [Boolean] Whether the Tab has an associated panel.
103
- # @param panel_id [String] Only applies if `with_panel` is `true`. Unique id of panel.
104
- # @param icon_classes [Boolean] Classes that must always be applied to icons.
105
- # @param wrapper_arguments [Hash] <%= link_to_system_arguments_docs %> to be used in the `<li>` wrapper when the tab is an item in a list.
106
- # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
107
- def initialize(list: false, selected: false, with_panel: false, panel_id: "", icon_classes: "", wrapper_arguments: {}, **system_arguments)
108
- @selected = selected
109
- @icon_classes = icon_classes
110
- @list = list
111
- @with_panel = with_panel
112
-
113
- @system_arguments = system_arguments
114
- @id = @system_arguments[:id]
115
- @wrapper_arguments = wrapper_arguments
116
-
117
- if with_panel || @system_arguments[:tag] == :button
118
- @system_arguments[:tag] = :button
119
- @system_arguments[:type] = :button
120
- @system_arguments[:role] = :tab
121
- panel_id(panel_id)
122
- # https://www.w3.org/TR/wai-aria-practices/#presentation_role
123
- @wrapper_arguments[:role] = :presentation
124
- else
125
- @system_arguments[:tag] = :a
126
- end
127
-
128
- @wrapper_arguments[:tag] = :li
129
- @wrapper_arguments[:display] ||= :inline_flex
130
-
131
- return unless @selected
132
-
133
- if @system_arguments[:tag] == :a
134
- aria_current = aria("current", system_arguments) || DEFAULT_ARIA_CURRENT_FOR_ANCHOR
135
- @system_arguments[:"aria-current"] = fetch_or_fallback(ARIA_CURRENT_OPTIONS_FOR_ANCHOR, aria_current, DEFAULT_ARIA_CURRENT_FOR_ANCHOR)
136
- else
137
- @system_arguments[:"aria-selected"] = true
138
- end
139
- end
140
-
141
- def wrapper
142
- unless @list
143
- yield
144
- return # returning `yield` caused a double render
145
- end
146
-
147
- render(Primer::BaseComponent.new(**@wrapper_arguments)) do
148
- yield if block_given?
149
- end
150
- end
151
-
152
- private
153
-
154
- def panel_id(panel_id)
155
- if panel_id.blank?
156
- raise ArgumentError, "`panel_id` is required" unless Rails.env.production?
157
- else
158
- @panel_id = panel_id
159
- @system_arguments[:"aria-controls"] = @panel_id
160
- end
161
- end
5
+ # nodoc
6
+ class TabComponent < Primer::Alpha::Navigation::Tab
7
+ status :deprecated
162
8
  end
163
9
  end
164
10
  end
@@ -3,7 +3,7 @@
3
3
  module Primer
4
4
  # Use `Truncate` to shorten overflowing text with an ellipsis.
5
5
  class Truncate < Primer::Component
6
- status :beta
6
+ status :deprecated
7
7
 
8
8
  DEFAULT_TAG = :div
9
9
  TAG_OPTIONS = [DEFAULT_TAG, :span, :p, :strong].freeze
@@ -26,6 +26,15 @@ deprecations:
26
26
  autocorrect: true
27
27
  replacement: "Primer::Beta::IconButton"
28
28
 
29
+ - component: "Primer::Navigation::TabComponent"
30
+ autocorrect: true
31
+ replacement: "Primer::Alpha::Navigation::Tab"
32
+
29
33
  - component: "Primer::Tooltip"
30
34
  autocorrect: true
31
35
  replacement: "Primer::Alpha::Tooltip"
36
+
37
+ - component: "Primer::Truncate"
38
+ autocorrect: false
39
+ replacement: "Primer::Beta::Truncate"
40
+ guide: "https://primer.style/view-components/guides/primer_truncate"