@gitlab/ui 42.3.1 → 42.5.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 +21 -0
- package/dist/components/base/drawer/drawer.js +5 -1
- package/dist/components/base/label/label.js +10 -2
- package/dist/index.css +1 -1
- package/dist/index.css.map +1 -1
- package/package.json +1 -1
- package/src/components/base/drawer/drawer.scss +20 -0
- package/src/components/base/drawer/drawer.spec.js +1 -0
- package/src/components/base/drawer/drawer.stories.js +55 -13
- package/src/components/base/drawer/drawer.vue +10 -0
- package/src/components/base/label/label.scss +0 -4
- package/src/components/base/label/label.spec.js +35 -1
- package/src/components/base/label/label.stories.js +4 -0
- package/src/components/base/label/label.vue +16 -4
package/package.json
CHANGED
|
@@ -10,6 +10,8 @@ $gl-sidebar-width: 290px;
|
|
|
10
10
|
@include gl-shadow-drawer;
|
|
11
11
|
@include gl-font-base;
|
|
12
12
|
@include gl-line-height-normal;
|
|
13
|
+
@include gl-display-flex;
|
|
14
|
+
@include gl-flex-direction-column;
|
|
13
15
|
|
|
14
16
|
.gl-drawer-header-sticky {
|
|
15
17
|
@include gl-bg-white;
|
|
@@ -51,6 +53,20 @@ $gl-sidebar-width: 290px;
|
|
|
51
53
|
}
|
|
52
54
|
}
|
|
53
55
|
|
|
56
|
+
.gl-drawer-footer {
|
|
57
|
+
@include gl-border-t-solid;
|
|
58
|
+
@include gl-border-t-gray-100;
|
|
59
|
+
@include gl-border-t-1;
|
|
60
|
+
@include gl-px-6;
|
|
61
|
+
@include gl-py-5;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.gl-drawer-footer-sticky {
|
|
65
|
+
@include gl-bg-white;
|
|
66
|
+
@include gl-bottom-0;
|
|
67
|
+
@include gl-sticky;
|
|
68
|
+
}
|
|
69
|
+
|
|
54
70
|
.gl-drawer-header {
|
|
55
71
|
@include gl-border-b-solid;
|
|
56
72
|
@include gl-border-b-gray-100;
|
|
@@ -74,6 +90,10 @@ $gl-sidebar-width: 290px;
|
|
|
74
90
|
@include gl-border-none;
|
|
75
91
|
}
|
|
76
92
|
|
|
93
|
+
.gl-drawer-body {
|
|
94
|
+
@include gl-flex-grow-1;
|
|
95
|
+
}
|
|
96
|
+
|
|
77
97
|
.gl-drawer-body > * {
|
|
78
98
|
@include gl-border-b-solid;
|
|
79
99
|
@include gl-border-b-gray-100;
|
|
@@ -90,6 +90,7 @@ describe('drawer component', () => {
|
|
|
90
90
|
${'title'} | ${'.gl-drawer-title'}
|
|
91
91
|
${'header'} | ${'.gl-drawer-header'}
|
|
92
92
|
${'default'} | ${'.gl-drawer-body'}
|
|
93
|
+
${'footer'} | ${'.gl-drawer-footer'}
|
|
93
94
|
`('renders nodes when added to the $slot slot', ({ slot, parentSelector }) => {
|
|
94
95
|
mountWithOpts({
|
|
95
96
|
slots: {
|
|
@@ -4,7 +4,19 @@ import readme from './drawer.md';
|
|
|
4
4
|
|
|
5
5
|
const components = { GlDrawer, GlButton };
|
|
6
6
|
|
|
7
|
-
const
|
|
7
|
+
const generateDrawerContent = (items) =>
|
|
8
|
+
items
|
|
9
|
+
.map(
|
|
10
|
+
(str) => `
|
|
11
|
+
<div>
|
|
12
|
+
<label class="gl-font-weight-bold">${str}</label>
|
|
13
|
+
<div>None</div>
|
|
14
|
+
</div>
|
|
15
|
+
`
|
|
16
|
+
)
|
|
17
|
+
.join('');
|
|
18
|
+
|
|
19
|
+
const drawerContent = generateDrawerContent([
|
|
8
20
|
'One',
|
|
9
21
|
'Two',
|
|
10
22
|
'Three',
|
|
@@ -19,16 +31,9 @@ const drawerContent = [
|
|
|
19
31
|
'Twelve',
|
|
20
32
|
'Thirteen',
|
|
21
33
|
'Fourteen',
|
|
22
|
-
]
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
<div>
|
|
26
|
-
<label class="gl-font-weight-bold">${str}</label>
|
|
27
|
-
<div>None</div>
|
|
28
|
-
</div>
|
|
29
|
-
`
|
|
30
|
-
)
|
|
31
|
-
.join('');
|
|
34
|
+
]);
|
|
35
|
+
|
|
36
|
+
const drawerContentShortList = generateDrawerContent(['One', 'Two', 'Three']);
|
|
32
37
|
|
|
33
38
|
const createSidebarTemplate = (content) => `
|
|
34
39
|
<gl-drawer
|
|
@@ -106,6 +111,40 @@ export const WithActions = (_args, { viewMode }) => ({
|
|
|
106
111
|
});
|
|
107
112
|
WithActions.args = generateProps();
|
|
108
113
|
|
|
114
|
+
export const WithStickyFooterShortContent = (_args, { viewMode }) => ({
|
|
115
|
+
...storyOptions(viewMode),
|
|
116
|
+
template: `
|
|
117
|
+
<div>
|
|
118
|
+
<gl-button @click="toggle">Toggle Drawer</gl-button>
|
|
119
|
+
${createSidebarTemplate(`
|
|
120
|
+
<template #title>List Settings</template>
|
|
121
|
+
${drawerContentShortList}
|
|
122
|
+
<template #footer>
|
|
123
|
+
Drawer footer
|
|
124
|
+
</template>
|
|
125
|
+
`)}
|
|
126
|
+
</div>`,
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
WithStickyFooterShortContent.args = generateProps();
|
|
130
|
+
|
|
131
|
+
export const WithStickyFooter = (_args, { viewMode }) => ({
|
|
132
|
+
...storyOptions(viewMode),
|
|
133
|
+
template: `
|
|
134
|
+
<div>
|
|
135
|
+
<gl-button @click="toggle">Toggle Drawer</gl-button>
|
|
136
|
+
${createSidebarTemplate(`
|
|
137
|
+
<template #title>List Settings</template>
|
|
138
|
+
${drawerContent}
|
|
139
|
+
<template #footer>
|
|
140
|
+
Drawer footer
|
|
141
|
+
</template>
|
|
142
|
+
`)}
|
|
143
|
+
</div>`,
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
WithStickyFooter.args = generateProps();
|
|
147
|
+
|
|
109
148
|
export const SidebarVariant = (_args, { viewMode }) => ({
|
|
110
149
|
...storyOptions(viewMode),
|
|
111
150
|
template: `
|
|
@@ -128,7 +167,7 @@ SidebarVariant.args = generateProps({
|
|
|
128
167
|
variant: drawerVariants.sidebar,
|
|
129
168
|
});
|
|
130
169
|
|
|
131
|
-
export const
|
|
170
|
+
export const StickyHeaderFooter = (_args, { viewMode }) => ({
|
|
132
171
|
...storyOptions(viewMode),
|
|
133
172
|
template: `
|
|
134
173
|
<div>
|
|
@@ -136,10 +175,13 @@ export const StickyHeader = (_args, { viewMode }) => ({
|
|
|
136
175
|
${createSidebarTemplate(`
|
|
137
176
|
<template #title>List Settings</template>
|
|
138
177
|
${drawerContent}
|
|
178
|
+
<template #footer>
|
|
179
|
+
Drawer footer
|
|
180
|
+
</template>
|
|
139
181
|
`)}
|
|
140
182
|
</div>`,
|
|
141
183
|
});
|
|
142
|
-
|
|
184
|
+
StickyHeaderFooter.args = generateProps({
|
|
143
185
|
headerSticky: true,
|
|
144
186
|
});
|
|
145
187
|
|
|
@@ -56,6 +56,9 @@ export default {
|
|
|
56
56
|
zIndex: this.headerSticky ? maxZIndex : null,
|
|
57
57
|
};
|
|
58
58
|
},
|
|
59
|
+
shouldRenderFooter() {
|
|
60
|
+
return Boolean(this.$slots.footer);
|
|
61
|
+
},
|
|
59
62
|
variantClass() {
|
|
60
63
|
return `gl-drawer-${this.variant}`;
|
|
61
64
|
},
|
|
@@ -110,6 +113,13 @@ export default {
|
|
|
110
113
|
<div class="gl-drawer-body">
|
|
111
114
|
<slot></slot>
|
|
112
115
|
</div>
|
|
116
|
+
<div
|
|
117
|
+
v-if="shouldRenderFooter"
|
|
118
|
+
class="gl-drawer-footer gl-drawer-footer-sticky"
|
|
119
|
+
:style="{ zIndex }"
|
|
120
|
+
>
|
|
121
|
+
<slot name="footer"></slot>
|
|
122
|
+
</div>
|
|
113
123
|
</aside>
|
|
114
124
|
</transition>
|
|
115
125
|
</template>
|
|
@@ -36,9 +36,11 @@ describe('Label component', () => {
|
|
|
36
36
|
};
|
|
37
37
|
|
|
38
38
|
const findLink = () => wrapper.findComponent(GlLink);
|
|
39
|
+
const findContent = () => wrapper.find('.gl-label-link');
|
|
39
40
|
const findTitle = () => wrapper.find('.gl-label-text');
|
|
40
41
|
const findSubTitle = () => wrapper.find('.gl-label-text-scoped');
|
|
41
|
-
const
|
|
42
|
+
const findTooltip = () => wrapper.findComponent(GlTooltip);
|
|
43
|
+
const findTooltipText = () => findTooltip().text();
|
|
42
44
|
const findCloseButton = () => wrapper.findComponent(CloseButton);
|
|
43
45
|
|
|
44
46
|
describe('basic label', () => {
|
|
@@ -137,6 +139,22 @@ describe('Label component', () => {
|
|
|
137
139
|
expect(wrapper.emitted().close).toBeFalsy();
|
|
138
140
|
});
|
|
139
141
|
});
|
|
142
|
+
|
|
143
|
+
describe('label has no target', () => {
|
|
144
|
+
const props = { ...defaultProps, target: '' };
|
|
145
|
+
|
|
146
|
+
it('renders the label content as text', () => {
|
|
147
|
+
createComponent(props, { mountFn: mount });
|
|
148
|
+
|
|
149
|
+
expect(findContent().element.tagName.toLowerCase()).toBe('span');
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
it('does not render a link', () => {
|
|
153
|
+
createComponent(props, { mountFn: shallowMount });
|
|
154
|
+
|
|
155
|
+
expect(findLink().exists()).toBe(false);
|
|
156
|
+
});
|
|
157
|
+
});
|
|
140
158
|
});
|
|
141
159
|
|
|
142
160
|
describe('scoped label', () => {
|
|
@@ -220,5 +238,21 @@ describe('Label component', () => {
|
|
|
220
238
|
expect(wrapper.emitted().close).toBeFalsy();
|
|
221
239
|
});
|
|
222
240
|
});
|
|
241
|
+
|
|
242
|
+
describe('label has no target', () => {
|
|
243
|
+
const props = { ...defaultProps, target: '' };
|
|
244
|
+
|
|
245
|
+
it('renders the label content as text', () => {
|
|
246
|
+
createComponent(props, { mountFn: mount });
|
|
247
|
+
|
|
248
|
+
expect(findContent().element.tagName.toLowerCase()).toBe('span');
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
it('does not render a link', () => {
|
|
252
|
+
createComponent(props, { mountFn: shallowMount });
|
|
253
|
+
|
|
254
|
+
expect(findLink().exists()).toBe(false);
|
|
255
|
+
});
|
|
256
|
+
});
|
|
223
257
|
});
|
|
224
258
|
});
|
|
@@ -54,6 +54,9 @@ Scoped.args = generateProps({ title: 'scoped::label', scoped: true });
|
|
|
54
54
|
export const WithCloseButton = Template.bind({});
|
|
55
55
|
WithCloseButton.args = generateProps({ showCloseButton: true });
|
|
56
56
|
|
|
57
|
+
export const WithoutTarget = Template.bind({});
|
|
58
|
+
WithoutTarget.args = generateProps({ target: '' });
|
|
59
|
+
|
|
57
60
|
export default {
|
|
58
61
|
title: 'base/label',
|
|
59
62
|
component: GlLabel,
|
|
@@ -70,6 +73,7 @@ export default {
|
|
|
70
73
|
},
|
|
71
74
|
size: {
|
|
72
75
|
options: labelSizeOptions,
|
|
76
|
+
control: 'select',
|
|
73
77
|
},
|
|
74
78
|
tooltipPlacement: {
|
|
75
79
|
options: tooltipPlacements,
|
|
@@ -41,7 +41,7 @@ export default {
|
|
|
41
41
|
target: {
|
|
42
42
|
type: String,
|
|
43
43
|
required: false,
|
|
44
|
-
default: '
|
|
44
|
+
default: '',
|
|
45
45
|
},
|
|
46
46
|
scoped: {
|
|
47
47
|
type: Boolean,
|
|
@@ -91,6 +91,12 @@ export default {
|
|
|
91
91
|
closeIconSize() {
|
|
92
92
|
return this.size === 'sm' ? 12 : 16;
|
|
93
93
|
},
|
|
94
|
+
labelComponent() {
|
|
95
|
+
return this.target ? GlLink : 'span';
|
|
96
|
+
},
|
|
97
|
+
tooltipTarget() {
|
|
98
|
+
return this.target ? this.$refs.labelTitle.$el : this.$refs.labelTitle;
|
|
99
|
+
},
|
|
94
100
|
},
|
|
95
101
|
watch: {
|
|
96
102
|
title() {
|
|
@@ -122,14 +128,20 @@ export default {
|
|
|
122
128
|
|
|
123
129
|
<template>
|
|
124
130
|
<span class="gl-label" :class="cssClasses" :style="cssVariables" v-bind="$attrs" @click="onClick">
|
|
125
|
-
<
|
|
131
|
+
<component
|
|
132
|
+
:is="labelComponent"
|
|
133
|
+
ref="labelTitle"
|
|
134
|
+
:href="target ? target : false"
|
|
135
|
+
class="gl-label-link"
|
|
136
|
+
tabindex="0"
|
|
137
|
+
>
|
|
126
138
|
<span class="gl-label-text">
|
|
127
139
|
{{ scopedKey }}
|
|
128
140
|
</span>
|
|
129
141
|
<span v-if="scoped && scopedValue" class="gl-label-text-scoped">
|
|
130
142
|
{{ scopedValue }}
|
|
131
143
|
</span>
|
|
132
|
-
</
|
|
144
|
+
</component>
|
|
133
145
|
<close-button
|
|
134
146
|
v-if="showCloseButton"
|
|
135
147
|
class="gl-label-close gl-p-0!"
|
|
@@ -140,7 +152,7 @@ export default {
|
|
|
140
152
|
/>
|
|
141
153
|
<gl-tooltip
|
|
142
154
|
v-if="description"
|
|
143
|
-
:target="() =>
|
|
155
|
+
:target="() => tooltipTarget"
|
|
144
156
|
:placement="tooltipPlacement"
|
|
145
157
|
boundary="viewport"
|
|
146
158
|
>
|