primer_view_components 0.11.0 → 0.13.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +50 -0
  3. data/app/assets/javascripts/app/components/primer/alpha/tool_tip.d.ts +1 -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_bar_element.js +8 -3
  9. data/app/components/primer/alpha/action_bar_element.ts +8 -1
  10. data/app/components/primer/alpha/action_list/form_wrapper.html.erb +4 -2
  11. data/app/components/primer/alpha/action_list/form_wrapper.rb +20 -9
  12. data/app/components/primer/alpha/action_menu/action_menu_element.js +1 -10
  13. data/app/components/primer/alpha/action_menu/action_menu_element.ts +0 -11
  14. data/app/components/primer/alpha/action_menu.rb +120 -3
  15. data/app/components/primer/alpha/modal_dialog.js +10 -13
  16. data/app/components/primer/alpha/modal_dialog.ts +10 -13
  17. data/app/components/primer/alpha/segmented_control/item.html.erb +1 -8
  18. data/app/components/primer/alpha/segmented_control/item.rb +38 -4
  19. data/app/components/primer/alpha/segmented_control.css +1 -1
  20. data/app/components/primer/alpha/segmented_control.css.json +14 -13
  21. data/app/components/primer/alpha/segmented_control.css.map +1 -1
  22. data/app/components/primer/alpha/segmented_control.pcss +75 -66
  23. data/app/components/primer/alpha/segmented_control.rb +10 -0
  24. data/app/components/primer/alpha/text_field.css +1 -1
  25. data/app/components/primer/alpha/tool_tip.d.ts +1 -0
  26. data/app/components/primer/alpha/tool_tip.js +26 -93
  27. data/app/components/primer/alpha/tool_tip.ts +25 -91
  28. data/app/components/primer/beta/base_button.rb +4 -0
  29. data/app/components/primer/beta/button.css +1 -1
  30. data/app/components/primer/beta/button.css.map +1 -1
  31. data/app/components/primer/beta/button.pcss +6 -2
  32. data/lib/primer/accessibility.rb +3 -1
  33. data/lib/primer/static/generate_info_arch.rb +86 -5
  34. data/lib/primer/view_components/version.rb +1 -1
  35. data/previews/primer/alpha/action_menu_preview/single_select_form_items.html.erb +31 -0
  36. data/previews/primer/alpha/action_menu_preview/with_actions.html.erb +1 -1
  37. data/previews/primer/alpha/action_menu_preview.rb +8 -2
  38. data/previews/primer/alpha/check_box_preview.rb +1 -0
  39. data/previews/primer/alpha/dialog_preview/autofocus_element.html.erb +8 -0
  40. data/previews/primer/alpha/dialog_preview.rb +5 -0
  41. data/previews/primer/alpha/radio_button_preview.rb +1 -0
  42. data/previews/primer/alpha/segmented_control_preview.rb +35 -0
  43. data/previews/primer/alpha/tooltip_preview/tooltip_with_dialog_moving_focus_to_input.html.erb +23 -0
  44. data/previews/primer/alpha/tooltip_preview.rb +6 -1
  45. data/previews/primer/beta/button_group_preview.rb +6 -6
  46. data/previews/primer/beta/button_preview.rb +20 -2
  47. data/previews/primer/beta/icon_button_preview.rb +3 -0
  48. data/static/arguments.json +6 -0
  49. data/static/classes.json +12 -0
  50. data/static/constants.json +12 -1
  51. data/static/info_arch.json +125 -160
  52. data/static/previews.json +91 -172
  53. metadata +5 -310
@@ -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 _ActionBarElement_instances, _ActionBarElement_initialBarWidth, _ActionBarElement_previousBarWidth, _ActionBarElement_focusZoneAbortController, _ActionBarElement_itemGap, _ActionBarElement_availableSpace, _ActionBarElement_menuSpace, _ActionBarElement_shrink, _ActionBarElement_grow, _ActionBarElement_showItem, _ActionBarElement_hideItem, _ActionBarElement_menuItems_get;
18
+ var _ActionBarElement_instances, _ActionBarElement_initialBarWidth, _ActionBarElement_previousBarWidth, _ActionBarElement_focusZoneAbortController, _ActionBarElement_isVisible, _ActionBarElement_itemGap, _ActionBarElement_availableSpace, _ActionBarElement_menuSpace, _ActionBarElement_shrink, _ActionBarElement_grow, _ActionBarElement_showItem, _ActionBarElement_hideItem, _ActionBarElement_menuItems_get;
19
19
  import { controller, targets, target } from '@github/catalyst';
20
20
  import { focusZone, FocusKeys } from '@primer/behaviors';
21
21
  const instersectionObserver = new IntersectionObserver(entries => {
@@ -94,12 +94,17 @@ let ActionBarElement = class ActionBarElement extends HTMLElement {
94
94
  bindKeys: FocusKeys.ArrowHorizontal | FocusKeys.HomeAndEnd,
95
95
  focusOutBehavior: 'wrap',
96
96
  focusableElementFilter: element => {
97
- return !element.closest('.ActionBar-item[hidden]') && !element.closest('li.ActionListItem');
97
+ return __classPrivateFieldGet(this, _ActionBarElement_instances, "m", _ActionBarElement_isVisible).call(this, element);
98
98
  }
99
99
  }), "f");
100
100
  }
101
101
  };
102
- _ActionBarElement_initialBarWidth = new WeakMap(), _ActionBarElement_previousBarWidth = new WeakMap(), _ActionBarElement_focusZoneAbortController = new WeakMap(), _ActionBarElement_instances = new WeakSet(), _ActionBarElement_itemGap = function _ActionBarElement_itemGap() {
102
+ _ActionBarElement_initialBarWidth = new WeakMap(), _ActionBarElement_previousBarWidth = new WeakMap(), _ActionBarElement_focusZoneAbortController = new WeakMap(), _ActionBarElement_instances = new WeakSet(), _ActionBarElement_isVisible = function _ActionBarElement_isVisible(element) {
103
+ // Safari doesn't support `checkVisibility` yet.
104
+ if (typeof element.checkVisibility === 'function')
105
+ return element.checkVisibility();
106
+ return Boolean(element.offsetParent || element.offsetWidth || element.offsetHeight);
107
+ }, _ActionBarElement_itemGap = function _ActionBarElement_itemGap() {
103
108
  var _a;
104
109
  return parseInt((_a = window.getComputedStyle(this.itemContainer)) === null || _a === void 0 ? void 0 : _a.columnGap, 10) || 0;
105
110
  }, _ActionBarElement_availableSpace = function _ActionBarElement_availableSpace() {
@@ -86,11 +86,18 @@ class ActionBarElement extends HTMLElement {
86
86
  bindKeys: FocusKeys.ArrowHorizontal | FocusKeys.HomeAndEnd,
87
87
  focusOutBehavior: 'wrap',
88
88
  focusableElementFilter: element => {
89
- return !element.closest('.ActionBar-item[hidden]') && !element.closest('li.ActionListItem')
89
+ return this.#isVisible(element)
90
90
  }
91
91
  })
92
92
  }
93
93
 
94
+ #isVisible(element: HTMLElement): boolean {
95
+ // Safari doesn't support `checkVisibility` yet.
96
+ if (typeof element.checkVisibility === 'function') return element.checkVisibility()
97
+
98
+ return Boolean(element.offsetParent || element.offsetWidth || element.offsetHeight)
99
+ }
100
+
94
101
  #itemGap(): number {
95
102
  return parseInt(window.getComputedStyle(this.itemContainer)?.columnGap, 10) || 0
96
103
  }
@@ -1,7 +1,9 @@
1
1
  <% if form_required? %>
2
2
  <%= form_with(url: @action, method: @http_method, **@form_arguments) do %>
3
- <% if render_input? %>
4
- <%= render(Primer::BaseComponent.new(tag: :input, **@input_arguments)) %>
3
+ <% if render_inputs? %>
4
+ <% @inputs.each do |input_arguments| %>
5
+ <%= render(Primer::BaseComponent.new(tag: :input, **input_arguments)) %>
6
+ <% end %>
5
7
  <% end %>
6
8
  <%= content %>
7
9
  <% end %>
@@ -24,14 +24,25 @@ module Primer
24
24
 
25
25
  name = @form_arguments.delete(:name)
26
26
  value = @form_arguments.delete(:value) || name
27
+ inputs = @form_arguments.delete(:inputs) || []
27
28
 
28
- @input_arguments = {
29
- type: :hidden,
30
- name: name,
31
- value: value,
32
- data: { list_item_input: true },
33
- **(@form_arguments.delete(:input_arguments) || {})
34
- }
29
+ # For the older version of this component that only allowed you to
30
+ # specify a single input
31
+ if inputs.empty?
32
+ inputs << {
33
+ name: name,
34
+ value: value,
35
+ **(@form_arguments.delete(:input_arguments) || {})
36
+ }
37
+ end
38
+
39
+ @inputs = inputs.map do |input_data|
40
+ input_data = input_data.dup
41
+ input_data[:type] ||= :hidden
42
+ input_data[:data] ||= {}
43
+ input_data[:data][:list_item_input] = true
44
+ input_data
45
+ end
35
46
  end
36
47
 
37
48
  def get?
@@ -42,8 +53,8 @@ module Primer
42
53
  @action && !get?
43
54
  end
44
55
 
45
- def render_input?
46
- @input_arguments[:name].present?
56
+ def render_inputs?
57
+ @inputs.present?
47
58
  end
48
59
 
49
60
  private
@@ -109,7 +109,7 @@ let ActionMenuElement = class ActionMenuElement extends HTMLElement {
109
109
  __classPrivateFieldGet(this, _ActionMenuElement_abortController, "f").abort();
110
110
  }
111
111
  handleEvent(event) {
112
- var _a, _b, _c;
112
+ var _a;
113
113
  const targetIsInvoker = (_a = this.invokerElement) === null || _a === void 0 ? void 0 : _a.contains(event.target);
114
114
  const eventIsActivation = __classPrivateFieldGet(this, _ActionMenuElement_instances, "m", _ActionMenuElement_isActivation).call(this, event);
115
115
  if (targetIsInvoker && event.type === 'mousedown') {
@@ -127,10 +127,6 @@ let ActionMenuElement = class ActionMenuElement extends HTMLElement {
127
127
  __classPrivateFieldSet(this, _ActionMenuElement_invokerBeingClicked, false, "f");
128
128
  return;
129
129
  }
130
- // Ignore events within dialogs within menus
131
- if (((_b = event.target) === null || _b === void 0 ? void 0 : _b.closest('dialog')) || ((_c = event.target) === null || _c === void 0 ? void 0 : _c.closest('modal-dialog'))) {
132
- return;
133
- }
134
130
  if (event.type === 'focusout') {
135
131
  if (__classPrivateFieldGet(this, _ActionMenuElement_invokerBeingClicked, "f"))
136
132
  return;
@@ -249,11 +245,6 @@ _ActionMenuElement_abortController = new WeakMap(), _ActionMenuElement_originalL
249
245
  item.setAttribute('aria-checked', `${checked}`);
250
246
  }
251
247
  __classPrivateFieldGet(this, _ActionMenuElement_instances, "m", _ActionMenuElement_updateInput).call(this);
252
- if (event instanceof KeyboardEvent && event.target instanceof HTMLButtonElement) {
253
- // prevent buttons from being clicked twice
254
- event.preventDefault();
255
- return;
256
- }
257
248
  }, _ActionMenuElement_activateItem = function _ActionMenuElement_activateItem(event, item) {
258
249
  const eventWillActivateByDefault = (event instanceof MouseEvent && event.type === 'click') ||
259
250
  (event instanceof KeyboardEvent &&
@@ -172,11 +172,6 @@ export class ActionMenuElement extends HTMLElement {
172
172
  return
173
173
  }
174
174
 
175
- // Ignore events within dialogs within menus
176
- if ((event.target as Element)?.closest('dialog') || (event.target as Element)?.closest('modal-dialog')) {
177
- return
178
- }
179
-
180
175
  if (event.type === 'focusout') {
181
176
  if (this.#invokerBeingClicked) return
182
177
 
@@ -283,12 +278,6 @@ export class ActionMenuElement extends HTMLElement {
283
278
  }
284
279
 
285
280
  this.#updateInput()
286
-
287
- if (event instanceof KeyboardEvent && event.target instanceof HTMLButtonElement) {
288
- // prevent buttons from being clicked twice
289
- event.preventDefault()
290
- return
291
- }
292
281
  }
293
282
 
294
283
  #activateItem(event: Event, item: Element) {
@@ -3,14 +3,131 @@
3
3
 
4
4
  module Primer
5
5
  module Alpha
6
- # ActionMenu is used for actions, navigation, to display secondary options, or single/multi select lists. They appear when users interact with buttons, actions, or other controls.
6
+ # ActionMenu is used for actions, navigation, to display secondary options, or single/multi select lists. They appear when
7
+ # users interact with buttons, actions, or other controls.
7
8
  #
8
9
  # The only allowed elements for the `Item` components are: `:a`, `:button`, and `:clipboard-copy`. The default is `:button`.
9
10
  #
11
+ # ### Select variants
12
+ #
13
+ # While `ActionMenu`s default to a list of buttons that can link to other pages, copy text to the clipboard, etc, they also support
14
+ # `single` and `multiple` select variants. The single select variant allows a single item to be "selected" (i.e. marked "active")
15
+ # when clicked, which will cause a check mark to appear to the left of the item text. When the `multiple` select variant is chosen,
16
+ # multiple items may be selected and check marks will appear next to each selected item.
17
+ #
18
+ # Use the `select_variant:` option to control which variant the `ActionMenu` uses. For more information, see the documentation on
19
+ # supported arguments below.
20
+ #
21
+ # ### Dynamic labels
22
+ #
23
+ # When using the `single` select variant, an optional label indicating the selected item can be displayed inside the menu button.
24
+ # Dynamic labels can also be prefixed with custom text.
25
+ #
26
+ # Pass `dynamic_label: true` to enable dynamic label behavior, and pass `dynamic_label_prefix: "<string>"` to set a custom prefix.
27
+ # For more information, see the documentation on supported arguments below.
28
+ #
29
+ # ### `ActionMenu`s as form inputs
30
+ #
31
+ # When using either the `single` or `multiple` select variants, `ActionMenu`s can be used as form inputs. They behave very
32
+ # similarly to how HTML `<select>` boxes behave, and play nicely with Rails' built-in form mechanisms. Pass arguments via the
33
+ # `form_arguments:` argument, including the Rails form builder object and the name of the field:
34
+ #
35
+ # ```erb
36
+ # <% form_with(url: update_merge_strategy_path) do |f| %>
37
+ # <%= render(Primer::Alpha::ActionMenu.new(form_arguments: { builder: f, name: "merge_strategy" })) do |menu| %>
38
+ # <% menu.with_item(label: "Fast forward", data: { value: "fast_forward" }) %>
39
+ # <% menu.with_item(label: "Recursive", data: { value: "recursive" }) %>
40
+ # <% menu.with_item(label: "Ours", data: { value: "ours" }) %>
41
+ # <% menu.with_item(label: "Theirs", data: { value: "theirs" }) %>
42
+ # <% end %>
43
+ # <% end %>
44
+ # ```
45
+ #
46
+ # The value of the `data: { value: ... }` argument is sent to the server on submit, keyed using the name provided above
47
+ # (eg. `"merge_strategy"`). If no value is provided for an item, the value of that item is the item's label. Here's the
48
+ # corresponding `MergeStrategyController` that might be written to handle the form above:
49
+ #
50
+ # ```ruby
51
+ # class MergeStrategyController < ApplicationController
52
+ # def update
53
+ # puts "You chose #{merge_strategy_params[:merge_strategy]}"
54
+ # end
55
+ #
56
+ # private
57
+ #
58
+ # def merge_strategy_params
59
+ # params.permit(:merge_strategy)
60
+ # end
61
+ # end
62
+ # ```
63
+ #
64
+ # ### `ActionMenu` items that submit forms
65
+ #
66
+ # Whereas `ActionMenu` items normally permit navigation via `<a>` tags which make HTTP `get` requests, `ActionMenu` items
67
+ # also permit navigation via `POST` requests. To enable this behavior, include the `href:` argument as normal, but also pass
68
+ # the `form_arguments:` argument to the appropriate item:
69
+ #
70
+ # ```erb
71
+ # <%= render(Primer::Alpha::ActionMenu.new) do |menu| %>
72
+ # <% menu.with_item(
73
+ # label: "Repository",
74
+ # href: update_repo_grouping_path,
75
+ # form_arguments: {
76
+ # method: :post,
77
+ # name: "group_by",
78
+ # value: "repository"
79
+ # }
80
+ # ) %>
81
+ # <% end %>
82
+ # ```
83
+ #
84
+ # Make sure to specify `method: :post`, as the default is `:get`. When clicked, the list item will submit a POST request to
85
+ # the URL passed in the `href:` argument, including a parameter named `"group_by"` with a value of `"repository"`. If no value
86
+ # is given, the name, eg. `"group_by"`, will be used as the value.
87
+ #
88
+ # It is possible to include multiple fields on submit. Instead of passing the `name:` and `value:` arguments, pass an array via
89
+ # the `inputs:` argument:
90
+ #
91
+ # ```erb
92
+ # <%= render(Primer::Alpha::ActionMenu.new) do |menu| %>
93
+ # <% menu.with_show_button { "Group By" } %>
94
+ # <% menu.with_item(
95
+ # label: "Repository",
96
+ # href: update_repo_grouping_path,
97
+ # form_arguments: {
98
+ # method: :post,
99
+ # inputs: [{
100
+ # name: "group_by",
101
+ # value: "repository"
102
+ # }, {
103
+ # name: "some_other_field",
104
+ # value: "some value",
105
+ # }],
106
+ # }
107
+ # ) %>
108
+ # <% end %>
109
+ # ```
110
+ #
111
+ # ### Form arguments
112
+ #
113
+ # The following table summarizes the arguments allowed in the `form_arguments:` hash mentioned above.
114
+ #
115
+ # |Name |Type |Default|Description|
116
+ # |:----------------|:-------------|:------|:----------|
117
+ # |`method` |`Symbol` |`:get` |The HTTP request method to use to submit the form. One of `:get`, `:post`, `:patch`, `:put`, `:delete`, or `:head`|
118
+ # |`name` |`String` |`nil` |The name of the field that will be sent to the server on submit.|
119
+ # |`value` |`String` |`nil` |The value of the field that will be sent to the server on submit.|
120
+ # |`input_arguments`|`Hash` |`{}` |Additional key/value pairs to emit as HTML attributes on the `<input type="hidden">` element.|
121
+ # |`inputs` |`Array<Hash>` |`[]` |An array of hashes representing HTML `<input type="hidden">` elements. Must contain at least `name:` and `value:` keys. If additional key/value pairs are provided, they are emitted as HTML attributes on the `<input>` element. This argument supercedes the `name:`, `value:`, and `:input_arguments` arguments listed above.|
122
+ #
123
+ # The elements of the `inputs:` array will be emitted as HTML `<input type="hidden">` elements.
124
+ #
10
125
  # @accessibility
11
- # The action for the menu item needs to be on the element with `role="menuitem"`. Semantics are removed for everything nested inside of it. When a menu item is selected, the menu will close immediately.
126
+ # The action for the menu item needs to be on the element with `role="menuitem"`. Semantics are removed for everything
127
+ # nested inside of it. When a menu item is selected, the menu will close immediately.
12
128
  #
13
- # Additional information around the keyboard functionality and implementation can be found on the [WAI-ARIA Authoring Practices](https://www.w3.org/TR/wai-aria-practices-1.2/#menu).
129
+ # Additional information around the keyboard functionality and implementation can be found on the
130
+ # [WAI-ARIA Authoring Practices](https://www.w3.org/TR/wai-aria-practices-1.2/#menu).
14
131
  class ActionMenu < Primer::Component
15
132
  status :alpha
16
133
 
@@ -38,19 +38,16 @@ function clickHandler(event) {
38
38
  return;
39
39
  }
40
40
  }
41
- // Find the top level dialog that is open.
42
- const topLevelDialog = overlayStack[overlayStack.length - 1];
43
- if (!topLevelDialog)
41
+ if (!overlayStack.length)
44
42
  return;
45
- dialogId = button.getAttribute('data-close-dialog-id');
46
- if (dialogId === topLevelDialog.id) {
47
- overlayStack.pop();
48
- topLevelDialog.close();
49
- }
50
- dialogId = button.getAttribute('data-submit-dialog-id');
51
- if (dialogId === topLevelDialog.id) {
52
- overlayStack.pop();
53
- topLevelDialog.close(true);
43
+ dialogId = button.getAttribute('data-close-dialog-id') || button.getAttribute('data-submit-dialog-id');
44
+ if (dialogId) {
45
+ const dialog = document.getElementById(dialogId);
46
+ if (dialog instanceof ModalDialogElement) {
47
+ const dialogIndex = overlayStack.findIndex(ele => ele.id === dialogId);
48
+ overlayStack.splice(dialogIndex, 1);
49
+ dialog.close(button.hasAttribute('data-submit-dialog-id'));
50
+ }
54
51
  }
55
52
  }
56
53
  function keydownHandler(event) {
@@ -107,7 +104,7 @@ export class ModalDialogElement extends HTMLElement {
107
104
  if (__classPrivateFieldGet(this, _ModalDialogElement_focusAbortController, "f").signal.aborted) {
108
105
  __classPrivateFieldSet(this, _ModalDialogElement_focusAbortController, new AbortController(), "f");
109
106
  }
110
- focusTrap(this, undefined, __classPrivateFieldGet(this, _ModalDialogElement_focusAbortController, "f").signal);
107
+ focusTrap(this, this.querySelector('[autofocus]'), __classPrivateFieldGet(this, _ModalDialogElement_focusAbortController, "f").signal);
111
108
  overlayStack.push(this);
112
109
  }
113
110
  else {
@@ -30,20 +30,17 @@ function clickHandler(event: Event) {
30
30
  return
31
31
  }
32
32
  }
33
- // Find the top level dialog that is open.
34
- const topLevelDialog = overlayStack[overlayStack.length - 1]
35
- if (!topLevelDialog) return
36
33
 
37
- dialogId = button.getAttribute('data-close-dialog-id')
38
- if (dialogId === topLevelDialog.id) {
39
- overlayStack.pop()
40
- topLevelDialog.close()
41
- }
34
+ if (!overlayStack.length) return
42
35
 
43
- dialogId = button.getAttribute('data-submit-dialog-id')
44
- if (dialogId === topLevelDialog.id) {
45
- overlayStack.pop()
46
- topLevelDialog.close(true)
36
+ dialogId = button.getAttribute('data-close-dialog-id') || button.getAttribute('data-submit-dialog-id')
37
+ if (dialogId) {
38
+ const dialog = document.getElementById(dialogId)
39
+ if (dialog instanceof ModalDialogElement) {
40
+ const dialogIndex = overlayStack.findIndex(ele => ele.id === dialogId)
41
+ overlayStack.splice(dialogIndex, 1)
42
+ dialog.close(button.hasAttribute('data-submit-dialog-id'))
43
+ }
47
44
  }
48
45
  }
49
46
 
@@ -107,7 +104,7 @@ export class ModalDialogElement extends HTMLElement {
107
104
  if (this.#focusAbortController.signal.aborted) {
108
105
  this.#focusAbortController = new AbortController()
109
106
  }
110
- focusTrap(this, undefined, this.#focusAbortController.signal)
107
+ focusTrap(this, this.querySelector('[autofocus]') as HTMLElement, this.#focusAbortController.signal)
111
108
  overlayStack.push(this)
112
109
  } else {
113
110
  if (!this.open) return
@@ -2,12 +2,5 @@
2
2
  "SegmentedControl-item",
3
3
  "SegmentedControl-item--selected": @selected
4
4
  ) %>" role="listitem" data-targets="segmented-control.items">
5
- <% if @hide_labels %>
6
- <%= render Primer::Beta::IconButton.new(icon: @icon, "aria-label": @label, **@system_arguments) %>
7
- <% else %>
8
- <%= render Primer::Beta::Button.new(**@system_arguments) do |button| %>
9
- <% button.with_leading_visual_icon(icon: @icon) unless @icon.nil? %>
10
- <%= @label %>
11
- <% end %>
12
- <% end %>
5
+ <%= render @button %>
13
6
  </li>
@@ -13,16 +13,50 @@ module Primer
13
13
  # @param selected [Boolean] Whether the item is selected
14
14
  # @param icon [Symbol] The icon to use
15
15
  # @param hide_labels [Symbol] Whether to only show the icon
16
- def initialize(label:, selected: false, icon: nil, hide_labels: false, **system_arguments)
17
- @icon = icon
18
- @hide_labels = hide_labels
19
- @label = label
16
+ def initialize(
17
+ label:,
18
+ selected: false,
19
+ icon: nil,
20
+ hide_labels: false,
21
+ **system_arguments
22
+ )
20
23
  @selected = selected
21
24
 
22
25
  @system_arguments = system_arguments
23
26
  @system_arguments[:"data-action"] = "click:segmented-control#select" if system_arguments[:href].nil?
24
27
  @system_arguments[:"aria-current"] = selected
25
28
  @system_arguments[:scheme] = :invisible
29
+
30
+ if hide_labels
31
+ @button = Primer::Beta::IconButton.new(
32
+ icon: icon,
33
+ "aria-label": label,
34
+ **@system_arguments
35
+ )
36
+ else
37
+ @button = Primer::Beta::Button.new(**@system_arguments)
38
+ @button.with_leading_visual_icon(icon: icon) if icon
39
+ @button.with_content(label)
40
+ end
41
+ end
42
+
43
+ # @!parse
44
+ # # Optional trailing Label
45
+ # #
46
+ # # @param system_arguments [Hash] The arguments accepted by <%= link_to_component(Primer::Beta::Button) %>'s `with_trailing_visual_label` slot.
47
+ # renders_one(:trailing_visual_label)
48
+
49
+ # Optional trailing label.
50
+ #
51
+ # @param system_arguments [Hash] The arguments accepted by <%= link_to_component(Primer::Beta::Button) %>'s `with_trailing_visual_label` slot.
52
+ def with_trailing_visual_label(**system_arguments, &block)
53
+ @button.with_trailing_visual_label(**system_arguments, &block)
54
+ end
55
+
56
+ private
57
+
58
+ def before_render
59
+ content
26
60
  end
27
61
  end
28
62
  end
@@ -1 +1 @@
1
- .SegmentedControl{background-color:var(--controlTrack-bgColor-rest,var(--color-segmented-control-bg));border-radius:var(--borderRadius-medium,.375rem);display:inline-flex;list-style:none}.SegmentedControl-item{border:var(--borderWidth-thin,max(1px,.0625rem)) solid #0000;border-radius:var(--borderRadius-medium,.375rem);display:inline-flex;padding:var(--control-xsmall-paddingInline-condensed,.25rem);position:relative}.SegmentedControl-item .Button--invisible:hover:not(:disabled){background-color:var(--controlTrack-bgColor-hover,var(--color-action-list-item-default-hover-bg))}.SegmentedControl-item .Button--invisible:active:not(:disabled){background-color:var(--controlTrack-bgColor-active,var(--color-action-list-item-default-active-bg))}.SegmentedControl-item.SegmentedControl-item--selected{background-color:var(--controlKnob-bgColor-rest,var(--color-segmented-control-button-bg));border-color:var(--controlKnob-borderColor-rest,var(--color-segmented-control-button-selected-border))}.SegmentedControl-item.SegmentedControl-item--selected .Button{font-weight:var(--base-text-weight-semibold,600)}.SegmentedControl-item.SegmentedControl-item--selected .Button:hover{background-color:initial}.SegmentedControl-item.SegmentedControl-item--selected:before{border-color:#0000!important}.SegmentedControl-item.SegmentedControl-item--selected+.SegmentedControl-item:before{border-color:#0000}.SegmentedControl-item .Button-label[data-content]:before{content:attr(data-content);display:block;font-weight:var(--base-text-weight-semibold,600);height:0;visibility:hidden}.SegmentedControl-item:not(:first-child):before{border-left:var(--borderWidth-thin,max(1px,.0625rem)) solid var(--borderColor-default,var(--color-border-default));content:"";inset:0 0 0 -1px;margin-bottom:var(--control-medium-paddingBlock,.375rem);margin-top:var(--control-medium-paddingBlock,.375rem);position:absolute}.SegmentedControl-item .Button{border:0;color:var(--button-default-fgColor-rest,var(--color-btn-text));font-weight:var(--base-text-weight-normal,400);transition:none}.SegmentedControl-item .Button:focus-visible{border-radius:calc(var(--borderRadius-medium,.375rem) - 5px);outline-offset:calc(var(--control-xsmall-paddingInline-condensed,.25rem) - var(--borderWidth-thin,max(1px, .0625rem)))}.SegmentedControl-item .Button--small{height:calc(var(--control-small-size,1.75rem) - var(--control-xsmall-paddingInline-condensed,.25rem)*2 - var(--borderWidth-thin,max(1px, .0625rem))*2);padding:0 calc(var(--control-small-paddingInline-condensed,.5rem) - var(--control-xsmall-paddingInline-condensed,.25rem))}.SegmentedControl-item .Button--small.Button--iconOnly{width:calc(var(--control-medium-size,2rem) - var(--control-xsmall-paddingInline-condensed,.25rem)*2 - var(--borderWidth-thin,max(1px, .0625rem))*2)}.SegmentedControl-item .Button--small.Button--iconOnly:before{content:"";height:100%;left:50%;min-height:var(--control-medium-size,2rem);min-width:var(--control-medium-size,2rem);position:absolute;top:50%;transform:translateX(-50%) translateY(-50%);width:100%}.SegmentedControl-item .Button--medium{height:calc(var(--control-medium-size,2rem) - var(--control-xsmall-paddingInline-condensed,.25rem)*2 - var(--borderWidth-thin,max(1px, .0625rem))*2);padding:0 calc(var(--control-medium-paddingInline-normal,.75rem) - var(--control-xsmall-paddingInline-condensed,.25rem))}.SegmentedControl-item .Button--medium.Button--iconOnly{width:calc(var(--control-medium-size,2rem) - var(--control-xsmall-paddingInline-condensed,.25rem)*2 - var(--borderWidth-thin,max(1px, .0625rem))*2)}.SegmentedControl-item .Button--medium.Button--iconOnly:before{content:"";height:100%;left:50%;min-height:var(--control-medium-size,2rem);min-width:var(--control-medium-size,2rem);position:absolute;top:50%;transform:translateX(-50%) translateY(-50%);width:100%}.SegmentedControl-item .Button--large{height:calc(var(--control-large-size,2.5rem) - var(--control-xsmall-paddingInline-condensed,.25rem)*2 - var(--borderWidth-thin,max(1px, .0625rem))*2);padding:0 calc(var(--control-large-paddingInline-spacious,1rem) - var(--control-xsmall-paddingInline-condensed,.25rem))}.SegmentedControl-item .Button--large.Button--iconOnly{width:calc(var(--control-large-size,2.5rem) - var(--control-xsmall-paddingInline-condensed,.25rem)*2 - var(--borderWidth-thin,max(1px, .0625rem))*2)}.SegmentedControl-item .Button--large.Button--iconOnly:before{content:"";height:100%;left:50%;min-height:var(--control-large-size,2.5rem);min-width:var(--control-large-size,2.5rem);position:absolute;top:50%;transform:translateX(-50%) translateY(-50%);width:100%}.SegmentedControl-item .Button--iconOnly{padding:initial}.SegmentedControl-item .Button--invisible.Button--invisible-noVisuals .Button-label{color:var(--button-default-fgColor-rest,var(--color-btn-text))}.SegmentedControl--fullWidth{display:flex}.SegmentedControl--fullWidth .SegmentedControl-item{flex:1;justify-content:center}.SegmentedControl--fullWidth .Button--iconOnly,.SegmentedControl--fullWidth .Button-withTooltip{width:100%}
1
+ .SegmentedControl{--segmentedControl-item-padding:var(--control-small-paddingBlock,0.25rem);background-color:var(--controlTrack-bgColor-rest,var(--color-segmented-control-bg));border-radius:var(--borderRadius-medium,.375rem);display:inline-flex;list-style:none}.SegmentedControl--iconOnly .Button--iconOnly.Button--large,.SegmentedControl--iconOnly .Button--iconOnly.Button--medium,.SegmentedControl--iconOnly .Button--iconOnly.Button--small{padding-inline:0!important;width:100%}.SegmentedControl--small{--segmentedControl-item-padding:var(--control-xsmall-paddingBlock,0.125rem)}.SegmentedControl--small .SegmentedControl-item{height:var(--control-small-size,1.75rem)}.SegmentedControl--small .SegmentedControl-item .Button{padding-inline:calc(var(--control-xsmall-paddingInline-normal,.5rem) - var(--segmentedControl-item-padding))}.SegmentedControl--small.SegmentedControl--iconOnly .SegmentedControl-item{width:var(--control-small-size,1.75rem)}.SegmentedControl--medium .SegmentedControl-item{height:var(--control-medium-size,2rem)}.SegmentedControl--medium.SegmentedControl--iconOnly .SegmentedControl-item{width:var(--control-medium-size,2rem)}.SegmentedControl--large .SegmentedControl-item{height:var(--control-large-size,2.5rem)}.SegmentedControl--large .SegmentedControl-item .Button{padding-inline:calc(var(--control-large-paddingInline-normal,.75rem) - var(--segmentedControl-item-padding))}.SegmentedControl--large.SegmentedControl--iconOnly .SegmentedControl-item{width:var(--control-large-size,2.5rem)}.SegmentedControl-item{border:var(--borderWidth-thin,max(1px,.0625rem)) solid #0000;border-radius:var(--borderRadius-medium,.375rem);display:inline-flex;height:var(--control-medium-size,2rem);justify-content:center;padding:var(--segmentedControl-item-padding);position:relative}.SegmentedControl-item .Button-withTooltip{width:100%}.SegmentedControl-item .Button--invisible:hover:not(:disabled){background-color:var(--controlTrack-bgColor-hover,var(--color-action-list-item-default-hover-bg))}.SegmentedControl-item .Button--invisible:active:not(:disabled){background-color:var(--controlTrack-bgColor-active,var(--color-action-list-item-default-active-bg))}.SegmentedControl-item.SegmentedControl-item--selected{background-color:var(--controlKnob-bgColor-rest,var(--color-segmented-control-button-bg));border-color:var(--controlKnob-borderColor-rest,var(--color-segmented-control-button-selected-border))}.SegmentedControl-item.SegmentedControl-item--selected .Button{font-weight:var(--base-text-weight-semibold,600)}.SegmentedControl-item.SegmentedControl-item--selected .Button:hover{background-color:initial}.SegmentedControl-item.SegmentedControl-item--selected:before{border-color:#0000!important}.SegmentedControl-item.SegmentedControl-item--selected+.SegmentedControl-item:before{border-color:#0000}.SegmentedControl-item .Button-label[data-content]:before{content:attr(data-content);display:block;font-weight:var(--base-text-weight-semibold,600);height:0;visibility:hidden}.SegmentedControl-item:not(:first-child):before{border-left:var(--borderWidth-thin,max(1px,.0625rem)) solid var(--borderColor-default,var(--color-border-default));content:"";inset:0 0 0 -1px;margin-bottom:var(--control-medium-paddingBlock,.375rem);margin-top:var(--control-medium-paddingBlock,.375rem);position:absolute}.SegmentedControl-item .Button{border:0;border-radius:calc(var(--borderRadius-medium,.375rem) - var(--segmentedControl-item-padding)/2);font-weight:var(--base-text-weight-normal,400);height:100%;padding-inline:calc(var(--control-medium-paddingInline-normal,.75rem) - var(--segmentedControl-item-padding));width:100%}.SegmentedControl-item .Button:focus-visible{border-radius:calc(var(--borderRadius-medium,.375rem) - var(--segmentedControl-item-padding)/1);outline-offset:calc(var(--segmentedControl-item-padding) - var(--borderWidth-thin,max(1px, .0625rem)))}.SegmentedControl-item .Button--invisible.Button--invisible-noVisuals .Button-label{color:var(--button-default-fgColor-rest,var(--color-btn-text))}.SegmentedControl--fullWidth{display:flex}.SegmentedControl--fullWidth .SegmentedControl-item{flex:1;justify-content:center}
@@ -2,7 +2,20 @@
2
2
  "name": "alpha/segmented_control",
3
3
  "selectors": [
4
4
  ".SegmentedControl",
5
+ ".SegmentedControl--iconOnly .Button--iconOnly.Button--large",
6
+ ".SegmentedControl--iconOnly .Button--iconOnly.Button--medium",
7
+ ".SegmentedControl--iconOnly .Button--iconOnly.Button--small",
8
+ ".SegmentedControl--small",
9
+ ".SegmentedControl--small .SegmentedControl-item",
10
+ ".SegmentedControl--small .SegmentedControl-item .Button",
11
+ ".SegmentedControl--small.SegmentedControl--iconOnly .SegmentedControl-item",
12
+ ".SegmentedControl--medium .SegmentedControl-item",
13
+ ".SegmentedControl--medium.SegmentedControl--iconOnly .SegmentedControl-item",
14
+ ".SegmentedControl--large .SegmentedControl-item",
15
+ ".SegmentedControl--large .SegmentedControl-item .Button",
16
+ ".SegmentedControl--large.SegmentedControl--iconOnly .SegmentedControl-item",
5
17
  ".SegmentedControl-item",
18
+ ".SegmentedControl-item .Button-withTooltip",
6
19
  ".SegmentedControl-item .Button--invisible:hover:not(:disabled)",
7
20
  ".SegmentedControl-item .Button--invisible:active:not(:disabled)",
8
21
  ".SegmentedControl-item.SegmentedControl-item--selected",
@@ -14,20 +27,8 @@
14
27
  ".SegmentedControl-item:not(:first-child):before",
15
28
  ".SegmentedControl-item .Button",
16
29
  ".SegmentedControl-item .Button:focus-visible",
17
- ".SegmentedControl-item .Button--small",
18
- ".SegmentedControl-item .Button--small.Button--iconOnly",
19
- ".SegmentedControl-item .Button--small.Button--iconOnly:before",
20
- ".SegmentedControl-item .Button--medium",
21
- ".SegmentedControl-item .Button--medium.Button--iconOnly",
22
- ".SegmentedControl-item .Button--medium.Button--iconOnly:before",
23
- ".SegmentedControl-item .Button--large",
24
- ".SegmentedControl-item .Button--large.Button--iconOnly",
25
- ".SegmentedControl-item .Button--large.Button--iconOnly:before",
26
- ".SegmentedControl-item .Button--iconOnly",
27
30
  ".SegmentedControl-item .Button--invisible.Button--invisible-noVisuals .Button-label",
28
31
  ".SegmentedControl--fullWidth",
29
- ".SegmentedControl--fullWidth .SegmentedControl-item",
30
- ".SegmentedControl--fullWidth .Button--iconOnly",
31
- ".SegmentedControl--fullWidth .Button-withTooltip"
32
+ ".SegmentedControl--fullWidth .SegmentedControl-item"
32
33
  ]
33
34
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["segmented_control.pcss","<no source>"],"names":[],"mappings":"AAEA,kBAGE,mFAAqF,CACrF,gDAAyC,CAHzC,mBAAoB,CACpB,eAGF,CAEA,uBAGE,4DAAiD,CACjD,gDAAyC,CAFzC,mBAAoB,CAGpB,4DAAsD,CAJtD,iBAkIF,CA3HI,+DACE,iGACF,CAEA,gEACE,mGACF,CAIF,uDACE,yFAA2F,CAC3F,sGAiBF,CAfE,+DACE,gDAKF,CAHE,qEACE,wBACF,CAGF,8DACE,4BACF,CAEA,qFACE,kBACF,CAIF,0DAKE,0BAA2B,CAJ3B,aAAc,CAEd,gDAA6C,CAD7C,QAAS,CAET,iBAEF,CAIE,gDAME,kHAAqE,CADrE,UAAW,CAHX,gBAAiB,CAEjB,wDAAiD,CADjD,qDAA8C,CAF9C,iBAMF,CAIF,+BACE,QAAS,CAGT,8DAAyC,CAFzC,8CAA2C,CAC3C,eAOF,CAJE,6CAEE,4DAAqD,CADrD,sHAEF,CAGF,sCACE,sJAEC,CACD,yHAWF,CATE,uDACE,mJAOF,CAFI,8DC9FR,WAAA,YAAA,SAAA,2CAAA,0CAAA,kBAAA,QAAA,4CAAA,UD8FoF,CAKlF,uCACE,oJAEC,CACD,wHAWF,CATE,wDACE,mJAOF,CAFI,+DC/GR,WAAA,YAAA,SAAA,2CAAA,0CAAA,kBAAA,QAAA,4CAAA,UD+GoF,CAKlF,sCACE,qJAEC,CACD,uHAWF,CATE,uDACE,oJAOF,CAFI,8DChIR,WAAA,YAAA,SAAA,4CAAA,2CAAA,kBAAA,QAAA,4CAAA,UDgIkF,CAKhF,yCACE,eACF,CAEA,oFACE,8DACF,CAIF,6BACE,YAYF,CAVE,oDACE,MAAO,CACP,sBACF,CAGA,gGAEE,UACF","file":"segmented_control.css","sourcesContent":["/* SegmentedControl */\n\n.SegmentedControl {\n display: inline-flex;\n list-style: none;\n background-color: var(--controlTrack-bgColor-rest, var(--color-segmented-control-bg));\n border-radius: var(--borderRadius-medium);\n}\n\n.SegmentedControl-item {\n position: relative;\n display: inline-flex;\n border: var(--borderWidth-thin) solid transparent;\n border-radius: var(--borderRadius-medium);\n padding: var(--control-xsmall-paddingInline-condensed);\n\n & .Button--invisible {\n &:hover:not(:disabled) {\n background-color: var(--controlTrack-bgColor-hover, var(--color-action-list-item-default-hover-bg));\n }\n\n &:active:not(:disabled) {\n background-color: var(--controlTrack-bgColor-active, var(--color-action-list-item-default-active-bg));\n }\n }\n\n /* Selected ---------------------------------------- */\n &.SegmentedControl-item--selected {\n background-color: var(--controlKnob-bgColor-rest, var(--color-segmented-control-button-bg));\n border-color: var(--controlKnob-borderColor-rest, var(--color-segmented-control-button-selected-border));\n\n & .Button {\n font-weight: var(--base-text-weight-semibold);\n\n &:hover {\n background-color: transparent;\n }\n }\n\n &::before {\n border-color: transparent !important;\n }\n\n & + .SegmentedControl-item::before {\n border-color: transparent;\n }\n }\n\n /* renders a visibly hidden \"copy\" of the text in bold, reserving box space for when text becomes bold on selected */\n & .Button-label[data-content]::before {\n display: block;\n height: 0;\n font-weight: var(--base-text-weight-semibold);\n visibility: hidden;\n content: attr(data-content);\n }\n\n /* Separator lines */\n &:not(:first-child) {\n &::before {\n position: absolute;\n inset: 0 0 0 -1px;\n margin-top: var(--control-medium-paddingBlock);\n margin-bottom: var(--control-medium-paddingBlock);\n content: '';\n border-left: var(--borderWidth-thin) solid var(--borderColor-default);\n }\n }\n\n /* Button ----------------------------------------- */\n & .Button {\n border: 0;\n font-weight: var(--base-text-weight-normal);\n transition: none;\n color: var(--button-default-fgColor-rest);\n\n &:focus-visible {\n outline-offset: calc(var(--control-xsmall-paddingInline-condensed) - var(--borderWidth-thin));\n border-radius: calc(var(--borderRadius-medium) - 5px);\n }\n }\n\n & .Button--small {\n height: calc(\n var(--control-small-size) - var(--control-xsmall-paddingInline-condensed) * 2 - var(--borderWidth-thin) * 2\n );\n padding: 0 calc(var(--control-small-paddingInline-condensed) - var(--control-xsmall-paddingInline-condensed));\n\n &.Button--iconOnly {\n width: calc(\n var(--control-medium-size) - var(--control-xsmall-paddingInline-condensed) * 2 - var(--borderWidth-thin) * 2\n );\n\n &::before {\n @mixin minTouchTarget var(--control-medium-size), var(--control-medium-size);\n }\n }\n }\n\n & .Button--medium {\n height: calc(\n var(--control-medium-size) - var(--control-xsmall-paddingInline-condensed) * 2 - var(--borderWidth-thin) * 2\n );\n padding: 0 calc(var(--control-medium-paddingInline-normal) - var(--control-xsmall-paddingInline-condensed));\n\n &.Button--iconOnly {\n width: calc(\n var(--control-medium-size) - var(--control-xsmall-paddingInline-condensed) * 2 - var(--borderWidth-thin) * 2\n );\n\n &::before {\n @mixin minTouchTarget var(--control-medium-size), var(--control-medium-size);\n }\n }\n }\n\n & .Button--large {\n height: calc(\n var(--control-large-size) - var(--control-xsmall-paddingInline-condensed) * 2 - var(--borderWidth-thin) * 2\n );\n padding: 0 calc(var(--control-large-paddingInline-spacious) - var(--control-xsmall-paddingInline-condensed));\n\n &.Button--iconOnly {\n width: calc(\n var(--control-large-size) - var(--control-xsmall-paddingInline-condensed) * 2 - var(--borderWidth-thin) * 2\n );\n\n &::before {\n @mixin minTouchTarget var(--control-large-size), var(--control-large-size);\n }\n }\n }\n\n & .Button--iconOnly {\n padding: initial;\n }\n\n & .Button--invisible.Button--invisible-noVisuals .Button-label {\n color: var(--button-default-fgColor-rest);\n }\n}\n\n/* fullWidth */\n.SegmentedControl--fullWidth {\n display: flex;\n\n & .SegmentedControl-item {\n flex: 1;\n justify-content: center;\n }\n\n /* is .Button-withTooltip used anywhere? can't find use of it */\n & .Button--iconOnly,\n & .Button-withTooltip {\n width: 100%;\n }\n}\n",null]}
1
+ {"version":3,"sources":["segmented_control.pcss"],"names":[],"mappings":"AAEA,kBACE,yEAAkE,CAIlE,mFAAqF,CACrF,gDAAyC,CAHzC,mBAAoB,CACpB,eAGF,CAGE,qLAIE,0BAA4B,CAD5B,UAEF,CAKF,yBACE,2EAeF,CAbE,gDACE,wCAKF,CAHE,wDACE,4GACF,CAIA,2EACE,uCACF,CAKF,iDACE,sCACF,CAGE,4EACE,qCACF,CAKF,gDACE,uCAKF,CAHE,wDACE,4GACF,CAIA,2EACE,sCACF,CAMJ,uBAIE,4DAAiD,CACjD,gDAAyC,CAHzC,mBAAoB,CAIpB,sCAAkC,CAHlC,sBAAuB,CAIvB,4CAA6C,CAN7C,iBAoFF,CA5EE,2CACE,UACF,CAIE,+DACE,iGACF,CAEA,gEACE,mGACF,CAIF,uDACE,yFAA2F,CAC3F,sGAiBF,CAfE,+DACE,gDAKF,CAHE,qEACE,wBACF,CAGF,8DACE,4BACF,CAEA,qFACE,kBACF,CAIF,0DAKE,0BAA2B,CAJ3B,aAAc,CAEd,gDAA6C,CAD7C,QAAS,CAET,iBAEF,CAIE,gDAME,kHAAqE,CADrE,UAAW,CAHX,gBAAiB,CAEjB,wDAAiD,CADjD,qDAA8C,CAF9C,iBAMF,CAIF,+BAGE,QAAS,CAET,+FAA0F,CAD1F,8CAA2C,CAH3C,WAAY,CAKZ,6GAAuG,CAJvG,UAUF,CAJE,6CAEE,+FAA0F,CAD1F,sGAEF,CAGF,oFACE,8DACF,CAIF,6BACE,YAMF,CAJE,oDACE,MAAO,CACP,sBACF","file":"segmented_control.css","sourcesContent":["/* SegmentedControl */\n\n.SegmentedControl {\n --segmentedControl-item-padding: var(--control-small-paddingBlock);\n\n display: inline-flex;\n list-style: none;\n background-color: var(--controlTrack-bgColor-rest, var(--color-segmented-control-bg));\n border-radius: var(--borderRadius-medium);\n}\n\n.SegmentedControl--iconOnly {\n & .Button--iconOnly.Button--small,\n & .Button--iconOnly.Button--medium,\n & .Button--iconOnly.Button--large {\n width: 100%;\n padding-inline: 0 !important;\n }\n}\n\n/* sizes */\n\n.SegmentedControl--small {\n --segmentedControl-item-padding: var(--control-xsmall-paddingBlock);\n\n & .SegmentedControl-item {\n height: var(--control-small-size);\n\n & .Button {\n padding-inline: calc(var(--control-xsmall-paddingInline-normal) - var(--segmentedControl-item-padding));\n }\n }\n\n &.SegmentedControl--iconOnly {\n & .SegmentedControl-item {\n width: var(--control-small-size);\n }\n }\n}\n\n.SegmentedControl--medium {\n & .SegmentedControl-item {\n height: var(--control-medium-size);\n }\n\n &.SegmentedControl--iconOnly {\n & .SegmentedControl-item {\n width: var(--control-medium-size);\n }\n }\n}\n\n.SegmentedControl--large {\n & .SegmentedControl-item {\n height: var(--control-large-size);\n\n & .Button {\n padding-inline: calc(var(--control-large-paddingInline-normal) - var(--segmentedControl-item-padding));\n }\n }\n\n &.SegmentedControl--iconOnly {\n & .SegmentedControl-item {\n width: var(--control-large-size);\n }\n }\n}\n\n/* item */\n\n.SegmentedControl-item {\n position: relative;\n display: inline-flex;\n justify-content: center;\n border: var(--borderWidth-thin) solid transparent;\n border-radius: var(--borderRadius-medium);\n height: var(--control-medium-size);\n padding: var(--segmentedControl-item-padding);\n\n & .Button-withTooltip {\n width: 100%;\n }\n\n /* button color overrides */\n & .Button--invisible {\n &:hover:not(:disabled) {\n background-color: var(--controlTrack-bgColor-hover, var(--color-action-list-item-default-hover-bg));\n }\n\n &:active:not(:disabled) {\n background-color: var(--controlTrack-bgColor-active, var(--color-action-list-item-default-active-bg));\n }\n }\n\n /* Selected ---------------------------------------- */\n &.SegmentedControl-item--selected {\n background-color: var(--controlKnob-bgColor-rest, var(--color-segmented-control-button-bg));\n border-color: var(--controlKnob-borderColor-rest, var(--color-segmented-control-button-selected-border));\n\n & .Button {\n font-weight: var(--base-text-weight-semibold);\n\n &:hover {\n background-color: transparent;\n }\n }\n\n &::before {\n border-color: transparent !important;\n }\n\n & + .SegmentedControl-item::before {\n border-color: transparent;\n }\n }\n\n /* renders a visibly hidden \"copy\" of the text in bold, reserving box space for when text becomes bold on selected */\n & .Button-label[data-content]::before {\n display: block;\n height: 0;\n font-weight: var(--base-text-weight-semibold);\n visibility: hidden;\n content: attr(data-content);\n }\n\n /* Separator lines */\n &:not(:first-child) {\n &::before {\n position: absolute;\n inset: 0 0 0 -1px;\n margin-top: var(--control-medium-paddingBlock);\n margin-bottom: var(--control-medium-paddingBlock);\n content: '';\n border-left: var(--borderWidth-thin) solid var(--borderColor-default);\n }\n }\n\n /* Button ----------------------------------------- */\n & .Button {\n height: 100%;\n width: 100%;\n border: 0;\n font-weight: var(--base-text-weight-normal);\n border-radius: calc(var(--borderRadius-medium) - var(--segmentedControl-item-padding) / 2);\n padding-inline: calc(var(--control-medium-paddingInline-normal) - var(--segmentedControl-item-padding));\n\n &:focus-visible {\n outline-offset: calc(var(--segmentedControl-item-padding) - var(--borderWidth-thin));\n border-radius: calc(var(--borderRadius-medium) - var(--segmentedControl-item-padding) / 1);\n }\n }\n\n & .Button--invisible.Button--invisible-noVisuals .Button-label {\n color: var(--button-default-fgColor-rest);\n }\n}\n\n/* fullWidth */\n.SegmentedControl--fullWidth {\n display: flex;\n\n & .SegmentedControl-item {\n flex: 1;\n justify-content: center;\n }\n}\n"]}