@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.
- package/CHANGELOG.md +14 -0
- package/dist/components/base/badge/badge.js +12 -1
- package/dist/components/base/filtered_search/filtered_search_term.js +6 -3
- package/dist/components/base/filtered_search/filtered_search_token.js +8 -5
- package/dist/index.css +1 -1
- package/dist/index.css.map +1 -1
- package/dist/tokens/css/tokens.css +1 -1
- package/dist/tokens/css/tokens.dark.css +1 -1
- package/dist/tokens/js/tokens.dark.js +1 -1
- package/dist/tokens/js/tokens.js +1 -1
- package/dist/tokens/scss/_tokens.dark.scss +1 -1
- package/dist/tokens/scss/_tokens.scss +1 -1
- package/package.json +2 -2
- package/src/components/base/badge/badge.scss +40 -3
- package/src/components/base/badge/badge.spec.js +11 -3
- package/src/components/base/badge/badge.stories.js +48 -0
- package/src/components/base/badge/badge.vue +20 -8
- package/src/components/base/filtered_search/filtered_search.spec.js +1 -1
- package/src/components/base/filtered_search/filtered_search_term.vue +7 -3
- package/src/components/base/filtered_search/filtered_search_token.spec.js +1 -0
- package/src/components/base/filtered_search/filtered_search_token.vue +10 -5
- package/src/directives/outside/outside.md +26 -0
package/dist/tokens/js/tokens.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gitlab/ui",
|
|
3
|
-
"version": "71.
|
|
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.
|
|
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-
|
|
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
|
-
|
|
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
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
:
|
|
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('
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
316
|
+
stopMousedownOnCloseButton(event) {
|
|
314
317
|
if (event.target.closest(TOKEN_CLOSE_SELECTOR)) {
|
|
315
|
-
event
|
|
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
|