@gitlab/ui 73.0.0 → 73.1.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/experimental/duo/chat/duo_chat.js +9 -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/dist/utility_classes.css +1 -1
- package/dist/utility_classes.css.map +1 -1
- package/dist/utils/play_utils.js +11 -0
- package/package.json +4 -1
- package/src/components/base/filtered_search/filtered_search.stories.js +10 -3
- package/src/components/base/filtered_search/filtered_search_suggestion_list.stories.js +6 -3
- package/src/components/base/filtered_search/filtered_search_term.stories.js +2 -3
- package/src/components/base/filtered_search/filtered_search_token.stories.js +5 -20
- package/src/components/base/filtered_search/filtered_search_token_segment.stories.js +3 -6
- package/src/components/base/form/form_combobox/form_combobox.stories.js +23 -9
- package/src/components/base/sorting/sorting.stories.js +8 -3
- package/src/components/base/toast/toast.stories.js +12 -9
- package/src/components/base/token_selector/token_selector.stories.js +8 -3
- package/src/components/base/tooltip/tooltip.stories.js +13 -3
- package/src/components/experimental/duo/chat/duo_chat.spec.js +13 -0
- package/src/components/experimental/duo/chat/duo_chat.stories.js +6 -1
- package/src/components/experimental/duo/chat/duo_chat.vue +13 -1
- package/src/components/utilities/animated_number/animated_number.stories.js +0 -13
- package/src/scss/utilities.scss +2 -2
- package/src/scss/utility-mixins/typography.scss +1 -1
- package/src/utils/play_utils.js +9 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gitlab/ui",
|
|
3
|
-
"version": "73.
|
|
3
|
+
"version": "73.1.0",
|
|
4
4
|
"description": "GitLab UI Components",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -107,9 +107,12 @@
|
|
|
107
107
|
"@storybook/addon-a11y": "7.6.10",
|
|
108
108
|
"@storybook/addon-docs": "7.6.10",
|
|
109
109
|
"@storybook/addon-essentials": "7.6.10",
|
|
110
|
+
"@storybook/addon-interactions": "7.6.10",
|
|
110
111
|
"@storybook/addon-viewport": "7.6.10",
|
|
111
112
|
"@storybook/builder-webpack5": "7.6.10",
|
|
113
|
+
"@storybook/jest": "0.2.3",
|
|
112
114
|
"@storybook/test-runner": "0.16.0",
|
|
115
|
+
"@storybook/testing-library": "0.2.2",
|
|
113
116
|
"@storybook/theming": "7.6.10",
|
|
114
117
|
"@storybook/vue": "7.6.10",
|
|
115
118
|
"@storybook/vue-webpack5": "7.6.10",
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import last from 'lodash/last';
|
|
2
|
+
import { userEvent, within, waitFor } from '@storybook/testing-library';
|
|
3
|
+
import { expect } from '@storybook/jest';
|
|
2
4
|
import GlLoadingIcon from '../loading_icon/loading_icon.vue';
|
|
3
5
|
import GlIcon from '../icon/icon.vue';
|
|
4
6
|
import GlToken from '../token/token.vue';
|
|
@@ -451,9 +453,6 @@ export const WithHistoryItems = () => ({
|
|
|
451
453
|
return typeof val === 'string';
|
|
452
454
|
},
|
|
453
455
|
},
|
|
454
|
-
mounted() {
|
|
455
|
-
this.$nextTick(() => this.$el.querySelector('.gl-dropdown-toggle').click());
|
|
456
|
-
},
|
|
457
456
|
template: `
|
|
458
457
|
<div>
|
|
459
458
|
{{ value }}
|
|
@@ -471,6 +470,14 @@ export const WithHistoryItems = () => ({
|
|
|
471
470
|
</div>
|
|
472
471
|
`,
|
|
473
472
|
});
|
|
473
|
+
WithHistoryItems.play = async ({ canvasElement }) => {
|
|
474
|
+
const canvas = within(canvasElement);
|
|
475
|
+
const button = canvas.getByRole('button', { name: 'Toggle history' });
|
|
476
|
+
await userEvent.click(button);
|
|
477
|
+
await waitFor(() =>
|
|
478
|
+
expect(within(document).getByRole('menu', { name: 'Toggle history' })).toBeVisible()
|
|
479
|
+
);
|
|
480
|
+
};
|
|
474
481
|
|
|
475
482
|
export const WithFriendlyText = () => ({
|
|
476
483
|
components,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { userEvent, within } from '@storybook/testing-library';
|
|
1
2
|
import GlFilteredSearchSuggestionList from './filtered_search_suggestion_list.vue';
|
|
2
3
|
import GlFilteredSearchSuggestion from './filtered_search_suggestion.vue';
|
|
3
4
|
import { provide } from './common_story_options';
|
|
@@ -20,9 +21,6 @@ export const Default = () => ({
|
|
|
20
21
|
);
|
|
21
22
|
},
|
|
22
23
|
},
|
|
23
|
-
mounted() {
|
|
24
|
-
this.$refs.suggestions.nextItem();
|
|
25
|
-
},
|
|
26
24
|
template: `
|
|
27
25
|
<div>
|
|
28
26
|
<button @click="$refs.suggestions.prevItem()">prev</button>
|
|
@@ -36,6 +34,11 @@ export const Default = () => ({
|
|
|
36
34
|
</div>
|
|
37
35
|
`,
|
|
38
36
|
});
|
|
37
|
+
Default.play = async ({ canvasElement }) => {
|
|
38
|
+
const canvas = within(canvasElement);
|
|
39
|
+
const button = canvas.getByRole('button', { name: 'next' });
|
|
40
|
+
await userEvent.click(button);
|
|
41
|
+
};
|
|
39
42
|
|
|
40
43
|
export default {
|
|
41
44
|
title: 'base/filtered-search/suggestion-list',
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import PortalVue from 'portal-vue';
|
|
2
2
|
import Vue from 'vue';
|
|
3
|
+
import { triggerBlurEvent } from '../../../utils/play_utils';
|
|
3
4
|
import { provide } from './common_story_options';
|
|
4
5
|
import readme from './filtered_search_term.md';
|
|
5
6
|
import GlFilteredSearchTerm from './filtered_search_term.vue';
|
|
@@ -26,9 +27,6 @@ export const Default = (_args, { argTypes }) => ({
|
|
|
26
27
|
availableTokens,
|
|
27
28
|
};
|
|
28
29
|
},
|
|
29
|
-
mounted() {
|
|
30
|
-
this.$nextTick(() => document.activeElement.blur());
|
|
31
|
-
},
|
|
32
30
|
template: `
|
|
33
31
|
<div>
|
|
34
32
|
<div> {{ value.data }} </div>
|
|
@@ -47,6 +45,7 @@ export const Default = (_args, { argTypes }) => ({
|
|
|
47
45
|
`,
|
|
48
46
|
});
|
|
49
47
|
Default.args = generateProps();
|
|
48
|
+
Default.play = triggerBlurEvent;
|
|
50
49
|
|
|
51
50
|
export default {
|
|
52
51
|
title: 'base/filtered-search/term',
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import PortalVue from 'portal-vue';
|
|
2
2
|
import Vue from 'vue';
|
|
3
|
+
import { triggerBlurEvent } from '../../../utils/play_utils';
|
|
3
4
|
import GlIcon from '../icon/icon.vue';
|
|
4
5
|
import GlDatepicker from '../datepicker/datepicker.vue';
|
|
5
6
|
import { provide } from './common_story_options';
|
|
@@ -30,11 +31,6 @@ export const Default = (args, { argTypes }) => ({
|
|
|
30
31
|
},
|
|
31
32
|
};
|
|
32
33
|
},
|
|
33
|
-
mounted() {
|
|
34
|
-
this.$nextTick(() => {
|
|
35
|
-
document.activeElement.blur();
|
|
36
|
-
});
|
|
37
|
-
},
|
|
38
34
|
template: `
|
|
39
35
|
<div>
|
|
40
36
|
<div> {{ value }} </div>
|
|
@@ -58,6 +54,7 @@ export const Default = (args, { argTypes }) => ({
|
|
|
58
54
|
`,
|
|
59
55
|
});
|
|
60
56
|
Default.args = generateProps();
|
|
57
|
+
Default.play = triggerBlurEvent;
|
|
61
58
|
|
|
62
59
|
// eslint-disable-next-line no-unused-vars
|
|
63
60
|
export const WithCustomOperatorsOptions = (args, { argTypes }) => ({
|
|
@@ -80,11 +77,6 @@ export const WithCustomOperatorsOptions = (args, { argTypes }) => ({
|
|
|
80
77
|
},
|
|
81
78
|
};
|
|
82
79
|
},
|
|
83
|
-
mounted() {
|
|
84
|
-
this.$nextTick(() => {
|
|
85
|
-
document.activeElement.blur();
|
|
86
|
-
});
|
|
87
|
-
},
|
|
88
80
|
template: `
|
|
89
81
|
<div>
|
|
90
82
|
<div> {{ value }} </div>
|
|
@@ -108,6 +100,7 @@ export const WithCustomOperatorsOptions = (args, { argTypes }) => ({
|
|
|
108
100
|
`,
|
|
109
101
|
});
|
|
110
102
|
WithCustomOperatorsOptions.args = generateProps();
|
|
103
|
+
WithCustomOperatorsOptions.play = triggerBlurEvent;
|
|
111
104
|
|
|
112
105
|
// eslint-disable-next-line no-unused-vars
|
|
113
106
|
export const WithStaticOptions = (args, { argTypes }) => ({
|
|
@@ -130,11 +123,6 @@ export const WithStaticOptions = (args, { argTypes }) => ({
|
|
|
130
123
|
},
|
|
131
124
|
};
|
|
132
125
|
},
|
|
133
|
-
mounted() {
|
|
134
|
-
this.$nextTick(() => {
|
|
135
|
-
document.activeElement.blur();
|
|
136
|
-
});
|
|
137
|
-
},
|
|
138
126
|
template: `
|
|
139
127
|
<div>
|
|
140
128
|
<div> {{ value }} </div>
|
|
@@ -153,6 +141,7 @@ export const WithStaticOptions = (args, { argTypes }) => ({
|
|
|
153
141
|
`,
|
|
154
142
|
});
|
|
155
143
|
WithStaticOptions.args = generateProps();
|
|
144
|
+
WithStaticOptions.play = triggerBlurEvent;
|
|
156
145
|
|
|
157
146
|
// eslint-disable-next-line no-unused-vars
|
|
158
147
|
export const WithDataSegmentInputAttributes = (args, { argTypes }) => ({
|
|
@@ -178,11 +167,6 @@ export const WithDataSegmentInputAttributes = (args, { argTypes }) => ({
|
|
|
178
167
|
},
|
|
179
168
|
};
|
|
180
169
|
},
|
|
181
|
-
mounted() {
|
|
182
|
-
this.$nextTick(() => {
|
|
183
|
-
document.activeElement.blur();
|
|
184
|
-
});
|
|
185
|
-
},
|
|
186
170
|
template: `
|
|
187
171
|
<div>
|
|
188
172
|
<div> {{ value }} </div>
|
|
@@ -200,6 +184,7 @@ export const WithDataSegmentInputAttributes = (args, { argTypes }) => ({
|
|
|
200
184
|
`,
|
|
201
185
|
});
|
|
202
186
|
WithDataSegmentInputAttributes.args = generateProps();
|
|
187
|
+
WithDataSegmentInputAttributes.play = triggerBlurEvent;
|
|
203
188
|
|
|
204
189
|
export default {
|
|
205
190
|
title: 'base/filtered-search/token',
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import PortalVue from 'portal-vue';
|
|
2
2
|
import Vue from 'vue';
|
|
3
|
+
import { triggerBlurEvent } from '../../../utils/play_utils';
|
|
3
4
|
import GlFilteredSearchSuggestion from './filtered_search_suggestion.vue';
|
|
4
5
|
import { provide } from './common_story_options';
|
|
5
6
|
import readme from './filtered_search_token_segment.md';
|
|
@@ -38,9 +39,6 @@ export const Default = (args, { argTypes }) => ({
|
|
|
38
39
|
value: 'demo1',
|
|
39
40
|
};
|
|
40
41
|
},
|
|
41
|
-
mounted() {
|
|
42
|
-
this.$nextTick(() => document.activeElement.blur());
|
|
43
|
-
},
|
|
44
42
|
template: `
|
|
45
43
|
<div>
|
|
46
44
|
<div>v-model value: {{ value }} </div>
|
|
@@ -63,6 +61,7 @@ export const Default = (args, { argTypes }) => ({
|
|
|
63
61
|
`,
|
|
64
62
|
});
|
|
65
63
|
Default.args = generateProps();
|
|
64
|
+
Default.play = triggerBlurEvent;
|
|
66
65
|
|
|
67
66
|
// eslint-disable-next-line no-unused-vars
|
|
68
67
|
export const WithStaticOptions = (args, { argTypes }) => ({
|
|
@@ -77,9 +76,6 @@ export const WithStaticOptions = (args, { argTypes }) => ({
|
|
|
77
76
|
staticOptions,
|
|
78
77
|
};
|
|
79
78
|
},
|
|
80
|
-
mounted() {
|
|
81
|
-
this.$nextTick(() => document.activeElement.blur());
|
|
82
|
-
},
|
|
83
79
|
template: `
|
|
84
80
|
<div>
|
|
85
81
|
<div>v-model value: {{ value }} </div>
|
|
@@ -99,6 +95,7 @@ export const WithStaticOptions = (args, { argTypes }) => ({
|
|
|
99
95
|
`,
|
|
100
96
|
});
|
|
101
97
|
WithStaticOptions.args = generateProps();
|
|
98
|
+
WithStaticOptions.play = triggerBlurEvent;
|
|
102
99
|
|
|
103
100
|
export default {
|
|
104
101
|
title: 'base/filtered-search/token-segment',
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { userEvent, within, waitFor } from '@storybook/testing-library';
|
|
2
|
+
import { expect } from '@storybook/jest';
|
|
1
3
|
import { makeContainer } from '../../../../utils/story_decorators/container';
|
|
2
4
|
import { stringTokenList, labelText, objectTokenList, actionsList } from './constants';
|
|
3
5
|
import readme from './form_combobox.md';
|
|
@@ -41,12 +43,9 @@ Default.args = generateProps();
|
|
|
41
43
|
export const WithObjectValue = (args, { argTypes }) => ({
|
|
42
44
|
components: { GlFormCombobox },
|
|
43
45
|
props: Object.keys(argTypes),
|
|
44
|
-
mounted() {
|
|
45
|
-
this.$nextTick(() => this.$refs.combobox.openSuggestions(objectTokenList));
|
|
46
|
-
},
|
|
47
46
|
data: () => {
|
|
48
47
|
return {
|
|
49
|
-
value: '
|
|
48
|
+
value: '',
|
|
50
49
|
};
|
|
51
50
|
},
|
|
52
51
|
template: `
|
|
@@ -68,25 +67,40 @@ export const WithObjectValue = (args, { argTypes }) => ({
|
|
|
68
67
|
});
|
|
69
68
|
WithObjectValue.args = generateProps({ tokenList: objectTokenList, matchValueToAttr: 'title' });
|
|
70
69
|
WithObjectValue.decorators = [makeContainer({ height: '370px' })];
|
|
70
|
+
WithObjectValue.play = async ({ canvasElement }) => {
|
|
71
|
+
const canvas = within(canvasElement);
|
|
72
|
+
const searchbox = canvas.getByRole('searchbox');
|
|
73
|
+
userEvent.type(searchbox, 'g');
|
|
74
|
+
|
|
75
|
+
await waitFor(() =>
|
|
76
|
+
expect(within(document).getByRole('menuitem', { name: '1 giraffe' })).toBeVisible()
|
|
77
|
+
);
|
|
78
|
+
};
|
|
71
79
|
|
|
72
80
|
export const WithActions = (args, { argTypes }) => ({
|
|
73
81
|
components: { GlFormCombobox },
|
|
74
82
|
props: Object.keys(argTypes),
|
|
75
|
-
|
|
76
|
-
this.$nextTick(() => this.$refs.combobox.openSuggestions(['dog']));
|
|
77
|
-
},
|
|
83
|
+
template,
|
|
78
84
|
data: () => {
|
|
79
85
|
return {
|
|
80
|
-
value: '
|
|
86
|
+
value: '',
|
|
81
87
|
};
|
|
82
88
|
},
|
|
83
|
-
template,
|
|
84
89
|
});
|
|
85
90
|
WithActions.args = generateProps({
|
|
86
91
|
tokenList: stringTokenList,
|
|
87
92
|
actionList: actionsList,
|
|
88
93
|
});
|
|
89
94
|
WithActions.decorators = [makeContainer({ height: '180px' })];
|
|
95
|
+
WithActions.play = async ({ canvasElement }) => {
|
|
96
|
+
const canvas = within(canvasElement);
|
|
97
|
+
const searchbox = canvas.getByRole('searchbox');
|
|
98
|
+
userEvent.type(searchbox, 'dog');
|
|
99
|
+
|
|
100
|
+
await waitFor(() =>
|
|
101
|
+
expect(within(document).getByRole('menuitem', { name: 'dog' })).toBeVisible()
|
|
102
|
+
);
|
|
103
|
+
};
|
|
90
104
|
|
|
91
105
|
export default {
|
|
92
106
|
title: 'base/form/form-combobox',
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { userEvent, within, waitFor } from '@storybook/testing-library';
|
|
2
|
+
import { expect } from '@storybook/jest';
|
|
1
3
|
import { makeContainer } from '../../../utils/story_decorators/container';
|
|
2
4
|
import GlSorting from './sorting.vue';
|
|
3
5
|
import readme from './sorting.md';
|
|
@@ -44,9 +46,6 @@ const template = `
|
|
|
44
46
|
const Template = (args) => ({
|
|
45
47
|
components,
|
|
46
48
|
props: Object.keys(args),
|
|
47
|
-
mounted() {
|
|
48
|
-
this.$nextTick(() => this.$el.querySelector('button').click());
|
|
49
|
-
},
|
|
50
49
|
template,
|
|
51
50
|
});
|
|
52
51
|
|
|
@@ -72,6 +71,12 @@ Object.assign(Default, {
|
|
|
72
71
|
}),
|
|
73
72
|
parameters: {},
|
|
74
73
|
});
|
|
74
|
+
Default.play = async ({ canvasElement }) => {
|
|
75
|
+
const canvas = within(canvasElement);
|
|
76
|
+
const button = canvas.getByTestId('base-dropdown-toggle');
|
|
77
|
+
await userEvent.click(button);
|
|
78
|
+
await waitFor(() => expect(canvas.getByRole('listbox')).toBeVisible());
|
|
79
|
+
};
|
|
75
80
|
|
|
76
81
|
export default {
|
|
77
82
|
title: 'base/sorting',
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { userEvent, within, waitFor } from '@storybook/testing-library';
|
|
2
|
+
import { expect } from '@storybook/jest';
|
|
1
3
|
import Vue from 'vue';
|
|
2
4
|
import GlButton from '../button/button.vue';
|
|
3
5
|
import GlToast from './toast';
|
|
@@ -7,6 +9,13 @@ Vue.use(GlToast);
|
|
|
7
9
|
|
|
8
10
|
const components = { GlToast, GlButton };
|
|
9
11
|
|
|
12
|
+
const play = async ({ canvasElement }) => {
|
|
13
|
+
const canvas = within(canvasElement);
|
|
14
|
+
const button = canvas.getByRole('button');
|
|
15
|
+
await userEvent.click(button);
|
|
16
|
+
await waitFor(() => expect(within(document).getByRole('status')).toBeVisible());
|
|
17
|
+
};
|
|
18
|
+
|
|
10
19
|
const Template = (args, { argTypes }) => ({
|
|
11
20
|
props: Object.keys(argTypes),
|
|
12
21
|
components,
|
|
@@ -19,12 +28,10 @@ const Template = (args, { argTypes }) => ({
|
|
|
19
28
|
this.$toast.show('This is the default toast.');
|
|
20
29
|
},
|
|
21
30
|
},
|
|
22
|
-
mounted() {
|
|
23
|
-
this.showToast();
|
|
24
|
-
},
|
|
25
31
|
});
|
|
26
32
|
|
|
27
33
|
export const Default = Template.bind({});
|
|
34
|
+
Default.play = play;
|
|
28
35
|
|
|
29
36
|
export const WithActions = () => ({
|
|
30
37
|
components,
|
|
@@ -42,10 +49,8 @@ export const WithActions = () => ({
|
|
|
42
49
|
});
|
|
43
50
|
},
|
|
44
51
|
},
|
|
45
|
-
mounted() {
|
|
46
|
-
this.showToast();
|
|
47
|
-
},
|
|
48
52
|
});
|
|
53
|
+
WithActions.play = play;
|
|
49
54
|
|
|
50
55
|
export const WithLongContent = () => ({
|
|
51
56
|
components,
|
|
@@ -66,10 +71,8 @@ export const WithLongContent = () => ({
|
|
|
66
71
|
);
|
|
67
72
|
},
|
|
68
73
|
},
|
|
69
|
-
mounted() {
|
|
70
|
-
this.showToast();
|
|
71
|
-
},
|
|
72
74
|
});
|
|
75
|
+
WithLongContent.play = play;
|
|
73
76
|
|
|
74
77
|
export default {
|
|
75
78
|
title: 'base/toast',
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { userEvent, within, waitFor } from '@storybook/testing-library';
|
|
2
|
+
import { expect } from '@storybook/jest';
|
|
1
3
|
import readme from './token_selector.md';
|
|
2
4
|
import GlTokenSelector from './token_selector.vue';
|
|
3
5
|
|
|
@@ -45,9 +47,6 @@ const Template = (args, { argTypes }) => ({
|
|
|
45
47
|
components: { GlTokenSelector },
|
|
46
48
|
props: Object.keys(argTypes),
|
|
47
49
|
template,
|
|
48
|
-
mounted() {
|
|
49
|
-
document.querySelector('.gl-token-selector input[type="text"]').focus();
|
|
50
|
-
},
|
|
51
50
|
data() {
|
|
52
51
|
return {
|
|
53
52
|
filteredDropdownItems: [],
|
|
@@ -90,6 +89,12 @@ const Template = (args, { argTypes }) => ({
|
|
|
90
89
|
export const Default = Template.bind({});
|
|
91
90
|
Default.tags = ['skip-visual-test'];
|
|
92
91
|
Default.args = generateProps();
|
|
92
|
+
Default.play = async ({ canvasElement }) => {
|
|
93
|
+
const canvas = within(canvasElement);
|
|
94
|
+
const button = canvas.getByRole('textbox');
|
|
95
|
+
await userEvent.click(button);
|
|
96
|
+
await waitFor(() => expect(canvas.getByRole('menu')).toBeVisible());
|
|
97
|
+
};
|
|
93
98
|
|
|
94
99
|
export default {
|
|
95
100
|
title: 'base/token_selector',
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { userEvent, within, waitFor } from '@storybook/testing-library';
|
|
2
|
+
import { expect } from '@storybook/jest';
|
|
1
3
|
import { GlTooltipDirective } from '../../../directives/tooltip';
|
|
2
4
|
import GlButton from '../button/button.vue';
|
|
3
5
|
import GlTooltip from './tooltip.vue';
|
|
@@ -19,31 +21,39 @@ function makeTooltip(modifier = '') {
|
|
|
19
21
|
</gl-button>
|
|
20
22
|
</div>
|
|
21
23
|
`,
|
|
22
|
-
mounted() {
|
|
23
|
-
this.$nextTick(() => this.$el.querySelector('button').focus());
|
|
24
|
-
},
|
|
25
24
|
};
|
|
26
25
|
}
|
|
27
26
|
|
|
27
|
+
const play = async ({ canvasElement }) => {
|
|
28
|
+
const canvas = within(canvasElement);
|
|
29
|
+
const button = canvas.getByRole('button');
|
|
30
|
+
await userEvent.click(button);
|
|
31
|
+
await waitFor(() => expect(within(document).getByRole('tooltip')).toBeVisible());
|
|
32
|
+
};
|
|
33
|
+
|
|
28
34
|
export const TopDefault = (args, argTypes) => ({
|
|
29
35
|
...makeTooltip(),
|
|
30
36
|
props: Object.keys(argTypes),
|
|
31
37
|
});
|
|
38
|
+
TopDefault.play = play;
|
|
32
39
|
|
|
33
40
|
export const Right = (args, argTypes) => ({
|
|
34
41
|
...makeTooltip('.right'),
|
|
35
42
|
props: Object.keys(argTypes),
|
|
36
43
|
});
|
|
44
|
+
Right.play = play;
|
|
37
45
|
|
|
38
46
|
export const Bottom = (args, argTypes) => ({
|
|
39
47
|
...makeTooltip('.bottom'),
|
|
40
48
|
props: Object.keys(argTypes),
|
|
41
49
|
});
|
|
50
|
+
Bottom.play = play;
|
|
42
51
|
|
|
43
52
|
export const Left = (args, argTypes) => ({
|
|
44
53
|
...makeTooltip('.left'),
|
|
45
54
|
props: Object.keys(argTypes),
|
|
46
55
|
});
|
|
56
|
+
Left.play = play;
|
|
47
57
|
|
|
48
58
|
// A default export contains higher-level info about the component and the stories' settings.
|
|
49
59
|
export default {
|
|
@@ -76,6 +76,7 @@ describe('GlDuoChat', () => {
|
|
|
76
76
|
const findChatConversations = () => wrapper.findAllComponents(DuoChatConversation);
|
|
77
77
|
const findCustomLoader = () => wrapper.findComponent(DuoChatLoader);
|
|
78
78
|
const findError = () => wrapper.find('[data-testid="chat-error"]');
|
|
79
|
+
const findHeader = () => wrapper.find('[data-testid="chat-header"]');
|
|
79
80
|
const findFooter = () => wrapper.find('[data-testid="chat-footer"]');
|
|
80
81
|
const findPromptForm = () => wrapper.find('[data-testid="chat-prompt-form"]');
|
|
81
82
|
const findGeneratedByAI = () => wrapper.find('[data-testid="chat-legal-warning"]');
|
|
@@ -224,6 +225,18 @@ describe('GlDuoChat', () => {
|
|
|
224
225
|
expect(findBadge().props('type')).toBe(expectedProp);
|
|
225
226
|
}
|
|
226
227
|
);
|
|
228
|
+
|
|
229
|
+
describe('showHeader', () => {
|
|
230
|
+
it.each`
|
|
231
|
+
desc | showHeader | shouldRender
|
|
232
|
+
${'renders'} | ${undefined} | ${true}
|
|
233
|
+
${'does not render'} | ${false} | ${false}
|
|
234
|
+
${'renders'} | ${true} | ${true}
|
|
235
|
+
`('$desc the header when showHeader is "$showHeader"', ({ showHeader, shouldRender }) => {
|
|
236
|
+
createComponent({ propsData: { showHeader } });
|
|
237
|
+
expect(findHeader().exists()).toBe(shouldRender);
|
|
238
|
+
});
|
|
239
|
+
});
|
|
227
240
|
});
|
|
228
241
|
|
|
229
242
|
describe('chat', () => {
|
|
@@ -47,6 +47,7 @@ const generateProps = ({
|
|
|
47
47
|
badgeHelpPageUrl = defaultValue('badgeHelpPageUrl'),
|
|
48
48
|
badgeType = defaultValue('badgeType'),
|
|
49
49
|
toolName = defaultValue('toolName'),
|
|
50
|
+
showHeader = defaultValue('showHeader'),
|
|
50
51
|
} = {}) => ({
|
|
51
52
|
title,
|
|
52
53
|
messages,
|
|
@@ -58,6 +59,7 @@ const generateProps = ({
|
|
|
58
59
|
badgeType,
|
|
59
60
|
toolName,
|
|
60
61
|
slashCommands,
|
|
62
|
+
showHeader,
|
|
61
63
|
});
|
|
62
64
|
|
|
63
65
|
export const Default = (args, { argTypes }) => ({
|
|
@@ -78,6 +80,7 @@ export const Default = (args, { argTypes }) => ({
|
|
|
78
80
|
:badge-help-page-url="badgeHelpPageUrl"
|
|
79
81
|
:badge-type="badgeType"
|
|
80
82
|
:tool-name="toolName"
|
|
83
|
+
:show-header="showHeader"
|
|
81
84
|
/>`,
|
|
82
85
|
});
|
|
83
86
|
Default.args = generateProps({
|
|
@@ -172,6 +175,7 @@ export const Interactive = (args, { argTypes }) => ({
|
|
|
172
175
|
:badge-help-page-url="badgeHelpPageUrl"
|
|
173
176
|
:badge-type="badgeType"
|
|
174
177
|
:tool-name="toolName"
|
|
178
|
+
:show-header="showHeader"
|
|
175
179
|
@send-chat-prompt="onSendChatPrompt"
|
|
176
180
|
@chat-hidden="onChatHidden"
|
|
177
181
|
/>
|
|
@@ -197,7 +201,8 @@ export const Slots = (args, { argTypes }) => ({
|
|
|
197
201
|
:predefined-prompts="predefinedPrompts"
|
|
198
202
|
:badge-help-page-url="badgeHelpPageUrl"
|
|
199
203
|
:badge-type="badgeType"
|
|
200
|
-
:tool-name="toolName"
|
|
204
|
+
:tool-name="toolName"
|
|
205
|
+
:show-header="showHeader">
|
|
201
206
|
|
|
202
207
|
<template #hero>
|
|
203
208
|
<pre class="code-block rounded code highlight gl-border-b gl-rounded-0! gl-mb-0 gl-overflow-y-auto solarized-light" style="max-height: 20rem; overflow-y: auto;">
|
|
@@ -149,6 +149,14 @@ export default {
|
|
|
149
149
|
default: () => [],
|
|
150
150
|
validator: slashCommandsValidator,
|
|
151
151
|
},
|
|
152
|
+
/**
|
|
153
|
+
* Whether the header should be displayed.
|
|
154
|
+
*/
|
|
155
|
+
showHeader: {
|
|
156
|
+
type: Boolean,
|
|
157
|
+
required: false,
|
|
158
|
+
default: true,
|
|
159
|
+
},
|
|
152
160
|
},
|
|
153
161
|
data() {
|
|
154
162
|
return {
|
|
@@ -327,7 +335,11 @@ export default {
|
|
|
327
335
|
data-testid="chat-component"
|
|
328
336
|
@scroll="handleScrollingTrottled"
|
|
329
337
|
>
|
|
330
|
-
<header
|
|
338
|
+
<header
|
|
339
|
+
v-if="showHeader"
|
|
340
|
+
data-testid="chat-header"
|
|
341
|
+
class="gl-drawer-header gl-drawer-header-sticky gl-z-index-200 gl-p-0! gl-border-b-0"
|
|
342
|
+
>
|
|
331
343
|
<div
|
|
332
344
|
class="drawer-title gl-display-flex gl-justify-content-start gl-align-items-center gl-p-5"
|
|
333
345
|
>
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { setStoryTimeout } from '../../../utils/test_utils';
|
|
2
1
|
import readme from './animated_number.md';
|
|
3
2
|
import GlAnimatedNumber from './animated_number.vue';
|
|
4
3
|
|
|
@@ -31,26 +30,14 @@ const Template = (args, { argTypes }) => ({
|
|
|
31
30
|
template,
|
|
32
31
|
data() {
|
|
33
32
|
return {
|
|
34
|
-
isLoading: false,
|
|
35
|
-
loadTimer: null,
|
|
36
33
|
updatedNumber: this.initialNumber,
|
|
37
34
|
};
|
|
38
35
|
},
|
|
39
36
|
methods: {
|
|
40
|
-
loadView() {
|
|
41
|
-
clearTimeout(this.loadTimer);
|
|
42
|
-
this.isLoading = true;
|
|
43
|
-
this.loadTimer = setStoryTimeout(() => {
|
|
44
|
-
this.isLoading = false;
|
|
45
|
-
}, 1500);
|
|
46
|
-
},
|
|
47
37
|
updateNumber() {
|
|
48
38
|
this.updatedNumber = Math.floor(Math.random() * 100);
|
|
49
39
|
},
|
|
50
40
|
},
|
|
51
|
-
mounted() {
|
|
52
|
-
this.loadView();
|
|
53
|
-
},
|
|
54
41
|
});
|
|
55
42
|
|
|
56
43
|
export const InitialAnimate = Template.bind({});
|
package/src/scss/utilities.scss
CHANGED
|
@@ -8957,12 +8957,12 @@ $gl-animate-skeleton-loader-max-width: 64 * $grid-size;
|
|
|
8957
8957
|
margin-bottom: $gl-mb-heading !important;
|
|
8958
8958
|
}
|
|
8959
8959
|
|
|
8960
|
-
.gl-heading-
|
|
8960
|
+
.gl-heading-display{
|
|
8961
8961
|
@include gl-heading-scale-800;
|
|
8962
8962
|
margin-bottom: $gl-mb-heading-display;
|
|
8963
8963
|
}
|
|
8964
8964
|
|
|
8965
|
-
.gl-heading-
|
|
8965
|
+
.gl-heading-display\!{
|
|
8966
8966
|
@include gl-heading-scale-800;
|
|
8967
8967
|
margin-bottom: $gl-mb-heading-display !important;
|
|
8968
8968
|
}
|