@gitlab/ui 68.0.0 → 68.1.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gitlab/ui",
3
- "version": "68.0.0",
3
+ "version": "68.1.0",
4
4
  "description": "GitLab UI Components",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",
@@ -27,8 +27,11 @@ import GlIcon from '../../icon/icon.vue';
27
27
  import { OutsideDirective } from '../../../../directives/outside/outside';
28
28
  import { DEFAULT_OFFSET, FIXED_WIDTH_CLASS } from './constants';
29
29
 
30
+ export const BASE_DROPDOWN_CLASS = 'gl-new-dropdown';
31
+
30
32
  export default {
31
33
  name: 'BaseDropdown',
34
+ BASE_DROPDOWN_CLASS,
32
35
  components: {
33
36
  GlButton,
34
37
  GlIcon,
@@ -429,7 +432,7 @@ export default {
429
432
  </script>
430
433
 
431
434
  <template>
432
- <div v-outside="close" class="gl-new-dropdown" :class="{ 'gl-display-block!': block }">
435
+ <div v-outside="close" :class="[$options.BASE_DROPDOWN_CLASS, { 'gl-display-block!': block }]">
433
436
  <component
434
437
  :is="toggleComponent"
435
438
  v-bind="toggleAttributes"
@@ -2,6 +2,7 @@ import { mount } from '@vue/test-utils';
2
2
  import { autoUpdate } from '@floating-ui/dom';
3
3
  import { nextTick } from 'vue';
4
4
  import * as utils from '../../../../utils/utils';
5
+ import { useMockIntersectionObserver } from '../../../../utils/use_mock_intersection_observer';
5
6
  import GlBaseDropdown from '../base_dropdown/base_dropdown.vue';
6
7
  import {
7
8
  GL_DROPDOWN_SHOWN,
@@ -15,6 +16,7 @@ import {
15
16
  POSITION_ABSOLUTE,
16
17
  POSITION_FIXED,
17
18
  } from '../constants';
19
+ import GlCollapsibleListbox from '../listbox/listbox.vue';
18
20
  import GlDisclosureDropdown from './disclosure_dropdown.vue';
19
21
  import GlDisclosureDropdownItem from './disclosure_dropdown_item.vue';
20
22
  import GlDisclosureDropdownGroup from './disclosure_dropdown_group.vue';
@@ -33,7 +35,12 @@ describe('GlDisclosureDropdown', () => {
33
35
  const buildWrapper = (propsData, slots = {}) => {
34
36
  wrapper = mount(GlDisclosureDropdown, {
35
37
  propsData,
36
- components: { GlDisclosureDropdownItem, GlDisclosureDropdownGroup },
38
+ components: {
39
+ GlDisclosureDropdown,
40
+ GlDisclosureDropdownItem,
41
+ GlDisclosureDropdownGroup,
42
+ GlCollapsibleListbox,
43
+ },
37
44
  slots,
38
45
  attachTo: document.body,
39
46
  });
@@ -43,8 +50,9 @@ describe('GlDisclosureDropdown', () => {
43
50
  const findDisclosureContent = () => wrapper.find('[data-testid="disclosure-content"]');
44
51
  const findDisclosureItems = (root = wrapper) => root.findAllComponents(GlDisclosureDropdownItem);
45
52
  const findDisclosureGroups = () => wrapper.findAllComponents(GlDisclosureDropdownGroup);
46
- const findListItem = (index) => findDisclosureItems().at(index).findComponent(ITEM_SELECTOR);
47
- const findDropdownMenu = () => wrapper.find("[data-testid='base-dropdown-menu']");
53
+ const findListItem = (index, root = wrapper) =>
54
+ findDisclosureItems(root).at(index).findComponent(ITEM_SELECTOR);
55
+ const findDropdownMenu = (root = wrapper) => root.find("[data-testid='base-dropdown-menu']");
48
56
 
49
57
  jest.spyOn(utils, 'filterVisible').mockImplementation((items) => items);
50
58
 
@@ -402,4 +410,33 @@ describe('GlDisclosureDropdown', () => {
402
410
  expect(findDropdownMenu().classes()).not.toContain('gl-display-block!');
403
411
  });
404
412
  });
413
+
414
+ describe('nested dropdowns', () => {
415
+ useMockIntersectionObserver();
416
+
417
+ it.each`
418
+ dropdown | getClickItem
419
+ ${'gl-disclosure-dropdown'} | ${(nestedWrapper) => findListItem(0, nestedWrapper)}
420
+ ${'gl-collapsible-listbox'} | ${(nestedWrapper) => nestedWrapper.find('[data-testid="listbox-item-1"]')}
421
+ `('should only close the target $dropdown', async ({ dropdown, getClickItem }) => {
422
+ const slots = {
423
+ default: `
424
+ <${dropdown}
425
+ :items="[{ text: 'First', action: () => {}, value: '1' }]"
426
+ start-opened
427
+ data-testid="nested"
428
+ />
429
+ `,
430
+ };
431
+ buildWrapper({ startOpened: true }, slots);
432
+ const isOpened = (root) => findDropdownMenu(root).classes('gl-display-block!');
433
+ const nestedWrapper = wrapper.findComponent("[data-testid='nested']");
434
+
435
+ getClickItem(nestedWrapper).trigger('click');
436
+ await nextTick();
437
+
438
+ expect(isOpened(wrapper)).toBe(true);
439
+ expect(isOpened(nestedWrapper)).toBe(false);
440
+ });
441
+ });
405
442
  });
@@ -24,11 +24,12 @@ import {
24
24
  dropdownPlacements,
25
25
  dropdownVariantOptions,
26
26
  } from '../../../../utils/constants';
27
- import GlBaseDropdown from '../base_dropdown/base_dropdown.vue';
27
+ import GlBaseDropdown, { BASE_DROPDOWN_CLASS } from '../base_dropdown/base_dropdown.vue';
28
28
  import GlDisclosureDropdownItem, { ITEM_CLASS } from './disclosure_dropdown_item.vue';
29
29
  import GlDisclosureDropdownGroup from './disclosure_dropdown_group.vue';
30
30
  import { itemsValidator, isItem, hasOnlyListItems } from './utils';
31
31
 
32
+ export const DROPDOWN_SELECTOR = `.${BASE_DROPDOWN_CLASS}`;
32
33
  export const ITEM_SELECTOR = `.${ITEM_CLASS}`;
33
34
 
34
35
  export default {
@@ -336,7 +337,11 @@ export default {
336
337
  this.$emit('action', action);
337
338
  },
338
339
  handleAutoClose(e) {
339
- if (this.autoClose && e.target.closest(ITEM_SELECTOR)) {
340
+ if (
341
+ this.autoClose &&
342
+ e.target.closest(ITEM_SELECTOR) &&
343
+ e.target.closest(DROPDOWN_SELECTOR) === this.$refs.baseDropdown.$el
344
+ ) {
340
345
  this.closeAndFocus();
341
346
  }
342
347
  },
@@ -7504,6 +7504,16 @@ $gl-animate-skeleton-loader-max-width: 64 * $grid-size;
7504
7504
  padding-right: $gl-spacing-scale-2 !important;
7505
7505
  }
7506
7506
  }
7507
+ .gl-sm-pr-4 {
7508
+ @include gl-media-breakpoint-up(sm) {
7509
+ padding-right: $gl-spacing-scale-4;
7510
+ }
7511
+ }
7512
+ .gl-sm-pr-4\! {
7513
+ @include gl-media-breakpoint-up(sm) {
7514
+ padding-right: $gl-spacing-scale-4 !important;
7515
+ }
7516
+ }
7507
7517
  .gl-sm-pl-0 {
7508
7518
  @include gl-media-breakpoint-up(sm) {
7509
7519
  padding-left: 0;
@@ -1226,6 +1226,12 @@
1226
1226
  }
1227
1227
  }
1228
1228
 
1229
+ @mixin gl-sm-pr-4 {
1230
+ @include gl-media-breakpoint-up(sm) {
1231
+ @include gl-pr-4;
1232
+ }
1233
+ }
1234
+
1229
1235
  @mixin gl-sm-pl-0 {
1230
1236
  @include gl-media-breakpoint-up(sm) {
1231
1237
  @include gl-pl-0;