primer_view_components 0.0.68 → 0.0.69

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.
@@ -0,0 +1,377 @@
1
+ import type {AnchorAlignment, AnchorSide} from '@primer/behaviors'
2
+ import {getAnchoredPosition} from '@primer/behaviors'
3
+
4
+ const TOOLTIP_OPEN_CLASS = 'tooltip-open'
5
+
6
+ type Direction = 'n' | 's' | 'e' | 'w' | 'ne' | 'se' | 'nw' | 'sw'
7
+
8
+ const DIRECTION_CLASSES = [
9
+ 'tooltip-n',
10
+ 'tooltip-s',
11
+ 'tooltip-e',
12
+ 'tooltip-w',
13
+ 'tooltip-ne',
14
+ 'tooltip-se',
15
+ 'tooltip-nw',
16
+ 'tooltip-sw'
17
+ ]
18
+
19
+ class TooltipElement extends HTMLElement {
20
+ styles() {
21
+ return `
22
+ :host {
23
+ position: absolute;
24
+ z-index: 1000000;
25
+ padding: .5em .75em;
26
+ font: normal normal 11px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
27
+ -webkit-font-smoothing: subpixel-antialiased;
28
+ color: var(--color-fg-on-emphasis);
29
+ text-align: center;
30
+ text-decoration: none;
31
+ text-shadow: none;
32
+ text-transform: none;
33
+ letter-spacing: normal;
34
+ word-wrap: break-word;
35
+ white-space: pre;
36
+ background: var(--color-neutral-emphasis-plus);
37
+ border-radius: 6px;
38
+ opacity: 0;
39
+ max-width: 250px;
40
+ word-wrap: break-word;
41
+ white-space: normal
42
+ }
43
+
44
+ :host:before{
45
+ position: absolute;
46
+ z-index: 1000001;
47
+ color: var(--color-neutral-emphasis-plus);
48
+ content: "";
49
+ border: 6px solid transparent;
50
+ opacity: 0
51
+ }
52
+
53
+ @keyframes tooltip-appear {
54
+ from {
55
+ opacity: 0
56
+ }
57
+ to {
58
+ opacity: 1
59
+ }
60
+ }
61
+
62
+ :host:after{
63
+ position: absolute;
64
+ display: block;
65
+ right: 0;
66
+ left: 0;
67
+ height: 12px;
68
+ content: ""
69
+ }
70
+
71
+ :host(.${TOOLTIP_OPEN_CLASS}),
72
+ :host(.${TOOLTIP_OPEN_CLASS}):before {
73
+ animation-name: tooltip-appear;
74
+ animation-duration: .1s;
75
+ animation-fill-mode: forwards;
76
+ animation-timing-function: ease-in;
77
+ animation-delay: .4s
78
+ }
79
+
80
+ :host(.tooltip-s):before,
81
+ :host(.tooltip-se):before,
82
+ :host(.tooltip-sw):before {
83
+ right: 50%;
84
+ bottom: 100%;
85
+ margin-right: -6px;
86
+ border-bottom-color: var(--color-neutral-emphasis-plus)
87
+ }
88
+
89
+ :host(.tooltip-s):after,
90
+ :host(.tooltip-se):after,
91
+ :host(.tooltip-sw):after {
92
+ bottom: 100%
93
+ }
94
+
95
+ :host(.tooltip-n):before,
96
+ :host(.tooltip-ne):before,
97
+ :host(.tooltip-nw):before {
98
+ top: 100%;
99
+ right: 50%;
100
+ margin-right: -6px;
101
+ border-top-color: var(--color-neutral-emphasis-plus)
102
+ }
103
+
104
+ :host(.tooltip-n):after,
105
+ :host(.tooltip-ne):after,
106
+ :host(.tooltip-nw):after {
107
+ top: 100%
108
+ }
109
+
110
+ :host(.tooltip-se):before,
111
+ :host(.tooltip-ne):before {
112
+ right: auto
113
+ }
114
+
115
+ :host(.tooltip-sw):before,
116
+ :host(.tooltip-nw):before {
117
+ right: 0;
118
+ margin-right: 6px
119
+ }
120
+
121
+ :host(.tooltip-w):before {
122
+ top: 50%;
123
+ bottom: 50%;
124
+ left: 100%;
125
+ margin-top: -6px;
126
+ border-left-color: var(--color-neutral-emphasis-plus)
127
+ }
128
+
129
+ :host(.tooltip-e):before {
130
+ top: 50%;
131
+ right: 100%;
132
+ bottom: 50%;
133
+ margin-top: -6px;
134
+ border-right-color: var(--color-neutral-emphasis-plus)
135
+ }
136
+ `
137
+ }
138
+
139
+ #abortController: AbortController | undefined
140
+ #align: AnchorAlignment = 'center'
141
+ #side: AnchorSide = 'outside-bottom'
142
+ #allowUpdatePosition = false
143
+
144
+ get htmlFor(): string {
145
+ return this.getAttribute('for') || ''
146
+ }
147
+
148
+ set htmlFor(value: string) {
149
+ this.setAttribute('for', value)
150
+ }
151
+
152
+ get type(): 'description' | 'label' {
153
+ const type = this.getAttribute('data-type')
154
+ return type === 'label' ? 'label' : 'description'
155
+ }
156
+
157
+ set type(value: 'description' | 'label') {
158
+ this.setAttribute('data-type', value)
159
+ }
160
+
161
+ get direction(): Direction {
162
+ return (this.getAttribute('data-direction') || 's') as Direction
163
+ }
164
+
165
+ set direction(value: Direction) {
166
+ this.setAttribute('data-direction', value)
167
+ }
168
+
169
+ get control(): HTMLElement | null {
170
+ return this.ownerDocument.getElementById(this.htmlFor)
171
+ }
172
+
173
+ constructor() {
174
+ super()
175
+ const shadow = this.attachShadow({mode: 'open'})
176
+ shadow.innerHTML = `
177
+ <style>
178
+ ${this.styles()}
179
+ </style>
180
+ <slot></slot>
181
+ `
182
+ }
183
+
184
+ connectedCallback() {
185
+ this.hidden = true
186
+ this.#allowUpdatePosition = true
187
+
188
+ if (!this.id) {
189
+ this.id = `tooltip-${Date.now()}-${(Math.random() * 10000).toFixed(0)}`
190
+ }
191
+
192
+ if (!this.control) return
193
+
194
+ this.setAttribute('role', 'tooltip')
195
+
196
+ this.#abortController?.abort()
197
+ this.#abortController = new AbortController()
198
+ const {signal} = this.#abortController
199
+
200
+ this.addEventListener('mouseleave', this, {signal})
201
+ this.control.addEventListener('mouseenter', this, {signal})
202
+ this.control.addEventListener('mouseleave', this, {signal})
203
+ this.control.addEventListener('focus', this, {signal})
204
+ this.control.addEventListener('blur', this, {signal})
205
+ this.ownerDocument.addEventListener('keydown', this, {signal})
206
+ }
207
+
208
+ disconnectedCallback() {
209
+ this.#abortController?.abort()
210
+ }
211
+
212
+ handleEvent(event: Event) {
213
+ if (!this.control) return
214
+
215
+ // Ensures that tooltip stays open when hovering between tooltip and element
216
+ // WCAG Success Criterion 1.4.13 Hoverable
217
+ if ((event.type === 'mouseenter' || event.type === 'focus') && this.hidden) {
218
+ this.hidden = false
219
+ } else if (event.type === 'blur') {
220
+ this.hidden = true
221
+ } else if (
222
+ event.type === 'mouseleave' &&
223
+ (event as MouseEvent).relatedTarget !== this.control &&
224
+ (event as MouseEvent).relatedTarget !== this
225
+ ) {
226
+ this.hidden = true
227
+ } else if (event.type === 'keydown' && (event as KeyboardEvent).key === 'Escape' && !this.hidden) {
228
+ this.hidden = true
229
+ }
230
+ }
231
+
232
+ static observedAttributes = ['data-type', 'data-direction', 'id', 'hidden']
233
+
234
+ attributeChangedCallback(name: string) {
235
+ if (name === 'id' || name === 'data-type') {
236
+ if (!this.id || !this.control) return
237
+ if (this.type === 'label') {
238
+ this.control.setAttribute('aria-labelledby', this.id)
239
+ } else {
240
+ let describedBy = this.control.getAttribute('aria-describedby')
241
+ describedBy ? (describedBy = `${describedBy} ${this.id}`) : (describedBy = this.id)
242
+ this.control.setAttribute('aria-describedby', describedBy)
243
+ }
244
+ } else if (name === 'hidden') {
245
+ if (this.hidden) {
246
+ this.classList.remove(TOOLTIP_OPEN_CLASS, ...DIRECTION_CLASSES)
247
+ } else {
248
+ this.classList.add(TOOLTIP_OPEN_CLASS)
249
+ for (const tooltip of this.ownerDocument.querySelectorAll<HTMLElement>(this.tagName)) {
250
+ if (tooltip !== this) tooltip.hidden = true
251
+ }
252
+ this.#updatePosition()
253
+ }
254
+ } else if (name === 'data-direction') {
255
+ this.classList.remove(...DIRECTION_CLASSES)
256
+ const direction = this.direction
257
+ if (direction === 'n') {
258
+ this.#align = 'center'
259
+ this.#side = 'outside-top'
260
+ } else if (direction === 'ne') {
261
+ this.#align = 'start'
262
+ this.#side = 'outside-top'
263
+ } else if (direction === 'e') {
264
+ this.#align = 'center'
265
+ this.#side = 'outside-right'
266
+ } else if (direction === 'se') {
267
+ this.#align = 'start'
268
+ this.#side = 'outside-bottom'
269
+ } else if (direction === 's') {
270
+ this.#align = 'center'
271
+ this.#side = 'outside-bottom'
272
+ } else if (direction === 'sw') {
273
+ this.#align = 'end'
274
+ this.#side = 'outside-bottom'
275
+ } else if (direction === 'w') {
276
+ this.#align = 'center'
277
+ this.#side = 'outside-left'
278
+ } else if (direction === 'nw') {
279
+ this.#align = 'end'
280
+ this.#side = 'outside-top'
281
+ }
282
+ }
283
+ }
284
+
285
+ // `getAnchoredPosition` may calibrate `anchoredSide` but does not recalibrate `align`.
286
+ // Therefore, we need to determine which `align` is best based on the initial `getAnchoredPosition` calcluation.
287
+ // Related: https://github.com/primer/behaviors/issues/63
288
+ #adjustedAnchorAlignment(anchorSide: AnchorSide): AnchorAlignment | undefined {
289
+ if (!this.control) return
290
+
291
+ const tooltipPosition = this.getBoundingClientRect()
292
+ const targetPosition = this.control.getBoundingClientRect()
293
+ const tooltipWidth = tooltipPosition.width
294
+
295
+ const tooltipCenter = tooltipPosition.left + tooltipWidth / 2
296
+ const targetCenter = targetPosition.x + targetPosition.width / 2
297
+
298
+ if (Math.abs(tooltipCenter - targetCenter) < 2 || anchorSide === 'outside-left' || anchorSide === 'outside-right') {
299
+ return 'center'
300
+ } else if (tooltipPosition.left === targetPosition.left) {
301
+ return 'start'
302
+ } else if (tooltipPosition.right === targetPosition.right) {
303
+ return 'end'
304
+ } else if (tooltipCenter < targetCenter) {
305
+ if (tooltipPosition.left === 0) return 'start'
306
+ return 'end'
307
+ } else {
308
+ if (tooltipPosition.right === 0) return 'end'
309
+ return 'start'
310
+ }
311
+ }
312
+
313
+ #updatePosition() {
314
+ if (!this.control) return
315
+ if (!this.#allowUpdatePosition || this.hidden) return
316
+
317
+ const TOOLTIP_OFFSET = 10
318
+
319
+ this.style.left = `0px` // Ensures we have reliable tooltip width in `getAnchoredPosition`
320
+ let position = getAnchoredPosition(this, this.control, {
321
+ side: this.#side,
322
+ align: this.#align,
323
+ anchorOffset: TOOLTIP_OFFSET
324
+ })
325
+ let anchorSide = position.anchorSide
326
+
327
+ // We need to set tooltip position in order to determine ideal align.
328
+ this.style.top = `${position.top}px`
329
+ this.style.left = `${position.left}px`
330
+ let direction: Direction = 's'
331
+
332
+ const align = this.#adjustedAnchorAlignment(anchorSide)
333
+ if (!align) return
334
+
335
+ this.style.left = `0px` // Reset tooltip position again to ensure accurate width in `getAnchoredPosition`
336
+ position = getAnchoredPosition(this, this.control, {side: anchorSide, align, anchorOffset: TOOLTIP_OFFSET})
337
+ anchorSide = position.anchorSide
338
+
339
+ this.style.top = `${position.top}px`
340
+ this.style.left = `${position.left}px`
341
+
342
+ if (anchorSide === 'outside-left') {
343
+ direction = 'w'
344
+ } else if (anchorSide === 'outside-right') {
345
+ direction = 'e'
346
+ } else if (anchorSide === 'outside-top') {
347
+ if (align === 'center') {
348
+ direction = 'n'
349
+ } else if (align === 'start') {
350
+ direction = 'ne'
351
+ } else {
352
+ direction = 'nw'
353
+ }
354
+ } else {
355
+ if (align === 'center') {
356
+ direction = 's'
357
+ } else if (align === 'start') {
358
+ direction = 'se'
359
+ } else {
360
+ direction = 'sw'
361
+ }
362
+ }
363
+
364
+ this.classList.add(`tooltip-${direction}`)
365
+ }
366
+ }
367
+
368
+ if (!window.customElements.get('tool-tip')) {
369
+ window.TooltipElement = TooltipElement
370
+ window.customElements.define('tool-tip', TooltipElement)
371
+ }
372
+
373
+ declare global {
374
+ interface Window {
375
+ TooltipElement: typeof TooltipElement
376
+ }
377
+ }
@@ -5,7 +5,7 @@ require "primer/classify"
5
5
  module Primer
6
6
  # All Primer ViewComponents accept a standard set of options called system arguments, mimicking the [styled-system API](https://styled-system.com/table) used by [Primer React](https://primer.style/components/system-props).
7
7
  #
8
- # Under the hood, system arguments are [mapped](https://github.com/primer/view_components/blob/main/app/lib/primer/classify.rb) to Primer CSS classes, with any remaining options passed to Rails' [`content_tag`](https://api.rubyonrails.org/classes/ActionView/Helpers/TagHelper.html#method-i-content_tag).
8
+ # Under the hood, system arguments are [mapped](https://github.com/primer/view_components/blob/main/lib/primer/classify.rb) to Primer CSS classes, with any remaining options passed to Rails' [`content_tag`](https://api.rubyonrails.org/classes/ActionView/Helpers/TagHelper.html#method-i-content_tag).
9
9
  #
10
10
  # ## Responsive values
11
11
  #
@@ -85,7 +85,7 @@ module Primer
85
85
  #
86
86
  # | Name | Type | Description |
87
87
  # | :- | :- | :- |
88
- # | `clearfix` | Boolean | Wether to assign the `clearfix` class. |
88
+ # | `clearfix` | Boolean | Whether to assign the `clearfix` class. |
89
89
  # | `col` | Integer | Number of columns. <%= one_of(Primer::Classify::Utilities.mappings(:col)) %> |
90
90
  # | `container` | Symbol | Size of the container. <%= one_of(Primer::Classify::Utilities.mappings(:container)) %> |
91
91
  #
@@ -92,6 +92,7 @@ module Primer
92
92
  @system_arguments[:tag] = system_arguments[:tag] || :span
93
93
  @system_arguments[:classes] = class_names(
94
94
  "Truncate-text",
95
+ system_arguments[:classes],
95
96
  "Truncate-text--primary": priority,
96
97
  "Truncate-text--expandable": expandable
97
98
  )
@@ -49,7 +49,7 @@ module Primer
49
49
  # <% end %>
50
50
  #
51
51
  # @param overlay [Symbol] Dictates the type of overlay to render with. <%= one_of(Primer::DetailsComponent::OVERLAY_MAPPINGS.keys) %>
52
- # @param reset [Boolean] Defatuls to false. If set to true, it will remove the default caret and remove style from the summary element
52
+ # @param reset [Boolean] Defaults to false. If set to true, it will remove the default caret and remove style from the summary element
53
53
  # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
54
54
  def initialize(overlay: NO_OVERLAY, reset: false, **system_arguments)
55
55
  @system_arguments = deny_tag_argument(**system_arguments)
@@ -6,7 +6,7 @@ module Primer
6
6
  # @accessibility
7
7
  # `IconButton` requires an `aria-label`, which will provide assistive technologies with an accessible label.
8
8
  # The `aria-label` should describe the action to be invoked rather than the icon itself. For instance,
9
- # if your `IconButton` renders a magnifying glass icon and invokves a search action, the `aria-label` should be
9
+ # if your `IconButton` renders a magnifying glass icon and invokes a search action, the `aria-label` should be
10
10
  # `"Search"` instead of `"Magnifying glass"`.
11
11
  # [Learn more about best functional image practices (WAI Images)](https://www.w3.org/WAI/tutorials/images/functional)
12
12
  class IconButton < Primer::Component
@@ -93,7 +93,7 @@ module Primer
93
93
  # <ol>
94
94
  # <li>Michael Jackson</li>
95
95
  # <li>Michael Bolton</li>
96
- # <li>Michael Buble</li>
96
+ # <li>Michael Bublé</li>
97
97
  # </ol>
98
98
  #
99
99
  # <p>And an unordered task list:</p>
@@ -5,3 +5,4 @@ import './time_ago_component';
5
5
  import './local_time';
6
6
  import './image_crop';
7
7
  import './dropdown';
8
+ import './alpha/tooltip';
@@ -5,3 +5,4 @@ import './time_ago_component';
5
5
  import './local_time';
6
6
  import './image_crop';
7
7
  import './dropdown';
8
+ import './alpha/tooltip';
@@ -5,3 +5,4 @@ import './time_ago_component'
5
5
  import './local_time'
6
6
  import './image_crop'
7
7
  import './dropdown'
8
+ import './alpha/tooltip'
@@ -1,5 +1,5 @@
1
1
  <%= render Primer::BaseComponent.new(**@system_arguments) do %>
2
2
  <%= heading %>
3
- <%= actions %>
4
3
  <%= description %>
4
+ <%= actions %>
5
5
  <% end %>
@@ -4,7 +4,7 @@ module Primer
4
4
  # Use `Subhead` as the start of a section. The `:heading` slot will render an `<h2>` font-sized text.
5
5
  #
6
6
  # - Optionally set the `:description` slot to render a short description and the `:actions` slot for a related action.
7
- # - Use a succint, one-line description for the `:description` slot. For longer descriptions, omit the description slot and render a paragraph below the `Subhead`.
7
+ # - Use a succinct, one-line description for the `:description` slot. For longer descriptions, omit the description slot and render a paragraph below the `Subhead`.
8
8
  # - Use the actions slot to render a related action to the right of the heading. Use <%= link_to_component(Primer::ButtonComponent) %> or <%= link_to_component(Primer::LinkComponent) %>.
9
9
  #
10
10
  # @accessibility
@@ -39,6 +39,10 @@
39
39
  - color-fg-severe
40
40
  :danger:
41
41
  - color-fg-danger
42
+ :open:
43
+ - color-fg-open
44
+ :closed:
45
+ - color-fg-closed
42
46
  :done:
43
47
  - color-fg-done
44
48
  :sponsors:
@@ -78,6 +82,14 @@
78
82
  - color-bg-danger
79
83
  :danger_emphasis:
80
84
  - color-bg-danger-emphasis
85
+ :open:
86
+ - color-bg-open
87
+ :open_emphasis:
88
+ - color-bg-open-emphasis
89
+ :closed:
90
+ - color-bg-closed
91
+ :closed_emphasis:
92
+ - color-bg-closed-emphasis
81
93
  :done:
82
94
  - color-bg-done
83
95
  :done_emphasis:
@@ -113,6 +125,14 @@
113
125
  - color-border-danger
114
126
  :danger_emphasis:
115
127
  - color-border-danger-emphasis
128
+ :open:
129
+ - color-border-open
130
+ :open_emphasis:
131
+ - color-border-open-emphasis
132
+ :closed:
133
+ - color-border-closed
134
+ :closed_emphasis:
135
+ - color-border-closed-emphasis
116
136
  :done:
117
137
  - color-border-done
118
138
  :done_emphasis:
@@ -15,7 +15,7 @@ module ERBLint
15
15
  constant: "TAG_OPTIONS"
16
16
  ).freeze
17
17
 
18
- # CloseButton component has preference when this class is seen in conjuction with `btn`.
18
+ # CloseButton component has preference when this class is seen in conjunction with `btn`.
19
19
  DISALLOWED_CLASSES = %w[close-button].freeze
20
20
  CLASSES = %w[btn btn-link].freeze
21
21
  MESSAGE = "We are migrating buttons to use [Primer::ButtonComponent](https://primer.style/view-components/components/button), please try to use that instead of raw HTML."
@@ -5,7 +5,7 @@ module Primer
5
5
  module VERSION
6
6
  MAJOR = 0
7
7
  MINOR = 0
8
- PATCH = 68
8
+ PATCH = 69
9
9
 
10
10
  STRING = [MAJOR, MINOR, PATCH].join(".")
11
11
  end
@@ -207,7 +207,7 @@ module RuboCop
207
207
  return node.source unless node.type == :str
208
208
  return ":#{node.value}" unless node.value.include?("-")
209
209
 
210
- # If the icon contains `-` we need to cast the string as a symbole
210
+ # If the icon contains `-` we need to cast the string as a symbol
211
211
  # E.g: `arrow-down` becomes `:"arrow-down"`
212
212
  ":#{node.source}"
213
213
  end
data/lib/tasks/docs.rake CHANGED
@@ -82,7 +82,8 @@ namespace :docs do
82
82
  Primer::Alpha::UnderlineNav,
83
83
  Primer::Alpha::UnderlinePanels,
84
84
  Primer::Alpha::TabNav,
85
- Primer::Alpha::TabPanels
85
+ Primer::Alpha::TabPanels,
86
+ Primer::Alpha::Tooltip
86
87
  ]
87
88
 
88
89
  js_components = [
@@ -94,7 +95,8 @@ namespace :docs do
94
95
  Primer::TabContainerComponent,
95
96
  Primer::TimeAgoComponent,
96
97
  Primer::Alpha::UnderlinePanels,
97
- Primer::Alpha::TabPanels
98
+ Primer::Alpha::TabPanels,
99
+ Primer::Alpha::Tooltip
98
100
  ]
99
101
 
100
102
  all_components = Primer::Component.descendants - [Primer::BaseComponent]
@@ -168,12 +170,12 @@ namespace :docs do
168
170
  f.puts("| Name | Type | Default | Description |")
169
171
  f.puts("| :- | :- | :- | :- |")
170
172
 
171
- docummented_params = params.map(&:name)
173
+ documented_params = params.map(&:name)
172
174
  component_params = component.instance_method(:initialize).parameters.map { |p| p.last.to_s }
173
175
 
174
- if (docummented_params & component_params).size != component_params.size
176
+ if (documented_params & component_params).size != component_params.size
175
177
  err = { arguments: {} }
176
- (component_params - docummented_params).each do |arg|
178
+ (component_params - documented_params).each do |arg|
177
179
  err[:arguments][arg] = "Not documented"
178
180
  end
179
181
 
@@ -86,7 +86,7 @@ namespace :utilities do
86
86
  classname.sub!(/^[^-]+-/, "")
87
87
  end
88
88
 
89
- # Change the rest from hypens to underscores
89
+ # Change the rest from hyphens to underscores
90
90
  classname.sub!(/-/, "_")
91
91
 
92
92
  # convert padding/margin negative values ie n7 to -7
data/static/arguments.yml CHANGED
@@ -95,6 +95,30 @@
95
95
  type: Hash
96
96
  default: N/A
97
97
  description: "[System arguments](/system-arguments)"
98
+ - component: Tooltip
99
+ source: https://github.com/primer/view_components/tree/main/app/components/primer/alpha/tooltip.rb
100
+ parameters:
101
+ - name: for_id
102
+ type: String
103
+ default: N/A
104
+ description: The ID of the element that the tooltip should be attached to.
105
+ - name: type
106
+ type: Symbol
107
+ default: N/A
108
+ description: One of `:description` and `:label`.
109
+ - name: direction
110
+ type: Symbol
111
+ default: "`:s`"
112
+ description: One of `:e`, `:n`, `:ne`, `:nw`, `:s`, `:se`, `:sw`, or `:w`.
113
+ - name: text
114
+ type: String
115
+ default: N/A
116
+ description: The text content of the tooltip. This should be brief and no longer
117
+ than a sentence.
118
+ - name: system_arguments
119
+ type: Hash
120
+ default: N/A
121
+ description: "[System arguments](/system-arguments)"
98
122
  - component: UnderlineNav
99
123
  source: https://github.com/primer/view_components/tree/main/app/components/primer/alpha/underline_nav.rb
100
124
  parameters:
@@ -453,7 +477,7 @@
453
477
  - name: reset
454
478
  type: Boolean
455
479
  default: "`false`"
456
- description: Defatuls to false. If set to true, it will remove the default caret
480
+ description: Defaults to false. If set to true, it will remove the default caret
457
481
  and remove style from the summary element
458
482
  - name: system_arguments
459
483
  type: Hash
@@ -6,6 +6,7 @@
6
6
  "Primer::Alpha::Layout::Sidebar": "",
7
7
  "Primer::Alpha::TabNav": "",
8
8
  "Primer::Alpha::TabPanels": "",
9
+ "Primer::Alpha::Tooltip": "",
9
10
  "Primer::Alpha::UnderlineNav": "",
10
11
  "Primer::Alpha::UnderlinePanels": "",
11
12
  "Primer::BaseButton": "",
data/static/classes.yml CHANGED
@@ -171,6 +171,7 @@
171
171
  - ".left-0"
172
172
  - ".lh-0"
173
173
  - ".list-style-none"
174
+ - ".m-2"
174
175
  - ".markdown-body"
175
176
  - ".mb-0"
176
177
  - ".mb-2"
@@ -138,6 +138,24 @@
138
138
  "div"
139
139
  ]
140
140
  },
141
+ "Primer::Alpha::Tooltip": {
142
+ "DIRECTION_DEFAULT": "s",
143
+ "DIRECTION_OPTIONS": [
144
+ "s",
145
+ "n",
146
+ "e",
147
+ "w",
148
+ "ne",
149
+ "nw",
150
+ "se",
151
+ "sw"
152
+ ],
153
+ "TYPE_FALLBACK": "description",
154
+ "TYPE_OPTIONS": [
155
+ "label",
156
+ "description"
157
+ ]
158
+ },
141
159
  "Primer::Alpha::UnderlineNav": {
142
160
  "BODY_TAG_DEFAULT": "ul",
143
161
  "TAG_DEFAULT": "nav",
data/static/statuses.json CHANGED
@@ -6,6 +6,7 @@
6
6
  "Primer::Alpha::Layout::Sidebar": "alpha",
7
7
  "Primer::Alpha::TabNav": "alpha",
8
8
  "Primer::Alpha::TabPanels": "alpha",
9
+ "Primer::Alpha::Tooltip": "alpha",
9
10
  "Primer::Alpha::UnderlineNav": "alpha",
10
11
  "Primer::Alpha::UnderlinePanels": "alpha",
11
12
  "Primer::BaseButton": "beta",