openproject-primer_view_components 0.33.2 → 0.35.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +26 -0
  3. data/app/assets/javascripts/lib/primer/forms/primer_text_field.d.ts +27 -0
  4. data/app/assets/javascripts/primer_view_components.js +1 -1
  5. data/app/assets/javascripts/primer_view_components.js.map +1 -1
  6. data/app/assets/styles/primer_view_components.css +1 -1
  7. data/app/assets/styles/primer_view_components.css.map +1 -1
  8. data/app/components/primer/alpha/action_menu/action_menu_element.js +13 -43
  9. data/app/components/primer/alpha/action_menu/action_menu_element.ts +13 -51
  10. data/app/components/primer/alpha/tab_nav.css +1 -1
  11. data/app/components/primer/alpha/tab_nav.css.json +2 -0
  12. data/app/components/primer/alpha/tab_nav.css.map +1 -1
  13. data/app/components/primer/alpha/tab_nav.pcss +11 -1
  14. data/app/components/primer/alpha/tab_panels.html.erb +5 -9
  15. data/app/components/primer/alpha/tab_panels.rb +4 -13
  16. data/app/components/primer/alpha/text_field.rb +1 -0
  17. data/app/components/primer/alpha/underline_nav.css +1 -1
  18. data/app/components/primer/alpha/underline_nav.css.json +2 -0
  19. data/app/components/primer/alpha/underline_nav.css.map +1 -1
  20. data/app/components/primer/alpha/underline_nav.pcss +7 -1
  21. data/app/components/primer/alpha/underline_panels.css +1 -0
  22. data/app/components/primer/alpha/underline_panels.css.json +6 -0
  23. data/app/components/primer/alpha/underline_panels.css.map +1 -0
  24. data/app/components/primer/alpha/underline_panels.html.erb +6 -8
  25. data/app/components/primer/alpha/underline_panels.pcss +4 -0
  26. data/app/components/primer/alpha/underline_panels.rb +6 -14
  27. data/app/components/primer/beta/icon_button.rb +5 -0
  28. data/app/components/primer/beta/relative_time.rb +3 -0
  29. data/app/components/primer/beta/spinner.html.erb +3 -0
  30. data/app/components/primer/beta/spinner.rb +15 -1
  31. data/app/components/primer/open_project/page_header.html.erb +3 -0
  32. data/app/components/primer/open_project/page_header.rb +16 -1
  33. data/app/components/primer/primer.pcss +1 -0
  34. data/lib/primer/forms/dsl/text_field_input.rb +8 -1
  35. data/lib/primer/forms/primer_text_field.d.ts +27 -0
  36. data/lib/primer/forms/primer_text_field.js +17 -5
  37. data/lib/primer/forms/primer_text_field.ts +24 -5
  38. data/lib/primer/forms/text_field.html.erb +6 -2
  39. data/lib/primer/view_components/version.rb +2 -2
  40. data/previews/primer/alpha/text_field_preview.rb +11 -0
  41. data/previews/primer/beta/breadcrumbs_preview.rb +9 -0
  42. data/previews/primer/beta/icon_button_preview/summary_as_button.html.erb +12 -0
  43. data/previews/primer/beta/icon_button_preview.rb +95 -14
  44. data/previews/primer/beta/relative_time_preview/link_with_tooltip.html.erb +13 -0
  45. data/previews/primer/beta/relative_time_preview.rb +12 -0
  46. data/previews/primer/beta/spinner_preview.rb +2 -2
  47. data/previews/primer/open_project/page_header_preview.rb +53 -5
  48. data/static/arguments.json +12 -12
  49. data/static/constants.json +1 -0
  50. data/static/info_arch.json +104 -13
  51. data/static/previews.json +91 -0
  52. metadata +9 -3
@@ -7,17 +7,20 @@ module Primer
7
7
  class TextFieldInput < Input
8
8
  attr_reader(
9
9
  *%i[
10
- name label show_clear_button leading_visual clear_button_id
10
+ name label show_clear_button leading_visual leading_spinner clear_button_id
11
11
  visually_hide_label inset monospace field_wrap_classes auto_check_src
12
12
  ]
13
13
  )
14
14
 
15
+ alias leading_spinner? leading_spinner
16
+
15
17
  def initialize(name:, label:, **system_arguments)
16
18
  @name = name
17
19
  @label = label
18
20
 
19
21
  @show_clear_button = system_arguments.delete(:show_clear_button)
20
22
  @leading_visual = system_arguments.delete(:leading_visual)
23
+ @leading_spinner = !!system_arguments.delete(:leading_spinner)
21
24
  @clear_button_id = system_arguments.delete(:clear_button_id)
22
25
  @inset = system_arguments.delete(:inset)
23
26
  @monospace = system_arguments.delete(:monospace)
@@ -30,6 +33,10 @@ module Primer
30
33
  )
31
34
  end
32
35
 
36
+ if @leading_spinner && !@leading_visual
37
+ raise ArgumentError, "text fields that request a leading spinner must also specify a leading visual"
38
+ end
39
+
33
40
  super(**system_arguments)
34
41
 
35
42
  add_input_data(:target, "primer-text-field.inputElement #{system_arguments.dig(:data, :target) || ''}")
@@ -1 +1,28 @@
1
1
  import '@github/auto-check-element';
2
+ import type { AutoCheckErrorEvent, AutoCheckSuccessEvent } from '@github/auto-check-element';
3
+ declare global {
4
+ interface HTMLElementEventMap {
5
+ 'auto-check-success': AutoCheckSuccessEvent;
6
+ 'auto-check-error': AutoCheckErrorEvent;
7
+ }
8
+ }
9
+ export declare class PrimerTextFieldElement extends HTMLElement {
10
+ #private;
11
+ inputElement: HTMLInputElement;
12
+ validationElement: HTMLElement;
13
+ validationMessageElement: HTMLElement;
14
+ validationSuccessIcon: HTMLElement;
15
+ validationErrorIcon: HTMLElement;
16
+ leadingVisual: HTMLElement;
17
+ leadingSpinner: HTMLElement;
18
+ connectedCallback(): void;
19
+ disconnectedCallback(): void;
20
+ clearContents(): void;
21
+ clearError(): void;
22
+ setValidationMessage(message: string): void;
23
+ toggleValidationStyling(isError: boolean): void;
24
+ setSuccess(message: string): void;
25
+ setError(message: string): void;
26
+ showLeadingSpinner(): void;
27
+ hideLeadingSpinner(): void;
28
+ }
@@ -1,3 +1,4 @@
1
+ /* eslint-disable custom-elements/expose-class-on-global */
1
2
  var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
3
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
4
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -18,10 +19,7 @@ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (
18
19
  var _PrimerTextFieldElement_abortController;
19
20
  import '@github/auto-check-element';
20
21
  import { controller, target } from '@github/catalyst';
21
- // eslint-disable-next-line custom-elements/expose-class-on-global
22
- let PrimerTextFieldElement =
23
- // eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars
24
- class PrimerTextFieldElement extends HTMLElement {
22
+ let PrimerTextFieldElement = class PrimerTextFieldElement extends HTMLElement {
25
23
  constructor() {
26
24
  super(...arguments);
27
25
  _PrimerTextFieldElement_abortController.set(this, void 0);
@@ -83,6 +81,14 @@ class PrimerTextFieldElement extends HTMLElement {
83
81
  this.setValidationMessage(message);
84
82
  this.validationElement.hidden = false;
85
83
  }
84
+ showLeadingSpinner() {
85
+ this.leadingSpinner?.removeAttribute('hidden');
86
+ this.leadingVisual?.setAttribute('hidden', '');
87
+ }
88
+ hideLeadingSpinner() {
89
+ this.leadingSpinner?.setAttribute('hidden', '');
90
+ this.leadingVisual?.removeAttribute('hidden');
91
+ }
86
92
  };
87
93
  _PrimerTextFieldElement_abortController = new WeakMap();
88
94
  __decorate([
@@ -100,7 +106,13 @@ __decorate([
100
106
  __decorate([
101
107
  target
102
108
  ], PrimerTextFieldElement.prototype, "validationErrorIcon", void 0);
109
+ __decorate([
110
+ target
111
+ ], PrimerTextFieldElement.prototype, "leadingVisual", void 0);
112
+ __decorate([
113
+ target
114
+ ], PrimerTextFieldElement.prototype, "leadingSpinner", void 0);
103
115
  PrimerTextFieldElement = __decorate([
104
116
  controller
105
- // eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars
106
117
  ], PrimerTextFieldElement);
118
+ export { PrimerTextFieldElement };
@@ -1,15 +1,24 @@
1
+ /* eslint-disable custom-elements/expose-class-on-global */
2
+
1
3
  import '@github/auto-check-element'
4
+ import type {AutoCheckErrorEvent, AutoCheckSuccessEvent} from '@github/auto-check-element'
2
5
  import {controller, target} from '@github/catalyst'
3
6
 
4
- // eslint-disable-next-line custom-elements/expose-class-on-global
7
+ declare global {
8
+ interface HTMLElementEventMap {
9
+ 'auto-check-success': AutoCheckSuccessEvent
10
+ 'auto-check-error': AutoCheckErrorEvent
11
+ }
12
+ }
5
13
  @controller
6
- // eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars
7
- class PrimerTextFieldElement extends HTMLElement {
14
+ export class PrimerTextFieldElement extends HTMLElement {
8
15
  @target inputElement: HTMLInputElement
9
16
  @target validationElement: HTMLElement
10
17
  @target validationMessageElement: HTMLElement
11
18
  @target validationSuccessIcon: HTMLElement
12
19
  @target validationErrorIcon: HTMLElement
20
+ @target leadingVisual: HTMLElement
21
+ @target leadingSpinner: HTMLElement
13
22
 
14
23
  #abortController: AbortController | null
15
24
 
@@ -19,7 +28,7 @@ class PrimerTextFieldElement extends HTMLElement {
19
28
 
20
29
  this.addEventListener(
21
30
  'auto-check-success',
22
- async (event: any) => {
31
+ async (event: AutoCheckSuccessEvent) => {
23
32
  const message = await event.detail.response.text()
24
33
  if (message && message.length > 0) {
25
34
  this.setSuccess(message)
@@ -32,7 +41,7 @@ class PrimerTextFieldElement extends HTMLElement {
32
41
 
33
42
  this.addEventListener(
34
43
  'auto-check-error',
35
- async (event: any) => {
44
+ async (event: AutoCheckErrorEvent) => {
36
45
  const errorMessage = await event.detail.response.text()
37
46
  this.setError(errorMessage)
38
47
  },
@@ -85,4 +94,14 @@ class PrimerTextFieldElement extends HTMLElement {
85
94
  this.setValidationMessage(message)
86
95
  this.validationElement.hidden = false
87
96
  }
97
+
98
+ showLeadingSpinner(): void {
99
+ this.leadingSpinner?.removeAttribute('hidden')
100
+ this.leadingVisual?.setAttribute('hidden', '')
101
+ }
102
+
103
+ hideLeadingSpinner(): void {
104
+ this.leadingSpinner?.setAttribute('hidden', '')
105
+ this.leadingVisual?.removeAttribute('hidden')
106
+ }
88
107
  }
@@ -1,8 +1,12 @@
1
1
  <%= render(FormControl.new(input: @input, tag: :"primer-text-field")) do %>
2
2
  <%= content_tag(:div, **@field_wrap_arguments) do %>
3
- <% if @input.leading_visual %>
3
+ <%# leading spinner implies a leading visual %>
4
+ <% if @input.leading_visual || @input.leading_spinner? %>
4
5
  <span class="FormControl-input-leadingVisualWrap">
5
- <%= render(Primer::Beta::Octicon.new(**@input.leading_visual)) %>
6
+ <%= render(Primer::Beta::Octicon.new(**@input.leading_visual, data: { target: "primer-text-field.leadingVisual" })) %>
7
+ <% if @input.leading_spinner? %>
8
+ <%= render(Primer::Beta::Spinner.new(size: :small, hidden: true, data: { target: "primer-text-field.leadingSpinner" })) %>
9
+ <% end %>
6
10
  </span>
7
11
  <% end %>
8
12
  <%= render Primer::ConditionalWrapper.new(condition: @input.auto_check_src, tag: "auto-check", csrf: auto_check_authenticity_token, src: @input.auto_check_src) do %>
@@ -5,8 +5,8 @@ module Primer
5
5
  module ViewComponents
6
6
  module VERSION
7
7
  MAJOR = 0
8
- MINOR = 33
9
- PATCH = 2
8
+ MINOR = 35
9
+ PATCH = 0
10
10
 
11
11
  STRING = [MAJOR, MINOR, PATCH].join(".")
12
12
  end
@@ -23,6 +23,7 @@ module Primer
23
23
  # @param inset toggle
24
24
  # @param monospace toggle
25
25
  # @param leading_visual_icon octicon
26
+ # @param leading_spinner toggle
26
27
  # @param input_width [Symbol] select [auto, small, medium, large, xlarge, xxlarge]
27
28
  def playground(
28
29
  name: "my-text-field",
@@ -42,6 +43,7 @@ module Primer
42
43
  inset: false,
43
44
  monospace: false,
44
45
  leading_visual_icon: nil,
46
+ leading_spinner: false,
45
47
  input_width: nil
46
48
  )
47
49
  system_arguments = {
@@ -61,6 +63,7 @@ module Primer
61
63
  placeholder: placeholder,
62
64
  inset: inset,
63
65
  monospace: monospace,
66
+ leading_spinner: leading_spinner,
64
67
  input_width: input_width
65
68
  }
66
69
 
@@ -71,6 +74,14 @@ module Primer
71
74
  }
72
75
  end
73
76
 
77
+ # You're required to specify a leading visual if a leading spinner is requested
78
+ if leading_spinner && !leading_visual_icon
79
+ system_arguments[:leading_visual] = {
80
+ icon: :search,
81
+ size: :small
82
+ }
83
+ end
84
+
74
85
  render(Primer::Alpha::TextField.new(**system_arguments))
75
86
  end
76
87
 
@@ -38,6 +38,15 @@ module Primer
38
38
  def with_deprecated_truncate
39
39
  render_with_template
40
40
  end
41
+
42
+ # @label With a specific link target
43
+ def with_link_target(number_of_links: 2)
44
+ render(Primer::Beta::Breadcrumbs.new) do |component|
45
+ Array.new(number_of_links&.to_i || 3) do |i|
46
+ component.with_item(href: "##{i}", target: "_blank") { "Breadcrumb Item #{i + 1}" }
47
+ end
48
+ end
49
+ end
41
50
  end
42
51
  end
43
52
  end
@@ -0,0 +1,12 @@
1
+ <details>
2
+ <%= render(Primer::Beta::IconButton.new(
3
+ size: :medium,
4
+ id: "button-preview",
5
+ tag: tag,
6
+ disabled: false,
7
+ icon: :star,
8
+ "aria-label": "Link"
9
+ )) do %>
10
+ <% end %>
11
+ <p>A wrapping `details` tag is required when using the IconButton with the `:summary` tag</p>
12
+ </details>
@@ -10,7 +10,7 @@ module Primer
10
10
  # @param aria_label text
11
11
  # @param disabled toggle
12
12
  # @param inactive toggle
13
- # @param tag select [a, summary, button]
13
+ # @param tag select [a, button]
14
14
  # @param icon [Symbol] octicon
15
15
  # @param show_tooltip toggle
16
16
  def playground(
@@ -22,8 +22,13 @@ module Primer
22
22
  inactive: false,
23
23
  icon: :plus,
24
24
  aria_label: "Button",
25
- show_tooltip: true
25
+ show_tooltip: true,
26
+ href: nil
26
27
  )
28
+ # Sets default href to `a`, to ensure it's keyboard interactive and proper markup
29
+ if tag == :a && href.nil?
30
+ href = "#"
31
+ end
27
32
  render(Primer::Beta::IconButton.new(
28
33
  scheme: scheme,
29
34
  size: size,
@@ -33,7 +38,8 @@ module Primer
33
38
  inactive: inactive,
34
39
  icon: icon,
35
40
  "aria-label": aria_label,
36
- show_tooltip: show_tooltip
41
+ show_tooltip: show_tooltip,
42
+ href: href
37
43
  ))
38
44
  end
39
45
 
@@ -41,7 +47,7 @@ module Primer
41
47
  # @param size select [small, medium, large]
42
48
  # @param aria_label text
43
49
  # @param disabled toggle
44
- # @param tag select [a, summary, button]
50
+ # @param tag select [a, button]
45
51
  # @snapshot
46
52
  def default(
47
53
  size: :medium,
@@ -49,8 +55,13 @@ module Primer
49
55
  tag: :button,
50
56
  disabled: false,
51
57
  icon: :star,
52
- aria_label: "Button"
58
+ aria_label: "Button",
59
+ href: nil
53
60
  )
61
+ # Sets default href to `a`, to ensure it's keyboard interactive and proper markup
62
+ if tag == :a && href.nil?
63
+ href = "#"
64
+ end
54
65
  render(Primer::Beta::IconButton.new(
55
66
  scheme: :default,
56
67
  size: size,
@@ -58,7 +69,8 @@ module Primer
58
69
  tag: tag,
59
70
  disabled: disabled,
60
71
  icon: icon,
61
- "aria-label": aria_label
72
+ "aria-label": aria_label,
73
+ href: href
62
74
  ))
63
75
  end
64
76
 
@@ -66,7 +78,7 @@ module Primer
66
78
  # @param size select [small, medium, large]
67
79
  # @param aria_label text
68
80
  # @param disabled toggle
69
- # @param tag select [a, summary, button]
81
+ # @param tag select [a, button]
70
82
  # @snapshot
71
83
  def invisible(
72
84
  size: :medium,
@@ -74,8 +86,13 @@ module Primer
74
86
  tag: :button,
75
87
  disabled: false,
76
88
  icon: :x,
77
- aria_label: "Button"
89
+ aria_label: "Button",
90
+ href: nil
78
91
  )
92
+ # Sets default href to `a`, to ensure it's keyboard interactive and proper markup
93
+ if tag == :a && href.nil?
94
+ href = "#"
95
+ end
79
96
  render(Primer::Beta::IconButton.new(
80
97
  scheme: :invisible,
81
98
  size: size,
@@ -83,7 +100,8 @@ module Primer
83
100
  tag: tag,
84
101
  disabled: disabled,
85
102
  icon: icon,
86
- "aria-label": aria_label
103
+ "aria-label": aria_label,
104
+ href: href
87
105
  ))
88
106
  end
89
107
 
@@ -91,7 +109,7 @@ module Primer
91
109
  # @param size select [small, medium, large]
92
110
  # @param aria_label text
93
111
  # @param disabled toggle
94
- # @param tag select [a, summary, button]
112
+ # @param tag select [a, button]
95
113
  # @snapshot
96
114
  def primary(
97
115
  size: :medium,
@@ -99,8 +117,13 @@ module Primer
99
117
  tag: :button,
100
118
  disabled: false,
101
119
  icon: :x,
102
- aria_label: "Button"
120
+ aria_label: "Button",
121
+ href: nil
103
122
  )
123
+ # Sets default href to `a`, to ensure it's keyboard interactive and proper markup
124
+ if tag == :a && href.nil?
125
+ href = "#"
126
+ end
104
127
  render(Primer::Beta::IconButton.new(
105
128
  scheme: :primary,
106
129
  size: size,
@@ -108,7 +131,8 @@ module Primer
108
131
  tag: tag,
109
132
  disabled: disabled,
110
133
  icon: icon,
111
- "aria-label": aria_label
134
+ "aria-label": aria_label,
135
+ href: href
112
136
  ))
113
137
  end
114
138
 
@@ -116,7 +140,7 @@ module Primer
116
140
  # @param size select [small, medium, large]
117
141
  # @param aria_label text
118
142
  # @param disabled toggle
119
- # @param tag select [a, summary, button]
143
+ # @param tag select [a, button]
120
144
  # @snapshot
121
145
  def danger(
122
146
  size: :medium,
@@ -124,8 +148,13 @@ module Primer
124
148
  tag: :button,
125
149
  disabled: false,
126
150
  icon: :trash,
127
- aria_label: "Button"
151
+ aria_label: "Button",
152
+ href: nil
128
153
  )
154
+ # Sets default href to `a`, to ensure it's keyboard interactive and proper markup
155
+ if tag == :a && href.nil?
156
+ href = "#"
157
+ end
129
158
  render(Primer::Beta::IconButton.new(
130
159
  scheme: :danger,
131
160
  size: size,
@@ -133,9 +162,61 @@ module Primer
133
162
  tag: tag,
134
163
  disabled: disabled,
135
164
  icon: icon,
165
+ "aria-label": aria_label,
166
+ href: href
167
+ ))
168
+ end
169
+
170
+ # @label Link as button
171
+ # @param size select [small, medium, large]
172
+ # @param aria_label text
173
+ # @param disabled toggle
174
+ # @param href text
175
+ # @snapshot
176
+ def link_as_button(
177
+ size: :medium,
178
+ id: "button-preview",
179
+ tag: :a,
180
+ href: "#",
181
+ disabled: false,
182
+ icon: :star,
183
+ aria_label: "Link"
184
+ )
185
+ render(Primer::Beta::IconButton.new(
186
+ scheme: :default,
187
+ size: size,
188
+ id: id,
189
+ tag: tag,
190
+ href: href,
191
+ disabled: disabled,
192
+ icon: icon,
136
193
  "aria-label": aria_label
137
194
  ))
138
195
  end
196
+
197
+ # @label Summary as button
198
+ # @param size select [small, medium, large]
199
+ # @param aria_label text
200
+ # @param disabled toggle
201
+ # @snapshot
202
+ def summary_as_button(
203
+ size: :medium,
204
+ id: "button-preview",
205
+ tag: :summary,
206
+ disabled: false,
207
+ icon: :star,
208
+ aria_label: "Button"
209
+ )
210
+ render_with_template(locals: {
211
+ scheme: :default,
212
+ size: size,
213
+ id: id,
214
+ tag: tag,
215
+ disabled: disabled,
216
+ icon: icon,
217
+ "aria-label": aria_label
218
+ })
219
+ end
139
220
  end
140
221
  end
141
222
  end
@@ -0,0 +1,13 @@
1
+ <% time = Time.utc(2020, 1, 1, 0, 0, 0) %>
2
+
3
+ <%= render(Primer::Beta::Link.new(href: "#", id: "link")) do |link| %>
4
+ <% link.with_tooltip(id: "tool-tip", text: time.to_s) %>
5
+ <%= render(Primer::Beta::RelativeTime.new(id: "relative-time", datetime: time, no_title: true)) %>
6
+ <% end %>
7
+
8
+ <script>
9
+ // When `<relative-time>`’s `title` changes, update `<tool-tip>` text.
10
+ document.getElementById("relative-time").addEventListener("relative-time-updated", ({newTitle}) => {
11
+ document.getElementById("tool-tip").textContent = newTitle
12
+ })
13
+ </script>
@@ -281,6 +281,18 @@ module Primer
281
281
  title: title
282
282
  ))
283
283
  end
284
+
285
+ # @label No Title Attribute
286
+ # @snapshot
287
+ def no_title_attribute
288
+ render(Primer::Beta::RelativeTime.new(datetime: Time.utc(2020, 1, 1, 0, 0, 0), no_title: true))
289
+ end
290
+
291
+ # @label Link With Tooltip
292
+ # @snapshot
293
+ def link_with_tooltip
294
+ render_with_template
295
+ end
284
296
  end
285
297
  end
286
298
  end
@@ -7,8 +7,8 @@ module Primer
7
7
  # @label Playground
8
8
  #
9
9
  # @param size [Symbol] select [small, medium, large]
10
- def playground(size: :medium)
11
- render(Primer::Beta::Spinner.new(size: size))
10
+ def playground(size: :medium, sr_text: "Loading content...")
11
+ render(Primer::Beta::Spinner.new(size: size, sr_text: sr_text))
12
12
  end
13
13
 
14
14
  # @label Default Options
@@ -40,7 +40,7 @@ module Primer
40
40
  with_leading_action: with_leading_action,
41
41
  with_actions: with_actions,
42
42
  breadcrumb_items: breadcrumb_items,
43
- with_tab_nav: with_tab_nav})
43
+ with_tab_nav: with_tab_nav })
44
44
  end
45
45
 
46
46
  # @label Large title
@@ -71,8 +71,8 @@ module Primer
71
71
  component.with_breadcrumbs([{ href: "/foo", text: "Foo" }, { href: "/bar", text: "Bar" }, "Baz"])
72
72
 
73
73
  component.with_action_button(mobile_icon: "star", mobile_label: "Star") do |button|
74
- button.with_leading_visual_icon(icon: "star")
75
- "Star"
74
+ button.with_leading_visual_icon(icon: "star")
75
+ "Star"
76
76
  end
77
77
  component.with_action_menu(menu_arguments: { anchor_align: :end },
78
78
  button_arguments: { button_block: callback }) do |menu|
@@ -123,7 +123,6 @@ module Primer
123
123
  end
124
124
  end
125
125
 
126
-
127
126
  # @label With a single action
128
127
  # The single action will not be transformed into a menu on mobile, but remains in a smaller variant
129
128
  def single_action
@@ -180,13 +179,62 @@ module Primer
180
179
  header.with_description { "Last updated 5 minutes ago by XYZ." }
181
180
  header.with_tab_nav(label: "label") do |nav|
182
181
  Array.new(3) do |i|
183
- nav.with_tab(selected: i.zero? , href: "#") do |tab|
182
+ nav.with_tab(selected: i.zero?, href: "#") do |tab|
184
183
  tab.with_text { "Tab #{i + 1}" }
185
184
  end
186
185
  end
187
186
  end
188
187
  end
189
188
  end
189
+
190
+ # @label With a SegmentedControl
191
+ def segmented_control
192
+ render(Primer::OpenProject::PageHeader.new) do |component|
193
+ component.with_title { "Here's a segmented control" }
194
+ component.with_breadcrumbs(["Baz"])
195
+
196
+ component.with_action_segmented_control("aria-label": "Segmented control") do |control|
197
+ control.with_item(label: "Preview", icon: :eye, selected: true)
198
+ control.with_item(label: "Raw", icon: :"file-code")
199
+ end
200
+
201
+ component.with_action_button(mobile_icon: "star", mobile_label: "Star") do |button|
202
+ button.with_leading_visual_icon(icon: "star")
203
+ "Star"
204
+ end
205
+
206
+ callback = lambda do |button|
207
+ button.with_leading_visual_icon(icon: :gear)
208
+ "Settings"
209
+ end
210
+
211
+ component.with_action_menu(menu_arguments: { anchor_align: :end },
212
+ button_arguments: { button_block: callback }) do |menu|
213
+ menu.with_item(label: "Subitem 1") do |item|
214
+ item.with_leading_visual_icon(icon: :paste)
215
+ end
216
+ menu.with_item(label: "Subitem 2") do |item|
217
+ item.with_leading_visual_icon(icon: :log)
218
+ end
219
+ end
220
+ end
221
+ end
222
+
223
+ # @label With mobile icons-only SegmentedControl
224
+ def segmented_control_mobile_icons
225
+ render(Primer::OpenProject::PageHeader.new) do |component|
226
+ component.with_title { "Here's a segmented control" }
227
+ component.with_breadcrumbs(["Baz"])
228
+
229
+ component.with_action_segmented_control(
230
+ "aria-label": "Segmented control",
231
+ mobile_system_arguments: { hide_labels: true }
232
+ ) do |control|
233
+ control.with_item(label: "Preview", icon: :eye, selected: true)
234
+ control.with_item(label: "Raw", icon: :"file-code")
235
+ end
236
+ end
237
+ end
190
238
  end
191
239
  end
192
240
  end
@@ -2462,18 +2462,6 @@
2462
2462
  "default": "N/A",
2463
2463
  "description": "One of `:left` or `:right`. - Defaults to left"
2464
2464
  },
2465
- {
2466
- "name": "body_arguments",
2467
- "type": "Hash",
2468
- "default": "`{}`",
2469
- "description": "[System arguments](/system-arguments) for the body wrapper."
2470
- },
2471
- {
2472
- "name": "wrapper_arguments",
2473
- "type": "Hash",
2474
- "default": "`{}`",
2475
- "description": "[System arguments](/system-arguments) for the `TabContainer` wrapper."
2476
- },
2477
2465
  {
2478
2466
  "name": "system_arguments",
2479
2467
  "type": "Hash",
@@ -2764,6 +2752,12 @@
2764
2752
  "default": "N/A",
2765
2753
  "description": "Renders a leading visual icon before the text field's cursor. The hash will be passed to Primer's [Octicon](/components/beta/octicon) component."
2766
2754
  },
2755
+ {
2756
+ "name": "leading_spinner",
2757
+ "type": "Boolean",
2758
+ "default": "N/A",
2759
+ "description": "If `true`, a leading spinner will be included in the markup. The spinner can be shown via the `showLeadingSpinner()` JavaScript method, and hidden via `hideLeadingSpinner()`. If this argument is `true`, a leading visual must also be provided."
2760
+ },
2767
2761
  {
2768
2762
  "name": "show_clear_button",
2769
2763
  "type": "Boolean",
@@ -4254,6 +4248,12 @@
4254
4248
  "default": "`nil`",
4255
4249
  "description": "Provide a custom title to the element."
4256
4250
  },
4251
+ {
4252
+ "name": "no_title",
4253
+ "type": "Boolean",
4254
+ "default": "`false`",
4255
+ "description": "Removes the `title` attribute provided on the element by default."
4256
+ },
4257
4257
  {
4258
4258
  "name": "system_arguments",
4259
4259
  "type": "Hash",
@@ -1220,6 +1220,7 @@
1220
1220
  },
1221
1221
  "Primer::Beta::Spinner": {
1222
1222
  "DEFAULT_SIZE": "medium",
1223
+ "DEFAULT_SR_TEXT": "Loading",
1223
1224
  "DEFAULT_STYLE": "box-sizing: content-box; color: var(--color-icon-primary);",
1224
1225
  "SIZE_MAPPINGS": {
1225
1226
  "small": 16,