@gitlab/ui 64.18.0 → 64.18.2

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.
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Do not edit directly
3
- * Generated on Tue, 04 Jul 2023 11:29:36 GMT
3
+ * Generated on Wed, 05 Jul 2023 16:22:25 GMT
4
4
  */
5
5
 
6
6
  :root {
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Do not edit directly
3
- * Generated on Tue, 04 Jul 2023 11:29:36 GMT
3
+ * Generated on Wed, 05 Jul 2023 16:22:25 GMT
4
4
  */
5
5
 
6
6
  :root {
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Do not edit directly
3
- * Generated on Tue, 04 Jul 2023 11:29:36 GMT
3
+ * Generated on Wed, 05 Jul 2023 16:22:25 GMT
4
4
  */
5
5
 
6
6
  export const BLACK = "#fff";
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Do not edit directly
3
- * Generated on Tue, 04 Jul 2023 11:29:36 GMT
3
+ * Generated on Wed, 05 Jul 2023 16:22:25 GMT
4
4
  */
5
5
 
6
6
  export const BLACK = "#000";
@@ -1,6 +1,6 @@
1
1
 
2
2
  // Do not edit directly
3
- // Generated on Tue, 04 Jul 2023 11:29:36 GMT
3
+ // Generated on Wed, 05 Jul 2023 16:22:25 GMT
4
4
 
5
5
  $red-950: #fff4f3;
6
6
  $red-900: #fcf1ef;
@@ -1,6 +1,6 @@
1
1
 
2
2
  // Do not edit directly
3
- // Generated on Tue, 04 Jul 2023 11:29:36 GMT
3
+ // Generated on Wed, 05 Jul 2023 16:22:25 GMT
4
4
 
5
5
  $brand-gray-05: #2b2838 !default;
6
6
  $brand-gray-04: #45424d !default;
@@ -249,7 +249,6 @@ const formInputSizes = {
249
249
  const toggleLabelPosition = {
250
250
  hidden: 'hidden',
251
251
  left: 'left',
252
- block: 'block',
253
252
  top: 'top'
254
253
  };
255
254
  const tooltipActionEvents = ['open', 'close', 'enable', 'disable'];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gitlab/ui",
3
- "version": "64.18.0",
3
+ "version": "64.18.2",
4
4
  "description": "GitLab UI Components",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",
@@ -95,18 +95,18 @@
95
95
  "@rollup/plugin-commonjs": "^11.1.0",
96
96
  "@rollup/plugin-node-resolve": "^7.1.3",
97
97
  "@rollup/plugin-replace": "^2.3.2",
98
- "@storybook/addon-a11y": "7.0.23",
99
- "@storybook/addon-docs": "7.0.23",
100
- "@storybook/addon-essentials": "7.0.23",
101
- "@storybook/addon-storyshots": "7.0.23",
102
- "@storybook/addon-storyshots-puppeteer": "7.0.23",
103
- "@storybook/addon-viewport": "7.0.23",
104
- "@storybook/builder-webpack5": "7.0.23",
105
- "@storybook/theming": "7.0.23",
106
- "@storybook/vue": "7.0.23",
107
- "@storybook/vue-webpack5": "7.0.23",
108
- "@storybook/vue3": "7.0.23",
109
- "@storybook/vue3-webpack5": "7.0.23",
98
+ "@storybook/addon-a11y": "7.0.24",
99
+ "@storybook/addon-docs": "7.0.24",
100
+ "@storybook/addon-essentials": "7.0.24",
101
+ "@storybook/addon-storyshots": "7.0.24",
102
+ "@storybook/addon-storyshots-puppeteer": "7.0.24",
103
+ "@storybook/addon-viewport": "7.0.24",
104
+ "@storybook/builder-webpack5": "7.0.24",
105
+ "@storybook/theming": "7.0.24",
106
+ "@storybook/vue": "7.0.24",
107
+ "@storybook/vue-webpack5": "7.0.24",
108
+ "@storybook/vue3": "7.0.24",
109
+ "@storybook/vue3-webpack5": "7.0.24",
110
110
  "@vue/compat": "^3.2.40",
111
111
  "@vue/compiler-sfc": "^3.2.40",
112
112
  "@vue/test-utils": "1.3.0",
@@ -120,7 +120,7 @@
120
120
  "bootstrap": "4.6.2",
121
121
  "cypress": "12.16.0",
122
122
  "emoji-regex": "^10.0.0",
123
- "eslint": "8.42.0",
123
+ "eslint": "8.44.0",
124
124
  "eslint-import-resolver-jest": "3.0.2",
125
125
  "eslint-plugin-cypress": "2.13.3",
126
126
  "eslint-plugin-storybook": "0.6.12",
@@ -154,7 +154,7 @@
154
154
  "sass-loader": "^10.2.0",
155
155
  "sass-true": "^6.1.0",
156
156
  "start-server-and-test": "^1.10.6",
157
- "storybook": "7.0.23",
157
+ "storybook": "7.0.24",
158
158
  "storybook-dark-mode": "3.0.0",
159
159
  "style-dictionary": "^3.8.0",
160
160
  "stylelint": "14.9.1",
@@ -485,31 +485,33 @@ describe('GlCollapsibleListbox', () => {
485
485
  });
486
486
 
487
487
  it.each`
488
- title | multiple | selected
489
- ${'shows'} | ${true} | ${mockOptionsValues}
490
- ${'hides'} | ${false} | ${mockOptions[1].value}
488
+ description | props
489
+ ${'multi-select'} | ${{ multiple: true, selected: mockOptionsValues }}
490
+ ${'single-select'} | ${{ multiple: false, selected: mockOptions[1].value }}
491
491
  `(
492
- '$title the reset button if the label is provided and the selection is complete and mode if multiple mode is $multiple',
493
- ({ multiple, selected }) => {
492
+ 'shows the button if the label is provided and the selection is complete in $description mode',
493
+ ({ props }) => {
494
494
  buildWrapper({
495
495
  headerText: 'Select assignee',
496
496
  resetButtonLabel: 'Unassign',
497
- selected,
498
497
  items: mockOptions,
499
- multiple,
498
+ ...props,
500
499
  });
501
500
 
502
- expect(findResetButton().exists()).toBe(multiple);
501
+ expect(findResetButton().exists()).toBe(true);
503
502
  }
504
503
  );
505
504
 
506
- it('hides reset button if the label is provided and the selection is not complete', () => {
505
+ it.each`
506
+ description | props
507
+ ${'multi-select'} | ${{ multiple: true, selected: [] }}
508
+ ${'single-select'} | ${{ multiple: false, selected: [] }}
509
+ `('hides the button if the selection is empty in $description mode', ({ props }) => {
507
510
  buildWrapper({
508
511
  headerText: 'Select assignee',
509
512
  resetButtonLabel: 'Unassign',
510
- selected: mockOptions[1].value,
511
513
  items: mockOptions,
512
- multiple: true,
514
+ ...props,
513
515
  });
514
516
 
515
517
  expect(findResetButton().exists()).toBe(false);
@@ -527,22 +529,7 @@ describe('GlCollapsibleListbox', () => {
527
529
  expect(findResetButton().exists()).toBe(false);
528
530
  });
529
531
 
530
- it.each`
531
- description | props
532
- ${'multi-select'} | ${{ multiple: true, selected: [] }}
533
- ${'single-select'} | ${{ multiple: false, selected: null }}
534
- `('hides the button if the selection is empty in $description mode', ({ props }) => {
535
- buildWrapper({
536
- headerText: 'Select assignee',
537
- resetButtonLabel: 'Unassign',
538
- items: mockOptions,
539
- ...props,
540
- });
541
-
542
- expect(findResetButton().exists()).toBe(false);
543
- });
544
-
545
- it('on click, emits the reset event does not and call closeAndFocus() for multiple mode', () => {
532
+ it('on click, emits the `reset` event but does not call `closeAndFocus`', () => {
546
533
  buildWrapper({
547
534
  headerText: 'Select assignee',
548
535
  resetButtonLabel: 'Unassign',
@@ -572,24 +559,31 @@ describe('GlCollapsibleListbox', () => {
572
559
  expect(wrapper).toHaveLoggedVueErrors();
573
560
  });
574
561
 
575
- it.each`
576
- multiple | resetVisible | selectAllVisible
577
- ${false} | ${false} | ${false}
578
- ${true} | ${false} | ${true}
562
+ describe.each`
563
+ multiple | resetVisible | selectAllVisible | selected
564
+ ${false} | ${false} | ${false} | ${[]}
565
+ ${true} | ${false} | ${true} | ${[]}
579
566
  `(
580
- 'shows the select all button if the label is provided and the selection is empty and multiple option is $multiple',
581
- ({ multiple, resetVisible, selectAllVisible }) => {
582
- buildWrapper({
583
- headerText: 'Select assignee',
584
- resetButtonLabel: 'Unassign',
585
- showSelectAllButtonLabel: 'Select All',
586
- selected: [],
587
- items: mockOptions,
588
- multiple,
567
+ 'when label is provided, selection is empty and multiple option is $multiple',
568
+ ({ multiple, resetVisible, selectAllVisible, selected }) => {
569
+ beforeEach(() => {
570
+ buildWrapper({
571
+ headerText: 'Select assignee',
572
+ resetButtonLabel: 'Unassign',
573
+ showSelectAllButtonLabel: 'Select All',
574
+ items: mockOptions,
575
+ selected,
576
+ multiple,
577
+ });
578
+ });
579
+
580
+ it(`${selectAllVisible ? 'shows' : 'does not show'} the Select all button`, () => {
581
+ expect(findSelectAllButton().exists()).toBe(selectAllVisible);
589
582
  });
590
583
 
591
- expect(findResetButton().exists()).toBe(resetVisible);
592
- expect(findSelectAllButton().exists()).toBe(selectAllVisible);
584
+ it(`${resetVisible ? 'shows' : 'does not show'} the Reset button`, () => {
585
+ expect(findResetButton().exists()).toBe(resetVisible);
586
+ });
593
587
  }
594
588
  );
595
589
 
@@ -644,7 +638,7 @@ describe('GlCollapsibleListbox', () => {
644
638
  expect(findSelectAllButton().text()).toBe('Select All');
645
639
  });
646
640
 
647
- it('on click, emits the select-all event and calls closeAndFocus()', () => {
641
+ it('on click, emits the `select-all` event and calls `closeAndFocus`', () => {
648
642
  buildWrapper({
649
643
  headerText: 'Select assignee',
650
644
  resetButtonLabel: 'Unassign',
@@ -398,10 +398,6 @@ export default {
398
398
  return false;
399
399
  }
400
400
 
401
- if (!this.multiple) {
402
- return false;
403
- }
404
-
405
401
  /**
406
402
  * if dropdown has no items
407
403
  * reset all should be hidden
@@ -410,6 +406,13 @@ export default {
410
406
  return false;
411
407
  }
412
408
 
409
+ /**
410
+ * hide if no selection
411
+ */
412
+ if (this.selected.length === 0) {
413
+ return false;
414
+ }
415
+
413
416
  if (this.multiple) {
414
417
  return this.selected.length === this.items.length;
415
418
  }
@@ -29,18 +29,18 @@
29
29
  .gl-toggle {
30
30
  @include gl-cursor-not-allowed;
31
31
  @include gl-bg-gray-200;
32
- }
33
32
 
34
- .toggle-icon > svg {
35
- @include gl-fill-gray-200;
33
+ .toggle-icon > svg {
34
+ @include gl-fill-gray-200;
35
+ }
36
36
  }
37
37
 
38
38
  .gl-toggle.is-checked {
39
39
  @include gl-bg-blue-200;
40
- }
41
40
 
42
- .toggle-icon > svg {
43
- @include gl-fill-blue-200;
41
+ .toggle-icon > svg {
42
+ @include gl-fill-blue-200;
43
+ }
44
44
  }
45
45
 
46
46
  .gl-toggle-label,
@@ -50,32 +50,6 @@
50
50
  }
51
51
  }
52
52
 
53
- .gl-toggle-label-container {
54
- @include gl-flex-shrink-0;
55
- @include gl-display-flex;
56
- @include gl-flex-direction-column;
57
- }
58
-
59
- .gl-toggle-switch-container {
60
- @include gl-display-flex;
61
- @include gl-flex-direction-column;
62
- }
63
-
64
- .gl-toggle-label-position-block {
65
- @include gl-justify-content-space-between;
66
- @include gl-align-items-center;
67
- @include gl-w-full;
68
-
69
- .gl-toggle-label-container {
70
- @include gl-gap-2;
71
- }
72
-
73
- .gl-toggle-switch-container {
74
- @include gl-align-items-flex-end;
75
- @include gl-gap-2;
76
- }
77
- }
78
-
79
53
  .gl-help-label {
80
54
  @include gl-mt-3;
81
55
  @include gl-text-gray-500;
@@ -138,43 +138,31 @@ describe('toggle', () => {
138
138
 
139
139
  describe('label position', () => {
140
140
  describe.each`
141
- state | labelPosition | hasGlSrOnlyClass | flexDirection | showsHelpText | showsDescription
142
- ${'top'} | ${toggleLabelPosition.top} | ${false} | ${'gl-flex-direction-column'} | ${true} | ${true}
143
- ${'left'} | ${toggleLabelPosition.left} | ${false} | ${'gl-toggle-label-inline'} | ${false} | ${false}
144
- ${'hidden'} | ${toggleLabelPosition.hidden} | ${true} | ${'gl-flex-direction-column'} | ${true} | ${true}
145
- ${'block'} | ${toggleLabelPosition.block} | ${false} | ${'gl-toggle-label-inline'} | ${true} | ${true}
146
- `(
147
- 'when $state',
148
- ({ labelPosition, hasGlSrOnlyClass, flexDirection, showsHelpText, showsDescription }) => {
149
- beforeEach(() => {
150
- createWrapper({ labelPosition, help: helpText, description: descriptionText });
151
- });
152
-
153
- it(`${flexDirection} class is added to the label`, () => {
154
- const cssClasses = wrapper.find('[data-testid="toggle-wrapper"]').classes();
155
-
156
- expect(cssClasses).toContain(flexDirection);
157
- });
158
-
159
- it(`${hasGlSrOnlyClass ? 'adds' : 'does not add'} 'gl-sr-only' class to the label`, () => {
160
- const cssClasses = wrapper.find('[data-testid="toggle-label"]').classes();
161
- return hasGlSrOnlyClass
162
- ? expect(cssClasses).toContain('gl-sr-only')
163
- : expect(cssClasses).not.toContain('gl-sr-only');
164
- });
165
-
166
- it('has accessible name for the button', () => {
167
- expect(findButton().attributes('aria-labelledby')).toBeDefined();
168
- });
169
-
170
- it(`${showsHelpText ? 'shows' : 'does not show'} the help text`, () => {
171
- expect(findHelpElement().exists()).toBe(showsHelpText);
172
- });
173
-
174
- it(`${showsDescription ? 'shows' : 'does not show'} the description`, () => {
175
- expect(findDescriptionElement().exists()).toBe(showsDescription);
176
- });
177
- }
178
- );
141
+ state | labelPosition | hasGlSrOnlyClass | flexDirection
142
+ ${'top'} | ${toggleLabelPosition.top} | ${false} | ${'gl-flex-direction-column'}
143
+ ${'left'} | ${toggleLabelPosition.left} | ${false} | ${'gl-toggle-label-inline'}
144
+ ${'hidden'} | ${toggleLabelPosition.hidden} | ${true} | ${'gl-flex-direction-column'}
145
+ `('when $state', ({ labelPosition, hasGlSrOnlyClass, flexDirection }) => {
146
+ beforeEach(() => {
147
+ createWrapper({ labelPosition });
148
+ });
149
+
150
+ it(`${flexDirection} class is added to the label`, () => {
151
+ const cssClasses = wrapper.find('[data-testid="toggle-wrapper"]').classes();
152
+
153
+ return expect(cssClasses).toContain(flexDirection);
154
+ });
155
+
156
+ it(`${hasGlSrOnlyClass ? 'adds' : 'does not add'} 'gl-sr-only' class to the label`, () => {
157
+ const cssClasses = wrapper.find('[data-testid="toggle-label"]').classes();
158
+ return hasGlSrOnlyClass
159
+ ? expect(cssClasses).toContain('gl-sr-only')
160
+ : expect(cssClasses).not.toContain('gl-sr-only');
161
+ });
162
+
163
+ it('has accessible name for the button', () => {
164
+ expect(findButton().attributes('aria-labelledby')).toBeDefined();
165
+ });
166
+ });
179
167
  });
180
168
  });
@@ -67,12 +67,6 @@ LabelPositionLeft.args = generateProps({
67
67
  labelPosition: 'left',
68
68
  });
69
69
 
70
- export const LabelPositionBlock = Template.bind({});
71
- LabelPositionBlock.args = generateProps({
72
- labelPosition: 'block',
73
- description: withDescription,
74
- });
75
-
76
70
  export default {
77
71
  title: 'base/toggle',
78
72
  component: GlToggle,
@@ -90,42 +90,19 @@ export default {
90
90
  };
91
91
  },
92
92
  computed: {
93
- layoutAllowsDescription() {
94
- return this.isVerticalLayout || this.isBlockLayout;
95
- },
96
93
  shouldRenderDescription() {
97
- return (
98
- Boolean(this.$scopedSlots.description || this.description) && this.layoutAllowsDescription
99
- );
100
- },
101
- labelIsSrOnly() {
102
- return this.labelPosition === 'hidden';
103
- },
104
- layoutAllowsHelp() {
105
- return this.isVerticalLayout || this.isBlockLayout;
94
+ // eslint-disable-next-line @gitlab/vue-prefer-dollar-scopedslots
95
+ return Boolean(this.$scopedSlots.description || this.description) && this.isVerticalLayout;
106
96
  },
107
97
  shouldRenderHelp() {
108
- return Boolean(this.$scopedSlots.help || this.help) && this.layoutAllowsHelp;
109
- },
110
- labelContainerClasses() {
111
- return {
112
- 'gl-mb-3': this.isVerticalLayout && !this.labelIsSrOnly,
113
- };
114
- },
115
- labelClasses() {
116
- if (this.labelIsSrOnly) return 'gl-sr-only';
117
- return {
118
- 'gl-mb-2': this.shouldRenderDescription,
119
- 'gl-mb-3': !this.shouldRenderDescription && !this.isVerticalLayout,
120
- };
121
- },
122
- wrapperClasses() {
123
- return {
124
- 'gl-flex-direction-column': this.isVerticalLayout,
125
- 'gl-toggle-label-inline': !this.isVerticalLayout,
126
- 'is-disabled': this.disabled,
127
- 'gl-toggle-label-position-block': this.isBlockLayout,
128
- };
98
+ // eslint-disable-next-line @gitlab/vue-prefer-dollar-scopedslots
99
+ return Boolean(this.$slots.help || this.help) && this.isVerticalLayout;
100
+ },
101
+ toggleClasses() {
102
+ return [
103
+ { 'gl-sr-only': this.labelPosition === 'hidden' },
104
+ this.shouldRenderDescription ? 'gl-mb-2' : 'gl-mb-3',
105
+ ];
129
106
  },
130
107
  icon() {
131
108
  return this.value ? 'mobile-issue-close' : 'close';
@@ -139,9 +116,6 @@ export default {
139
116
  isVerticalLayout() {
140
117
  return this.labelPosition === 'top' || this.labelPosition === 'hidden';
141
118
  },
142
- isBlockLayout() {
143
- return this.labelPosition === 'block';
144
- },
145
119
  },
146
120
 
147
121
  beforeCreate() {
@@ -168,49 +142,54 @@ export default {
168
142
  <template>
169
143
  <div
170
144
  class="gl-toggle-wrapper gl-display-flex gl-mb-0"
171
- :class="wrapperClasses"
145
+ :class="{
146
+ 'gl-flex-direction-column': isVerticalLayout,
147
+ 'gl-toggle-label-inline': !isVerticalLayout,
148
+ 'is-disabled': disabled,
149
+ }"
172
150
  data-testid="toggle-wrapper"
173
151
  >
174
- <span :class="labelContainerClasses" class="gl-toggle-label-container">
175
- <span :id="labelId" :class="labelClasses" class="gl-toggle-label" data-testid="toggle-label">
176
- <!-- @slot The toggle's label. -->
177
- <slot name="label">{{ label }}</slot>
178
- </span>
179
- <span
180
- v-if="shouldRenderDescription"
181
- class="gl-description-label"
182
- data-testid="toggle-description"
183
- >
184
- <!-- @slot A description text to be shown below the label. -->
185
- <slot name="description">{{ description }}</slot>
186
- </span>
152
+ <span
153
+ :id="labelId"
154
+ :class="toggleClasses"
155
+ class="gl-toggle-label gl-flex-shrink-0"
156
+ data-testid="toggle-label"
157
+ >
158
+ <!-- @slot The toggle's label. -->
159
+ <slot name="label">{{ label }}</slot>
160
+ </span>
161
+ <span
162
+ v-if="shouldRenderDescription"
163
+ class="gl-description-label gl-mb-3"
164
+ data-testid="toggle-description"
165
+ >
166
+ <!-- @slot A description text to be shown below the label. -->
167
+ <slot name="description">{{ description }}</slot>
187
168
  </span>
188
- <span class="gl-toggle-switch-container">
189
- <input v-if="name" :name="name" :value="value" type="hidden" />
190
- <button
191
- role="switch"
192
- :aria-checked="isChecked"
193
- :aria-labelledby="labelId"
194
- :aria-describedby="helpId"
195
- :aria-disabled="disabled"
196
- :class="{
197
- 'gl-toggle': true,
198
- 'is-checked': value,
199
- 'is-disabled': disabled,
200
- }"
201
- class="gl-flex-shrink-0"
202
- type="button"
203
- @click.prevent="toggleFeature"
204
- >
205
- <gl-loading-icon v-if="isLoading" color="light" class="toggle-loading" />
206
- <span v-else :class="{ 'toggle-icon': true, disabled: disabled }">
207
- <gl-icon :name="icon" :size="16" />
208
- </span>
209
- </button>
210
- <span v-if="shouldRenderHelp" :id="helpId" class="gl-help-label" data-testid="toggle-help">
211
- <!-- @slot A help text to be shown below the toggle. -->
212
- <slot name="help">{{ help }}</slot>
169
+ <input v-if="name" :name="name" :value="value" type="hidden" />
170
+ <button
171
+ role="switch"
172
+ :aria-checked="isChecked"
173
+ :aria-labelledby="labelId"
174
+ :aria-describedby="helpId"
175
+ :aria-disabled="disabled"
176
+ :class="{
177
+ 'gl-toggle': true,
178
+ 'is-checked': value,
179
+ 'is-disabled': disabled,
180
+ }"
181
+ class="gl-flex-shrink-0"
182
+ type="button"
183
+ @click.prevent="toggleFeature"
184
+ >
185
+ <gl-loading-icon v-if="isLoading" color="light" class="toggle-loading" />
186
+ <span v-else :class="{ 'toggle-icon': true, disabled: disabled }">
187
+ <gl-icon :name="icon" :size="16" />
213
188
  </span>
189
+ </button>
190
+ <span v-if="shouldRenderHelp" :id="helpId" class="gl-help-label" data-testid="toggle-help">
191
+ <!-- @slot A help text to be shown below the toggle. -->
192
+ <slot name="help">{{ help }}</slot>
214
193
  </span>
215
194
  </div>
216
195
  </template>
@@ -297,7 +297,6 @@ export const formInputSizes = {
297
297
  export const toggleLabelPosition = {
298
298
  hidden: 'hidden',
299
299
  left: 'left',
300
- block: 'block',
301
300
  top: 'top',
302
301
  };
303
302