@gitlab/ui 59.5.0 → 60.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 +32 -0
- package/dist/components/base/banner/banner.js +1 -1
- package/dist/components/base/breadcrumb/breadcrumb.js +7 -5
- package/dist/components/base/new_dropdowns/base_dropdown/base_dropdown.js +7 -1
- package/dist/components/base/new_dropdowns/disclosure/disclosure_dropdown.js +10 -1
- package/dist/components/base/new_dropdowns/listbox/listbox.js +10 -1
- package/dist/index.css +2 -2
- package/dist/index.css.map +1 -1
- package/package.json +2 -2
- package/scss_to_js/scss_variables.js +2 -1
- package/scss_to_js/scss_variables.json +8 -3
- package/src/components/base/banner/banner.vue +1 -1
- package/src/components/base/breadcrumb/breadcrumb.md +14 -13
- package/src/components/base/breadcrumb/breadcrumb.scss +0 -8
- package/src/components/base/breadcrumb/breadcrumb.spec.js +16 -13
- package/src/components/base/breadcrumb/breadcrumb.stories.js +5 -9
- package/src/components/base/breadcrumb/breadcrumb.vue +15 -7
- package/src/components/base/new_dropdowns/base_dropdown/base_dropdown.spec.js +9 -0
- package/src/components/base/new_dropdowns/base_dropdown/base_dropdown.vue +6 -0
- package/src/components/base/new_dropdowns/disclosure/disclosure_dropdown.md +8 -0
- package/src/components/base/new_dropdowns/disclosure/disclosure_dropdown.spec.js +7 -0
- package/src/components/base/new_dropdowns/disclosure/disclosure_dropdown.vue +10 -0
- package/src/components/base/new_dropdowns/dropdown.scss +2 -1
- package/src/components/base/new_dropdowns/listbox/listbox.md +8 -0
- package/src/components/base/new_dropdowns/listbox/listbox.spec.js +7 -0
- package/src/components/base/new_dropdowns/listbox/listbox.stories.js +58 -1
- package/src/components/base/new_dropdowns/listbox/listbox.vue +10 -0
- package/src/scss/variables.scss +2 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gitlab/ui",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "60.1.0",
|
|
4
4
|
"description": "GitLab UI Components",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -90,7 +90,7 @@
|
|
|
90
90
|
"@gitlab/eslint-plugin": "18.3.0",
|
|
91
91
|
"@gitlab/fonts": "^1.2.0",
|
|
92
92
|
"@gitlab/stylelint-config": "4.1.0",
|
|
93
|
-
"@gitlab/svgs": "3.
|
|
93
|
+
"@gitlab/svgs": "3.38.0",
|
|
94
94
|
"@rollup/plugin-commonjs": "^11.1.0",
|
|
95
95
|
"@rollup/plugin-node-resolve": "^7.1.3",
|
|
96
96
|
"@rollup/plugin-replace": "^2.3.2",
|
|
@@ -331,7 +331,8 @@ export const glIconRadio = ''
|
|
|
331
331
|
export const defaultIconSize = '1rem'
|
|
332
332
|
export const glIconSizes = '8 12 14 16 24 32 48 72'
|
|
333
333
|
export const glDropdownWidth = '15rem'
|
|
334
|
-
export const
|
|
334
|
+
export const glNewDropdownMinWidth = '15.5rem'
|
|
335
|
+
export const glNewDropdownMaxWidth = '28.5rem'
|
|
335
336
|
export const glDropdownWidthNarrow = '10rem'
|
|
336
337
|
export const glDropdownWidthWide = '25rem'
|
|
337
338
|
export const glMaxDropdownMaxHeight = '19.5rem'
|
|
@@ -1766,9 +1766,14 @@
|
|
|
1766
1766
|
"compiledValue": "15rem"
|
|
1767
1767
|
},
|
|
1768
1768
|
{
|
|
1769
|
-
"name": "$gl-new-dropdown-width",
|
|
1770
|
-
"value": "px-to-rem(
|
|
1771
|
-
"compiledValue": "
|
|
1769
|
+
"name": "$gl-new-dropdown-min-width",
|
|
1770
|
+
"value": "px-to-rem(248px)",
|
|
1771
|
+
"compiledValue": "15.5rem"
|
|
1772
|
+
},
|
|
1773
|
+
{
|
|
1774
|
+
"name": "$gl-new-dropdown-max-width",
|
|
1775
|
+
"value": "px-to-rem(456px)",
|
|
1776
|
+
"compiledValue": "28.5rem"
|
|
1772
1777
|
},
|
|
1773
1778
|
{
|
|
1774
1779
|
"name": "$gl-dropdown-width-narrow",
|
|
@@ -95,7 +95,7 @@ export default {
|
|
|
95
95
|
body-class="gl-display-flex gl-p-0!"
|
|
96
96
|
>
|
|
97
97
|
<div v-if="svgPath" class="gl-banner-illustration">
|
|
98
|
-
<img :src="svgPath" alt=""
|
|
98
|
+
<img :src="svgPath" alt="" />
|
|
99
99
|
</div>
|
|
100
100
|
<div class="gl-banner-content">
|
|
101
101
|
<h2 class="gl-banner-title">{{ title }}</h2>
|
|
@@ -1,22 +1,23 @@
|
|
|
1
1
|
## Usage
|
|
2
2
|
|
|
3
|
-
This component
|
|
3
|
+
This component also allows for optional avatars on each item.
|
|
4
|
+
|
|
5
|
+
`avatarPath` should passed along with `text` and `href` in `items`.
|
|
6
|
+
Here is an example of how an item with an avatar should look:
|
|
4
7
|
|
|
5
8
|
**note:** the component supports passing the property `to` in the list items to enable navigation
|
|
6
9
|
through `vue-router`
|
|
7
10
|
|
|
8
11
|
### Example
|
|
9
12
|
|
|
10
|
-
```
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
</template>
|
|
21
|
-
</gl-breadcrumb>
|
|
13
|
+
```js
|
|
14
|
+
items = [
|
|
15
|
+
{
|
|
16
|
+
text: 'First item',
|
|
17
|
+
href: '#',
|
|
18
|
+
avatarPath: '/avatar.png',
|
|
19
|
+
},
|
|
20
|
+
];
|
|
21
|
+
|
|
22
|
+
<gl-breadcrumb :items="items" />
|
|
22
23
|
```
|
|
@@ -16,14 +16,6 @@ $breadcrumb-max-width: $grid-size * 16;
|
|
|
16
16
|
}
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
.gl-breadcrumb-avatar-tile {
|
|
20
|
-
@include gl-mr-2;
|
|
21
|
-
@include gl-border-1;
|
|
22
|
-
@include gl-border-solid;
|
|
23
|
-
@include gl-border-gray-a-08;
|
|
24
|
-
@include gl-rounded-base;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
19
|
// bootstrap overrides
|
|
28
20
|
.gl-breadcrumb-item {
|
|
29
21
|
@include gl-font-sm;
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { shallowMount } from '@vue/test-utils';
|
|
2
2
|
import { nextTick } from 'vue';
|
|
3
|
+
import avatarPath1 from '../../../../static/img/avatar.png';
|
|
4
|
+
import avatarPath3 from '../../../../static/img/avatar_1.png';
|
|
3
5
|
import Breadcrumb, { COLLAPSE_AT_SIZE } from './breadcrumb.vue';
|
|
4
6
|
import GlBreadcrumbItem from './breadcrumb_item.vue';
|
|
5
7
|
|
|
@@ -7,23 +9,27 @@ describe('Breadcrumb component', () => {
|
|
|
7
9
|
let wrapper;
|
|
8
10
|
|
|
9
11
|
const items = [
|
|
10
|
-
{ text: 'first_breadcrumb', href: '
|
|
12
|
+
{ text: 'first_breadcrumb', href: 'https://gitlab.com', avatarPath: avatarPath1 },
|
|
11
13
|
{
|
|
12
14
|
text: 'second_breadcrumb',
|
|
13
15
|
to: 'to_value',
|
|
14
16
|
},
|
|
15
|
-
{
|
|
17
|
+
{
|
|
18
|
+
text: 'third_breadcrumb',
|
|
19
|
+
href: 'https://about.gitlab.com',
|
|
20
|
+
avatarPath: avatarPath3,
|
|
21
|
+
},
|
|
16
22
|
];
|
|
17
23
|
|
|
18
24
|
const extraItems = [
|
|
19
|
-
{ text: 'fourth_breadcrumb', href: '
|
|
25
|
+
{ text: 'fourth_breadcrumb', href: 'https://gitlab.com' },
|
|
20
26
|
{
|
|
21
27
|
text: 'fifth_breadcrumb',
|
|
22
28
|
to: 'to_value',
|
|
23
29
|
},
|
|
24
30
|
];
|
|
25
31
|
|
|
26
|
-
const
|
|
32
|
+
const findAllAvatars = () => wrapper.findAll('[data-testid="avatar"]');
|
|
27
33
|
const findBreadcrumbItems = () => wrapper.findAllComponents(GlBreadcrumbItem);
|
|
28
34
|
const findCollapsedListExpander = () => wrapper.find('[data-testid="collapsed-expander"]');
|
|
29
35
|
|
|
@@ -35,9 +41,6 @@ describe('Breadcrumb component', () => {
|
|
|
35
41
|
const createComponent = (propsData = { items }) => {
|
|
36
42
|
wrapper = shallowMount(Breadcrumb, {
|
|
37
43
|
propsData,
|
|
38
|
-
slots: {
|
|
39
|
-
avatar: '<div data-testid="avatar-slot"></div>',
|
|
40
|
-
},
|
|
41
44
|
stubs: {
|
|
42
45
|
GlBreadcrumbItem,
|
|
43
46
|
},
|
|
@@ -50,19 +53,19 @@ describe('Breadcrumb component', () => {
|
|
|
50
53
|
];
|
|
51
54
|
};
|
|
52
55
|
|
|
53
|
-
describe('
|
|
54
|
-
it('has
|
|
56
|
+
describe('items', () => {
|
|
57
|
+
it('has one breadcrumb-item for each item in the items props', () => {
|
|
55
58
|
createComponent();
|
|
56
59
|
|
|
57
|
-
expect(
|
|
60
|
+
expect(findBreadcrumbItems()).toHaveLength(items.length);
|
|
58
61
|
});
|
|
59
62
|
});
|
|
60
63
|
|
|
61
|
-
describe('
|
|
62
|
-
it('
|
|
64
|
+
describe('avatars', () => {
|
|
65
|
+
it('renders 2 avatars when 2 avatarPaths are passed', () => {
|
|
63
66
|
createComponent();
|
|
64
67
|
|
|
65
|
-
expect(
|
|
68
|
+
expect(findAllAvatars()).toHaveLength(2);
|
|
66
69
|
});
|
|
67
70
|
});
|
|
68
71
|
|
|
@@ -1,24 +1,19 @@
|
|
|
1
|
-
import
|
|
1
|
+
import avatarPath1 from '../../../../static/img/avatar_1.png';
|
|
2
|
+
import avatarPath2 from '../../../../static/img/avatar_2.png';
|
|
2
3
|
import GlBreadcrumb from './breadcrumb.vue';
|
|
3
4
|
import readme from './breadcrumb.md';
|
|
4
5
|
|
|
5
6
|
const template = `
|
|
6
7
|
<gl-breadcrumb
|
|
7
8
|
:items="items"
|
|
8
|
-
|
|
9
|
-
<template #avatar>
|
|
10
|
-
<img alt=""
|
|
11
|
-
class="gl-breadcrumb-avatar-tile" src="${avatarPath}"
|
|
12
|
-
width="16"
|
|
13
|
-
height="16" />
|
|
14
|
-
</template>
|
|
15
|
-
</gl-breadcrumb>
|
|
9
|
+
/>
|
|
16
10
|
`;
|
|
17
11
|
|
|
18
12
|
const defaultItems = [
|
|
19
13
|
{
|
|
20
14
|
text: 'First item',
|
|
21
15
|
href: '#',
|
|
16
|
+
avatarPath: avatarPath1,
|
|
22
17
|
},
|
|
23
18
|
{
|
|
24
19
|
text: 'Second item',
|
|
@@ -27,6 +22,7 @@ const defaultItems = [
|
|
|
27
22
|
{
|
|
28
23
|
text: 'Third item',
|
|
29
24
|
href: '#',
|
|
25
|
+
avatarPath: avatarPath2,
|
|
30
26
|
},
|
|
31
27
|
{
|
|
32
28
|
text: 'Fourth item',
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
<script>
|
|
3
3
|
import { BBreadcrumb } from 'bootstrap-vue';
|
|
4
4
|
import GlButton from '../button/button.vue';
|
|
5
|
+
import GlAvatar from '../avatar/avatar.vue';
|
|
5
6
|
import { GlTooltipDirective } from '../../../directives/tooltip';
|
|
6
7
|
import GlBreadcrumbItem from './breadcrumb_item.vue';
|
|
7
8
|
|
|
@@ -12,6 +13,7 @@ export default {
|
|
|
12
13
|
BBreadcrumb,
|
|
13
14
|
GlButton,
|
|
14
15
|
GlBreadcrumbItem,
|
|
16
|
+
GlAvatar,
|
|
15
17
|
},
|
|
16
18
|
directives: {
|
|
17
19
|
GlTooltip: GlTooltipDirective,
|
|
@@ -25,9 +27,9 @@ export default {
|
|
|
25
27
|
type: Array,
|
|
26
28
|
required: true,
|
|
27
29
|
default: () => [{ text: '', href: '' }],
|
|
28
|
-
validator: (
|
|
29
|
-
return
|
|
30
|
-
const keys = Object.keys(
|
|
30
|
+
validator: (items) => {
|
|
31
|
+
return items.every((item) => {
|
|
32
|
+
const keys = Object.keys(item);
|
|
31
33
|
return keys.includes('text') && (keys.includes('href') || keys.includes('to'));
|
|
32
34
|
});
|
|
33
35
|
},
|
|
@@ -82,8 +84,6 @@ export default {
|
|
|
82
84
|
</script>
|
|
83
85
|
<template>
|
|
84
86
|
<nav class="gl-breadcrumbs" aria-label="Breadcrumb">
|
|
85
|
-
<!-- @slot The avatar to display. -->
|
|
86
|
-
<slot name="avatar"></slot>
|
|
87
87
|
<b-breadcrumb class="gl-breadcrumb-list" v-bind="$attrs" v-on="$listeners">
|
|
88
88
|
<template v-for="(item, index) in items">
|
|
89
89
|
<!-- eslint-disable-next-line vue/valid-v-for (for @vue/compat) -->
|
|
@@ -94,8 +94,16 @@ export default {
|
|
|
94
94
|
:href="item.href"
|
|
95
95
|
:to="item.to"
|
|
96
96
|
:aria-current="getAriaCurrentAttr(index)"
|
|
97
|
-
|
|
98
|
-
|
|
97
|
+
><gl-avatar
|
|
98
|
+
v-if="item.avatarPath"
|
|
99
|
+
:src="item.avatarPath"
|
|
100
|
+
:size="16"
|
|
101
|
+
aria-hidden="true"
|
|
102
|
+
class="gl-breadcrumb-avatar-tile gl-border gl-mr-2 gl-rounded-base!"
|
|
103
|
+
shape="rect"
|
|
104
|
+
data-testid="avatar"
|
|
105
|
+
/><span>{{ item.text }}</span>
|
|
106
|
+
</gl-breadcrumb-item>
|
|
99
107
|
|
|
100
108
|
<template v-if="showCollapsedBreadcrumbsExpander(index)">
|
|
101
109
|
<!-- eslint-disable-next-line vue/require-v-for-key (for @vue/compat) -->
|
|
@@ -80,6 +80,15 @@ describe('base dropdown', () => {
|
|
|
80
80
|
);
|
|
81
81
|
});
|
|
82
82
|
|
|
83
|
+
it('should pass custom options to popper.js, overriding built-in ones', async () => {
|
|
84
|
+
await buildWrapper({ placement: 'right', popperOptions: { placement: 'auto-start' } });
|
|
85
|
+
expect(mockCreatePopper).toHaveBeenCalledWith(
|
|
86
|
+
findDefaultDropdownToggle().element,
|
|
87
|
+
findDropdownMenu().element,
|
|
88
|
+
{ ...POPPER_CONFIG, placement: 'auto-start' }
|
|
89
|
+
);
|
|
90
|
+
});
|
|
91
|
+
|
|
83
92
|
it('should update popper instance when component is updated', async () => {
|
|
84
93
|
await buildWrapper();
|
|
85
94
|
await findDefaultDropdownToggle().trigger('click');
|
|
@@ -117,6 +117,11 @@ export default {
|
|
|
117
117
|
required: false,
|
|
118
118
|
default: null,
|
|
119
119
|
},
|
|
120
|
+
popperOptions: {
|
|
121
|
+
type: Object,
|
|
122
|
+
required: false,
|
|
123
|
+
default: () => ({}),
|
|
124
|
+
},
|
|
120
125
|
},
|
|
121
126
|
data() {
|
|
122
127
|
return {
|
|
@@ -192,6 +197,7 @@ export default {
|
|
|
192
197
|
return {
|
|
193
198
|
placement: dropdownPlacements[this.placement],
|
|
194
199
|
...POPPER_CONFIG,
|
|
200
|
+
...this.popperOptions,
|
|
195
201
|
};
|
|
196
202
|
},
|
|
197
203
|
},
|
|
@@ -122,3 +122,11 @@ To render custom group labels, use the `group-label` scoped slot:
|
|
|
122
122
|
|
|
123
123
|
Besides default components, disclosure dropdown can render miscellaneous content inside it.
|
|
124
124
|
In this case the user is responsible for handling all events and navigation inside the disclosure.
|
|
125
|
+
|
|
126
|
+
#### Dealing with long option texts
|
|
127
|
+
|
|
128
|
+
- Some options might have long non-wrapping text that would overflow the dropdown maximum width. In
|
|
129
|
+
such cases, it's recommended to override the `#list-item` slot and to truncate the option text using
|
|
130
|
+
`GlTruncate`.
|
|
131
|
+
- If the toggle text reflects the selected option text, it might be necessary to truncate
|
|
132
|
+
it too by overriding the `#toggle` slot.
|
|
@@ -37,6 +37,13 @@ describe('GlDisclosureDropdown', () => {
|
|
|
37
37
|
|
|
38
38
|
jest.spyOn(utils, 'filterVisible').mockImplementation((items) => items);
|
|
39
39
|
|
|
40
|
+
it('passes custom popper.js options to the base dropdown', () => {
|
|
41
|
+
const popperOptions = { foo: 'bar' };
|
|
42
|
+
buildWrapper({ popperOptions });
|
|
43
|
+
|
|
44
|
+
expect(findBaseDropdown().props('popperOptions')).toEqual(popperOptions);
|
|
45
|
+
});
|
|
46
|
+
|
|
40
47
|
describe('toggle text', () => {
|
|
41
48
|
it('should pass toggle text to the base dropdown', () => {
|
|
42
49
|
const toggleText = 'Merge requests';
|
|
@@ -164,6 +164,15 @@ export default {
|
|
|
164
164
|
required: false,
|
|
165
165
|
default: null,
|
|
166
166
|
},
|
|
167
|
+
/**
|
|
168
|
+
* Options to be passed to the underlying Popper.js instance.
|
|
169
|
+
* Overrides built-in options.
|
|
170
|
+
*/
|
|
171
|
+
popperOptions: {
|
|
172
|
+
type: Object,
|
|
173
|
+
required: false,
|
|
174
|
+
default: () => ({}),
|
|
175
|
+
},
|
|
167
176
|
},
|
|
168
177
|
data() {
|
|
169
178
|
return {
|
|
@@ -278,6 +287,7 @@ export default {
|
|
|
278
287
|
:loading="loading"
|
|
279
288
|
:no-caret="noCaret"
|
|
280
289
|
:placement="placement"
|
|
290
|
+
:popper-options="popperOptions"
|
|
281
291
|
class="gl-disclosure-dropdown"
|
|
282
292
|
@[$options.events.GL_DROPDOWN_SHOWN]="onShow"
|
|
283
293
|
@[$options.events.GL_DROPDOWN_HIDDEN]="onHide"
|
|
@@ -141,3 +141,11 @@ Screen reader will announce this text when the list is updated.
|
|
|
141
141
|
</template>
|
|
142
142
|
</gl-collapsible-listbox>
|
|
143
143
|
```
|
|
144
|
+
|
|
145
|
+
#### Dealing with long option texts
|
|
146
|
+
|
|
147
|
+
- Some options might have long non-wrapping text that would overflow the dropdown maximum width. In
|
|
148
|
+
such cases, it's recommended to override the `#list-item` slot and to truncate the option text using
|
|
149
|
+
`GlTruncate`.
|
|
150
|
+
- If the toggle text reflects the selected option text, it might be necessary to truncate
|
|
151
|
+
it too by overriding the `#toggle` slot.
|
|
@@ -43,6 +43,13 @@ describe('GlCollapsibleListbox', () => {
|
|
|
43
43
|
const findResetButton = () => wrapper.find("[data-testid='listbox-reset-button']");
|
|
44
44
|
const findIntersectionObserver = () => wrapper.findComponent(GlIntersectionObserver);
|
|
45
45
|
|
|
46
|
+
it('passes custom popper.js options to the base dropdown', () => {
|
|
47
|
+
const popperOptions = { foo: 'bar' };
|
|
48
|
+
buildWrapper({ popperOptions });
|
|
49
|
+
|
|
50
|
+
expect(findBaseDropdown().props('popperOptions')).toEqual(popperOptions);
|
|
51
|
+
});
|
|
52
|
+
|
|
46
53
|
describe('toggle text', () => {
|
|
47
54
|
describe.each`
|
|
48
55
|
toggleText | multiple | selected | expectedToggleText
|
|
@@ -10,6 +10,7 @@ import GlButtonGroup from '../../button_group/button_group.vue';
|
|
|
10
10
|
import GlButton from '../../button/button.vue';
|
|
11
11
|
import GlBadge from '../../badge/badge.vue';
|
|
12
12
|
import GlAvatar from '../../avatar/avatar.vue';
|
|
13
|
+
import GlTruncate from '../../../utilities/truncate/truncate.vue';
|
|
13
14
|
import { makeContainer } from '../../../../utils/story_decorators/container';
|
|
14
15
|
import { setStoryTimeout } from '../../../../utils/test_utils';
|
|
15
16
|
import { disableControls } from '../../../../utils/stories_utils';
|
|
@@ -20,6 +21,7 @@ import {
|
|
|
20
21
|
ARG_TYPE_SUBCATEGORY_ACCESSIBILITY,
|
|
21
22
|
ARG_TYPE_SUBCATEGORY_INFINITE_SCROLL,
|
|
22
23
|
} from '../../../../utils/stories_constants';
|
|
24
|
+
import { POSITION } from '../../../utilities/truncate/constants';
|
|
23
25
|
import readme from './listbox.md';
|
|
24
26
|
import { mockOptions, mockGroups, mockUsers } from './mock_data';
|
|
25
27
|
import { flattenedOptions } from './utils';
|
|
@@ -755,7 +757,6 @@ export const InfiniteScroll = (
|
|
|
755
757
|
},
|
|
756
758
|
}),
|
|
757
759
|
});
|
|
758
|
-
|
|
759
760
|
InfiniteScroll.argTypes = {
|
|
760
761
|
...disableControls(['infiniteScroll', 'infiniteScrollLoading', 'items']),
|
|
761
762
|
};
|
|
@@ -764,3 +765,59 @@ InfiniteScroll.parameters = {
|
|
|
764
765
|
};
|
|
765
766
|
InfiniteScroll.args = generateProps();
|
|
766
767
|
InfiniteScroll.decorators = [makeContainer({ height: '370px' })];
|
|
768
|
+
|
|
769
|
+
export const WithLongContent = (args, { argTypes: { items, ...argTypes } }) => ({
|
|
770
|
+
props: Object.keys(argTypes),
|
|
771
|
+
components: {
|
|
772
|
+
GlCollapsibleListbox,
|
|
773
|
+
GlButton,
|
|
774
|
+
GlTruncate,
|
|
775
|
+
},
|
|
776
|
+
data() {
|
|
777
|
+
const positions = Object.values(POSITION);
|
|
778
|
+
const longItems = Array.from({ length: positions.length }).map((_, index) => ({
|
|
779
|
+
value: `long_value_${index}`,
|
|
780
|
+
text: `${
|
|
781
|
+
index + 1
|
|
782
|
+
}. This is a super long option. Its text is so long that it overflows the max content width. Thankfully, we are truncating it!`,
|
|
783
|
+
truncatePosition: positions[index],
|
|
784
|
+
}));
|
|
785
|
+
|
|
786
|
+
return {
|
|
787
|
+
selected: longItems[0].value,
|
|
788
|
+
items: longItems,
|
|
789
|
+
};
|
|
790
|
+
},
|
|
791
|
+
mounted() {
|
|
792
|
+
if (this.startOpened) {
|
|
793
|
+
openListbox(this);
|
|
794
|
+
}
|
|
795
|
+
},
|
|
796
|
+
computed: {
|
|
797
|
+
customToggleText() {
|
|
798
|
+
return this.items.find(({ value }) => value === this.selected).text;
|
|
799
|
+
},
|
|
800
|
+
numberOfSearchResults() {
|
|
801
|
+
return this.filteredItems.length === 1 ? '1 result' : `${this.filteredItems.length} results`;
|
|
802
|
+
},
|
|
803
|
+
},
|
|
804
|
+
template: template(
|
|
805
|
+
`
|
|
806
|
+
<template #toggle>
|
|
807
|
+
<gl-button class="gl-w-30">
|
|
808
|
+
<gl-truncate :text="customToggleText" />
|
|
809
|
+
</gl-button>
|
|
810
|
+
</template>
|
|
811
|
+
<template #list-item="{ item }">
|
|
812
|
+
<gl-truncate :text="item.text" :position="item.truncatePosition" />
|
|
813
|
+
</template>
|
|
814
|
+
`,
|
|
815
|
+
{
|
|
816
|
+
label: `<span class="gl-my-0" id="listbox-label">Select the longest option</span>`,
|
|
817
|
+
bindingOverrides: {
|
|
818
|
+
':items': 'items',
|
|
819
|
+
},
|
|
820
|
+
}
|
|
821
|
+
),
|
|
822
|
+
});
|
|
823
|
+
WithLongContent.args = generateProps();
|
|
@@ -287,6 +287,15 @@ export default {
|
|
|
287
287
|
required: false,
|
|
288
288
|
default: false,
|
|
289
289
|
},
|
|
290
|
+
/**
|
|
291
|
+
* Options to be passed to the underlying Popper.js instance.
|
|
292
|
+
* Overrides built-in options.
|
|
293
|
+
*/
|
|
294
|
+
popperOptions: {
|
|
295
|
+
type: Object,
|
|
296
|
+
required: false,
|
|
297
|
+
default: () => ({}),
|
|
298
|
+
},
|
|
290
299
|
},
|
|
291
300
|
data() {
|
|
292
301
|
return {
|
|
@@ -585,6 +594,7 @@ export default {
|
|
|
585
594
|
:loading="loading"
|
|
586
595
|
:no-caret="noCaret"
|
|
587
596
|
:placement="placement"
|
|
597
|
+
:popper-options="popperOptions"
|
|
588
598
|
@[$options.events.GL_DROPDOWN_SHOWN]="onShow"
|
|
589
599
|
@[$options.events.GL_DROPDOWN_HIDDEN]="onHide"
|
|
590
600
|
>
|
package/src/scss/variables.scss
CHANGED
|
@@ -464,7 +464,8 @@ $gl-icon-sizes: 8 12 14 16 24 32 48 72;
|
|
|
464
464
|
|
|
465
465
|
// Dropdowns
|
|
466
466
|
$gl-dropdown-width: px-to-rem(240px);
|
|
467
|
-
$gl-new-dropdown-width: px-to-rem(
|
|
467
|
+
$gl-new-dropdown-min-width: px-to-rem(248px);
|
|
468
|
+
$gl-new-dropdown-max-width: px-to-rem(456px);
|
|
468
469
|
$gl-dropdown-width-narrow: px-to-rem(160px);
|
|
469
470
|
$gl-dropdown-width-wide: px-to-rem(400px);
|
|
470
471
|
$gl-max-dropdown-max-height: px-to-rem(312px);
|