openproject-primer_view_components 0.87.0 → 0.88.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +14 -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/components/primer/alpha/tree_view/tree_view.js +27 -11
  6. data/app/components/primer/alpha/tree_view/tree_view.ts +24 -9
  7. data/app/components/primer/open_project/avatar_fallback.js +1 -1
  8. data/app/components/primer/open_project/avatar_fallback.ts +1 -1
  9. data/app/components/primer/open_project/border_box/collapsible_header.js +1 -1
  10. data/app/components/primer/open_project/border_box/collapsible_header.ts +1 -1
  11. data/app/components/primer/open_project/collapsible_section.js +1 -1
  12. data/app/components/primer/open_project/collapsible_section.ts +1 -1
  13. data/app/components/primer/open_project/danger_dialog_form_helper.js +1 -1
  14. data/app/components/primer/open_project/danger_dialog_form_helper.ts +1 -1
  15. data/app/components/primer/open_project/fieldset.rb +2 -2
  16. data/app/components/primer/open_project/filterable_tree_view.js +2 -1
  17. data/app/components/primer/open_project/filterable_tree_view.ts +3 -2
  18. data/app/components/primer/open_project/flex_layout.rb +2 -2
  19. data/app/components/primer/open_project/inline_message.rb +1 -1
  20. data/app/components/primer/open_project/input_group.html.erb +9 -0
  21. data/app/components/primer/open_project/input_group.rb +13 -0
  22. data/app/components/primer/open_project/page_header.rb +1 -1
  23. data/app/components/primer/open_project/page_header_element.js +1 -1
  24. data/app/components/primer/open_project/page_header_element.ts +1 -1
  25. data/app/components/primer/open_project/pagination.rb +1 -3
  26. data/app/components/primer/open_project/sub_header.rb +16 -16
  27. data/app/components/primer/open_project/sub_header_element.js +1 -1
  28. data/app/components/primer/open_project/sub_header_element.ts +1 -1
  29. data/app/components/primer/open_project/zen_mode_button.js +1 -1
  30. data/app/components/primer/open_project/zen_mode_button.ts +1 -1
  31. data/lib/primer/view_components/version.rb +1 -1
  32. data/previews/primer/alpha/tree_view_preview/doubled_path.html.erb +12 -0
  33. data/previews/primer/alpha/tree_view_preview/form_input.html.erb +7 -7
  34. data/previews/primer/alpha/tree_view_preview.rb +6 -0
  35. data/previews/primer/open_project/input_group_preview.rb +9 -0
  36. data/static/arguments.json +8 -8
  37. data/static/info_arch.json +32 -9
  38. data/static/previews.json +23 -10
  39. metadata +2 -1
@@ -15,7 +15,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
15
15
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
16
16
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
17
17
  };
18
- var _TreeViewElement_instances, _TreeViewElement_abortController, _TreeViewElement_autoExpandFrom, _TreeViewElement_eventIsActivation, _TreeViewElement_nodeForEvent, _TreeViewElement_handleNodeEvent, _TreeViewElement_eventIsCheckboxToggle, _TreeViewElement_handleCheckboxToggle, _TreeViewElement_eventIsSingleSelection, _TreeViewElement_handleNodeActivated, _TreeViewElement_handleNodeFocused, _TreeViewElement_handleNodeKeyboardEvent;
18
+ var _TreeViewElement_instances, _TreeViewElement_abortController, _TreeViewElement_autoExpandFrom, _TreeViewElement_eventIsActivation, _TreeViewElement_nodeForEvent, _TreeViewElement_handleNodeEvent, _TreeViewElement_eventIsCheckboxToggle, _TreeViewElement_handleCheckboxToggle, _TreeViewElement_eventIsSingleSelection, _TreeViewElement_handleNodeActivated, _TreeViewElement_handleNodeFocused, _TreeViewElement_handleNodeKeyboardEvent, _TreeViewElement_checkNodeOnly;
19
19
  import { controller, target } from '@github/catalyst';
20
20
  import { useRovingTabIndex } from './tree_view_roving_tab_index';
21
21
  let TreeViewElement = class TreeViewElement extends HTMLElement {
@@ -97,8 +97,8 @@ let TreeViewElement = class TreeViewElement extends HTMLElement {
97
97
  // behavior for these element types is user- or browser-defined
98
98
  if (!(node instanceof HTMLDivElement))
99
99
  return;
100
- const path = this.getNodePath(node);
101
- const nodeInfo = this.infoFromNode(node, 'true');
100
+ const newCheckedValue = this.getNodeCheckedValue(node) === 'true' ? 'false' : 'true';
101
+ const nodeInfo = this.infoFromNode(node, newCheckedValue);
102
102
  const checkSuccess = this.dispatchEvent(new CustomEvent('treeViewBeforeNodeChecked', {
103
103
  bubbles: true,
104
104
  cancelable: true,
@@ -106,11 +106,11 @@ let TreeViewElement = class TreeViewElement extends HTMLElement {
106
106
  }));
107
107
  if (!checkSuccess)
108
108
  return;
109
- if (this.getNodeCheckedValue(node) === 'true') {
109
+ if (newCheckedValue === 'false') {
110
110
  this.setNodeCheckedValue(node, 'false');
111
111
  }
112
112
  else {
113
- this.checkOnlyAtPath(path);
113
+ __classPrivateFieldGet(this, _TreeViewElement_instances, "m", _TreeViewElement_checkNodeOnly).call(this, node);
114
114
  }
115
115
  this.dispatchEvent(new CustomEvent('treeViewNodeChecked', {
116
116
  bubbles: true,
@@ -142,7 +142,7 @@ let TreeViewElement = class TreeViewElement extends HTMLElement {
142
142
  return this.querySelector('[aria-current=true]');
143
143
  }
144
144
  get activeNodes() {
145
- return document.querySelectorAll('[aria-checked="true"]');
145
+ return this.querySelectorAll('[aria-checked="true"]');
146
146
  }
147
147
  expandAtPath(path) {
148
148
  const node = this.subTreeAtPath(path);
@@ -175,10 +175,10 @@ let TreeViewElement = class TreeViewElement extends HTMLElement {
175
175
  this.setNodeCheckedValue(node, 'false');
176
176
  }
177
177
  checkOnlyAtPath(path) {
178
- for (const el of this.activeNodes) {
179
- this.uncheckAtPath(this.getNodePath(el));
180
- }
181
- this.checkAtPath(path);
178
+ const node = this.nodeAtPath(path);
179
+ if (!node)
180
+ return;
181
+ __classPrivateFieldGet(this, _TreeViewElement_instances, "m", _TreeViewElement_checkNodeOnly).call(this, node);
182
182
  }
183
183
  toggleCheckedAtPath(path) {
184
184
  const node = this.nodeAtPath(path);
@@ -286,6 +286,9 @@ let TreeViewElement = class TreeViewElement extends HTMLElement {
286
286
  const payload = {
287
287
  path: this.getNodePath(node),
288
288
  };
289
+ const nodeId = node.getAttribute('data-node-id');
290
+ if (nodeId)
291
+ payload.nodeId = nodeId;
289
292
  const inputValue = this.getFormInputValueForNode(node);
290
293
  if (inputValue)
291
294
  payload.value = inputValue;
@@ -424,7 +427,12 @@ _TreeViewElement_handleNodeKeyboardEvent = function _TreeViewElement_handleNodeK
424
427
  }
425
428
  else if (this.selectVariant(node) === 'single') {
426
429
  event.preventDefault();
427
- this.checkOnlyAtPath(this.getNodePath(node));
430
+ if (this.getNodeCheckedValue(node) === 'true') {
431
+ this.setNodeCheckedValue(node, 'false');
432
+ }
433
+ else {
434
+ __classPrivateFieldGet(this, _TreeViewElement_instances, "m", _TreeViewElement_checkNodeOnly).call(this, node);
435
+ }
428
436
  }
429
437
  else if (node instanceof HTMLAnchorElement) {
430
438
  // simulate click on space
@@ -433,6 +441,14 @@ _TreeViewElement_handleNodeKeyboardEvent = function _TreeViewElement_handleNodeK
433
441
  break;
434
442
  }
435
443
  };
444
+ _TreeViewElement_checkNodeOnly = function _TreeViewElement_checkNodeOnly(node) {
445
+ for (const el of this.activeNodes) {
446
+ if (el === node)
447
+ continue;
448
+ this.setNodeCheckedValue(el, 'false');
449
+ }
450
+ this.setNodeCheckedValue(node, 'true');
451
+ };
436
452
  __decorate([
437
453
  target
438
454
  ], TreeViewElement.prototype, "formInputContainer", void 0);
@@ -179,8 +179,8 @@ export class TreeViewElement extends HTMLElement {
179
179
  // behavior for these element types is user- or browser-defined
180
180
  if (!(node instanceof HTMLDivElement)) return
181
181
 
182
- const path = this.getNodePath(node)
183
- const nodeInfo = this.infoFromNode(node, 'true')
182
+ const newCheckedValue = this.getNodeCheckedValue(node) === 'true' ? 'false' : 'true'
183
+ const nodeInfo = this.infoFromNode(node, newCheckedValue)
184
184
 
185
185
  const checkSuccess = this.dispatchEvent(
186
186
  new CustomEvent('treeViewBeforeNodeChecked', {
@@ -192,10 +192,10 @@ export class TreeViewElement extends HTMLElement {
192
192
 
193
193
  if (!checkSuccess) return
194
194
 
195
- if (this.getNodeCheckedValue(node) === 'true') {
195
+ if (newCheckedValue === 'false') {
196
196
  this.setNodeCheckedValue(node, 'false')
197
197
  } else {
198
- this.checkOnlyAtPath(path)
198
+ this.#checkNodeOnly(node)
199
199
  }
200
200
 
201
201
  this.dispatchEvent(
@@ -271,7 +271,11 @@ export class TreeViewElement extends HTMLElement {
271
271
  } else if (this.selectVariant(node) === 'single') {
272
272
  event.preventDefault()
273
273
 
274
- this.checkOnlyAtPath(this.getNodePath(node))
274
+ if (this.getNodeCheckedValue(node) === 'true') {
275
+ this.setNodeCheckedValue(node, 'false')
276
+ } else {
277
+ this.#checkNodeOnly(node)
278
+ }
275
279
  } else if (node instanceof HTMLAnchorElement) {
276
280
  // simulate click on space
277
281
  node.click()
@@ -313,7 +317,7 @@ export class TreeViewElement extends HTMLElement {
313
317
  }
314
318
 
315
319
  get activeNodes() {
316
- return document.querySelectorAll('[aria-checked="true"]')
320
+ return this.querySelectorAll('[aria-checked="true"]')
317
321
  }
318
322
 
319
323
  expandAtPath(path: string[]) {
@@ -352,11 +356,19 @@ export class TreeViewElement extends HTMLElement {
352
356
  }
353
357
 
354
358
  checkOnlyAtPath(path: string[]) {
359
+ const node = this.nodeAtPath(path)
360
+ if (!node) return
361
+
362
+ this.#checkNodeOnly(node)
363
+ }
364
+
365
+ #checkNodeOnly(node: Element) {
355
366
  for (const el of this.activeNodes) {
356
- this.uncheckAtPath(this.getNodePath(el))
367
+ if (el === node) continue
368
+ this.setNodeCheckedValue(el, 'false')
357
369
  }
358
370
 
359
- this.checkAtPath(path)
371
+ this.setNodeCheckedValue(node, 'true')
360
372
  }
361
373
 
362
374
  toggleCheckedAtPath(path: string[]) {
@@ -479,10 +491,13 @@ export class TreeViewElement extends HTMLElement {
479
491
  newInput.removeAttribute('data-target')
480
492
  newInput.removeAttribute('form')
481
493
 
482
- const payload: {path: string[]; value?: string} = {
494
+ const payload: {path: string[]; nodeId?: string; value?: string} = {
483
495
  path: this.getNodePath(node),
484
496
  }
485
497
 
498
+ const nodeId = node.getAttribute('data-node-id')
499
+ if (nodeId) payload.nodeId = nodeId
500
+
486
501
  const inputValue = this.getFormInputValueForNode(node)
487
502
  if (inputValue) payload.value = inputValue
488
503
 
@@ -100,6 +100,6 @@ let AvatarFallbackElement = class AvatarFallbackElement extends HTMLElement {
100
100
  }
101
101
  };
102
102
  AvatarFallbackElement = __decorate([
103
- controller
103
+ controller('avatar-fallback')
104
104
  ], AvatarFallbackElement);
105
105
  export { AvatarFallbackElement };
@@ -13,7 +13,7 @@ import {controller} from '@github/catalyst'
13
13
  * due to a Catalyst bug where @attr accessors aren't properly initialized
14
14
  * when elements have pre-existing attribute values.
15
15
  */
16
- @controller
16
+ @controller('avatar-fallback')
17
17
  export class AvatarFallbackElement extends HTMLElement {
18
18
  private img: HTMLImageElement | null = null
19
19
  private testImage: HTMLImageElement | null = null
@@ -17,5 +17,5 @@ let CollapsibleHeaderElement = class CollapsibleHeaderElement extends Collapsibl
17
17
  }
18
18
  };
19
19
  CollapsibleHeaderElement = __decorate([
20
- controller
20
+ controller('collapsible-header')
21
21
  ], CollapsibleHeaderElement);
@@ -1,7 +1,7 @@
1
1
  import {controller} from '@github/catalyst'
2
2
  import {CollapsibleElement} from '../collapsible'
3
3
 
4
- @controller
4
+ @controller('collapsible-header')
5
5
  class CollapsibleHeaderElement extends CollapsibleElement {
6
6
  connectedCallback() {
7
7
  if (!this.closest('.Box')) {
@@ -12,5 +12,5 @@ let CollapsibleSectionElement = class CollapsibleSectionElement extends Collapsi
12
12
  }
13
13
  };
14
14
  CollapsibleSectionElement = __decorate([
15
- controller
15
+ controller('collapsible-section')
16
16
  ], CollapsibleSectionElement);
@@ -1,7 +1,7 @@
1
1
  import {controller} from '@github/catalyst'
2
2
  import {CollapsibleElement} from './collapsible'
3
3
 
4
- @controller
4
+ @controller('collapsible-section')
5
5
  class CollapsibleSectionElement extends CollapsibleElement {
6
6
  get baseClass(): string {
7
7
  return 'CollapsibleSection'
@@ -62,7 +62,7 @@ __decorate([
62
62
  attr
63
63
  ], DangerDialogFormHelperElement.prototype, "confirmationLiveMessageUnchecked", void 0);
64
64
  DangerDialogFormHelperElement = __decorate([
65
- controller
65
+ controller('danger-dialog-form-helper')
66
66
  ], DangerDialogFormHelperElement);
67
67
  if (!window.customElements.get('danger-dialog-form-helper')) {
68
68
  window.DangerDialogFormHelperElement = DangerDialogFormHelperElement;
@@ -3,7 +3,7 @@ import type {LiveRegionElement} from '@primer/live-region-element'
3
3
 
4
4
  const SUBMIT_BUTTON_SELECTOR = 'input[type=submit],button[type=submit],button[data-submit-dialog-id]'
5
5
 
6
- @controller
6
+ @controller('danger-dialog-form-helper')
7
7
  class DangerDialogFormHelperElement extends HTMLElement {
8
8
  @target checkbox: HTMLInputElement | undefined
9
9
  @target liveRegion: LiveRegionElement
@@ -18,7 +18,7 @@ module Primer
18
18
  # @param legend_text [String] A legend should be short and concise. The String will also be read by assistive technology.
19
19
  # @param visually_hide_legend [Boolean] Controls if the legend is visible. If `true`, screen reader only text will be added.
20
20
  # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
21
- def initialize(legend_text: nil, visually_hide_legend: false, **system_arguments) # rubocop:disable Lint/MissingSuper
21
+ def initialize(legend_text: nil, visually_hide_legend: false, **system_arguments)
22
22
  @legend_text = legend_text
23
23
  @visually_hide_legend = visually_hide_legend
24
24
  @system_arguments = deny_tag_argument(**system_arguments)
@@ -40,7 +40,7 @@ module Primer
40
40
 
41
41
  attr_reader :text
42
42
 
43
- def initialize(text: nil, visually_hide_legend: false, **system_arguments) # rubocop:disable Lint/MissingSuper
43
+ def initialize(text: nil, visually_hide_legend: false, **system_arguments)
44
44
  @text = text
45
45
 
46
46
  @system_arguments = deny_tag_argument(**system_arguments)
@@ -224,6 +224,7 @@ _FilterableTreeViewElement_updateCheckedNodeIds = function _FilterableTreeViewEl
224
224
  }
225
225
  __classPrivateFieldGet(this, _FilterableTreeViewElement_checkedNodeIds, "f").set(nodeId, nodeInfo.checkedValue);
226
226
  const payload = { path: nodeInfo.path };
227
+ payload.nodeId = nodeId;
227
228
  const dataValue = node.getAttribute('data-value');
228
229
  if (dataValue)
229
230
  payload.value = dataValue;
@@ -689,7 +690,7 @@ __decorate([
689
690
  target
690
691
  ], FilterableTreeViewElement.prototype, "includeSubItemsCheckBox", void 0);
691
692
  FilterableTreeViewElement = __decorate([
692
- controller
693
+ controller('filterable-tree-view')
693
694
  ], FilterableTreeViewElement);
694
695
  export { FilterableTreeViewElement };
695
696
  if (!window.customElements.get('filterable-tree-view')) {
@@ -18,7 +18,7 @@ type NodeState = {
18
18
 
19
19
  const ASYNC_DEBOUNCE_MS = 300
20
20
 
21
- @controller
21
+ @controller('filterable-tree-view')
22
22
  export class FilterableTreeViewElement extends HTMLElement {
23
23
  @target filterInput: HTMLInputElement
24
24
  @target filterModeControlList: HTMLElement
@@ -119,7 +119,8 @@ export class FilterableTreeViewElement extends HTMLElement {
119
119
  }
120
120
 
121
121
  this.#checkedNodeIds.set(nodeId, nodeInfo.checkedValue)
122
- const payload: {path: string[]; value?: string} = {path: nodeInfo.path}
122
+ const payload: {path: string[]; nodeId?: string; value?: string} = {path: nodeInfo.path}
123
+ payload.nodeId = nodeId
123
124
  const dataValue = node.getAttribute('data-value')
124
125
  if (dataValue) payload.value = dataValue
125
126
  this.#checkedNodeFormPayloads.set(nodeId, payload)
@@ -29,10 +29,10 @@ module Primer
29
29
  # no slot provided
30
30
  return false if rows.empty? && columns.empty? && boxes.empty?
31
31
 
32
- if [rows, columns, boxes].count { |arr| !arr.empty? } == 1
32
+ if [rows, columns, boxes].one? { |arr| !arr.empty? }
33
33
  # only rows or columns or boxes are used
34
34
  true
35
- elsif [rows, columns, boxes].count { |arr| !arr.empty? } > 1
35
+ elsif [rows, columns, boxes].many? { |arr| !arr.empty? }
36
36
  # rows, columns and boxes are used together, which is not allowed
37
37
  raise ArgumentError, "You can't mix row, column and box slots"
38
38
  end
@@ -33,7 +33,7 @@ module Primer
33
33
  # @param scheme [Symbol] <%= one_of(Primer::OpenProject::InlineMessage::SCHEME_OPTIONS) %>
34
34
  # @param size [Symbol] <%= one_of(Primer::OpenProject::InlineMessage::SIZE_OPTIONS) %>
35
35
  # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
36
- def initialize(scheme:, size: DEFAULT_SIZE, **system_arguments) # rubocop:disable Lint/MissingSuper
36
+ def initialize(scheme:, size: DEFAULT_SIZE, **system_arguments)
37
37
  resolved_scheme = fetch_or_fallback(SCHEME_OPTIONS, scheme)
38
38
  resolved_size = fetch_or_fallback(SIZE_OPTIONS, size, DEFAULT_SIZE)
39
39
 
@@ -4,6 +4,15 @@
4
4
  <%= trailing_action %>
5
5
  <% end %>
6
6
 
7
+ <% if @text_input_validation_message %>
8
+ <div class="FormControl-inlineValidation mt-1" id="<%= @text_input_validation_message_id %>">
9
+ <span class="FormControl-inlineValidation--visual">
10
+ <%= render(Primer::Beta::Octicon.new(icon: :"alert-fill", size: :xsmall, aria: { hidden: true })) %>
11
+ </span>
12
+ <span><%= @text_input_validation_message %></span>
13
+ </div>
14
+ <% end %>
15
+
7
16
  <% if caption %>
8
17
  <%= caption %>
9
18
  <% end %>
@@ -49,6 +49,19 @@ module Primer
49
49
  renders_one :text_input, lambda { |readonly: true, **system_arguments|
50
50
  deny_single_argument(:input_width, "Set the `input_width` on the `InputGroup`", **system_arguments)
51
51
  deny_single_argument(:caption, "Set the `caption` on the `InputGroup`", **system_arguments)
52
+
53
+ # Extract validation_message so it can be rendered outside the flex row.
54
+ # This prevents the trailing action from misaligning when validation is present.
55
+ @text_input_validation_message = system_arguments.delete(:validation_message)
56
+ if @text_input_validation_message
57
+ @text_input_validation_message_id = self.class.generate_id(base_name: "input-group-validation")
58
+ system_arguments[:invalid] = true
59
+ system_arguments[:aria] = merge_aria(
60
+ system_arguments,
61
+ { aria: { describedby: @text_input_validation_message_id } }
62
+ )
63
+ end
64
+
52
65
  system_arguments[:input_width] = @system_arguments[:input_width]
53
66
 
54
67
  system_arguments[:classes] = class_names(
@@ -288,7 +288,7 @@ module Primer
288
288
  end
289
289
 
290
290
  def render_mobile_menu?
291
- actions.count > 1
291
+ actions.many?
292
292
  end
293
293
 
294
294
  def show_state?
@@ -15,7 +15,7 @@ let PageHeaderElement = class PageHeaderElement extends HTMLElement {
15
15
  }
16
16
  };
17
17
  PageHeaderElement = __decorate([
18
- controller
18
+ controller('page-header')
19
19
  ], PageHeaderElement);
20
20
  if (!window.customElements.get('page-header')) {
21
21
  window.PageHeaderElement = PageHeaderElement;
@@ -1,6 +1,6 @@
1
1
  import {controller} from '@github/catalyst'
2
2
 
3
- @controller
3
+ @controller('page-header')
4
4
  class PageHeaderElement extends HTMLElement {
5
5
  menuItemClick(event: Event) {
6
6
  const currentTarget = event.currentTarget as HTMLButtonElement
@@ -269,9 +269,7 @@ module Primer
269
269
  key = :"page-#{page[:num]}-break"
270
270
  content = "…"
271
271
 
272
- props.merge!(
273
- role: "presentation"
274
- )
272
+ props[:role] = "presentation"
275
273
  end
276
274
 
277
275
  props[:class] = class_names("Page", props[:class])
@@ -40,7 +40,7 @@ module Primer
40
40
  @mobile_actions ||= []
41
41
  mobile_component = Primer::Beta::IconButton.new(display: MOBILE_ACTIONS_DISPLAY,
42
42
  **icon_args)
43
- @mobile_actions.push({ component: mobile_component, block: block})
43
+ @mobile_actions.push({ component: mobile_component, block: block })
44
44
 
45
45
  Primer::OpenProject::SubHeader::Button.new(display: DESKTOP_ACTIONS_DISPLAY, **kwargs)
46
46
  end
@@ -65,9 +65,9 @@ module Primer
65
65
  mobile_component = Primer::OpenProject::SubHeader::Menu.new(icon_only: true,
66
66
  display: MOBILE_ACTIONS_DISPLAY,
67
67
  **kwargs)
68
- @mobile_actions.push({ component: mobile_component, block: block})
68
+ @mobile_actions.push({ component: mobile_component, block: block })
69
69
 
70
- Primer::OpenProject::SubHeader::Menu.new(icon_only: icon_only,display: DESKTOP_ACTIONS_DISPLAY, **kwargs)
70
+ Primer::OpenProject::SubHeader::Menu.new(icon_only: icon_only, display: DESKTOP_ACTIONS_DISPLAY, **kwargs)
71
71
  },
72
72
  }
73
73
  }
@@ -146,7 +146,7 @@ module Primer
146
146
  if icon_only
147
147
  Primer::Beta::IconButton.new(**icon_args)
148
148
  else
149
- @mobile_filter_button = Primer::Beta::IconButton.new(display: MOBILE_ACTIONS_DISPLAY,
149
+ @mobile_filter_button = Primer::Beta::IconButton.new(display: MOBILE_ACTIONS_DISPLAY,
150
150
  **icon_args)
151
151
 
152
152
  Primer::OpenProject::SubHeader::Button.new(display: DESKTOP_ACTIONS_DISPLAY, **kwargs)
@@ -194,18 +194,18 @@ module Primer
194
194
  }
195
195
 
196
196
  renders_one :segmented_control, lambda { |**system_arguments, &block|
197
- deny_tag_argument(**system_arguments)
198
- system_arguments[:mr] ||= 2
199
- system_arguments = set_as_hidden_filter_target(system_arguments)
200
-
201
- @segmented_control_block = block
202
- @mobile_segmented_control = Primer::OpenProject::SubHeader::SegmentedControl.new(
203
- hide_labels: true,
204
- display: MOBILE_ACTIONS_DISPLAY,
205
- **system_arguments
206
- )
207
-
208
- Primer::OpenProject::SubHeader::SegmentedControl.new(display: DESKTOP_ACTIONS_DISPLAY, **system_arguments)
197
+ deny_tag_argument(**system_arguments)
198
+ system_arguments[:mr] ||= 2
199
+ system_arguments = set_as_hidden_filter_target(system_arguments)
200
+
201
+ @segmented_control_block = block
202
+ @mobile_segmented_control = Primer::OpenProject::SubHeader::SegmentedControl.new(
203
+ hide_labels: true,
204
+ display: MOBILE_ACTIONS_DISPLAY,
205
+ **system_arguments
206
+ )
207
+
208
+ Primer::OpenProject::SubHeader::SegmentedControl.new(display: DESKTOP_ACTIONS_DISPLAY, **system_arguments)
209
209
  }
210
210
 
211
211
  renders_one :text, lambda { |**system_arguments|
@@ -69,7 +69,7 @@ __decorate([
69
69
  targets
70
70
  ], SubHeaderElement.prototype, "filterExpandButton", void 0);
71
71
  SubHeaderElement = __decorate([
72
- controller
72
+ controller('sub-header')
73
73
  ], SubHeaderElement);
74
74
  if (!window.customElements.get('sub-header')) {
75
75
  window.SubHeaderElement = SubHeaderElement;
@@ -1,6 +1,6 @@
1
1
  import {controller, target, targets} from '@github/catalyst'
2
2
 
3
- @controller
3
+ @controller('sub-header')
4
4
  class SubHeaderElement extends HTMLElement {
5
5
  @target filterInput: HTMLInputElement
6
6
  @targets shownItemsOnExpandedFilter: HTMLElement[]
@@ -56,7 +56,7 @@ __decorate([
56
56
  target
57
57
  ], ZenModeButtonElement.prototype, "button", void 0);
58
58
  ZenModeButtonElement = __decorate([
59
- controller
59
+ controller('zen-mode-button')
60
60
  ], ZenModeButtonElement);
61
61
  if (!window.customElements.get('zen-mode-button')) {
62
62
  window.ZenModeButtonElement = ZenModeButtonElement;
@@ -1,6 +1,6 @@
1
1
  import {controller, target} from '@github/catalyst'
2
2
 
3
- @controller
3
+ @controller('zen-mode-button')
4
4
  class ZenModeButtonElement extends HTMLElement {
5
5
  @target button: HTMLElement
6
6
  inZenMode = false
@@ -5,7 +5,7 @@ module Primer
5
5
  module ViewComponents
6
6
  module VERSION
7
7
  MAJOR = 0
8
- MINOR = 87
8
+ MINOR = 88
9
9
  PATCH = 0
10
10
 
11
11
  STRING = [MAJOR, MINOR, PATCH].join(".")
@@ -0,0 +1,12 @@
1
+ <div style="max-width: 400px">
2
+ <%= render(Primer::Alpha::TreeView.new) do |tree_view| %>
3
+ <% tree_view.with_sub_tree(label: "src", expanded: true, select_variant: :single) do |sub_tree| %>
4
+ <% sub_tree.with_leaf(label: "button.rb", select_variant: :single) %>
5
+ <% sub_tree.with_leaf(label: "icon_button.rb", current: true, select_variant: :single) %>
6
+ <% end %>
7
+
8
+ <% tree_view.with_leaf(label: "action_menu.rb", select_variant: :single) %>
9
+ <% tree_view.with_leaf(label: "action_menu.rb", select_variant: :single) %>
10
+ <% tree_view.with_leaf(label: "action_menu.rb", select_variant: :single) %>
11
+ <% end %>
12
+ </div>
@@ -1,15 +1,15 @@
1
1
  <%= form_with(url: primer_view_components.generic_form_submission_path(format: :json)) do |f| %>
2
2
  <%= render(Primer::Alpha::Stack.new) do %>
3
3
  <%= render(Primer::Alpha::TreeView.new(form_arguments: { builder: f, name: "folder_structure" })) do |tree| %>
4
- <% tree.with_sub_tree(label: "src", expanded: expanded, select_variant: select_variant, value: 0) do |sub_tree| %>
5
- <% sub_tree.with_leaf(label: "button.rb", select_variant: select_variant, value: 1, checked: true) %>
6
- <% sub_tree.with_leaf(label: "icon_button.rb", current: true, select_variant: select_variant, value: 2) %>
4
+ <% tree.with_sub_tree(label: "src", expanded: expanded, select_variant: select_variant, value: 0, data: { node_id: "src" }) do |sub_tree| %>
5
+ <% sub_tree.with_leaf(label: "button.rb", select_variant: select_variant, value: 1, checked: true, data: { node_id: "src-button-rb" }) %>
6
+ <% sub_tree.with_leaf(label: "icon_button.rb", current: true, select_variant: select_variant, value: 2, data: { node_id: "src-icon-button-rb" }) %>
7
7
  <% end %>
8
8
 
9
- <% tree.with_leaf(label: "action_menu.rb", select_variant: select_variant, value: 3) %>
10
- <% tree.with_sub_tree(label: "Docs & legal requirements", select_variant: select_variant, value: 4) do |sub_tree| %>
11
- <% sub_tree.with_leaf(label: "Readme.md", select_variant: select_variant, value: 5) %>
12
- <% sub_tree.with_leaf(label: "Copyright.md", select_variant: select_variant, value: 6) %>
9
+ <% tree.with_leaf(label: "action_menu.rb", select_variant: select_variant, value: 3, data: { node_id: "action-menu-rb" }) %>
10
+ <% tree.with_sub_tree(label: "Docs & legal requirements", select_variant: select_variant, value: 4, data: { node_id: "docs" }) do |sub_tree| %>
11
+ <% sub_tree.with_leaf(label: "Readme.md", select_variant: select_variant, value: 5, data: { node_id: "docs-readme-md" }) %>
12
+ <% sub_tree.with_leaf(label: "Copyright.md", select_variant: select_variant, value: 6, data: { node_id: "docs-copyright-md" }) %>
13
13
  <% end %>
14
14
  <% end %>
15
15
 
@@ -197,6 +197,12 @@ module Primer
197
197
  })
198
198
  end
199
199
 
200
+ # @label Doubled paths
201
+ # @hidden
202
+ def doubled_path
203
+ render_with_template
204
+ end
205
+
200
206
  private
201
207
 
202
208
  def coerce_bool(value)
@@ -71,6 +71,15 @@ module Primer
71
71
  menu.with_caption { "Some caption" }
72
72
  end
73
73
  end
74
+
75
+ # @label With error message
76
+ # @snapshot
77
+ def with_error_message
78
+ render(Primer::OpenProject::InputGroup.new) do |menu|
79
+ menu.with_text_input(name: "a name", label: "My input group", validation_message: "Custom validation message", value: "Copyable value")
80
+ menu.with_trailing_action_clipboard_copy_button(id: "button", value: "Copyable value", aria: { label: "Copy some text" })
81
+ end
82
+ end
74
83
  end
75
84
  end
76
85
  end
@@ -6188,25 +6188,25 @@
6188
6188
  {
6189
6189
  "name": "filter_input_arguments",
6190
6190
  "type": "Hash",
6191
- "default": "`DEFAULT_FILTER_INPUT_ARGUMENTS.dup`",
6191
+ "default": "`{}`",
6192
6192
  "description": "Arguments that will be passed to the [TextField](/components/alpha/textfield) component."
6193
6193
  },
6194
6194
  {
6195
6195
  "name": "filter_mode_control_arguments",
6196
6196
  "type": "Hash",
6197
- "default": "`DEFAULT_FILTER_MODE_CONTROL_ARGUMENTS.dup`",
6197
+ "default": "`{}`",
6198
6198
  "description": "Arguments that will be passed to the [SegmentedControl](/components/alpha/segmentedcontrol) component."
6199
6199
  },
6200
6200
  {
6201
6201
  "name": "include_sub_items_check_box_arguments",
6202
6202
  "type": "Hash",
6203
- "default": "`DEFAULT_INCLUDE_SUB_ITEMS_CHECK_BOX_ARGUMENTS.dup`",
6203
+ "default": "`{}`",
6204
6204
  "description": "Arguments that will be passed to the [CheckBox](/components/alpha/checkbox) component."
6205
6205
  },
6206
6206
  {
6207
6207
  "name": "no_results_node_arguments",
6208
6208
  "type": "Hash",
6209
- "default": "`DEFAULT_NO_RESULTS_NODE_ARGUMENTS.dup`",
6209
+ "default": "`{}`",
6210
6210
  "description": "Arguments that will be passed to a [TreeView::LeafNode](/components/alpha/treeviewleafnode) component that appears when no items match the filter criteria."
6211
6211
  }
6212
6212
  ]
@@ -6600,12 +6600,12 @@
6600
6600
  ]
6601
6601
  },
6602
6602
  {
6603
- "component": "OpenProject::SubHeader::QuickActionComponent",
6603
+ "component": "OpenProject::SubHeader::QuickAction",
6604
6604
  "status": "open_project",
6605
6605
  "a11y_reviewed": false,
6606
- "short_name": "OpenProjectSubHeaderQuickActionComponent",
6607
- "source": "https://github.com/primer/view_components/tree/main/app/components/primer/open_project/sub_header/quick_filter.rb",
6608
- "lookbook": "https://primer.style/view-components/lookbook/inspect/primer/open_project/sub_header/quick_filter/default/",
6606
+ "short_name": "OpenProjectSubHeaderQuickAction",
6607
+ "source": "https://github.com/primer/view_components/tree/main/app/components/primer/open_project/sub_header/quick_action_component.rb",
6608
+ "lookbook": "https://primer.style/view-components/lookbook/inspect/primer/open_project/sub_header/quick_action/default/",
6609
6609
  "parameters": []
6610
6610
  },
6611
6611
  {