@gitlab/ui 36.7.1 → 37.2.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 (121) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/dist/components/base/alert/alert.js +1 -11
  3. package/dist/components/base/card/card.js +1 -1
  4. package/dist/components/base/drawer/drawer.documentation.js +1 -1
  5. package/dist/components/base/form/form_input_group/form_input_group.documentation.js +2 -26
  6. package/dist/components/base/form/form_input_group/form_input_group.js +7 -0
  7. package/dist/components/base/loading_icon/loading_icon.js +1 -1
  8. package/dist/components/base/pagination/pagination.js +23 -2
  9. package/dist/components/base/path/data.js +2 -1
  10. package/dist/components/base/path/path.js +14 -7
  11. package/dist/components/base/tabs/tab/tab.js +4 -0
  12. package/dist/components/base/tabs/tabs/tabs.documentation.js +2 -14
  13. package/dist/components/base/tabs/tabs/tabs.js +8 -0
  14. package/dist/components/charts/area/area.documentation.js +1 -7
  15. package/dist/components/charts/legend/legend.js +12 -0
  16. package/dist/components/charts/line/line.documentation.js +2 -5
  17. package/dist/index.css +2 -2
  18. package/dist/index.css.map +1 -1
  19. package/dist/utils/stories_utils.js +13 -1
  20. package/documentation/components_documentation.js +0 -2
  21. package/documentation/documented_stories.js +6 -0
  22. package/package.json +2 -2
  23. package/src/components/base/accordion/accordion.stories.js +2 -1
  24. package/src/components/base/alert/alert.scss +0 -38
  25. package/src/components/base/alert/alert.spec.js +0 -1
  26. package/src/components/base/alert/alert.stories.js +0 -8
  27. package/src/components/base/alert/alert.vue +30 -41
  28. package/src/components/base/badge/badge.stories.js +4 -24
  29. package/src/components/base/card/card.vue +2 -2
  30. package/src/components/base/daterange_picker/daterange_picker.stories.js +10 -35
  31. package/src/components/base/drawer/drawer.documentation.js +1 -1
  32. package/src/components/base/form/form_input_group/form_input_group.documentation.js +0 -28
  33. package/src/components/base/form/form_input_group/form_input_group.md +0 -4
  34. package/src/components/base/form/form_input_group/form_input_group.stories.js +84 -62
  35. package/src/components/base/form/form_input_group/form_input_group.vue +9 -0
  36. package/src/components/base/icon/icon.stories.js +2 -5
  37. package/src/components/base/loading_icon/loading_icon.vue +1 -1
  38. package/src/components/base/pagination/pagination.spec.js +12 -2
  39. package/src/components/base/pagination/pagination.vue +23 -6
  40. package/src/components/base/path/__snapshots__/path.spec.js.snap +6 -0
  41. package/src/components/base/path/data.js +1 -0
  42. package/src/components/base/path/path.scss +6 -1
  43. package/src/components/base/path/path.spec.js +20 -0
  44. package/src/components/base/path/path.vue +18 -7
  45. package/src/components/base/tabs/tab/tab.vue +4 -0
  46. package/src/components/base/tabs/tabs/tabs.documentation.js +0 -12
  47. package/src/components/base/tabs/tabs/tabs.md +2 -7
  48. package/src/components/base/tabs/tabs/tabs.stories.js +219 -161
  49. package/src/components/base/tabs/tabs/tabs.vue +6 -0
  50. package/src/components/base/toggle/toggle.stories.js +2 -3
  51. package/src/components/charts/area/area.documentation.js +0 -5
  52. package/src/components/charts/area/area.stories.js +127 -127
  53. package/src/components/charts/bar/bar.stories.js +8 -5
  54. package/src/components/charts/heatmap/heatmap.stories.js +13 -16
  55. package/src/components/charts/legend/legend.stories.js +22 -15
  56. package/src/components/charts/legend/legend.vue +9 -0
  57. package/src/components/charts/line/line.documentation.js +0 -2
  58. package/src/components/charts/line/line.md +0 -2
  59. package/src/components/charts/line/line.stories.js +124 -113
  60. package/src/utils/stories_utils.js +6 -0
  61. package/src/utils/stories_utils.spec.js +18 -0
  62. package/dist/components/base/form/form_input_group/examples/form_input_group.basic.example.js +0 -38
  63. package/dist/components/base/form/form_input_group/examples/form_input_group.predefined_options.example.js +0 -54
  64. package/dist/components/base/form/form_input_group/examples/form_input_group.predefined_reactive.example.js +0 -55
  65. package/dist/components/base/form/form_input_group/examples/form_input_group.reactive.example.js +0 -48
  66. package/dist/components/base/form/form_input_group/examples/index.js +0 -27
  67. package/dist/components/base/tabs/tab/examples/index.js +0 -13
  68. package/dist/components/base/tabs/tab/examples/tab.basic.example.js +0 -38
  69. package/dist/components/base/tabs/tab/tab.documentation.js +0 -18
  70. package/dist/components/base/tabs/tabs/examples/index.js +0 -60
  71. package/dist/components/base/tabs/tabs/examples/tabs.basic.example.js +0 -38
  72. package/dist/components/base/tabs/tabs/examples/tabs.contentless_tab.example.js +0 -38
  73. package/dist/components/base/tabs/tabs/examples/tabs.counterbadges.example.js +0 -38
  74. package/dist/components/base/tabs/tabs/examples/tabs.custom_title.example.js +0 -38
  75. package/dist/components/base/tabs/tabs/examples/tabs.disabled.example.js +0 -38
  76. package/dist/components/base/tabs/tabs/examples/tabs.justified.example.js +0 -38
  77. package/dist/components/base/tabs/tabs/examples/tabs.no_tabs.example.js +0 -38
  78. package/dist/components/base/tabs/tabs/examples/tabs.scrollable.example.js +0 -47
  79. package/dist/components/base/tabs/tabs/examples/tabs.styles_only.example.js +0 -38
  80. package/dist/components/charts/area/examples/area.basic.example.js +0 -45
  81. package/dist/components/charts/area/examples/area.basic_plus.example.js +0 -53
  82. package/dist/components/charts/area/examples/index.js +0 -19
  83. package/dist/components/charts/legend/examples/index.js +0 -22
  84. package/dist/components/charts/legend/examples/legend.basic.example.js +0 -93
  85. package/dist/components/charts/legend/examples/legend.toggled.example.js +0 -100
  86. package/dist/components/charts/legend/legend.documentation.js +0 -21
  87. package/dist/components/charts/line/examples/index.js +0 -19
  88. package/dist/components/charts/line/examples/line.basic.example.js +0 -45
  89. package/dist/components/charts/line/examples/line.series.example.js +0 -53
  90. package/src/components/base/form/form_input_group/examples/form_input_group.basic.example.vue +0 -10
  91. package/src/components/base/form/form_input_group/examples/form_input_group.predefined_options.example.vue +0 -25
  92. package/src/components/base/form/form_input_group/examples/form_input_group.predefined_reactive.example.vue +0 -32
  93. package/src/components/base/form/form_input_group/examples/form_input_group.reactive.example.vue +0 -25
  94. package/src/components/base/form/form_input_group/examples/index.js +0 -32
  95. package/src/components/base/tabs/tab/examples/index.js +0 -15
  96. package/src/components/base/tabs/tab/examples/tab.basic.example.vue +0 -5
  97. package/src/components/base/tabs/tab/tab.documentation.js +0 -16
  98. package/src/components/base/tabs/tab/tab.md +0 -3
  99. package/src/components/base/tabs/tab/tab.stories.js +0 -12
  100. package/src/components/base/tabs/tabs/examples/index.js +0 -72
  101. package/src/components/base/tabs/tabs/examples/tabs.basic.example.vue +0 -6
  102. package/src/components/base/tabs/tabs/examples/tabs.contentless_tab.example.vue +0 -17
  103. package/src/components/base/tabs/tabs/examples/tabs.counterbadges.example.vue +0 -28
  104. package/src/components/base/tabs/tabs/examples/tabs.custom_title.example.vue +0 -9
  105. package/src/components/base/tabs/tabs/examples/tabs.disabled.example.vue +0 -7
  106. package/src/components/base/tabs/tabs/examples/tabs.justified.example.vue +0 -6
  107. package/src/components/base/tabs/tabs/examples/tabs.no_tabs.example.vue +0 -8
  108. package/src/components/base/tabs/tabs/examples/tabs.scrollable.example.vue +0 -20
  109. package/src/components/base/tabs/tabs/examples/tabs.styles_only.example.vue +0 -22
  110. package/src/components/charts/area/area.md +0 -1
  111. package/src/components/charts/area/examples/area.basic.example.vue +0 -14
  112. package/src/components/charts/area/examples/area.basic_plus.example.vue +0 -25
  113. package/src/components/charts/area/examples/index.js +0 -22
  114. package/src/components/charts/legend/examples/index.js +0 -27
  115. package/src/components/charts/legend/examples/legend.basic.example.vue +0 -55
  116. package/src/components/charts/legend/examples/legend.toggled.example.vue +0 -60
  117. package/src/components/charts/legend/legend.documentation.js +0 -19
  118. package/src/components/charts/legend/legend.md +0 -0
  119. package/src/components/charts/line/examples/index.js +0 -22
  120. package/src/components/charts/line/examples/line.basic.example.vue +0 -14
  121. package/src/components/charts/line/examples/line.series.example.vue +0 -25
@@ -1,6 +1,7 @@
1
1
  import iconSpriteInfo from '@gitlab/svgs/dist/icons.json';
2
2
  import { GlIcon } from '../../../index';
3
3
  import { iconSizeOptions } from '../../../utils/constants';
4
+ import { disableControls } from '../../../utils/stories_utils';
4
5
  import readme from './icon.md';
5
6
 
6
7
  const components = {
@@ -41,6 +42,7 @@ export default {
41
42
  storyshots: { disable: true },
42
43
  },
43
44
  argTypes: {
45
+ ...disableControls(['useDeprecatedSizes']),
44
46
  name: {
45
47
  control: {
46
48
  type: 'select',
@@ -53,10 +55,5 @@ export default {
53
55
  options: iconSizeOptions,
54
56
  },
55
57
  },
56
- useDeprecatedSizes: {
57
- control: {
58
- disable: true,
59
- },
60
- },
61
58
  },
62
59
  };
@@ -64,6 +64,6 @@ export default {
64
64
  </script>
65
65
  <template>
66
66
  <component :is="rootElementType" class="gl-spinner-container" role="status">
67
- <span :class="cssClasses" class="align-text-bottom" :aria-label="label"></span>
67
+ <span :class="cssClasses" class="gl-vertical-align-text-bottom!" :aria-label="label"></span>
68
68
  </component>
69
69
  </template>
@@ -16,6 +16,7 @@ const mockResizeWidth = (width) => {
16
16
  describe('pagination component', () => {
17
17
  let wrapper;
18
18
  const findButtons = () => wrapper.findAll('.page-link');
19
+ const findItems = () => wrapper.findAll('.page-item');
19
20
  const propsData = {
20
21
  value: 3,
21
22
  perPage: 5,
@@ -179,6 +180,7 @@ describe('pagination component', () => {
179
180
  it('shows 3rd page as active and enables all buttons', () => {
180
181
  const buttons = findButtons();
181
182
  expect(buttons.at(3).classes()).toEqual(expectClassActive);
183
+ expect(buttons.at(3).attributes('aria-current')).toEqual('page');
182
184
  buttons.wrappers.forEach((button) => {
183
185
  expect(button.element.tagName).not.toBe('SPAN');
184
186
  });
@@ -222,6 +224,7 @@ describe('pagination component', () => {
222
224
  const buttons = findButtons();
223
225
  expect(buttons.at(0).element.tagName).toBe('SPAN');
224
226
  expect(buttons.at(1).classes()).toEqual(expectClassActive);
227
+ expect(buttons.at(1).attributes('aria-current')).toEqual('page');
225
228
  expect(buttons.at(buttons.length - 1).element.tagName).not.toBe('SPAN');
226
229
  });
227
230
 
@@ -310,6 +313,7 @@ describe('pagination component', () => {
310
313
  const buttons = findButtons();
311
314
  expect(buttons.at(0).element.tagName).not.toBe('SPAN');
312
315
  expect(buttons.at(7).classes()).toEqual(expectClassActive);
316
+ expect(buttons.at(7).attributes('aria-current')).toEqual('page');
313
317
  expect(buttons.at(buttons.length - 1).element.tagName).toBe('SPAN');
314
318
  });
315
319
 
@@ -372,9 +376,12 @@ describe('pagination component', () => {
372
376
  value: 1,
373
377
  nextPage: 2,
374
378
  });
379
+ const prevItem = findItems().at(0);
380
+ expect(prevItem.attributes('aria-hidden')).toBe('true');
375
381
  const prevButton = findButtons().at(0);
376
382
  expect(prevButton.element.tagName).toBe('SPAN');
377
- expect(prevButton.attributes('aria-disabled')).toBe('true');
383
+ expect(prevButton.attributes('href')).toBeUndefined();
384
+ expect(prevButton.attributes('aria-label')).toBeUndefined();
378
385
  });
379
386
 
380
387
  it('disables next button when on last page', () => {
@@ -383,9 +390,12 @@ describe('pagination component', () => {
383
390
  value: 2,
384
391
  prevPage: 1,
385
392
  });
393
+ const nextItem = findItems().at(1);
394
+ expect(nextItem.attributes('aria-hidden')).toBe('true');
386
395
  const nextButton = findButtons().at(1);
387
396
  expect(nextButton.element.tagName).toBe('SPAN');
388
- expect(nextButton.attributes('aria-disabled')).toBe('true');
397
+ expect(nextButton.attributes('href')).toBeUndefined();
398
+ expect(nextButton.attributes('aria-label')).toBeUndefined();
389
399
  });
390
400
  });
391
401
  });
@@ -261,6 +261,22 @@ export default {
261
261
  nextPageIsDisabled() {
262
262
  return this.pageIsDisabled(this.value + 1);
263
263
  },
264
+ prevPageAriaLabel() {
265
+ return this.prevPageIsDisabled ? false : this.labelPrevPage || this.labelPage(this.value - 1);
266
+ },
267
+ nextPageAriaLabel() {
268
+ return this.nextPageIsDisabled ? false : this.labelNextPage || this.labelPage(this.value + 1);
269
+ },
270
+ prevPageHref() {
271
+ if (this.prevPageIsDisabled) return false;
272
+ if (this.isLinkBased) return this.linkGen(this.value - 1);
273
+ return '#';
274
+ },
275
+ nextPageHref() {
276
+ if (this.nextPageIsDisabled) return false;
277
+ if (this.isLinkBased) return this.linkGen(this.value + 1);
278
+ return '#';
279
+ },
264
280
  },
265
281
  created() {
266
282
  window.addEventListener('resize', debounce(this.setBreakpoint, resizeDebounceTime));
@@ -293,6 +309,7 @@ export default {
293
309
  const listeners = {};
294
310
  if (isActivePage) {
295
311
  attrs.class.push('active');
312
+ attrs['aria-current'] = 'page';
296
313
  }
297
314
  // Disable previous and/or next buttons if needed
298
315
  if (this.isLinkBased) {
@@ -368,13 +385,13 @@ export default {
368
385
  disabled: prevPageIsDisabled,
369
386
  'flex-fill': isFillAlign,
370
387
  }"
388
+ :aria-hidden="prevPageIsDisabled"
371
389
  >
372
390
  <component
373
391
  :is="prevPageIsDisabled ? 'span' : 'a'"
374
392
  class="gl-link page-link prev-page-item gl-display-flex"
375
- :aria-disabled="prevPageIsDisabled"
376
- :aria-label="labelPrevPage || labelPage(value - 1)"
377
- :href="isLinkBased ? linkGen(value - 1) : '#'"
393
+ :aria-label="prevPageAriaLabel"
394
+ :href="prevPageHref"
378
395
  @click="handlePrevious($event, value - 1)"
379
396
  >
380
397
  <!--
@@ -431,13 +448,13 @@ export default {
431
448
  disabled: nextPageIsDisabled,
432
449
  'flex-fill': isFillAlign,
433
450
  }"
451
+ :aria-hidden="nextPageIsDisabled"
434
452
  >
435
453
  <component
436
454
  :is="nextPageIsDisabled ? 'span' : 'a'"
437
455
  class="gl-link page-link next-page-item gl-display-flex"
438
- :aria-disabled="nextPageIsDisabled"
439
- :aria-label="labelNextPage || labelPage(value + 1)"
440
- :href="isLinkBased ? linkGen(value + 1) : '#'"
456
+ :aria-label="nextPageAriaLabel"
457
+ :href="nextPageHref"
441
458
  @click="handleNext($event, value + 1)"
442
459
  >
443
460
  <!--
@@ -155,7 +155,9 @@ exports[`Path matches the snapshot 1`] = `
155
155
  id="path-1-item-7"
156
156
  >
157
157
  <button
158
+ category="tertiary"
158
159
  class="gl-path-button"
160
+ disabled="disabled"
159
161
  >
160
162
  <!---->
161
163
 
@@ -383,7 +385,9 @@ exports[`Path renders the list of items with icons matches the snapshot 1`] = `
383
385
  id="path-15-item-7"
384
386
  >
385
387
  <button
388
+ category="tertiary"
386
389
  class="gl-path-button"
390
+ disabled="disabled"
387
391
  >
388
392
  <!---->
389
393
 
@@ -606,7 +610,9 @@ exports[`Path renders the list of items with metrics matches the snapshot 1`] =
606
610
  id="path-11-item-7"
607
611
  >
608
612
  <button
613
+ category="tertiary"
609
614
  class="gl-path-button"
615
+ disabled="disabled"
610
616
  >
611
617
  <!---->
612
618
 
@@ -30,6 +30,7 @@ export const mockPathItems = [
30
30
  {
31
31
  title: 'Eighth',
32
32
  metric: '8d',
33
+ disabled: true,
33
34
  },
34
35
  {
35
36
  title: 'Ninth',
@@ -78,7 +78,12 @@ $path-chevron-right-margin: px-to-rem(14px);
78
78
  @include gl-path-chevron;
79
79
  }
80
80
 
81
- &:hover {
81
+ &[disabled] {
82
+ @include gl-text-gray-400;
83
+ @include gl-cursor-not-allowed;
84
+ }
85
+
86
+ &:not([disabled]):hover {
82
87
  @include gl-path-active-item-color($gray-100);
83
88
  @include gl-text-gray-900;
84
89
  }
@@ -1,3 +1,4 @@
1
+ import { nextTick } from 'vue';
1
2
  import { shallowMount } from '@vue/test-utils';
2
3
  import { mockPathItems } from './data';
3
4
  import GlPath from './path.vue';
@@ -143,6 +144,17 @@ describe('Path', () => {
143
144
  it('selects the first item', () => {
144
145
  expect(pathItemAt(0).classList).toContain(SELECTED_CLASS_INDIGO);
145
146
  });
147
+
148
+ it('updates the selected item when props change', async () => {
149
+ const items = JSON.parse(JSON.stringify(mockPathItems));
150
+ items[3].selected = true;
151
+
152
+ wrapper.setProps({ items });
153
+ await nextTick();
154
+
155
+ expect(pathItemAt(0).classList).not.toContain(SELECTED_CLASS_INDIGO);
156
+ expect(pathItemAt(3).classList).toContain(SELECTED_CLASS_INDIGO);
157
+ });
146
158
  });
147
159
 
148
160
  describe('with a specifically selected item passed in', () => {
@@ -188,6 +200,14 @@ describe('Path', () => {
188
200
  ]);
189
201
  });
190
202
  });
203
+
204
+ describe('when a disabled item is clicked', () => {
205
+ it('does not emit the selected event', () => {
206
+ clickItemAt(7);
207
+
208
+ expect(wrapper.emitted('selected')).toBeUndefined();
209
+ });
210
+ });
191
211
  });
192
212
 
193
213
  describe('slots', () => {
@@ -21,9 +21,10 @@ export default {
21
21
  * A list of path items in the form:
22
22
  * ```
23
23
  * {
24
- * title: String, required
25
- * metric: Any, optional
26
- * icon: String, optional
24
+ * title: String, required
25
+ * metric: Any, optional
26
+ * icon: String, optional
27
+ * disabled: Boolean, optional
27
28
  * }
28
29
  * ```
29
30
  */
@@ -78,9 +79,14 @@ export default {
78
79
  return this.scrollLeft + BOUNDARY_WIDTH;
79
80
  },
80
81
  },
81
- mounted() {
82
- const selectedIndex = this.items.findIndex((item) => item.selected);
83
- this.selectedIndex = selectedIndex > 0 ? selectedIndex : 0;
82
+ watch: {
83
+ items: {
84
+ immediate: true,
85
+ handler(items) {
86
+ const selectedIndex = items.findIndex((item) => item.selected);
87
+ this.selectedIndex = selectedIndex > 0 ? selectedIndex : 0;
88
+ },
89
+ },
84
90
  },
85
91
  beforeCreate() {
86
92
  this.pathUuid = uniqueId('path-');
@@ -164,7 +170,12 @@ export default {
164
170
  :key="index"
165
171
  class="gl-path-nav-list-item"
166
172
  >
167
- <button :class="pathItemClass(index)" @click="onItemClicked(index)">
173
+ <button
174
+ :class="pathItemClass(index)"
175
+ :category="item.disabled ? 'tertiary' : undefined"
176
+ :disabled="item.disabled"
177
+ @click="onItemClicked(index)"
178
+ >
168
179
  <gl-icon
169
180
  v-if="shouldDisplayIcon(item.icon)"
170
181
  :name="item.icon"
@@ -15,6 +15,9 @@ export default {
15
15
  required: false,
16
16
  default: '',
17
17
  },
18
+ /**
19
+ * Query string parameter value to use when `gl-tabs` `sync-active-tab-with-query-params` prop is set to `true`.
20
+ */
18
21
  queryParamValue: {
19
22
  type: String,
20
23
  required: false,
@@ -36,6 +39,7 @@ export default {
36
39
  },
37
40
  };
38
41
  </script>
42
+
39
43
  <template>
40
44
  <b-tab
41
45
  :title-link-class="linkClass"
@@ -1,18 +1,6 @@
1
- import examples from './examples';
2
1
  import description from './tabs.md';
3
2
 
4
3
  export default {
5
4
  description,
6
- examples,
7
- bootstrapComponent: 'b-tabs',
8
5
  followsDesignSystem: true,
9
- propsInfo: {
10
- syncActiveTabWithQueryParams: {
11
- additionalInfo:
12
- 'Sync active tab with query string parameters. Allows for deep linking into specific tabs.',
13
- },
14
- queryParamName: {
15
- additionalInfo: 'Name to use for query string parameter.',
16
- },
17
- },
18
6
  };
@@ -1,15 +1,10 @@
1
- # Tabs
2
-
3
- <!-- STORY -->
4
- ## Usage
5
-
6
1
  Tabs are used to divide content into meaningful, related sections. Tabs allow users to focus on one
7
2
  specific view at a time while maintaining sight of all the relevant content options available. Each
8
3
  tab, when active, will reveal it’s own unique content.
9
4
 
10
5
  ## Using the component Vue
11
6
 
12
- ~~~js
7
+ ~~~html
13
8
  <gl-tabs>
14
9
  <gl-tab title="Tab 1">
15
10
  Tab panel 1
@@ -22,7 +17,7 @@ tab, when active, will reveal it’s own unique content.
22
17
 
23
18
  ## Using the component HTML
24
19
 
25
- ~~~js
20
+ ~~~html
26
21
  <div class="tabs gl-tabs">
27
22
  <ul role="tablist" class="nav gl-tabs-nav">
28
23
  <li role="presentation" class="nav-item">