@gitlab/ui 71.1.0 → 71.2.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.
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Do not edit directly
3
- * Generated on Fri, 24 Nov 2023 01:03:35 GMT
3
+ * Generated on Thu, 30 Nov 2023 19:25:01 GMT
4
4
  */
5
5
 
6
6
  :root {
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Do not edit directly
3
- * Generated on Fri, 24 Nov 2023 01:03:35 GMT
3
+ * Generated on Thu, 30 Nov 2023 19:25:01 GMT
4
4
  */
5
5
 
6
6
  :root.gl-dark {
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Do not edit directly
3
- * Generated on Fri, 24 Nov 2023 01:03:35 GMT
3
+ * Generated on Thu, 30 Nov 2023 19:25:01 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, 24 Nov 2023 01:03:35 GMT
3
+ * Generated on Thu, 30 Nov 2023 19:25:01 GMT
4
4
  */
5
5
 
6
6
  export const DATA_VIZ_GREEN_50 = "#ddfab7";
@@ -1,6 +1,6 @@
1
1
 
2
2
  // Do not edit directly
3
- // Generated on Fri, 24 Nov 2023 01:03:35 GMT
3
+ // Generated on Thu, 30 Nov 2023 19:25:01 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, 24 Nov 2023 01:03:35 GMT
3
+ // Generated on Thu, 30 Nov 2023 19:25:01 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": "71.1.0",
3
+ "version": "71.2.0",
4
4
  "description": "GitLab UI Components",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",
@@ -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.5.1",
125
+ "cypress": "13.6.0",
126
126
  "cypress-axe": "^1.4.0",
127
127
  "cypress-real-events": "^1.11.0",
128
128
  "dompurify": "^3.0.0",
@@ -66,23 +66,38 @@
66
66
  .gl-badge {
67
67
  @include gl-display-inline-flex;
68
68
  @include gl-align-items-center;
69
- @include gl-font-sm;
69
+ @include gl-justify-content-center;
70
70
  @include gl-font-weight-normal;
71
71
  @include gl-line-height-normal;
72
- @include gl-py-2;
73
- @include gl-px-3;
74
72
 
75
73
  &.sm {
76
74
  @include gl-py-0;
75
+ @include gl-px-3;
76
+ @include gl-gap-2;
77
+ @include gl-font-sm;
78
+
79
+ min-height: 1rem;
80
+ min-width: 1rem;
77
81
  }
78
82
 
79
83
  &.md {
80
84
  @include gl-py-2;
85
+ @include gl-px-3;
86
+ @include gl-gap-2;
87
+ @include gl-font-sm;
88
+
89
+ min-height: 1.5rem;
90
+ min-width: 1.5rem;
81
91
  }
82
92
 
83
93
  &.lg {
84
94
  @include gl-py-3;
95
+ @include gl-px-4;
96
+ @include gl-gap-2;
85
97
  @include gl-font-base;
98
+
99
+ min-height: 2rem;
100
+ min-width: 2rem;
86
101
  }
87
102
 
88
103
  .gl-badge-icon {
@@ -91,6 +106,28 @@
91
106
  @include gl-flex-shrink-0;
92
107
  @include gl-top-auto;
93
108
  }
109
+
110
+ &.gl-badge-round-icon.gl-badge-icon-only {
111
+ @include gl-px-0;
112
+ }
113
+
114
+ &.sm.gl-badge-round-icon:not(.gl-badge-icon-only) {
115
+ @include gl-pl-1;
116
+ }
117
+
118
+ &.md.gl-badge-round-icon:not(.gl-badge-icon-only) {
119
+ .gl-badge-icon.s12 {
120
+ @include gl-ml-n1;
121
+ }
122
+
123
+ .gl-badge-icon.s16 {
124
+ @include gl-ml-n2;
125
+ }
126
+ }
127
+
128
+ &.lg.gl-badge-round-icon:not(.gl-badge-icon-only) {
129
+ @include gl-pl-3;
130
+ }
94
131
  }
95
132
 
96
133
  /* Variants */
@@ -39,9 +39,7 @@ describe('badge', () => {
39
39
  });
40
40
 
41
41
  it('with correct class', () => {
42
- const icon = findIcon();
43
-
44
- expect(icon.classes('gl-mr-2')).toBe(hasSlot);
42
+ expect(wrapper.classes('gl-badge-icon-only')).toBe(!hasSlot);
45
43
  });
46
44
 
47
45
  it('with correct size', () => {
@@ -51,6 +49,16 @@ describe('badge', () => {
51
49
  });
52
50
  });
53
51
 
52
+ describe('with "roundIcon" prop', () => {
53
+ beforeEach(() => {
54
+ createComponent({ propsData: { icon: 'warning', roundIcon: true } });
55
+ });
56
+
57
+ it('has `gl-badge-round-icon` class', () => {
58
+ expect(wrapper.classes()).toContain('gl-badge-round-icon');
59
+ });
60
+ });
61
+
54
62
  describe('without "icon" prop', () => {
55
63
  const mockSlotContent = 'slot-content';
56
64
  beforeEach(() => {
@@ -27,6 +27,7 @@ const generateProps = ({
27
27
  content = 'TestBadge',
28
28
  icon = '',
29
29
  iconSize = defaultValue('iconSize'),
30
+ roundIcon = false,
30
31
  } = {}) => ({
31
32
  variant,
32
33
  size,
@@ -34,6 +35,7 @@ const generateProps = ({
34
35
  content,
35
36
  icon,
36
37
  iconSize,
38
+ roundIcon,
37
39
  });
38
40
 
39
41
  const Template = (args, { argTypes }) => ({
@@ -156,6 +158,52 @@ IconOnly.args = generateProps({
156
158
  icon: 'calendar',
157
159
  });
158
160
 
161
+ export const AllVariantsAndCategories = (args, { argTypes }) => ({
162
+ components: { GlBadge },
163
+ props: Object.keys(argTypes),
164
+ template: `
165
+ <div>
166
+ <div class="gl-display-flex gl-gap-3">
167
+ <gl-badge variant="info" size="sm" icon="terminal" iconSize="sm" />
168
+ <gl-badge variant="info" size="sm" icon="cancel" :roundIcon="true" iconSize="sm" />
169
+ <gl-badge variant="info" size="sm" icon="terminal" iconSize="sm">Small</gl-badge>
170
+ <gl-badge variant="info" size="sm" icon="cancel" :roundIcon="true" iconSize="sm">Small</gl-badge>
171
+ <gl-badge variant="info" size="sm">Small</gl-badge>
172
+ <gl-badge variant="info" size="sm">5</gl-badge>
173
+ </div>
174
+ <div class="gl-display-flex gl-gap-3 gl-mt-6">
175
+ <gl-badge variant="info" size="md" icon="terminal" iconSize="sm" />
176
+ <gl-badge variant="info" size="md" icon="cancel" :roundIcon="true" iconSize="sm" />
177
+ <gl-badge variant="info" size="md" icon="terminal" iconSize="sm">Medium</gl-badge>
178
+ <gl-badge variant="info" size="md" icon="cancel" :roundIcon="true" iconSize="sm">Medium</gl-badge>
179
+ <gl-badge variant="info" size="md">Medium</gl-badge>
180
+ </div>
181
+ <div class="gl-display-flex gl-gap-3 gl-mt-3">
182
+ <gl-badge variant="info" size="md" icon="terminal" iconSize="md" />
183
+ <gl-badge variant="info" size="md" icon="cancel" :roundIcon="true" iconSize="md" />
184
+ <gl-badge variant="info" size="md" icon="terminal" iconSize="md">Medium</gl-badge>
185
+ <gl-badge variant="info" size="md" icon="cancel" :roundIcon="true" iconSize="md">Medium</gl-badge>
186
+ <gl-badge variant="info" size="md">5</gl-badge>
187
+ </div>
188
+ <div class="gl-display-flex gl-gap-3 gl-mt-6">
189
+ <gl-badge variant="info" size="lg" icon="terminal" iconSize="md" />
190
+ <gl-badge variant="info" size="lg" icon="cancel" :roundIcon="true" iconSize="md" />
191
+ <gl-badge variant="info" size="lg" icon="terminal" iconSize="md">Large</gl-badge>
192
+ <gl-badge variant="info" size="lg" icon="cancel" :roundIcon="true" iconSize="md">Large</gl-badge>
193
+ <gl-badge variant="info" size="lg">5</gl-badge>
194
+ <gl-badge variant="info" size="lg">Large</gl-badge>
195
+ </div>
196
+ </div>
197
+ `,
198
+ });
199
+ AllVariantsAndCategories.argTypes = disableControls([
200
+ 'iconSize',
201
+ 'icon',
202
+ 'variant',
203
+ 'size',
204
+ 'roundIcon',
205
+ ]);
206
+
159
207
  export default {
160
208
  title: 'base/badge',
161
209
  component: GlBadge,
@@ -55,6 +55,14 @@ export default {
55
55
  validator: (value) => Object.keys(badgeIconSizeOptions).includes(value),
56
56
  required: false,
57
57
  },
58
+ /**
59
+ * Whether the `icon` is round. Affects padding around the icon.
60
+ */
61
+ roundIcon: {
62
+ type: Boolean,
63
+ default: false,
64
+ required: false,
65
+ },
58
66
  },
59
67
  computed: {
60
68
  hasIconOnly() {
@@ -72,14 +80,18 @@ export default {
72
80
  </script>
73
81
 
74
82
  <template>
75
- <b-badge v-bind="$attrs" :variant="variant" :class="['gl-badge', size]" :role="role" pill>
76
- <gl-icon
77
- v-if="icon"
78
- class="gl-badge-icon"
79
- :size="iconSizeComputed"
80
- :class="{ 'gl-mr-2': !hasIconOnly }"
81
- :name="icon"
82
- />
83
+ <b-badge
84
+ v-bind="$attrs"
85
+ :variant="variant"
86
+ :class="[
87
+ 'gl-badge',
88
+ size,
89
+ { 'gl-badge-icon-only': hasIconOnly, 'gl-badge-round-icon': roundIcon },
90
+ ]"
91
+ :role="role"
92
+ pill
93
+ >
94
+ <gl-icon v-if="icon" class="gl-badge-icon" :size="iconSizeComputed" :name="icon" />
83
95
  <!-- @slot The badge content to display. -->
84
96
  <slot></slot>
85
97
  </b-badge>
@@ -809,7 +809,7 @@ describe('Filtered search integration tests', () => {
809
809
  wrapper.findAllComponents(GlFilteredSearchToken).wrappers.map((cmp) => cmp.props('active'))
810
810
  ).toEqual([false, false, false]);
811
811
 
812
- await wrapper.find('.gl-token-close').trigger('mousedown');
812
+ await wrapper.find('.gl-token-close').trigger('click');
813
813
 
814
814
  expect(
815
815
  wrapper.findAllComponents(GlFilteredSearchToken).wrappers.map((cmp) => cmp.props('active'))
@@ -125,7 +125,9 @@ export default {
125
125
  },
126
126
  },
127
127
  eventListeners() {
128
- return this.viewOnly ? {} : { mousedown: this.destroyByClose };
128
+ return this.viewOnly
129
+ ? {}
130
+ : { mousedown: this.stopMousedownOnCloseButton, close: this.destroyByClose };
129
131
  },
130
132
  },
131
133
  methods: {
@@ -139,12 +141,14 @@ export default {
139
141
  */
140
142
  this.$emit('destroy', { intent: INTENT_ACTIVATE_PREVIOUS });
141
143
  },
142
- destroyByClose(event) {
144
+ stopMousedownOnCloseButton(event) {
143
145
  if (event.target.closest(TOKEN_CLOSE_SELECTOR)) {
144
146
  stopEvent(event);
145
- this.$emit('destroy');
146
147
  }
147
148
  },
149
+ destroyByClose() {
150
+ this.$emit('destroy');
151
+ },
148
152
  onComplete(type) {
149
153
  if (type === TERM_TOKEN_TYPE) {
150
154
  // We've completed this term token
@@ -274,6 +274,7 @@ describe('Filtered search token', () => {
274
274
  preventDefault: preventDefaultSpy,
275
275
  stopPropagation: stopPropagationSpy,
276
276
  });
277
+ closeWrapper.trigger('click');
277
278
 
278
279
  expect(preventDefaultSpy).toHaveBeenCalled();
279
280
  expect(stopPropagationSpy).toHaveBeenCalled();
@@ -2,6 +2,7 @@
2
2
  import cloneDeep from 'lodash/cloneDeep';
3
3
  import isEqual from 'lodash/isEqual';
4
4
  import GlToken from '../token/token.vue';
5
+ import { stopEvent } from '../../../utils/utils';
5
6
  import GlFilteredSearchTokenSegment from './filtered_search_token_segment.vue';
6
7
  import { createTerm, tokenToOption, TOKEN_CLOSE_SELECTOR } from './filtered_search_utils';
7
8
 
@@ -118,7 +119,9 @@ export default {
118
119
  },
119
120
 
120
121
  eventListeners() {
121
- return this.viewOnly ? {} : { mousedown: this.destroyByClose };
122
+ return this.viewOnly
123
+ ? {}
124
+ : { mousedown: this.stopMousedownOnCloseButton, close: this.destroyByClose };
122
125
  },
123
126
  },
124
127
  segments: {
@@ -310,13 +313,15 @@ export default {
310
313
  this.$emit('complete');
311
314
  },
312
315
 
313
- destroyByClose(event) {
316
+ stopMousedownOnCloseButton(event) {
314
317
  if (event.target.closest(TOKEN_CLOSE_SELECTOR)) {
315
- event.preventDefault();
316
- event.stopPropagation();
317
- this.$emit('destroy');
318
+ stopEvent(event);
318
319
  }
319
320
  },
321
+
322
+ destroyByClose() {
323
+ this.$emit('destroy');
324
+ },
320
325
  },
321
326
  };
322
327
  </script>
@@ -22,6 +22,32 @@ export default {
22
22
  </template>
23
23
  ```
24
24
 
25
+ ### When handler expects arguments
26
+
27
+ In case a click handler expects an arument to be passed, simple `v-outside="onClick('foo')"` will
28
+ invoke the handler instantly when mounting the component and the directive won't be active. The
29
+ simplest solution to pass the arguments to the directive is to wrap the handler into an anonumous
30
+ function.
31
+
32
+ ```html
33
+ <script>
34
+ import { GlOutsideDirective as Outside } from '@gitlab/ui';
35
+
36
+ export default {
37
+ directives: { Outside },
38
+ methods: {
39
+ onClick(foo) {
40
+ // This
41
+ },
42
+ },
43
+ };
44
+ </script>
45
+
46
+ <template>
47
+ <div v-outside="() => onClick('foo')">Click anywhere but here</div>
48
+ </template>
49
+ ```
50
+
25
51
  ## Caveats
26
52
 
27
53
  - If a click event is stopped (e.g., via `event.stopPropagation()`) before it