@gitlab/ui 67.4.0 → 67.5.1
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 +16 -0
- package/dist/components/base/sorting/sorting.js +47 -5
- package/dist/components/base/sorting/sorting_item.js +3 -0
- package/dist/components/experimental/duo/chat/components/duo_chat_message/duo_chat_message.js +1 -2
- 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/dist/utility_classes.css +1 -1
- package/dist/utility_classes.css.map +1 -1
- package/package.json +2 -2
- package/scss_to_js/scss_variables.js +146 -146
- package/scss_to_js/scss_variables.json +1278 -1278
- package/src/components/base/sorting/sorting.md +82 -2
- package/src/components/base/sorting/sorting.spec.js +138 -14
- package/src/components/base/sorting/sorting.stories.js +69 -2
- package/src/components/base/sorting/sorting.vue +68 -7
- package/src/components/base/sorting/sorting_item.md +1 -1
- package/src/components/base/sorting/sorting_item.vue +3 -0
- package/src/components/experimental/duo/chat/components/duo_chat_message/duo_chat_message.vue +1 -2
- package/src/scss/storybook.scss +1 -1
- package/src/scss/storybook_dark_mode.scss +0 -1
- package/src/scss/tokens.scss +2 -0
- package/src/scss/utilities.scss +8 -0
- package/src/scss/utility-mixins/z-index.scss +1 -1
- package/src/scss/variables.scss +1 -185
- package/translations.json +2 -0
|
@@ -1,8 +1,88 @@
|
|
|
1
|
-
## Usage
|
|
2
|
-
|
|
3
1
|
The sorting component allows the user to select the field on which they would like to sort a list
|
|
4
2
|
and whether to sort in ascending or descending order.
|
|
5
3
|
|
|
4
|
+
Provide a list of sort options via the `sortOptions` prop with this structure:
|
|
5
|
+
|
|
6
|
+
```typescript
|
|
7
|
+
type sortOptionsProp = Array<{
|
|
8
|
+
value: string
|
|
9
|
+
text: string
|
|
10
|
+
}>
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
The `value` should be a unique primitive value, and `text` is the user-facing
|
|
14
|
+
string for that option.
|
|
15
|
+
|
|
16
|
+
Set the currently selected sort option by passing a value to the `sortBy` prop.
|
|
17
|
+
This should equal one of the `sortOptions` values. The selected sort option is
|
|
18
|
+
rendered with a check mark next to it in the dropdown menu.
|
|
19
|
+
|
|
20
|
+
When the user changes the selected sort option, a `sortByChange` event is
|
|
21
|
+
emitted, with the `value` of the option as the only payload.
|
|
22
|
+
|
|
23
|
+
The text of the dropdown trigger button is the `text` of the selected sort
|
|
24
|
+
option. Pass a string to the `text` prop to override this behavior.
|
|
25
|
+
|
|
26
|
+
When the user clicks on the sort direction button, a `sortDirectionChange`
|
|
27
|
+
event is emitted, with a boolean value as its only payload. If the payload is
|
|
28
|
+
`true`, the new order is ascending; otherwise it's descending.
|
|
29
|
+
|
|
30
|
+
A complete implementation example might look like:
|
|
31
|
+
|
|
32
|
+
```html
|
|
33
|
+
<template>
|
|
34
|
+
<gl-sorting
|
|
35
|
+
:sort-options="sortOptions"
|
|
36
|
+
:sort-by="sortBy"
|
|
37
|
+
:is-ascending="isAscending"
|
|
38
|
+
@sortByChange="onSortByChange"
|
|
39
|
+
@sortDirectionChange="onDirectionChange"
|
|
40
|
+
/>
|
|
41
|
+
</template>
|
|
42
|
+
|
|
43
|
+
<script>
|
|
44
|
+
import { GlSorting } from '@gitlab/ui';
|
|
45
|
+
|
|
46
|
+
export default {
|
|
47
|
+
components: {
|
|
48
|
+
GlSorting,
|
|
49
|
+
},
|
|
50
|
+
data() {
|
|
51
|
+
const sortOptions = [{
|
|
52
|
+
value: 'name',
|
|
53
|
+
text: 'Name',
|
|
54
|
+
}, {
|
|
55
|
+
value: 'date',
|
|
56
|
+
text: 'Date',
|
|
57
|
+
}];
|
|
58
|
+
|
|
59
|
+
return {
|
|
60
|
+
isAscending: false,
|
|
61
|
+
sortBy: sortOptions[0].value,
|
|
62
|
+
sortOptions,
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
methods: {
|
|
66
|
+
onSortByChange(value) {
|
|
67
|
+
this.sortBy = value;
|
|
68
|
+
this.sortMyData(this.sortBy, this.isAscending);
|
|
69
|
+
},
|
|
70
|
+
onDirectionChange(isAscending) {
|
|
71
|
+
this.isAscending = isAscending;
|
|
72
|
+
this.sortMyData(this.sortBy, this.isAscending);
|
|
73
|
+
},
|
|
74
|
+
sortMyData(sortBy, isAscending) {
|
|
75
|
+
// Use sortBy and direction to sort your data
|
|
76
|
+
},
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
</script>
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Deprecated usage
|
|
83
|
+
|
|
84
|
+
> **NOTE:** This documents the deprecated API, which will be removed in a future major release.
|
|
85
|
+
|
|
6
86
|
The dropdown part of the sorting component is a standard `gl-dropdown` component, with the items
|
|
7
87
|
exposed as a slot. Inside the `gl-sorting` component, you should add a list of `gl-sorting-item`
|
|
8
88
|
components to construct your sorting options. The check icon will be displayed when a
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { mount } from '@vue/test-utils';
|
|
2
|
+
import { useMockIntersectionObserver } from '~/utils/use_mock_intersection_observer';
|
|
3
|
+
import GlCollapsibleListbox from '../new_dropdowns/listbox/listbox.vue';
|
|
2
4
|
import GlDropdown from '../dropdown/dropdown.vue';
|
|
3
5
|
import GlIcon from '../icon/icon.vue';
|
|
4
6
|
import GlSorting from './sorting.vue';
|
|
@@ -14,9 +16,15 @@ describe('sorting component', () => {
|
|
|
14
16
|
isAscending,
|
|
15
17
|
};
|
|
16
18
|
|
|
17
|
-
const selectDropdownButton = () => wrapper.find('
|
|
18
|
-
const selectDirectionButton = () => wrapper.
|
|
19
|
+
const selectDropdownButton = () => wrapper.find('button');
|
|
20
|
+
const selectDirectionButton = () => wrapper.findAll('button').at(1);
|
|
19
21
|
const selectDropdown = () => wrapper.findComponent(GlDropdown);
|
|
22
|
+
const findListbox = () => wrapper.findComponent(GlCollapsibleListbox);
|
|
23
|
+
const findListboxItem = (text) =>
|
|
24
|
+
wrapper
|
|
25
|
+
.findAll('[role="option"]')
|
|
26
|
+
.filter((w) => w.text().includes(text))
|
|
27
|
+
.at(0);
|
|
20
28
|
|
|
21
29
|
const createComponent = (propsData) => {
|
|
22
30
|
wrapper = mount(GlSorting, {
|
|
@@ -30,14 +38,12 @@ describe('sorting component', () => {
|
|
|
30
38
|
it('should display default text in dropdown', () => {
|
|
31
39
|
createComponent();
|
|
32
40
|
|
|
33
|
-
expect(wrapper.vm.text).toBe(defaultDropdownText);
|
|
34
41
|
expect(selectDropdownButton().text()).toBe(defaultDropdownText);
|
|
35
42
|
});
|
|
36
43
|
|
|
37
44
|
it('should have a default sort direction of desc and displays the descending icon', () => {
|
|
38
45
|
createComponent();
|
|
39
46
|
|
|
40
|
-
expect(wrapper.vm.isAscending).toBe(false);
|
|
41
47
|
expect(selectDirectionButton().findComponent(GlIcon).props('name')).toBe('sort-highest');
|
|
42
48
|
});
|
|
43
49
|
|
|
@@ -45,21 +51,17 @@ describe('sorting component', () => {
|
|
|
45
51
|
const newDropdownText = 'Some new text';
|
|
46
52
|
|
|
47
53
|
createComponent({
|
|
48
|
-
...defaultProps,
|
|
49
54
|
text: newDropdownText,
|
|
50
55
|
});
|
|
51
56
|
|
|
52
|
-
expect(wrapper.vm.text).toBe(newDropdownText);
|
|
53
57
|
expect(selectDropdownButton().text()).toBe(newDropdownText);
|
|
54
58
|
});
|
|
55
59
|
|
|
56
60
|
it('should accept isAscending true as a default sort direction and display the ascending icon', () => {
|
|
57
61
|
createComponent({
|
|
58
|
-
...defaultProps,
|
|
59
62
|
isAscending: true,
|
|
60
63
|
});
|
|
61
64
|
|
|
62
|
-
expect(wrapper.vm.isAscending).toBe(true);
|
|
63
65
|
expect(selectDirectionButton().findComponent(GlIcon).props('name')).toBe('sort-lowest');
|
|
64
66
|
});
|
|
65
67
|
|
|
@@ -71,21 +73,19 @@ describe('sorting component', () => {
|
|
|
71
73
|
expect(wrapper.emitted('sortDirectionChange')[0]).toEqual([true]);
|
|
72
74
|
});
|
|
73
75
|
|
|
74
|
-
it('should allow custom sort
|
|
76
|
+
it('should allow custom sort direction text to be applied', () => {
|
|
75
77
|
const newDirectionTooltip = 'New tooltip text';
|
|
76
78
|
|
|
77
79
|
createComponent({
|
|
78
|
-
...defaultProps,
|
|
79
80
|
sortDirectionToolTip: newDirectionTooltip,
|
|
80
81
|
});
|
|
81
82
|
|
|
82
|
-
expect(wrapper.vm.sortDirectionToolTip).toBe(newDirectionTooltip);
|
|
83
83
|
expect(selectDirectionButton().attributes('title')).toBe(newDirectionTooltip);
|
|
84
|
+
expect(selectDirectionButton().attributes('aria-label')).toBe(newDirectionTooltip);
|
|
84
85
|
});
|
|
85
86
|
|
|
86
87
|
it('adds classes passed in `dropdownClass` prop to dropdown', () => {
|
|
87
88
|
createComponent({
|
|
88
|
-
...defaultProps,
|
|
89
89
|
dropdownClass: 'foo-bar',
|
|
90
90
|
});
|
|
91
91
|
|
|
@@ -94,7 +94,6 @@ describe('sorting component', () => {
|
|
|
94
94
|
|
|
95
95
|
it('adds classes passed in `dropdownToggleClass` prop to dropdown toggle', () => {
|
|
96
96
|
createComponent({
|
|
97
|
-
...defaultProps,
|
|
98
97
|
dropdownToggleClass: 'foo-bar',
|
|
99
98
|
});
|
|
100
99
|
|
|
@@ -103,7 +102,6 @@ describe('sorting component', () => {
|
|
|
103
102
|
|
|
104
103
|
it('adds classes passed in `sortDirectionToggleClass` prop to sort direction toggle', () => {
|
|
105
104
|
createComponent({
|
|
106
|
-
...defaultProps,
|
|
107
105
|
sortDirectionToggleClass: 'foo-bar',
|
|
108
106
|
});
|
|
109
107
|
|
|
@@ -111,4 +109,130 @@ describe('sorting component', () => {
|
|
|
111
109
|
expect.arrayContaining(['sorting-direction-button', 'foo-bar'])
|
|
112
110
|
);
|
|
113
111
|
});
|
|
112
|
+
|
|
113
|
+
it('sets aria-label of sort direction button', async () => {
|
|
114
|
+
createComponent();
|
|
115
|
+
|
|
116
|
+
expect(selectDirectionButton().attributes('aria-label')).toBe('Sort direction: descending');
|
|
117
|
+
|
|
118
|
+
await wrapper.setProps({ isAscending: true });
|
|
119
|
+
|
|
120
|
+
expect(selectDirectionButton().attributes('aria-label')).toBe('Sort direction: ascending');
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
describe('using listbox', () => {
|
|
124
|
+
useMockIntersectionObserver();
|
|
125
|
+
|
|
126
|
+
it('should display given toggle text in dropdown', () => {
|
|
127
|
+
createComponent({ sortOptions: [] });
|
|
128
|
+
|
|
129
|
+
expect(selectDropdownButton().text()).toBe(defaultDropdownText);
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it('should use the selected sort option text in dropdown if text is not given', () => {
|
|
133
|
+
createComponent({ text: null, sortOptions: [{ value: 0, text: 'Foo' }], sortBy: 0 });
|
|
134
|
+
|
|
135
|
+
expect(selectDropdownButton().text()).toBe('Foo');
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
it('renders the given sort options', () => {
|
|
139
|
+
createComponent({
|
|
140
|
+
sortOptions: [
|
|
141
|
+
{ value: 'foo', text: 'Foo' },
|
|
142
|
+
{ value: 'bar', text: 'Bar' },
|
|
143
|
+
],
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
expect(findListboxItem('Foo').exists()).toBe(true);
|
|
147
|
+
expect(findListboxItem('Bar').exists()).toBe(true);
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
it('emits sortByChange event when user changes sort option', async () => {
|
|
151
|
+
createComponent({
|
|
152
|
+
sortOptions: [
|
|
153
|
+
{ value: 'foo', text: 'Foo' },
|
|
154
|
+
{ value: 'bar', text: 'Bar' },
|
|
155
|
+
],
|
|
156
|
+
sortBy: 'foo',
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
await findListboxItem('Foo').trigger('click');
|
|
160
|
+
expect(wrapper.emitted('sortByChange')).toBe(undefined);
|
|
161
|
+
|
|
162
|
+
await findListboxItem('Bar').trigger('click');
|
|
163
|
+
expect(wrapper.emitted('sortByChange')).toEqual([['bar']]);
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
it('should have a default sort direction of desc and displays the descending icon', () => {
|
|
167
|
+
createComponent({ sortOptions: [] });
|
|
168
|
+
|
|
169
|
+
expect(selectDirectionButton().findComponent(GlIcon).props('name')).toBe('sort-highest');
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
it('should accept isAscending true as a default sort direction and display the ascending icon', () => {
|
|
173
|
+
createComponent({
|
|
174
|
+
sortOptions: [],
|
|
175
|
+
isAscending: true,
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
expect(selectDirectionButton().findComponent(GlIcon).props('name')).toBe('sort-lowest');
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
it('should emit the sortDirectionChange event when direction button is clicked', () => {
|
|
182
|
+
createComponent({ sortOptions: [] });
|
|
183
|
+
|
|
184
|
+
selectDirectionButton().trigger('click');
|
|
185
|
+
|
|
186
|
+
expect(wrapper.emitted('sortDirectionChange')[0]).toEqual([true]);
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
it('should allow custom sort tooltip to be applied', () => {
|
|
190
|
+
const newDirectionTooltip = 'New tooltip text';
|
|
191
|
+
|
|
192
|
+
createComponent({
|
|
193
|
+
sortDirectionToolTip: newDirectionTooltip,
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
expect(selectDirectionButton().attributes('title')).toBe(newDirectionTooltip);
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
it('adds classes passed in `dropdownClass` prop to dropdown', () => {
|
|
200
|
+
createComponent({
|
|
201
|
+
sortOptions: [],
|
|
202
|
+
dropdownClass: 'foo-bar',
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
expect(findListbox().classes()).toContain('foo-bar');
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
it('adds classes passed in `dropdownToggleClass` prop to dropdown toggle', () => {
|
|
209
|
+
createComponent({
|
|
210
|
+
sortOptions: [],
|
|
211
|
+
dropdownToggleClass: 'foo-bar',
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
expect(selectDropdownButton().classes()).toEqual(expect.arrayContaining(['foo-bar']));
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
it('adds classes passed in `sortDirectionToggleClass` prop to sort direction toggle', () => {
|
|
218
|
+
createComponent({
|
|
219
|
+
sortOptions: [],
|
|
220
|
+
sortDirectionToggleClass: 'foo-bar',
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
expect(selectDirectionButton().classes()).toEqual(
|
|
224
|
+
expect.arrayContaining(['sorting-direction-button', 'foo-bar'])
|
|
225
|
+
);
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
it('sets aria-label of sort direction button', async () => {
|
|
229
|
+
createComponent({ sortOptions: [] });
|
|
230
|
+
|
|
231
|
+
expect(selectDirectionButton().attributes('aria-label')).toBe('Sort direction: descending');
|
|
232
|
+
|
|
233
|
+
await wrapper.setProps({ isAscending: true });
|
|
234
|
+
|
|
235
|
+
expect(selectDirectionButton().attributes('aria-label')).toBe('Sort direction: ascending');
|
|
236
|
+
});
|
|
237
|
+
});
|
|
114
238
|
});
|
|
@@ -12,6 +12,8 @@ const propDefault = (prop) => GlSorting.props[prop].default;
|
|
|
12
12
|
|
|
13
13
|
const generateProps = ({
|
|
14
14
|
text = 'Sorting options',
|
|
15
|
+
sortOptions = propDefault('sortOptions'),
|
|
16
|
+
sortBy = propDefault('sortBy'),
|
|
15
17
|
isAscending = propDefault('isAscending'),
|
|
16
18
|
sortDirectionToolTip = propDefault('sortDirectionToolTip'),
|
|
17
19
|
dropdownClass = propDefault('dropdownClass'),
|
|
@@ -19,6 +21,8 @@ const generateProps = ({
|
|
|
19
21
|
sortDirectionToggleClass = propDefault('sortDirectionToggleClass'),
|
|
20
22
|
} = {}) => ({
|
|
21
23
|
text,
|
|
24
|
+
sortOptions,
|
|
25
|
+
sortBy,
|
|
22
26
|
isAscending,
|
|
23
27
|
sortDirectionToolTip,
|
|
24
28
|
dropdownClass,
|
|
@@ -50,12 +54,75 @@ const Template = (args) => ({
|
|
|
50
54
|
});
|
|
51
55
|
|
|
52
56
|
export const Default = Template.bind({});
|
|
53
|
-
Default
|
|
57
|
+
Object.assign(Default, {
|
|
58
|
+
args: generateProps(),
|
|
59
|
+
parameters: {
|
|
60
|
+
controls: {
|
|
61
|
+
// These props/events only apply when using the listbox form, so don't
|
|
62
|
+
// show their controls.
|
|
63
|
+
exclude: ['sortBy', 'sortOptions', 'sortByChange'],
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
export const UsingListbox = (args) => ({
|
|
69
|
+
components,
|
|
70
|
+
props: Object.keys(args),
|
|
71
|
+
mounted() {
|
|
72
|
+
// The first button is the dropdown trigger.
|
|
73
|
+
this.$nextTick(() => this.$el.querySelector('button').click());
|
|
74
|
+
},
|
|
75
|
+
template: `
|
|
76
|
+
<gl-sorting
|
|
77
|
+
:text="text"
|
|
78
|
+
:sort-options="sortOptions"
|
|
79
|
+
:sort-by="sortBy"
|
|
80
|
+
:is-ascending="isAscending"
|
|
81
|
+
:sort-direction-tool-tip="sortDirectionToolTip"
|
|
82
|
+
:dropdown-class="dropdownClass"
|
|
83
|
+
:dropdown-toggle-class="dropdownToggleClass"
|
|
84
|
+
:sort-direction-toggle-class="sortDirectionToggleClass"
|
|
85
|
+
/>
|
|
86
|
+
`,
|
|
87
|
+
});
|
|
88
|
+
Object.assign(UsingListbox, {
|
|
89
|
+
args: generateProps({
|
|
90
|
+
text: '',
|
|
91
|
+
sortOptions: [
|
|
92
|
+
{
|
|
93
|
+
value: 'first',
|
|
94
|
+
text: 'First item',
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
value: 'second',
|
|
98
|
+
text: 'Second item',
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
value: 'third',
|
|
102
|
+
text: 'Third item',
|
|
103
|
+
},
|
|
104
|
+
],
|
|
105
|
+
sortBy: 'first',
|
|
106
|
+
}),
|
|
107
|
+
parameters: {
|
|
108
|
+
controls: {
|
|
109
|
+
// The default slot is deprecated, so don't show it in the controls.
|
|
110
|
+
exclude: ['default'],
|
|
111
|
+
},
|
|
112
|
+
},
|
|
113
|
+
});
|
|
54
114
|
|
|
55
115
|
export default {
|
|
56
116
|
title: 'base/sorting',
|
|
57
117
|
component: GlSorting,
|
|
58
|
-
decorators: [
|
|
118
|
+
decorators: [
|
|
119
|
+
makeContainer({
|
|
120
|
+
height: '150px',
|
|
121
|
+
display: 'flex',
|
|
122
|
+
justifyContent: 'center',
|
|
123
|
+
alignItems: 'flex-start',
|
|
124
|
+
}),
|
|
125
|
+
],
|
|
59
126
|
parameters: {
|
|
60
127
|
docs: {
|
|
61
128
|
description: {
|
|
@@ -2,13 +2,17 @@
|
|
|
2
2
|
import { GlTooltipDirective } from '../../../directives/tooltip';
|
|
3
3
|
import GlButton from '../button/button.vue';
|
|
4
4
|
import GlButtonGroup from '../button_group/button_group.vue';
|
|
5
|
+
import GlCollapsibleListbox from '../new_dropdowns/listbox/listbox.vue';
|
|
6
|
+
import { isOption } from '../new_dropdowns/listbox/utils';
|
|
5
7
|
import GlDropdown from '../dropdown/dropdown.vue';
|
|
8
|
+
import { translate } from '../../../utils/i18n';
|
|
6
9
|
|
|
7
10
|
export default {
|
|
8
11
|
name: 'GlSorting',
|
|
9
12
|
components: {
|
|
10
13
|
GlButton,
|
|
11
14
|
GlButtonGroup,
|
|
15
|
+
GlCollapsibleListbox,
|
|
12
16
|
GlDropdown,
|
|
13
17
|
},
|
|
14
18
|
directives: {
|
|
@@ -23,6 +27,24 @@ export default {
|
|
|
23
27
|
required: false,
|
|
24
28
|
default: '',
|
|
25
29
|
},
|
|
30
|
+
/**
|
|
31
|
+
* Sort options to display in the dropdown
|
|
32
|
+
*/
|
|
33
|
+
sortOptions: {
|
|
34
|
+
type: Array,
|
|
35
|
+
required: false,
|
|
36
|
+
default: null,
|
|
37
|
+
validator: (sortOptions) => sortOptions.every(isOption),
|
|
38
|
+
},
|
|
39
|
+
/**
|
|
40
|
+
* The value of the item currently selected in the dropdown.
|
|
41
|
+
* Only to be used with the `sortOptions` prop.
|
|
42
|
+
*/
|
|
43
|
+
sortBy: {
|
|
44
|
+
type: [String, Number],
|
|
45
|
+
required: false,
|
|
46
|
+
default: null,
|
|
47
|
+
},
|
|
26
48
|
/**
|
|
27
49
|
* Determines the current sort order icon displayed.
|
|
28
50
|
*/
|
|
@@ -32,12 +54,13 @@ export default {
|
|
|
32
54
|
default: false,
|
|
33
55
|
},
|
|
34
56
|
/**
|
|
35
|
-
* The text
|
|
57
|
+
* The text for the tooltip and aria-label of the sort direction toggle
|
|
58
|
+
* button instead of the defaults for ascending/descending.
|
|
36
59
|
*/
|
|
37
60
|
sortDirectionToolTip: {
|
|
38
61
|
type: String,
|
|
39
62
|
required: false,
|
|
40
|
-
default:
|
|
63
|
+
default: null,
|
|
41
64
|
},
|
|
42
65
|
/**
|
|
43
66
|
* Additional class(es) to apply to the root element of the GlDropdown.
|
|
@@ -68,8 +91,23 @@ export default {
|
|
|
68
91
|
localSortDirection() {
|
|
69
92
|
return this.isAscending ? 'sort-lowest' : 'sort-highest';
|
|
70
93
|
},
|
|
71
|
-
|
|
72
|
-
|
|
94
|
+
sortDirectionText() {
|
|
95
|
+
if (this.sortDirectionToolTip) return this.sortDirectionToolTip;
|
|
96
|
+
|
|
97
|
+
return this.isAscending
|
|
98
|
+
? translate('GlSorting.sortAscending', 'Sort direction: ascending')
|
|
99
|
+
: translate('GlSorting.sortDescending', 'Sort direction: descending');
|
|
100
|
+
},
|
|
101
|
+
useListbox() {
|
|
102
|
+
return Boolean(this.sortOptions);
|
|
103
|
+
},
|
|
104
|
+
listboxToggleClass() {
|
|
105
|
+
return [
|
|
106
|
+
this.dropdownToggleClass,
|
|
107
|
+
'gl-rounded-top-right-none!',
|
|
108
|
+
'gl-rounded-bottom-right-none!',
|
|
109
|
+
'gl-focus-z-index-1',
|
|
110
|
+
];
|
|
73
111
|
},
|
|
74
112
|
},
|
|
75
113
|
methods: {
|
|
@@ -86,13 +124,36 @@ export default {
|
|
|
86
124
|
*/
|
|
87
125
|
this.$emit('sortDirectionChange', newDirection);
|
|
88
126
|
},
|
|
127
|
+
onSortByChanged(event) {
|
|
128
|
+
/**
|
|
129
|
+
* Emitted when the sort field is changed.
|
|
130
|
+
*
|
|
131
|
+
* The event's payload is the value of the selected sort field.
|
|
132
|
+
*
|
|
133
|
+
* Only emitted when using the `sortOptions` prop.
|
|
134
|
+
*
|
|
135
|
+
* @property {string|number} value
|
|
136
|
+
*/
|
|
137
|
+
this.$emit('sortByChange', event);
|
|
138
|
+
},
|
|
89
139
|
},
|
|
90
140
|
};
|
|
91
141
|
</script>
|
|
92
142
|
|
|
93
143
|
<template>
|
|
94
144
|
<gl-button-group class="gl-sorting">
|
|
145
|
+
<gl-collapsible-listbox
|
|
146
|
+
v-if="useListbox"
|
|
147
|
+
:toggle-text="text"
|
|
148
|
+
:items="sortOptions"
|
|
149
|
+
:selected="sortBy"
|
|
150
|
+
:toggle-class="listboxToggleClass"
|
|
151
|
+
:class="dropdownClass"
|
|
152
|
+
placement="right"
|
|
153
|
+
@select="onSortByChanged"
|
|
154
|
+
/>
|
|
95
155
|
<gl-dropdown
|
|
156
|
+
v-else
|
|
96
157
|
v-bind="$props"
|
|
97
158
|
:text="text"
|
|
98
159
|
category="secondary"
|
|
@@ -100,14 +161,14 @@ export default {
|
|
|
100
161
|
:toggle-class="dropdownToggleClass"
|
|
101
162
|
right
|
|
102
163
|
>
|
|
103
|
-
<!-- @slot
|
|
164
|
+
<!-- @slot Deprecated slot to place the dropdown items, works best with a gl-sorting-item component. -->
|
|
104
165
|
<slot></slot>
|
|
105
166
|
</gl-dropdown>
|
|
106
167
|
<gl-button
|
|
107
168
|
v-gl-tooltip
|
|
108
|
-
:title="
|
|
169
|
+
:title="sortDirectionText"
|
|
109
170
|
:icon="localSortDirection"
|
|
110
|
-
:aria-label="
|
|
171
|
+
:aria-label="sortDirectionText"
|
|
111
172
|
:class="['sorting-direction-button', sortDirectionToggleClass]"
|
|
112
173
|
@click="toggleSortDirection"
|
|
113
174
|
/>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
> **NOTE:** This component is deprecated. Instead, use the `sortOptions` prop of `GlSorting`.
|
|
2
2
|
|
|
3
3
|
The sorting item component is meant to be used for clickable entries inside a `gl-sorting` component.
|
|
4
4
|
This is a wrapper around the `gl-dropdown-item` component and includes a check icon when active,
|
|
@@ -5,6 +5,9 @@ import GlIcon from '../icon/icon.vue';
|
|
|
5
5
|
/**
|
|
6
6
|
* Sorting Item
|
|
7
7
|
*
|
|
8
|
+
* NOTE: This component is deprecated. Instead, use the `sortOptions` prop of
|
|
9
|
+
* `GlSorting`.
|
|
10
|
+
*
|
|
8
11
|
* This is written as a functional component because it is a simple wrapper over
|
|
9
12
|
* the GlDropdownItem component and does not use internal state. Functional
|
|
10
13
|
* components are cheaper to render and often used as wrappers like this. We're
|
package/src/components/experimental/duo/chat/components/duo_chat_message/duo_chat_message.vue
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
<script>
|
|
2
|
-
import { nextTick } from 'vue';
|
|
3
2
|
import GlDuoUserFeedback from '../../../user_feedback/user_feedback.vue';
|
|
4
3
|
import { SafeHtmlDirective as SafeHtml } from '../../../../../../directives/safe_html/safe_html';
|
|
5
4
|
import { MESSAGE_MODEL_ROLES } from '../../constants';
|
|
@@ -77,7 +76,7 @@ export default {
|
|
|
77
76
|
},
|
|
78
77
|
methods: {
|
|
79
78
|
async hydrateContentWithGFM() {
|
|
80
|
-
await nextTick();
|
|
79
|
+
await this.$nextTick();
|
|
81
80
|
this.renderGFM(this.$refs.content);
|
|
82
81
|
},
|
|
83
82
|
async messageUpdateHandler() {
|
package/src/scss/storybook.scss
CHANGED
package/src/scss/utilities.scss
CHANGED
|
@@ -9285,10 +9285,18 @@ $gl-animate-skeleton-loader-max-width: 64 * $grid-size;
|
|
|
9285
9285
|
z-index: 1
|
|
9286
9286
|
}
|
|
9287
9287
|
|
|
9288
|
+
.gl-focus-z-index-1:focus {
|
|
9289
|
+
z-index: 1
|
|
9290
|
+
}
|
|
9291
|
+
|
|
9288
9292
|
.gl-z-index-1\! {
|
|
9289
9293
|
z-index: 1 !important
|
|
9290
9294
|
}
|
|
9291
9295
|
|
|
9296
|
+
.gl-focus-z-index-1\!:focus {
|
|
9297
|
+
z-index: 1 !important
|
|
9298
|
+
}
|
|
9299
|
+
|
|
9292
9300
|
.gl-z-index-2 {
|
|
9293
9301
|
z-index: 2
|
|
9294
9302
|
}
|