@gitlab/ui 78.2.1 → 78.2.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 +7 -0
- package/README.md +5 -0
- package/dist/components/base/table/table.js +19 -5
- package/dist/index.css +1 -1
- 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/package.json +2 -2
- package/src/components/base/filtered_search/filtered_search.stories.js +1 -1
- package/src/components/base/table/table.scss +11 -4
- package/src/components/base/table/table.spec.js +58 -9
- package/src/components/base/table/table.stories.js +1 -0
- package/src/components/base/table/table.vue +25 -20
package/dist/tokens/js/tokens.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gitlab/ui",
|
|
3
|
-
"version": "78.2.
|
|
3
|
+
"version": "78.2.2",
|
|
4
4
|
"description": "GitLab UI Components",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -102,7 +102,7 @@
|
|
|
102
102
|
"@gitlab/eslint-plugin": "19.4.0",
|
|
103
103
|
"@gitlab/fonts": "^1.3.0",
|
|
104
104
|
"@gitlab/stylelint-config": "6.1.0",
|
|
105
|
-
"@gitlab/svgs": "3.
|
|
105
|
+
"@gitlab/svgs": "3.90.0",
|
|
106
106
|
"@rollup/plugin-commonjs": "^11.1.0",
|
|
107
107
|
"@rollup/plugin-node-resolve": "^7.1.3",
|
|
108
108
|
"@rollup/plugin-replace": "^2.3.2",
|
|
@@ -349,7 +349,7 @@ const tokens = [
|
|
|
349
349
|
token: UserToken,
|
|
350
350
|
},
|
|
351
351
|
{ type: 'user', icon: 'user', title: 'Assignee', dataType: 'user', token: UserToken },
|
|
352
|
-
{ type: 'milestone', icon: '
|
|
352
|
+
{ type: 'milestone', icon: 'milestone', title: 'Milestone', unique: true, token: MilestoneToken },
|
|
353
353
|
{ type: 'label', icon: 'labels', title: 'Label', token: LabelToken },
|
|
354
354
|
{ type: 'weight', icon: 'weight', title: 'Weight', unique: true, token: GlFilteredSearchToken },
|
|
355
355
|
{
|
|
@@ -18,13 +18,12 @@ table.gl-table {
|
|
|
18
18
|
@include gl-font-weight-bold;
|
|
19
19
|
@include gl-text-gray-900;
|
|
20
20
|
|
|
21
|
-
&.gl-text-right >
|
|
22
|
-
@include gl-display-flex;
|
|
21
|
+
&.gl-text-right > div {
|
|
23
22
|
flex-direction: row-reverse;
|
|
24
23
|
|
|
25
|
-
|
|
24
|
+
div.gl-ml-2 {
|
|
26
25
|
@include gl-ml-0;
|
|
27
|
-
@include gl-mr-
|
|
26
|
+
@include gl-mr-2;
|
|
28
27
|
}
|
|
29
28
|
}
|
|
30
29
|
|
|
@@ -129,6 +128,14 @@ table.gl-table {
|
|
|
129
128
|
&.table-hover td.table-secondary:hover {
|
|
130
129
|
background-color: $gray-10;
|
|
131
130
|
}
|
|
131
|
+
|
|
132
|
+
thead th:hover {
|
|
133
|
+
background-color: transparent !important;
|
|
134
|
+
|
|
135
|
+
[name='sort-icon'] {
|
|
136
|
+
display: flex !important;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
132
139
|
}
|
|
133
140
|
|
|
134
141
|
.table.b-table > thead > tr > th,
|
|
@@ -27,7 +27,10 @@ describe('GlTable', () => {
|
|
|
27
27
|
};
|
|
28
28
|
|
|
29
29
|
const findBTable = () => wrapper.findComponent(BTable);
|
|
30
|
-
const
|
|
30
|
+
const findColHeaderAt = (index) => findBTable().find('thead').findAll('th').at(index);
|
|
31
|
+
const findFirstColHeader = () => findColHeaderAt(0);
|
|
32
|
+
const findSortIconForHeaderAt = (index) =>
|
|
33
|
+
findColHeaderAt(index).find('[data-testid="sort-icon"]');
|
|
31
34
|
|
|
32
35
|
afterEach(() => {
|
|
33
36
|
logWarning.mockClear();
|
|
@@ -80,19 +83,31 @@ describe('GlTable', () => {
|
|
|
80
83
|
});
|
|
81
84
|
|
|
82
85
|
describe('sortable columns', () => {
|
|
83
|
-
const
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
86
|
+
const fields = [
|
|
87
|
+
{
|
|
88
|
+
key: 'name',
|
|
89
|
+
label: 'Name column',
|
|
90
|
+
sortable: true,
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
key: 'age',
|
|
94
|
+
label: 'Age column',
|
|
95
|
+
sortable: true,
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
key: 'email',
|
|
99
|
+
label: 'Email column',
|
|
100
|
+
sortable: false,
|
|
101
|
+
},
|
|
102
|
+
];
|
|
88
103
|
|
|
89
104
|
describe('without custom slots', () => {
|
|
90
105
|
beforeEach(() => {
|
|
91
|
-
factory({ mountFn: mount, props: { fields
|
|
106
|
+
factory({ mountFn: mount, props: { fields } });
|
|
92
107
|
});
|
|
93
108
|
|
|
94
109
|
it('sets the correct column label', () => {
|
|
95
|
-
expect(findFirstColHeader().text()).toMatch(
|
|
110
|
+
expect(findFirstColHeader().text()).toMatch(fields[0].label);
|
|
96
111
|
});
|
|
97
112
|
|
|
98
113
|
it('renders the ascending sort icon', async () => {
|
|
@@ -112,6 +127,40 @@ describe('GlTable', () => {
|
|
|
112
127
|
|
|
113
128
|
expect(headerText).toContain('↓');
|
|
114
129
|
});
|
|
130
|
+
|
|
131
|
+
it('sets initial sorting column using the sortBy property', () => {
|
|
132
|
+
factory({ mountFn: mount, props: { fields, sortBy: 'age' } });
|
|
133
|
+
|
|
134
|
+
expect(findSortIconForHeaderAt(0).classes()).toContain('gl-display-none');
|
|
135
|
+
expect(findSortIconForHeaderAt(1).classes()).not.toContain('gl-display-none');
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
it('sets initial sorting direction using the sortDesc property', () => {
|
|
139
|
+
factory({
|
|
140
|
+
mountFn: mount,
|
|
141
|
+
props: { fields, sortBy: 'age', sortDesc: true },
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
expect(findColHeaderAt(1).text()).toContain('↓');
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
it('does not render sort icon for non-sortable columns', () => {
|
|
148
|
+
expect(findSortIconForHeaderAt(2).exists()).toBe(false);
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
describe('changing the active sort column', () => {
|
|
152
|
+
it('hides sorting icon in previous active sort column', async () => {
|
|
153
|
+
await findColHeaderAt(0).trigger('click');
|
|
154
|
+
|
|
155
|
+
expect(findSortIconForHeaderAt(0).classes()).not.toContain('gl-display-none');
|
|
156
|
+
expect(findSortIconForHeaderAt(1).classes()).toContain('gl-display-none');
|
|
157
|
+
|
|
158
|
+
await findColHeaderAt(1).trigger('click');
|
|
159
|
+
|
|
160
|
+
expect(findSortIconForHeaderAt(0).classes()).toContain('gl-display-none');
|
|
161
|
+
expect(findSortIconForHeaderAt(1).classes()).not.toContain('gl-display-none');
|
|
162
|
+
});
|
|
163
|
+
});
|
|
115
164
|
});
|
|
116
165
|
|
|
117
166
|
describe('when headers are customized via slots', () => {
|
|
@@ -121,7 +170,7 @@ describe('GlTable', () => {
|
|
|
121
170
|
factory({
|
|
122
171
|
mountFn: mount,
|
|
123
172
|
props: {
|
|
124
|
-
fields
|
|
173
|
+
fields,
|
|
125
174
|
},
|
|
126
175
|
scopedSlots: {
|
|
127
176
|
'head(name)': `<div>${customSlotContent}</div>`,
|
|
@@ -73,11 +73,22 @@ export default {
|
|
|
73
73
|
isSortable({ field }) {
|
|
74
74
|
return field?.sortable;
|
|
75
75
|
},
|
|
76
|
+
activeSortingColumn({ field }) {
|
|
77
|
+
return this.localSortBy === field?.key;
|
|
78
|
+
},
|
|
76
79
|
getSortingIcon({ field }) {
|
|
77
|
-
if (this.
|
|
78
|
-
|
|
80
|
+
if (this.activeSortingColumn({ field })) {
|
|
81
|
+
if (this.localSortDesc) {
|
|
82
|
+
return '↓';
|
|
83
|
+
}
|
|
84
|
+
return '↑';
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (this.$attrs['sort-direction'] === 'desc') {
|
|
88
|
+
return '↓';
|
|
79
89
|
}
|
|
80
|
-
|
|
90
|
+
|
|
91
|
+
return '↑';
|
|
81
92
|
},
|
|
82
93
|
},
|
|
83
94
|
};
|
|
@@ -96,27 +107,21 @@ export default {
|
|
|
96
107
|
<slot :name="slotName" v-bind="scope"></slot>
|
|
97
108
|
</template>
|
|
98
109
|
<template v-for="headSlotName in headSlots" #[headSlotName]="scope">
|
|
99
|
-
<
|
|
110
|
+
<div :key="headSlotName" class="gl-display-flex">
|
|
100
111
|
<slot :name="headSlotName" v-bind="scope"
|
|
101
112
|
><span>{{ scope.label }}</span></slot
|
|
102
113
|
><template v-if="isSortable(scope)">
|
|
103
|
-
<
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
class="gl-ml-3 gl-min-w-5 gl-text-gray-900 gl-text-center"
|
|
113
|
-
name="sort-icon"
|
|
114
|
-
>
|
|
115
|
-
↓
|
|
116
|
-
</span>
|
|
117
|
-
<span v-else class="gl-display-inline-block gl-w-5 gl-h-3 gl-ml-3"></span>
|
|
114
|
+
<div class="gl-ml-2 gl-w-5 gl-text-gray-900 gl-display-flex gl-justify-content-center">
|
|
115
|
+
<span
|
|
116
|
+
name="sort-icon"
|
|
117
|
+
data-testid="sort-icon"
|
|
118
|
+
:class="{ 'gl-display-none': !activeSortingColumn(scope) }"
|
|
119
|
+
>
|
|
120
|
+
{{ getSortingIcon(scope) }}
|
|
121
|
+
</span>
|
|
122
|
+
</div>
|
|
118
123
|
</template>
|
|
119
|
-
</
|
|
124
|
+
</div>
|
|
120
125
|
</template>
|
|
121
126
|
</b-table>
|
|
122
127
|
</template>
|