@gitlab/ui 38.9.0 → 38.10.2
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 +27 -0
- package/dist/components/base/filtered_search/filtered_search.js +0 -5
- package/dist/components/base/popover/popover.js +7 -1
- package/dist/components/base/toast/toast.js +5 -2
- package/dist/components/charts/tooltip/tooltip.js +7 -1
- package/dist/index.css +1 -1
- package/dist/index.css.map +1 -1
- package/dist/utility_classes.css +1 -1
- package/dist/utility_classes.css.map +1 -1
- package/package.json +1 -1
- package/src/components/base/filtered_search/filtered_search.vue +0 -5
- package/src/components/base/infinite_scroll/infinite_scroll.stories.js +37 -13
- package/src/components/base/pagination/pagination.stories.js +65 -83
- package/src/components/base/popover/popover.scss +3 -1
- package/src/components/base/popover/popover.spec.js +15 -1
- package/src/components/base/popover/popover.stories.js +1 -1
- package/src/components/base/popover/popover.vue +7 -0
- package/src/components/base/toast/toast.js +5 -2
- package/src/components/base/toast/toast.spec.js +42 -0
- package/src/components/charts/tooltip/tooltip.spec.js +42 -0
- package/src/components/charts/tooltip/tooltip.vue +13 -1
- package/src/scss/utilities.scss +32 -0
- package/src/scss/utility-mixins/color.scss +4 -0
- package/src/scss/utility-mixins/sizing.scss +12 -0
package/package.json
CHANGED
|
@@ -1,52 +1,76 @@
|
|
|
1
1
|
import { setStoryTimeout } from '../../../utils/test_utils';
|
|
2
|
-
import { GlInfiniteScroll } from '../../../index';
|
|
2
|
+
import { GlInfiniteScroll, GlLoadingIcon } from '../../../index';
|
|
3
3
|
import readme from './infinite_scroll.md';
|
|
4
4
|
|
|
5
5
|
const ITEMS_BATCH_SIZE = 20;
|
|
6
6
|
|
|
7
7
|
const template = `
|
|
8
8
|
<gl-infinite-scroll
|
|
9
|
-
:
|
|
10
|
-
:fetched-items="
|
|
11
|
-
|
|
9
|
+
:total-items="totalItems"
|
|
10
|
+
:fetched-items="localFetchedItems"
|
|
11
|
+
:max-list-height="maxListHeight"
|
|
12
|
+
@bottomReached="onBottomReached"
|
|
12
13
|
>
|
|
13
14
|
<template #items>
|
|
14
15
|
<ul class="list-group list-group-flushed list-unstyled">
|
|
15
|
-
<li v-for="item in
|
|
16
|
+
<li v-for="item in localFetchedItems" :key="item" class="list-group-item">Item #{{ item }}</li>
|
|
16
17
|
</ul>
|
|
17
18
|
</template>
|
|
18
19
|
|
|
19
|
-
<template #default>
|
|
20
|
+
<template v-if="localIsLoading" #default>
|
|
20
21
|
<div class="gl-mt-3">
|
|
21
|
-
<gl-loading-icon
|
|
22
|
-
<span v-else>{{ fetchedItems }} items loaded</span>
|
|
22
|
+
<gl-loading-icon />
|
|
23
23
|
</div>
|
|
24
24
|
</template>
|
|
25
25
|
</gl-infinite-scroll>
|
|
26
26
|
`;
|
|
27
27
|
|
|
28
|
-
const generateProps = ({
|
|
28
|
+
const generateProps = ({
|
|
29
|
+
isLoading = false,
|
|
30
|
+
totalItems = null,
|
|
31
|
+
fetchedItems = ITEMS_BATCH_SIZE,
|
|
32
|
+
maxListHeight = 285,
|
|
33
|
+
} = {}) => ({
|
|
29
34
|
isLoading,
|
|
35
|
+
totalItems,
|
|
30
36
|
fetchedItems,
|
|
37
|
+
maxListHeight,
|
|
31
38
|
});
|
|
32
39
|
|
|
33
40
|
const Template = (args, { argTypes }) => ({
|
|
34
41
|
components: {
|
|
35
42
|
GlInfiniteScroll,
|
|
43
|
+
GlLoadingIcon,
|
|
36
44
|
},
|
|
37
45
|
props: Object.keys(argTypes),
|
|
46
|
+
watch: {
|
|
47
|
+
fetchedItems: {
|
|
48
|
+
immediate: true,
|
|
49
|
+
handler(fetchedItems) {
|
|
50
|
+
this.localFetchedItems = fetchedItems;
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
isLoading: {
|
|
54
|
+
immediate: true,
|
|
55
|
+
handler(isLoading) {
|
|
56
|
+
this.localIsLoading = isLoading;
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
},
|
|
38
60
|
data() {
|
|
39
61
|
return {
|
|
40
62
|
loadTimer: null,
|
|
63
|
+
localFetchedItems: null,
|
|
64
|
+
localIsLoading: false,
|
|
41
65
|
};
|
|
42
66
|
},
|
|
43
67
|
methods: {
|
|
44
|
-
|
|
68
|
+
onBottomReached() {
|
|
45
69
|
clearTimeout(this.loadTimer);
|
|
46
|
-
this.
|
|
70
|
+
this.localIsLoading = true;
|
|
47
71
|
this.loadTimer = setStoryTimeout(() => {
|
|
48
|
-
this.
|
|
49
|
-
this.
|
|
72
|
+
this.localFetchedItems += ITEMS_BATCH_SIZE;
|
|
73
|
+
this.localIsLoading = false;
|
|
50
74
|
}, 500);
|
|
51
75
|
},
|
|
52
76
|
},
|
|
@@ -4,27 +4,51 @@ import GlPagination from './pagination.vue';
|
|
|
4
4
|
|
|
5
5
|
const components = { GlPagination };
|
|
6
6
|
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
const defaultValue = (name) => GlPagination.props[name].default;
|
|
8
|
+
|
|
9
|
+
const generateProps = ({
|
|
10
|
+
page = 3,
|
|
11
|
+
align = defaultValue('align'),
|
|
12
|
+
disabled = defaultValue('disabled'),
|
|
13
|
+
linkGen = defaultValue('linkGen'),
|
|
14
|
+
nextPage = defaultValue('nextPage'),
|
|
15
|
+
nextText = defaultValue('nextText'),
|
|
16
|
+
perPage = 10, // Existing stories/shots used this value instead of the default
|
|
17
|
+
prevPage = defaultValue('prevPage'),
|
|
18
|
+
prevText = defaultValue('prevText'),
|
|
19
|
+
totalItems = 200, // The component's default value of 0 is for compact pagination, which most stories here do not use.
|
|
11
20
|
} = {}) => ({
|
|
12
|
-
|
|
13
|
-
|
|
21
|
+
page,
|
|
22
|
+
align,
|
|
14
23
|
disabled,
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
initialPage: page,
|
|
24
|
+
linkGen,
|
|
25
|
+
nextPage,
|
|
26
|
+
nextText,
|
|
19
27
|
perPage,
|
|
28
|
+
prevPage,
|
|
29
|
+
prevText,
|
|
20
30
|
totalItems,
|
|
21
|
-
...generateBaseProps(),
|
|
22
31
|
});
|
|
23
32
|
|
|
24
|
-
const
|
|
33
|
+
const template = `
|
|
34
|
+
<gl-pagination
|
|
35
|
+
v-model="page"
|
|
36
|
+
:align="align"
|
|
37
|
+
:disabled="disabled"
|
|
38
|
+
:link-gen="linkGen"
|
|
39
|
+
:next-page="nextPage"
|
|
40
|
+
:next-text="nextText"
|
|
41
|
+
:per-page="perPage"
|
|
42
|
+
:prev-page="prevPage"
|
|
43
|
+
:prev-text="prevText"
|
|
44
|
+
:total-items="totalItems"
|
|
45
|
+
/>
|
|
46
|
+
`;
|
|
47
|
+
|
|
48
|
+
const defaults = (args) => ({
|
|
25
49
|
data() {
|
|
26
50
|
return {
|
|
27
|
-
|
|
51
|
+
currentPage: args.page,
|
|
28
52
|
alignOptions,
|
|
29
53
|
};
|
|
30
54
|
},
|
|
@@ -33,33 +57,20 @@ const defaults = {
|
|
|
33
57
|
this.page = page;
|
|
34
58
|
},
|
|
35
59
|
},
|
|
36
|
-
};
|
|
60
|
+
});
|
|
37
61
|
|
|
38
62
|
export const Default = (args, { argTypes }) => ({
|
|
39
63
|
components,
|
|
40
64
|
props: Object.keys(argTypes),
|
|
41
|
-
...defaults,
|
|
42
|
-
template
|
|
43
|
-
v-model="page"
|
|
44
|
-
:per-page="perPage"
|
|
45
|
-
:total-items="totalItems"
|
|
46
|
-
:prev-text="prevText"
|
|
47
|
-
:next-text="nextText"
|
|
48
|
-
:disabled="disabled"
|
|
49
|
-
/>`,
|
|
65
|
+
...defaults(args),
|
|
66
|
+
template,
|
|
50
67
|
});
|
|
51
|
-
Default.args =
|
|
68
|
+
Default.args = generateProps();
|
|
52
69
|
|
|
53
|
-
export const Compact = () => ({
|
|
70
|
+
export const Compact = (args, { argTypes }) => ({
|
|
54
71
|
components,
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
data() {
|
|
58
|
-
return {
|
|
59
|
-
page: 1,
|
|
60
|
-
alignOptions,
|
|
61
|
-
};
|
|
62
|
-
},
|
|
72
|
+
props: Object.keys(argTypes),
|
|
73
|
+
...defaults(args),
|
|
63
74
|
computed: {
|
|
64
75
|
prevPage() {
|
|
65
76
|
return Math.max(this.page - 1, 0);
|
|
@@ -70,72 +81,37 @@ export const Compact = () => ({
|
|
|
70
81
|
},
|
|
71
82
|
},
|
|
72
83
|
template: `
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
:prev-text="prevText"
|
|
79
|
-
:next-text="nextText"
|
|
80
|
-
:disabled="disabled"
|
|
81
|
-
:align="alignOptions.center"
|
|
82
|
-
/>
|
|
83
|
-
Page {{ page }} of 3
|
|
84
|
-
</div>`,
|
|
84
|
+
<div class="text-center gl-font-base">
|
|
85
|
+
${template}
|
|
86
|
+
Page {{ page }} of 3
|
|
87
|
+
</div>
|
|
88
|
+
`,
|
|
85
89
|
});
|
|
90
|
+
Compact.args = generateProps({ page: 1, totalItems: 0, align: alignOptions.center });
|
|
86
91
|
|
|
87
92
|
export const LinkBased = (args, { argTypes }) => ({
|
|
88
93
|
components,
|
|
89
94
|
props: Object.keys(argTypes),
|
|
90
|
-
...defaults,
|
|
91
|
-
|
|
92
|
-
linkGen(page) {
|
|
93
|
-
return `/page/${page}`;
|
|
94
|
-
},
|
|
95
|
-
},
|
|
96
|
-
template: `<gl-pagination
|
|
97
|
-
v-model="page"
|
|
98
|
-
:per-page="perPage"
|
|
99
|
-
:total-items="totalItems"
|
|
100
|
-
:prev-text="prevText"
|
|
101
|
-
:next-text="nextText"
|
|
102
|
-
:disabled="disabled"
|
|
103
|
-
:link-gen="linkGen"
|
|
104
|
-
/>`,
|
|
95
|
+
...defaults(args),
|
|
96
|
+
template,
|
|
105
97
|
});
|
|
106
|
-
LinkBased.args =
|
|
98
|
+
LinkBased.args = generateProps({ linkGen: (page) => `/page/${page}` });
|
|
107
99
|
|
|
108
100
|
export const AlignCenter = (args, { argTypes }) => ({
|
|
109
101
|
components,
|
|
110
102
|
props: Object.keys(argTypes),
|
|
111
|
-
...defaults,
|
|
112
|
-
template
|
|
113
|
-
v-model="page"
|
|
114
|
-
:per-page="perPage"
|
|
115
|
-
:total-items="totalItems"
|
|
116
|
-
:prev-text="prevText"
|
|
117
|
-
:next-text="nextText"
|
|
118
|
-
:disabled="disabled"
|
|
119
|
-
:align="alignOptions.center"
|
|
120
|
-
/>`,
|
|
103
|
+
...defaults(args),
|
|
104
|
+
template,
|
|
121
105
|
});
|
|
122
|
-
AlignCenter.args =
|
|
106
|
+
AlignCenter.args = generateProps({ align: alignOptions.center });
|
|
123
107
|
|
|
124
108
|
export const AlignRight = (args, { argTypes }) => ({
|
|
125
109
|
components,
|
|
126
110
|
props: Object.keys(argTypes),
|
|
127
|
-
...defaults,
|
|
128
|
-
template
|
|
129
|
-
v-model="page"
|
|
130
|
-
:per-page="perPage"
|
|
131
|
-
:total-items="totalItems"
|
|
132
|
-
:prev-text="prevText"
|
|
133
|
-
:next-text="nextText"
|
|
134
|
-
:disabled="disabled"
|
|
135
|
-
:align="alignOptions.right"
|
|
136
|
-
/>`,
|
|
111
|
+
...defaults(args),
|
|
112
|
+
template,
|
|
137
113
|
});
|
|
138
|
-
AlignRight.args =
|
|
114
|
+
AlignRight.args = generateProps({ align: alignOptions.right });
|
|
139
115
|
|
|
140
116
|
export default {
|
|
141
117
|
title: 'base/pagination',
|
|
@@ -148,4 +124,10 @@ export default {
|
|
|
148
124
|
},
|
|
149
125
|
},
|
|
150
126
|
},
|
|
127
|
+
argTypes: {
|
|
128
|
+
align: {
|
|
129
|
+
options: Object.values(alignOptions),
|
|
130
|
+
control: 'select',
|
|
131
|
+
},
|
|
132
|
+
},
|
|
151
133
|
};
|
|
@@ -67,10 +67,12 @@ $gl-popover-max-width: $grid-size * 35;
|
|
|
67
67
|
@include gl-font-sm;
|
|
68
68
|
@include gl-font-weight-bold;
|
|
69
69
|
@include gl-m-0;
|
|
70
|
+
@include gl-border-bottom-0;
|
|
71
|
+
@include gl-pb-0;
|
|
70
72
|
}
|
|
71
73
|
|
|
72
74
|
.popover-body {
|
|
73
|
-
@include gl-py-
|
|
75
|
+
@include gl-py-3;
|
|
74
76
|
@include gl-px-4;
|
|
75
77
|
|
|
76
78
|
> .popover-hr {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { shallowMount } from '@vue/test-utils';
|
|
2
|
-
import { tooltipActionEvents } from '../../../utils/constants';
|
|
2
|
+
import { tooltipActionEvents, popoverPlacements } from '../../../utils/constants';
|
|
3
3
|
import GlPopover from './popover.vue';
|
|
4
4
|
|
|
5
5
|
describe('GlPopover', () => {
|
|
@@ -49,6 +49,20 @@ describe('GlPopover', () => {
|
|
|
49
49
|
});
|
|
50
50
|
});
|
|
51
51
|
|
|
52
|
+
describe('placement', () => {
|
|
53
|
+
it(`uses "${popoverPlacements.top}" placement by default`, () => {
|
|
54
|
+
createWrapper();
|
|
55
|
+
|
|
56
|
+
expect(findBVPopover().props('placement')).toBe(popoverPlacements.top);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it('uses a defined placement', () => {
|
|
60
|
+
createWrapper({ placement: popoverPlacements.right });
|
|
61
|
+
|
|
62
|
+
expect(findBVPopover().props('placement')).toBe(popoverPlacements.right);
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
|
|
52
66
|
describe('close button', () => {
|
|
53
67
|
let doCloseMock;
|
|
54
68
|
|
|
@@ -26,7 +26,7 @@ const getTemplate = (id, slots = '') => `
|
|
|
26
26
|
</div>`;
|
|
27
27
|
|
|
28
28
|
const generateProps = ({
|
|
29
|
-
placement =
|
|
29
|
+
placement = defaultValue('placement'),
|
|
30
30
|
title = 'Popover',
|
|
31
31
|
triggers = defaultValue('triggers'),
|
|
32
32
|
cssClasses = defaultValue('cssClasses'),
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { BPopover } from 'bootstrap-vue';
|
|
3
3
|
import tooltipMixin from '../../mixins/tooltip_mixin';
|
|
4
4
|
import CloseButton from '../../shared_components/close_button/close_button.vue';
|
|
5
|
+
import { popoverPlacements } from '../../../utils/constants';
|
|
5
6
|
|
|
6
7
|
const popoverRefName = 'bPopover';
|
|
7
8
|
|
|
@@ -38,6 +39,11 @@ export default {
|
|
|
38
39
|
required: false,
|
|
39
40
|
default: false,
|
|
40
41
|
},
|
|
42
|
+
placement: {
|
|
43
|
+
type: String,
|
|
44
|
+
required: false,
|
|
45
|
+
default: popoverPlacements.top,
|
|
46
|
+
},
|
|
41
47
|
},
|
|
42
48
|
computed: {
|
|
43
49
|
customClass() {
|
|
@@ -66,6 +72,7 @@ export default {
|
|
|
66
72
|
:custom-class="customClass"
|
|
67
73
|
:triggers="triggers"
|
|
68
74
|
:title="title"
|
|
75
|
+
:placement="placement"
|
|
69
76
|
v-bind="$attrs"
|
|
70
77
|
v-on="$listeners"
|
|
71
78
|
>
|
|
@@ -50,11 +50,14 @@ function showToast(message, options = {}) {
|
|
|
50
50
|
const toast = { id, hide };
|
|
51
51
|
|
|
52
52
|
if (isFunction(options.onComplete)) {
|
|
53
|
-
|
|
53
|
+
const toastHiddenCallback = (e) => {
|
|
54
54
|
if (e.componentId === id) {
|
|
55
|
+
this.$root.$off('bv::toast:hidden', toastHiddenCallback);
|
|
55
56
|
options.onComplete(e);
|
|
56
57
|
}
|
|
57
|
-
}
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
this.$root.$on('bv::toast:hidden', toastHiddenCallback);
|
|
58
61
|
}
|
|
59
62
|
|
|
60
63
|
this.$bvToast.toast(message, {
|
|
@@ -27,4 +27,46 @@ describe('GlToast', () => {
|
|
|
27
27
|
hide: expect.any(Function),
|
|
28
28
|
});
|
|
29
29
|
});
|
|
30
|
+
|
|
31
|
+
describe('onComplete callback', () => {
|
|
32
|
+
let onCompleteSpy;
|
|
33
|
+
let toast;
|
|
34
|
+
|
|
35
|
+
beforeEach(() => {
|
|
36
|
+
onCompleteSpy = jest.fn();
|
|
37
|
+
|
|
38
|
+
toast = wrapper.vm.$toast.show('foo', {
|
|
39
|
+
onComplete: onCompleteSpy,
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it('calls onComplete callback only when matching toast hides', () => {
|
|
44
|
+
expect(onCompleteSpy).not.toHaveBeenCalled();
|
|
45
|
+
|
|
46
|
+
// Pretend some other toast was hidden.
|
|
47
|
+
wrapper.vm.$root.$emit('bv::toast:hidden', { componentId: 'some other toast' });
|
|
48
|
+
expect(onCompleteSpy).not.toHaveBeenCalled();
|
|
49
|
+
|
|
50
|
+
// Pretend our toast was hidden.
|
|
51
|
+
wrapper.vm.$root.$emit('bv::toast:hidden', { componentId: toast.id });
|
|
52
|
+
expect(onCompleteSpy).toHaveBeenCalledTimes(1);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it('unregisters global listener when toast is hidden', () => {
|
|
56
|
+
expect(onCompleteSpy).not.toHaveBeenCalled();
|
|
57
|
+
|
|
58
|
+
// Pretend the toast was hidden. Can't seem to do this directly in jsdom,
|
|
59
|
+
// so fake it by emitting the event we listen for.
|
|
60
|
+
const event = { componentId: toast.id };
|
|
61
|
+
wrapper.vm.$root.$emit('bv::toast:hidden', event);
|
|
62
|
+
expect(onCompleteSpy).toHaveBeenCalledTimes(1);
|
|
63
|
+
|
|
64
|
+
// This event won't fire more than once in practice, as once the toast is
|
|
65
|
+
// hidden it'll be destroyed and won't show again. This is here to
|
|
66
|
+
// indirectly test that the listener was removed when the toast is
|
|
67
|
+
// hidden the first time.
|
|
68
|
+
wrapper.vm.$root.$emit('bv::toast:hidden', event);
|
|
69
|
+
expect(onCompleteSpy).toHaveBeenCalledTimes(1);
|
|
70
|
+
});
|
|
71
|
+
});
|
|
30
72
|
});
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { shallowMount } from '@vue/test-utils';
|
|
2
|
+
import GlPopover from '../../base/popover/popover.vue';
|
|
3
|
+
import { popoverPlacements } from '../../../utils/constants';
|
|
4
|
+
import ChartTooltip from './tooltip.vue';
|
|
5
|
+
import { createMockChartInstance } from '~helpers/chart_stubs';
|
|
6
|
+
|
|
7
|
+
let mockChartInstance;
|
|
8
|
+
|
|
9
|
+
jest.mock('echarts', () => ({
|
|
10
|
+
getInstanceByDom: () => mockChartInstance,
|
|
11
|
+
}));
|
|
12
|
+
|
|
13
|
+
describe('ChartTooltip', () => {
|
|
14
|
+
let wrapper;
|
|
15
|
+
|
|
16
|
+
const findGlPopover = () => wrapper.findComponent(GlPopover);
|
|
17
|
+
|
|
18
|
+
const createWrapper = (props = {}) => {
|
|
19
|
+
mockChartInstance = createMockChartInstance();
|
|
20
|
+
wrapper = shallowMount(ChartTooltip, {
|
|
21
|
+
propsData: {
|
|
22
|
+
chart: mockChartInstance,
|
|
23
|
+
...props,
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
describe('GlPopover', () => {
|
|
29
|
+
it('is right-positioned by default', () => {
|
|
30
|
+
createWrapper();
|
|
31
|
+
|
|
32
|
+
expect(findGlPopover().props('placement')).toBe(popoverPlacements.right);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('applies passed placement if any', () => {
|
|
36
|
+
const placement = popoverPlacements.bottom;
|
|
37
|
+
createWrapper({ placement });
|
|
38
|
+
|
|
39
|
+
expect(findGlPopover().props('placement')).toBe(placement);
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
});
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import * as echarts from 'echarts';
|
|
3
3
|
import { uid } from '../../../utils/utils';
|
|
4
4
|
import GlPopover from '../../base/popover/popover.vue';
|
|
5
|
+
import { popoverPlacements } from '../../../utils/constants';
|
|
5
6
|
|
|
6
7
|
export default {
|
|
7
8
|
components: {
|
|
@@ -41,6 +42,11 @@ export default {
|
|
|
41
42
|
required: false,
|
|
42
43
|
default: null,
|
|
43
44
|
},
|
|
45
|
+
placement: {
|
|
46
|
+
type: String,
|
|
47
|
+
required: false,
|
|
48
|
+
default: popoverPlacements.right,
|
|
49
|
+
},
|
|
44
50
|
},
|
|
45
51
|
computed: {
|
|
46
52
|
containerId() {
|
|
@@ -80,7 +86,13 @@ export default {
|
|
|
80
86
|
Needs to be triggered programatically using `show` property
|
|
81
87
|
This is why `triggers` is currently set to an empty string
|
|
82
88
|
-->
|
|
83
|
-
<gl-popover
|
|
89
|
+
<gl-popover
|
|
90
|
+
v-bind="$attrs"
|
|
91
|
+
:target="containerId"
|
|
92
|
+
:container="containerId"
|
|
93
|
+
:placement="placement"
|
|
94
|
+
triggers=""
|
|
95
|
+
>
|
|
84
96
|
<template v-if="$scopedSlots.title" #title>
|
|
85
97
|
<slot name="title"></slot>
|
|
86
98
|
</template>
|
package/src/scss/utilities.scss
CHANGED
|
@@ -2433,6 +2433,14 @@
|
|
|
2433
2433
|
color: $purple-600 !important;
|
|
2434
2434
|
}
|
|
2435
2435
|
|
|
2436
|
+
.gl-text-purple-700 {
|
|
2437
|
+
color: $purple-700;
|
|
2438
|
+
}
|
|
2439
|
+
|
|
2440
|
+
.gl-text-purple-700\! {
|
|
2441
|
+
color: $purple-700 !important;
|
|
2442
|
+
}
|
|
2443
|
+
|
|
2436
2444
|
.gl-text-theme-indigo-200 {
|
|
2437
2445
|
color: $theme-indigo-200;
|
|
2438
2446
|
}
|
|
@@ -4495,6 +4503,30 @@
|
|
|
4495
4503
|
}
|
|
4496
4504
|
}
|
|
4497
4505
|
|
|
4506
|
+
.gl-md-w-half {
|
|
4507
|
+
@include gl-media-breakpoint-up(md) {
|
|
4508
|
+
width: 50%;
|
|
4509
|
+
}
|
|
4510
|
+
}
|
|
4511
|
+
|
|
4512
|
+
.gl-md-w-half\! {
|
|
4513
|
+
@include gl-media-breakpoint-up(md) {
|
|
4514
|
+
width: 50% !important;
|
|
4515
|
+
}
|
|
4516
|
+
}
|
|
4517
|
+
|
|
4518
|
+
.gl-lg-w-half {
|
|
4519
|
+
@include gl-media-breakpoint-up(lg) {
|
|
4520
|
+
width: 50%;
|
|
4521
|
+
}
|
|
4522
|
+
}
|
|
4523
|
+
|
|
4524
|
+
.gl-lg-w-half\! {
|
|
4525
|
+
@include gl-media-breakpoint-up(lg) {
|
|
4526
|
+
width: 50% !important;
|
|
4527
|
+
}
|
|
4528
|
+
}
|
|
4529
|
+
|
|
4498
4530
|
.gl-md-w-auto {
|
|
4499
4531
|
@include gl-media-breakpoint-up(md) {
|
|
4500
4532
|
width: auto;
|
|
@@ -234,6 +234,18 @@
|
|
|
234
234
|
}
|
|
235
235
|
}
|
|
236
236
|
|
|
237
|
+
@mixin gl-md-w-half {
|
|
238
|
+
@include gl-media-breakpoint-up(md) {
|
|
239
|
+
width: 50%;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
@mixin gl-lg-w-half {
|
|
244
|
+
@include gl-media-breakpoint-up(lg) {
|
|
245
|
+
width: 50%;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
237
249
|
@mixin gl-md-w-auto {
|
|
238
250
|
@include gl-media-breakpoint-up(md) {
|
|
239
251
|
width: auto;
|