@gitlab/ui 66.31.1 → 66.32.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.
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Do not edit directly
3
- * Generated on Fri, 13 Oct 2023 20:03:52 GMT
3
+ * Generated on Tue, 17 Oct 2023 08:12:24 GMT
4
4
  */
5
5
 
6
6
  :root {
@@ -1,9 +1,9 @@
1
1
  /**
2
2
  * Do not edit directly
3
- * Generated on Fri, 13 Oct 2023 20:03:52 GMT
3
+ * Generated on Tue, 17 Oct 2023 08:12:24 GMT
4
4
  */
5
5
 
6
- :root {
6
+ :root.gl-dark {
7
7
  --red-950: #fff4f3;
8
8
  --red-900: #fcf1ef;
9
9
  --red-800: #fdd4cd;
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Do not edit directly
3
- * Generated on Fri, 13 Oct 2023 20:03:52 GMT
3
+ * Generated on Tue, 17 Oct 2023 08:12:24 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 Fri, 13 Oct 2023 20:03:52 GMT
3
+ * Generated on Tue, 17 Oct 2023 08:12:24 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 Fri, 13 Oct 2023 20:03:52 GMT
3
+ // Generated on Tue, 17 Oct 2023 08:12:24 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 Fri, 13 Oct 2023 20:03:52 GMT
3
+ // Generated on Tue, 17 Oct 2023 08:12:24 GMT
4
4
 
5
5
  $gl-line-height-52: 3.25rem;
6
6
  $gl-line-height-44: 2.75rem;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gitlab/ui",
3
- "version": "66.31.1",
3
+ "version": "66.32.1",
4
4
  "description": "GitLab UI Components",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",
@@ -88,12 +88,12 @@
88
88
  },
89
89
  "devDependencies": {
90
90
  "@arkweid/lefthook": "0.7.7",
91
- "@babel/core": "^7.23.0",
92
- "@babel/preset-env": "^7.22.20",
91
+ "@babel/core": "^7.23.2",
92
+ "@babel/preset-env": "^7.23.2",
93
93
  "@babel/preset-react": "^7.22.15",
94
- "@gitlab/eslint-plugin": "19.0.0",
95
- "@gitlab/fonts": "^1.2.0",
96
- "@gitlab/stylelint-config": "5.0.0",
94
+ "@gitlab/eslint-plugin": "19.2.0",
95
+ "@gitlab/fonts": "^1.3.0",
96
+ "@gitlab/stylelint-config": "5.0.1",
97
97
  "@gitlab/svgs": "3.66.0",
98
98
  "@rollup/plugin-commonjs": "^11.1.0",
99
99
  "@rollup/plugin-node-resolve": "^7.1.3",
@@ -122,7 +122,7 @@
122
122
  "babel-loader": "^8.0.5",
123
123
  "babel-plugin-require-context-hook": "^1.0.0",
124
124
  "bootstrap": "4.6.2",
125
- "cypress": "13.3.0",
125
+ "cypress": "13.3.1",
126
126
  "cypress-axe": "^1.4.0",
127
127
  "dompurify": "^3.0.0",
128
128
  "emoji-regex": "^10.0.0",
@@ -6,6 +6,7 @@ import {
6
6
  GL_DROPDOWN_FOCUS_CONTENT,
7
7
  GL_DROPDOWN_HIDDEN,
8
8
  GL_DROPDOWN_SHOWN,
9
+ GL_DROPDOWN_BEFORE_CLOSE,
9
10
  GL_DROPDOWN_CONTENTS_CLASS,
10
11
  } from '../constants';
11
12
  import { waitForAnimationFrame } from '../../../../utils/test_utils';
@@ -28,7 +29,7 @@ const DEFAULT_BTN_TOGGLE_CLASSES = [
28
29
  describe('base dropdown', () => {
29
30
  let wrapper;
30
31
 
31
- const buildWrapper = (propsData, slots = {}) => {
32
+ const buildWrapper = (propsData, slots = {}, listeners = {}) => {
32
33
  wrapper = mount(GlBaseDropdown, {
33
34
  propsData: {
34
35
  toggleId: 'dropdown-toggle-btn-1',
@@ -39,6 +40,7 @@ describe('base dropdown', () => {
39
40
  ...slots,
40
41
  },
41
42
  attachTo: document.body,
43
+ listeners,
42
44
  });
43
45
  };
44
46
 
@@ -332,6 +334,60 @@ describe('base dropdown', () => {
332
334
  });
333
335
  });
334
336
 
337
+ describe('beforeClose event', () => {
338
+ let event;
339
+
340
+ beforeEach(() => {
341
+ event = undefined;
342
+ buildWrapper(undefined, undefined, {
343
+ [GL_DROPDOWN_BEFORE_CLOSE]({ originalEvent, preventDefault }) {
344
+ event = originalEvent;
345
+ preventDefault();
346
+ },
347
+ });
348
+ });
349
+
350
+ it('should prevent closing', async () => {
351
+ const toggle = findDefaultDropdownToggle();
352
+ const menu = findDropdownMenu();
353
+
354
+ await toggle.trigger('click');
355
+
356
+ menu.element.focus();
357
+ await menu.trigger('keydown.esc');
358
+ expect(menu.classes('gl-display-block!')).toBe(true);
359
+ expect(toggle.attributes('aria-expanded')).toBeDefined();
360
+ expect(wrapper.emitted(GL_DROPDOWN_HIDDEN)).toBeUndefined();
361
+ expect(toggle.element).not.toHaveFocus();
362
+ });
363
+
364
+ it('should contain original keyboard event', async () => {
365
+ const toggle = findDefaultDropdownToggle();
366
+ const menu = findDropdownMenu();
367
+ await toggle.trigger('click');
368
+ await menu.trigger('keydown.esc');
369
+ expect(event.type).toBe('keydown');
370
+ });
371
+
372
+ it('should contain original toggle click event', async () => {
373
+ const toggle = findDefaultDropdownToggle();
374
+ await toggle.trigger('click');
375
+ await toggle.trigger('click');
376
+ expect(event.type).toBe('click');
377
+ });
378
+
379
+ it('should contain original outside click event', async () => {
380
+ const outsideElement = document.createElement('div');
381
+ document.body.appendChild(outsideElement);
382
+
383
+ const toggle = findDefaultDropdownToggle();
384
+ await toggle.trigger('click');
385
+ const click = new MouseEvent('click', { bubbles: true });
386
+ outsideElement.dispatchEvent(click);
387
+ expect(event).toBe(click);
388
+ });
389
+ });
390
+
335
391
  describe('Custom toggle', () => {
336
392
  const customToggleTestId = 'custom-toggle';
337
393
  const toggleContent = `<button data-testid="${customToggleTestId}">Custom toggle</button>`;
@@ -11,6 +11,7 @@ import {
11
11
  import {
12
12
  GL_DROPDOWN_SHOWN,
13
13
  GL_DROPDOWN_HIDDEN,
14
+ GL_DROPDOWN_BEFORE_CLOSE,
14
15
  GL_DROPDOWN_FOCUS_CONTENT,
15
16
  ENTER,
16
17
  SPACE,
@@ -202,7 +203,7 @@ export default {
202
203
  ...this.ariaAttributes,
203
204
  listeners: {
204
205
  keydown: (event) => this.onKeydown(event),
205
- click: () => this.toggle(),
206
+ click: (event) => this.toggle(event),
206
207
  },
207
208
  };
208
209
  }
@@ -212,7 +213,7 @@ export default {
212
213
  class: 'gl-new-dropdown-custom-toggle',
213
214
  listeners: {
214
215
  keydown: (event) => this.onKeydown(event),
215
- click: () => this.toggle(),
216
+ click: (event) => this.toggle(event),
216
217
  },
217
218
  };
218
219
  },
@@ -333,7 +334,17 @@ export default {
333
334
  this.observer?.disconnect();
334
335
  this.stopAutoUpdate?.();
335
336
  },
336
- async toggle() {
337
+ async toggle(event) {
338
+ if (event && this.visible) {
339
+ let prevented = false;
340
+ this.$emit(GL_DROPDOWN_BEFORE_CLOSE, {
341
+ originalEvent: event,
342
+ preventDefault() {
343
+ prevented = true;
344
+ },
345
+ });
346
+ if (prevented) return false;
347
+ }
337
348
  this.visible = !this.visible;
338
349
 
339
350
  if (this.visible) {
@@ -352,6 +363,9 @@ export default {
352
363
  this.stopFloating();
353
364
  this.$emit(GL_DROPDOWN_HIDDEN);
354
365
  }
366
+
367
+ // this is to check whether `toggle` was prevented or not
368
+ return true;
355
369
  },
356
370
  open() {
357
371
  if (this.visible) {
@@ -359,18 +373,20 @@ export default {
359
373
  }
360
374
  this.toggle();
361
375
  },
362
- close() {
376
+ close(event) {
363
377
  if (!this.visible) {
364
378
  return;
365
379
  }
366
- this.toggle();
380
+ this.toggle(event);
367
381
  },
368
- closeAndFocus() {
382
+ async closeAndFocus(event) {
369
383
  if (!this.visible) {
370
384
  return;
371
385
  }
372
- this.toggle();
373
- this.focusToggle();
386
+ const hasToggled = await this.toggle(event);
387
+ if (hasToggled) {
388
+ this.focusToggle();
389
+ }
374
390
  },
375
391
  focusToggle() {
376
392
  this.toggleElement.focus();
@@ -392,7 +408,7 @@ export default {
392
408
  }
393
409
 
394
410
  if ((code === ENTER && toggleOnEnter) || (code === SPACE && toggleOnSpace)) {
395
- this.toggle();
411
+ this.toggle(event);
396
412
  }
397
413
 
398
414
  if (code === ARROW_DOWN) {
@@ -1,6 +1,7 @@
1
1
  // base dropdown events
2
2
  export const GL_DROPDOWN_SHOWN = 'shown';
3
3
  export const GL_DROPDOWN_HIDDEN = 'hidden';
4
+ export const GL_DROPDOWN_BEFORE_CLOSE = 'beforeClose';
4
5
  export const GL_DROPDOWN_FOCUS_CONTENT = 'focusContent';
5
6
 
6
7
  // KEY Codes
@@ -38,6 +38,27 @@ The disclosure dropdown is closed by any of the following:
38
38
  - clicking anywhere outside the component
39
39
  - clicking the action or link inside the dropdown
40
40
 
41
+ Before closing, `GlDisclosureDropdown` emits a `beforeClose` event with these properties:
42
+
43
+ 1. `originalEvent` – the event that triggered closing of the dropdown
44
+ 2. `preventDefault` – a method which will prevent closing of the dropdown
45
+
46
+ An example of using this event to prevent the dropdown from closing:
47
+
48
+ ```html
49
+ <gl-disclosure-dropdown @beforeClose="$event.preventDefault()" />
50
+ ```
51
+
52
+ Note that this method will also prevent the dropdown from closing even if the trigger button is clicked.
53
+
54
+ You can use the `preventDefault` to filter out events that are causing undesired dropdown closing:
55
+
56
+ ```html
57
+ <gl-disclosure-dropdown
58
+ @beforeClose="(e) => { ignoreElement.contains(e.originalEvent.target) && e.preventDefault() }"
59
+ />
60
+ ```
61
+
41
62
  After closing, `GlDisclosureDropdown` emits a `hidden` event.
42
63
 
43
64
  ### Setting disclosure dropdown items
@@ -5,6 +5,7 @@ import GlBaseDropdown from '../base_dropdown/base_dropdown.vue';
5
5
  import {
6
6
  GL_DROPDOWN_SHOWN,
7
7
  GL_DROPDOWN_HIDDEN,
8
+ GL_DROPDOWN_BEFORE_CLOSE,
8
9
  GL_DROPDOWN_FOCUS_CONTENT,
9
10
  ARROW_DOWN,
10
11
  ARROW_UP,
@@ -100,6 +101,20 @@ describe('GlDisclosureDropdown', () => {
100
101
  });
101
102
  });
102
103
 
104
+ describe('onClose', () => {
105
+ let data;
106
+
107
+ beforeEach(() => {
108
+ buildWrapper();
109
+ data = { event: {}, preventDefault() {} };
110
+ findBaseDropdown().vm.$emit(GL_DROPDOWN_BEFORE_CLOSE, data);
111
+ });
112
+
113
+ it('should re-emit the event', () => {
114
+ expect(wrapper.emitted(GL_DROPDOWN_BEFORE_CLOSE)).toStrictEqual([[data]]);
115
+ });
116
+ });
117
+
103
118
  describe('onHide', () => {
104
119
  beforeEach(() => {
105
120
  buildWrapper();
@@ -6,6 +6,7 @@ import { stopEvent, filterVisible } from '../../../../utils/utils';
6
6
  import {
7
7
  GL_DROPDOWN_SHOWN,
8
8
  GL_DROPDOWN_HIDDEN,
9
+ GL_DROPDOWN_BEFORE_CLOSE,
9
10
  GL_DROPDOWN_FOCUS_CONTENT,
10
11
  ENTER,
11
12
  SPACE,
@@ -35,6 +36,7 @@ export default {
35
36
  events: {
36
37
  GL_DROPDOWN_SHOWN,
37
38
  GL_DROPDOWN_HIDDEN,
39
+ GL_DROPDOWN_BEFORE_CLOSE,
38
40
  GL_DROPDOWN_FOCUS_CONTENT,
39
41
  },
40
42
  components: {
@@ -250,6 +252,14 @@ export default {
250
252
  */
251
253
  this.$emit(GL_DROPDOWN_SHOWN);
252
254
  },
255
+ onBeforeClose(event) {
256
+ /**
257
+ * Emitted when dropdown is about to be closed
258
+ *
259
+ * @event beforeClose
260
+ */
261
+ this.$emit(GL_DROPDOWN_BEFORE_CLOSE, event);
262
+ },
253
263
  onHide() {
254
264
  /**
255
265
  * Emitted when dropdown is hidden
@@ -349,6 +359,7 @@ export default {
349
359
  class="gl-disclosure-dropdown"
350
360
  @[$options.events.GL_DROPDOWN_SHOWN]="onShow"
351
361
  @[$options.events.GL_DROPDOWN_HIDDEN]="onHide"
362
+ @[$options.events.GL_DROPDOWN_BEFORE_CLOSE]="onBeforeClose"
352
363
  @[$options.events.GL_DROPDOWN_FOCUS_CONTENT]="onKeydown"
353
364
  >
354
365
  <template v-if="hasCustomToggle" #toggle>
@@ -28,6 +28,16 @@ $clear-button-size: 24px;
28
28
  }
29
29
  }
30
30
 
31
+ // top container radius minus its border size to avoid the small gap between the focus ring and container
32
+ $input-focus-ring-border-radius: calc($gl-border-radius-large - $gl-border-size-1);
33
+
34
+ &.gl-listbox-topmost {
35
+ .gl-listbox-search-input {
36
+ border-top-left-radius: $input-focus-ring-border-radius;
37
+ border-top-right-radius: $input-focus-ring-border-radius;
38
+ }
39
+ }
40
+
31
41
  .gl-listbox-search-icon {
32
42
  @include gl-absolute;
33
43
  top: calc(50% - #{$search-icon-size} / 2);
@@ -809,6 +809,7 @@ export default {
809
809
  :aria-owns="listboxId"
810
810
  data-testid="listbox-search-input"
811
811
  :placeholder="searchPlaceholder"
812
+ :class="{ 'gl-listbox-topmost': !headerText }"
812
813
  @input="search"
813
814
  @keydown.enter.prevent
814
815
  @keydown="onKeydown"
@@ -13,18 +13,34 @@ Usage:
13
13
  */
14
14
  font-display: block;
15
15
  font-style: normal;
16
- font-named-instance: 'Regular'; /* stylelint-disable property-no-unknown */
16
+ /* stylelint-disable-next-line property-no-unknown */
17
+ font-named-instance: 'Regular';
17
18
  src: url('../../static/fonts/GitLabSans.woff2') format('woff2');
18
19
  }
19
20
 
21
+ @font-face {
22
+ font-family: 'GitLab Sans';
23
+ font-weight: 100 900;
24
+ /**
25
+ * Applications should use a less aggressive font-display value than this.
26
+ * This is done to make sure Storybook Previews load the font.
27
+ */
28
+ font-display: block;
29
+ font-style: italic;
30
+ /* stylelint-disable-next-line property-no-unknown */
31
+ font-named-instance: 'Regular';
32
+ src: url('../../static/fonts/GitLabSans-Italic.woff2') format('woff2');
33
+ }
34
+
20
35
  /* -------------------------------------------------------
21
36
  Monospaced font: GitLab Mono.
22
37
 
23
38
  Usage:
24
- html { font-family: 'GitLab Mono', sans-serif; }
39
+ html { font-family: 'GitLab Mono', monospace; }
25
40
  */
26
41
  @font-face {
27
42
  font-family: 'GitLab Mono';
43
+ font-weight: 100 900;
28
44
  /**
29
45
  * Applications should use a less aggressive font-display value than this.
30
46
  * This is done to make sure Storybook Previews load the font.
@@ -33,3 +49,19 @@ Usage:
33
49
  font-style: normal;
34
50
  src: url('../../static/fonts/GitLabMono.woff2') format('woff2');
35
51
  }
52
+
53
+ @font-face {
54
+ font-family: 'GitLab Mono';
55
+ font-weight: 100 900;
56
+ /**
57
+ * Applications should use a less aggressive font-display value than this.
58
+ * This is done to make sure Storybook Previews load the font.
59
+ */
60
+ font-display: block;
61
+ font-style: italic;
62
+ src: url('../../static/fonts/GitLabMono-Italic.woff2') format('woff2');
63
+ }
64
+
65
+ * {
66
+ font-synthesis: none;
67
+ }
@@ -15,6 +15,7 @@
15
15
 
16
16
  @import 'components';
17
17
 
18
+ @import '../../dist/tokens/css/tokens';
18
19
  @import 'storybook_dark_mode';
19
20
 
20
21
  /**
@@ -1,4 +1,5 @@
1
1
  @import 'variables';
2
+ @import '../../dist/tokens/css/tokens.dark';
2
3
 
3
4
  // conditional overrides for dark mode for use in storybook.
4
5
  // Because we only use application.css from gitlab (and not
@@ -15,7 +16,6 @@
15
16
  // Note that we are assigning variables with different values due to the way GitLab inverts variables in dark mode.
16
17
  // e.g. text color is usually $gray-900, but in dark mode $gray-900 variable gets inverted to $gray-50
17
18
  --gl-text-color: #{$gray-50};
18
- --gray-600: #{$gray-300};
19
19
 
20
20
  color-scheme: dark;
21
21