@gitlab/ui 74.8.0 → 74.9.1

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 (26) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/components/base/filtered_search/filtered_search.js +15 -1
  3. package/dist/components/base/new_dropdowns/base_dropdown/base_dropdown.js +1 -1
  4. package/dist/components/base/search_box_by_click/search_box_by_click.js +12 -1
  5. package/dist/index.css +1 -1
  6. package/dist/index.css.map +1 -1
  7. package/dist/tokens/css/tokens.css +1 -1
  8. package/dist/tokens/css/tokens.dark.css +1 -1
  9. package/dist/tokens/js/tokens.dark.js +1 -1
  10. package/dist/tokens/js/tokens.js +1 -1
  11. package/dist/tokens/scss/_tokens.dark.scss +1 -1
  12. package/dist/tokens/scss/_tokens.scss +1 -1
  13. package/dist/utility_classes.css +1 -1
  14. package/dist/utility_classes.css.map +1 -1
  15. package/package.json +2 -2
  16. package/src/components/base/filtered_search/filtered_search.scss +6 -2
  17. package/src/components/base/filtered_search/filtered_search.spec.js +25 -1
  18. package/src/components/base/filtered_search/filtered_search.vue +16 -1
  19. package/src/components/base/new_dropdowns/base_dropdown/base_dropdown.spec.js +3 -3
  20. package/src/components/base/new_dropdowns/base_dropdown/base_dropdown.vue +1 -1
  21. package/src/components/base/search_box_by_click/search_box_by_click.scss +11 -3
  22. package/src/components/base/search_box_by_click/search_box_by_click.spec.js +42 -0
  23. package/src/components/base/search_box_by_click/search_box_by_click.stories.js +3 -0
  24. package/src/components/base/search_box_by_click/search_box_by_click.vue +18 -2
  25. package/src/scss/utilities.scss +10 -0
  26. package/src/scss/utility-mixins/border.scss +5 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gitlab/ui",
3
- "version": "74.8.0",
3
+ "version": "74.9.1",
4
4
  "description": "GitLab UI Components",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",
@@ -139,7 +139,7 @@
139
139
  "eslint": "8.56.0",
140
140
  "eslint-import-resolver-jest": "3.0.2",
141
141
  "eslint-plugin-cypress": "2.15.1",
142
- "eslint-plugin-storybook": "0.7.0",
142
+ "eslint-plugin-storybook": "0.8.0",
143
143
  "glob": "10.3.3",
144
144
  "identity-obj-proxy": "^3.0.0",
145
145
  "inquirer-select-directory": "^1.2.0",
@@ -10,13 +10,17 @@
10
10
  @include gl-pr-7;
11
11
  @include gl-inset-border-1-gray-400;
12
12
  @include gl-border-none;
13
- @include gl-rounded-left-base;
13
+ @include gl-rounded-base;
14
14
 
15
15
  .input-group-prepend + & {
16
16
  @include gl-rounded-left-none;
17
17
  }
18
18
  }
19
19
 
20
+ .gl-filtered-search-scrollable-container-with-search-button {
21
+ @include gl-rounded-right-none;
22
+ }
23
+
20
24
  .gl-filtered-search-scrollable {
21
25
  @include gl-display-flex;
22
26
  @include gl-overflow-y-auto;
@@ -44,4 +48,4 @@
44
48
  @include gl-pl-1;
45
49
  @include gl-h-6;
46
50
  min-width: $gl-spacing-scale-12;
47
- }
51
+ }
@@ -45,7 +45,7 @@ describe('Filtered search', () => {
45
45
  stubs: {
46
46
  GlSearchBoxByClick: {
47
47
  name: 'GlSearchBoxByClickStub',
48
- props: ['clearable', 'searchButtonAttributes'],
48
+ props: ['clearable', 'searchButtonAttributes', 'showSearchButton'],
49
49
  template: '<div><slot name="input"></slot></div>',
50
50
  },
51
51
  },
@@ -566,6 +566,30 @@ describe('Filtered search', () => {
566
566
  });
567
567
  });
568
568
  });
569
+
570
+ describe('showSearchButton', () => {
571
+ it('sets showSearchButton on the SearchBox component', () => {
572
+ createComponent({ showSearchButton: true });
573
+
574
+ expect(findSearchBox().props('showSearchButton')).toBe(true);
575
+ });
576
+
577
+ it('adds the *-with-search-button css modifier if true', () => {
578
+ createComponent({ showSearchButton: true });
579
+
580
+ expect(wrapper.find('.gl-filtered-search-scrollable-container').classes()).toContain(
581
+ 'gl-filtered-search-scrollable-container-with-search-button'
582
+ );
583
+ });
584
+
585
+ it('does not add the *-with-search-button css modifier if false', () => {
586
+ createComponent({ showSearchButton: false });
587
+
588
+ expect(wrapper.find('.gl-filtered-search-scrollable-container').classes()).not.toContain(
589
+ 'gl-filtered-search-scrollable-container-with-search-button'
590
+ );
591
+ });
592
+ });
569
593
  });
570
594
 
571
595
  describe('Filtered search integration tests', () => {
@@ -159,6 +159,17 @@ export default {
159
159
  required: false,
160
160
  default: termTokenDefinition.title,
161
161
  },
162
+ /**
163
+ * Display search button to perform a search.
164
+ *
165
+ * Note: it is required to ensure accessibility for WCAG 2.1 3.2.2: On Input.
166
+ * If the search button is hidden, a separate button should be provided for the same context.
167
+ */
168
+ showSearchButton: {
169
+ type: Boolean,
170
+ required: false,
171
+ default: true,
172
+ },
162
173
  },
163
174
  data() {
164
175
  return {
@@ -381,6 +392,7 @@ export default {
381
392
  :history-items="historyItems"
382
393
  :clearable="hasValue"
383
394
  :search-button-attributes="searchButtonAttributes"
395
+ :show-search-button="showSearchButton"
384
396
  :disabled="viewOnly"
385
397
  data-testid="filtered-search-input"
386
398
  @submit="submit"
@@ -396,7 +408,10 @@ export default {
396
408
  <template #input>
397
409
  <div
398
410
  class="gl-filtered-search-scrollable-container"
399
- :class="{ 'gl-bg-gray-10! gl-inset-border-1-gray-100!': viewOnly }"
411
+ :class="{
412
+ 'gl-filtered-search-scrollable-container-with-search-button': showSearchButton,
413
+ 'gl-bg-gray-10! gl-inset-border-1-gray-100!': viewOnly,
414
+ }"
400
415
  >
401
416
  <div class="gl-filtered-search-scrollable">
402
417
  <component
@@ -307,7 +307,7 @@ describe('base dropdown', () => {
307
307
  // close menu clicking toggle btn
308
308
  await toggle.trigger('click');
309
309
  expect(menu.classes('gl-display-block!')).toBe(false);
310
- expect(toggle.attributes('aria-expanded')).toBeUndefined();
310
+ expect(toggle.attributes('aria-expanded')).toBe('false');
311
311
  expect(wrapper.emitted(GL_DROPDOWN_HIDDEN)).toHaveLength(1);
312
312
  expect(toggle.element).toHaveFocus();
313
313
  });
@@ -332,7 +332,7 @@ describe('base dropdown', () => {
332
332
  await menu.trigger('keydown.esc');
333
333
 
334
334
  expect(menu.classes('gl-display-block!')).toBe(false);
335
- expect(toggle.attributes('aria-expanded')).toBeUndefined();
335
+ expect(toggle.attributes('aria-expanded')).toBe('false');
336
336
  expect(wrapper.emitted(GL_DROPDOWN_HIDDEN)).toHaveLength(1);
337
337
  expect(toggle.element).toHaveFocus();
338
338
  });
@@ -391,7 +391,7 @@ describe('base dropdown', () => {
391
391
  moveFocusWithinDropdown();
392
392
  await menu.trigger('keydown.esc');
393
393
  expect(menu.classes('gl-display-block!')).toBe(true);
394
- expect(toggle.attributes('aria-expanded')).toBeDefined();
394
+ expect(toggle.attributes('aria-expanded')).toBe('true');
395
395
  expect(wrapper.emitted(GL_DROPDOWN_HIDDEN)).toBeUndefined();
396
396
  expect(toggle.element).not.toHaveFocus();
397
397
  });
@@ -166,7 +166,7 @@ export default {
166
166
  ariaAttributes() {
167
167
  return {
168
168
  'aria-haspopup': this.ariaHaspopup,
169
- 'aria-expanded': this.visible,
169
+ 'aria-expanded': String(this.visible),
170
170
  'aria-controls': this.baseDropdownId,
171
171
  'aria-labelledby': this.toggleLabelledBy,
172
172
  };
@@ -54,8 +54,6 @@
54
54
  }
55
55
 
56
56
  .gl-search-box-by-click-input {
57
- @include gl-pr-7;
58
-
59
57
  &::-webkit-search-cancel-button {
60
58
  @include gl-display-none;
61
59
  }
@@ -64,7 +62,7 @@
64
62
  .gl-search-box-by-click-clear-button {
65
63
  @include gl-absolute;
66
64
  @include gl-top-2;
67
- @include gl-right-7;
65
+ @include gl-right-2;
68
66
  @include gl-mr-2;
69
67
  @include gl-z-index-3;
70
68
  }
@@ -74,3 +72,13 @@
74
72
  width: $gl-dropdown-width-wide;
75
73
  }
76
74
  }
75
+
76
+ .gl-search-box-by-click-with-search-button {
77
+ .gl-search-box-by-click-input {
78
+ @include gl-pr-7;
79
+ }
80
+
81
+ .gl-search-box-by-click-clear-button {
82
+ @include gl-right-7;
83
+ }
84
+ }
@@ -168,4 +168,46 @@ describe('search box by click component', () => {
168
168
 
169
169
  expect(findSearchButton().attributes('data-prop')).toBe(searchButtonAttributes['data-prop']);
170
170
  });
171
+
172
+ describe('showSearchButton', () => {
173
+ describe('when false', () => {
174
+ beforeEach(() => {
175
+ createComponent({ showSearchButton: false, value: 'some-value' });
176
+ });
177
+
178
+ it('does not render the search button', () => {
179
+ expect(findSearchButton().exists()).toBe(false);
180
+ });
181
+
182
+ it('overrides the border style of the input', () => {
183
+ expect(wrapper.findComponent(GlFormInput).classes()).toContain('gl-rounded-base!');
184
+ });
185
+
186
+ it('does not add *-with-search-button css modifier', () => {
187
+ expect(wrapper.find('.gl-search-box-by-click').classes()).not.toContain(
188
+ 'gl-search-box-by-click-with-search-button'
189
+ );
190
+ });
191
+ });
192
+
193
+ describe('when true', () => {
194
+ beforeEach(() => {
195
+ createComponent({ showSearchButton: true, value: 'some-value' });
196
+ });
197
+
198
+ it('does render the search button', () => {
199
+ expect(findSearchButton().exists()).toBe(true);
200
+ });
201
+
202
+ it('does not override the border style of the input', () => {
203
+ expect(wrapper.findComponent(GlFormInput).classes()).not.toContain('gl-rounded-base!');
204
+ });
205
+
206
+ it('adds *-with-search-button css modifier', () => {
207
+ expect(wrapper.find('.gl-search-box-by-click').classes()).toContain(
208
+ 'gl-search-box-by-click-with-search-button'
209
+ );
210
+ });
211
+ });
212
+ });
171
213
  });
@@ -15,6 +15,7 @@ const template = `
15
15
  :clear-recent-searches-text="clearRecentSearchesText"
16
16
  :no-recent-searches-text="noRecentSearchesText"
17
17
  :search-button-attributes="searchButtonAttributes"
18
+ :show-search-button="showSearchButton"
18
19
  @clear-history="clearCurrentHistory"
19
20
  />
20
21
  `;
@@ -33,6 +34,7 @@ const generateProps = ({
33
34
  clearRecentSearchesText = defaultValue('clearRecentSearchesText'),
34
35
  noRecentSearchesText = defaultValue('noRecentSearchesText'),
35
36
  searchButtonAttributes = defaultValue('searchButtonAttributes')(),
37
+ showSearchButton = defaultValue('showSearchButton'),
36
38
  } = {}) => ({
37
39
  disabled,
38
40
  value,
@@ -45,6 +47,7 @@ const generateProps = ({
45
47
  clearRecentSearchesText,
46
48
  noRecentSearchesText,
47
49
  searchButtonAttributes,
50
+ showSearchButton,
48
51
  });
49
52
 
50
53
  const Template = (args, { argTypes }) => ({
@@ -120,6 +120,17 @@ export default {
120
120
  required: false,
121
121
  default: () => ({}),
122
122
  },
123
+ /**
124
+ * Display search button to perform a search.
125
+ *
126
+ * Note: it is required to ensure accessibility for WCAG 2.1 3.2.2: On Input.
127
+ * If the search button is hidden, a separate button should be provided for the same context.
128
+ */
129
+ showSearchButton: {
130
+ type: Boolean,
131
+ required: false,
132
+ default: true,
133
+ },
123
134
  },
124
135
  data() {
125
136
  return {
@@ -201,7 +212,10 @@ export default {
201
212
  </script>
202
213
 
203
214
  <template>
204
- <gl-form-input-group class="gl-search-box-by-click">
215
+ <gl-form-input-group
216
+ class="gl-search-box-by-click"
217
+ :class="{ 'gl-search-box-by-click-with-search-button': showSearchButton }"
218
+ >
205
219
  <template v-if="historyItems" #prepend>
206
220
  <gl-dropdown
207
221
  ref="historyDropdown"
@@ -255,6 +269,7 @@ export default {
255
269
  ref="input"
256
270
  v-model="currentValue"
257
271
  class="gl-search-box-by-click-input"
272
+ :class="{ 'gl-rounded-base!': !showSearchButton }"
258
273
  v-bind="inputAttributes"
259
274
  :disabled="disabled"
260
275
  @focus="isFocused = true"
@@ -270,7 +285,8 @@ export default {
270
285
  data-testid="filtered-search-clear-button"
271
286
  @click="clearInput"
272
287
  />
273
- <template #append>
288
+
289
+ <template v-if="showSearchButton" #append>
274
290
  <gl-button
275
291
  v-bind="searchButtonAttributes"
276
292
  ref="searchButton"
@@ -1864,6 +1864,16 @@ $gl-animate-skeleton-loader-max-width: 64 * $grid-size;
1864
1864
  border-top-right-radius: 0 !important;
1865
1865
  }
1866
1866
 
1867
+ .gl-rounded-right-none {
1868
+ border-top-right-radius: 0;
1869
+ border-bottom-right-radius: 0;
1870
+ }
1871
+
1872
+ .gl-rounded-right-none\! {
1873
+ border-top-right-radius: 0 !important;
1874
+ border-bottom-right-radius: 0 !important;
1875
+ }
1876
+
1867
1877
  .gl-rounded-top-base {
1868
1878
  border-top-left-radius: $gl-border-radius-base;
1869
1879
  border-top-right-radius: $gl-border-radius-base;
@@ -426,6 +426,11 @@
426
426
  border-top-right-radius: 0;
427
427
  }
428
428
 
429
+ @mixin gl-rounded-right-none {
430
+ border-top-right-radius: 0;
431
+ border-bottom-right-radius: 0;
432
+ }
433
+
429
434
  @mixin gl-rounded-top-base {
430
435
  border-top-left-radius: $gl-border-radius-base;
431
436
  border-top-right-radius: $gl-border-radius-base;