@gitlab/ui 62.11.0 → 62.12.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gitlab/ui",
3
- "version": "62.11.0",
3
+ "version": "62.12.1",
4
4
  "description": "GitLab UI Components",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",
@@ -89,22 +89,22 @@
89
89
  "@gitlab/eslint-plugin": "19.0.0",
90
90
  "@gitlab/fonts": "^1.2.0",
91
91
  "@gitlab/stylelint-config": "4.1.0",
92
- "@gitlab/svgs": "3.45.0",
92
+ "@gitlab/svgs": "3.46.0",
93
93
  "@rollup/plugin-commonjs": "^11.1.0",
94
94
  "@rollup/plugin-node-resolve": "^7.1.3",
95
95
  "@rollup/plugin-replace": "^2.3.2",
96
- "@storybook/addon-a11y": "7.0.9",
97
- "@storybook/addon-docs": "7.0.9",
98
- "@storybook/addon-essentials": "7.0.9",
99
- "@storybook/addon-storyshots": "7.0.9",
100
- "@storybook/addon-storyshots-puppeteer": "7.0.9",
101
- "@storybook/addon-viewport": "7.0.9",
102
- "@storybook/builder-webpack5": "7.0.9",
103
- "@storybook/theming": "7.0.9",
104
- "@storybook/vue": "7.0.9",
105
- "@storybook/vue-webpack5": "7.0.9",
106
- "@storybook/vue3": "7.0.9",
107
- "@storybook/vue3-webpack5": "7.0.9",
96
+ "@storybook/addon-a11y": "7.0.11",
97
+ "@storybook/addon-docs": "7.0.11",
98
+ "@storybook/addon-essentials": "7.0.11",
99
+ "@storybook/addon-storyshots": "7.0.11",
100
+ "@storybook/addon-storyshots-puppeteer": "7.0.11",
101
+ "@storybook/addon-viewport": "7.0.11",
102
+ "@storybook/builder-webpack5": "7.0.11",
103
+ "@storybook/theming": "7.0.11",
104
+ "@storybook/vue": "7.0.11",
105
+ "@storybook/vue-webpack5": "7.0.11",
106
+ "@storybook/vue3": "7.0.11",
107
+ "@storybook/vue3-webpack5": "7.0.11",
108
108
  "@vue/compat": "^3.2.40",
109
109
  "@vue/compiler-sfc": "^3.2.40",
110
110
  "@vue/test-utils": "1.3.0",
@@ -116,7 +116,7 @@
116
116
  "babel-loader": "^8.0.5",
117
117
  "babel-plugin-require-context-hook": "^1.0.0",
118
118
  "bootstrap": "4.6.2",
119
- "cypress": "12.11.0",
119
+ "cypress": "12.12.0",
120
120
  "emoji-regex": "^10.0.0",
121
121
  "eslint": "8.40.0",
122
122
  "eslint-import-resolver-jest": "3.0.2",
@@ -1,21 +1,31 @@
1
- .gl-filtered-search-scrollable {
1
+ .gl-filtered-search-scrollable-container {
2
2
  @include gl-bg-white;
3
3
  @include gl-display-flex;
4
4
  @include gl-flex-grow-1;
5
5
  @include gl-flex-basis-0;
6
- @include gl-overflow-y-auto;
6
+ @include gl-overflow-hidden;
7
7
  @include gl-align-items-center;
8
- @include gl-p-2;
8
+ @include gl-py-2;
9
9
  @include gl-pl-4;
10
+ @include gl-pr-7;
10
11
  @include gl-inset-border-1-gray-400;
11
12
  @include gl-border-none;
12
13
  @include gl-rounded-top-left-base;
13
14
  @include gl-rounded-bottom-left-base;
14
15
  }
15
16
 
17
+ .gl-filtered-search-scrollable {
18
+ @include gl-display-flex;
19
+ @include gl-overflow-y-auto;
20
+ }
21
+
16
22
  .gl-filtered-search-item {
17
23
  @include gl-display-flex;
18
24
  @include gl-px-1;
25
+
26
+ &:first-child {
27
+ @include gl-pl-0;
28
+ }
19
29
  }
20
30
 
21
31
  .gl-filtered-search-last-item {
@@ -397,38 +397,40 @@ export default {
397
397
  </template>
398
398
  <template #input>
399
399
  <div
400
- class="gl-filtered-search-scrollable"
400
+ class="gl-filtered-search-scrollable-container"
401
401
  :class="{ 'gl-bg-gray-10! gl-inset-border-1-gray-100!': viewOnly }"
402
402
  >
403
- <component
404
- :is="getTokenComponent(token.type)"
405
- v-for="(token, idx) in tokens"
406
- ref="tokens"
407
- :key="token.id"
408
- v-model="token.value"
409
- :config="getTokenEntry(token.type)"
410
- :active="activeTokenIdx === idx"
411
- :cursor-position="intendedCursorPosition"
412
- :available-tokens="currentAvailableTokens"
413
- :current-value="tokens"
414
- :index="idx"
415
- :placeholder="termPlaceholder"
416
- :show-friendly-text="showFriendlyText"
417
- :search-input-attributes="searchInputAttributes"
418
- :view-only="viewOnly"
419
- :is-last-token="isLastToken(idx)"
420
- :class="getTokenClassList(idx)"
421
- :search-text-option-label="searchTextOptionLabel"
422
- @activate="activate(idx)"
423
- @deactivate="deactivate(token)"
424
- @destroy="destroyToken(idx, $event)"
425
- @replace="replaceToken(idx, $event)"
426
- @complete="completeToken"
427
- @submit="submit"
428
- @split="createTokens(idx, $event)"
429
- @previous="activatePreviousToken"
430
- @next="activateNextToken"
431
- />
403
+ <div class="gl-filtered-search-scrollable">
404
+ <component
405
+ :is="getTokenComponent(token.type)"
406
+ v-for="(token, idx) in tokens"
407
+ ref="tokens"
408
+ :key="token.id"
409
+ v-model="token.value"
410
+ :config="getTokenEntry(token.type)"
411
+ :active="activeTokenIdx === idx"
412
+ :cursor-position="intendedCursorPosition"
413
+ :available-tokens="currentAvailableTokens"
414
+ :current-value="tokens"
415
+ :index="idx"
416
+ :placeholder="termPlaceholder"
417
+ :show-friendly-text="showFriendlyText"
418
+ :search-input-attributes="searchInputAttributes"
419
+ :view-only="viewOnly"
420
+ :is-last-token="isLastToken(idx)"
421
+ :class="getTokenClassList(idx)"
422
+ :search-text-option-label="searchTextOptionLabel"
423
+ @activate="activate(idx)"
424
+ @deactivate="deactivate(token)"
425
+ @destroy="destroyToken(idx, $event)"
426
+ @replace="replaceToken(idx, $event)"
427
+ @complete="completeToken"
428
+ @submit="submit"
429
+ @split="createTokens(idx, $event)"
430
+ @previous="activatePreviousToken"
431
+ @next="activateNextToken"
432
+ />
433
+ </div>
432
434
  </div>
433
435
  <portal-target
434
436
  ref="menu"
@@ -71,6 +71,7 @@ type Option = {
71
71
  type Group = {
72
72
  text: string
73
73
  options: Array<Option>
74
+ textSrOnly?: boolean
74
75
  }
75
76
 
76
77
  type ItemsProp = Array<Option> | Array<Group>
@@ -104,7 +105,9 @@ template. If you want to render a custom template for items, use the
104
105
  Options can be contained within groups. A group has a required `text`
105
106
  property, which must be unique across all groups within the listbox, as
106
107
  it's used as a primary key. It also has a required property `items` that
107
- must be an array of options.
108
+ must be an array of options. Optionally, you can hide the group heading
109
+ by setting `textSrOnly` to `true`. In this case the `text` is only used
110
+ for accessibility purposes.
108
111
 
109
112
  Groups can be at most one level deep: a group can only contain options.
110
113
  Options and groups _cannot_ be siblings. Either all items are options,
@@ -387,6 +387,20 @@ describe('GlCollapsibleListbox', () => {
387
387
  expect(findListboxItems(groups.at(i))).toHaveLength(group.options.length);
388
388
  });
389
389
  });
390
+
391
+ it('passes the `textSrOnly` prop', () => {
392
+ const mockGroupsWithTextSrOnly = JSON.parse(JSON.stringify(mockGroups));
393
+ mockGroupsWithTextSrOnly[0].textSrOnly = true;
394
+ mockGroupsWithTextSrOnly[1].textSrOnly = false;
395
+ buildWrapper({ items: mockGroupsWithTextSrOnly });
396
+
397
+ const groups = findListboxGroups();
398
+
399
+ const expectedTextSrOnlyProps = mockGroupsWithTextSrOnly.map((group) => group.textSrOnly);
400
+ const actualTextSrOnlyProps = groups.wrappers.map((group) => group.props('textSrOnly'));
401
+
402
+ expect(actualTextSrOnlyProps).toEqual(expectedTextSrOnlyProps);
403
+ });
390
404
  });
391
405
 
392
406
  describe('when `searchable` is enabled', () => {
@@ -686,7 +686,12 @@ export default {
686
686
  </template>
687
687
 
688
688
  <template v-else>
689
- <gl-listbox-group :key="item.text" :name="item.text" :class="groupClasses(index)">
689
+ <gl-listbox-group
690
+ :key="item.text"
691
+ :name="item.text"
692
+ :text-sr-only="item.textSrOnly"
693
+ :class="groupClasses(index)"
694
+ >
690
695
  <template v-if="$scopedSlots['group-label']" #group-label>
691
696
  <!-- @slot Custom template for group names -->
692
697
  <slot name="group-label" :group="item"></slot>
@@ -44,4 +44,18 @@ describe('GlListboxGroup', () => {
44
44
 
45
45
  expect(findByTestId('custom-name', findLabelElement()).exists()).toBe(true);
46
46
  });
47
+
48
+ describe('`textSrOnly` is true', () => {
49
+ beforeEach(() => {
50
+ buildWrapper({
51
+ propsData: {
52
+ textSrOnly: true,
53
+ },
54
+ });
55
+ });
56
+
57
+ it('adds `gl-sr-only` class', () => {
58
+ expect(findLabelElement().classes('gl-sr-only')).toBe(true);
59
+ });
60
+ });
47
61
  });
@@ -8,6 +8,11 @@ export default {
8
8
  type: String,
9
9
  required: true,
10
10
  },
11
+ textSrOnly: {
12
+ type: Boolean,
13
+ required: false,
14
+ default: false,
15
+ },
11
16
  },
12
17
  created() {
13
18
  this.nameId = uniqueId('gl-listbox-group-');
@@ -21,6 +26,7 @@ export default {
21
26
  :id="nameId"
22
27
  role="presentation"
23
28
  class="gl-pl-4 gl-pt-3 gl-pb-2 gl-font-sm gl-font-weight-bold"
29
+ :class="{ 'gl-sr-only': textSrOnly }"
24
30
  >
25
31
  <slot name="group-label">{{ name }}</slot>
26
32
  </li>