@gitlab/ui 79.3.0 → 79.4.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/base/breadcrumb/breadcrumb.js +31 -5
- 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 +1 -1
- package/src/components/base/breadcrumb/breadcrumb.spec.js +61 -7
- package/src/components/base/breadcrumb/breadcrumb.stories.js +2 -0
- package/src/components/base/breadcrumb/breadcrumb.vue +32 -5
- package/src/components/base/form/form_date/form_date.stories.js +10 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
# [79.4.0](https://gitlab.com/gitlab-org/gitlab-ui/compare/v79.3.0...v79.4.0) (2024-04-25)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* **GlBreadcrumb:** Fix containerWidth calc with ResizeObserver ([daa8013](https://gitlab.com/gitlab-org/gitlab-ui/commit/daa80133e1e56383fb857c12cc9384c553a2b389))
|
|
7
|
+
* **GlBreadcrumb:** Fix details in resize calc ([4025e2e](https://gitlab.com/gitlab-org/gitlab-ui/commit/4025e2e0af2a41aa843ccd7c6f1fae25fd2ac170))
|
|
8
|
+
* **GlBreadcrumb:** Watch autoResize prop and react to change ([b4808bf](https://gitlab.com/gitlab-org/gitlab-ui/commit/b4808bfaa59646a6155b394d4c22d4a1c85c6cfb))
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
* **GlBreadcrumb:** Add boolean prop to disable auto-resize ([0dad528](https://gitlab.com/gitlab-org/gitlab-ui/commit/0dad528cb2774c3c7bd9ccdafb7f9c8b00a88c23))
|
|
14
|
+
|
|
1
15
|
# [79.3.0](https://gitlab.com/gitlab-org/gitlab-ui/compare/v79.2.0...v79.3.0) (2024-04-25)
|
|
2
16
|
|
|
3
17
|
|
|
@@ -50,6 +50,14 @@ var script = {
|
|
|
50
50
|
type: String,
|
|
51
51
|
required: false,
|
|
52
52
|
default: () => translate('GlBreadcrumb.showMoreLabel', 'Show more breadcrumbs')
|
|
53
|
+
},
|
|
54
|
+
/**
|
|
55
|
+
* Allows to disable auto-resize behavior. Items will then overflow their container instead of being collapsed into a dropdown.
|
|
56
|
+
*/
|
|
57
|
+
autoResize: {
|
|
58
|
+
type: Boolean,
|
|
59
|
+
required: false,
|
|
60
|
+
default: true
|
|
53
61
|
}
|
|
54
62
|
},
|
|
55
63
|
data() {
|
|
@@ -97,17 +105,23 @@ var script = {
|
|
|
97
105
|
items: {
|
|
98
106
|
handler: 'measureAndMakeBreadcrumbsFit',
|
|
99
107
|
deep: true
|
|
108
|
+
},
|
|
109
|
+
autoResize(newValue) {
|
|
110
|
+
if (newValue) this.enableAutoResize();else this.disableAutoResize();
|
|
100
111
|
}
|
|
101
112
|
},
|
|
102
113
|
created() {
|
|
103
114
|
this.debounceMakeBreadcrumbsFit = debounce(this.makeBreadcrumbsFit, 25);
|
|
104
115
|
},
|
|
105
116
|
mounted() {
|
|
106
|
-
|
|
107
|
-
|
|
117
|
+
if (this.autoResize) {
|
|
118
|
+
this.enableAutoResize();
|
|
119
|
+
} else {
|
|
120
|
+
this.resizeDone = true;
|
|
121
|
+
}
|
|
108
122
|
},
|
|
109
123
|
beforeDestroy() {
|
|
110
|
-
|
|
124
|
+
this.disableAutoResize();
|
|
111
125
|
},
|
|
112
126
|
methods: {
|
|
113
127
|
resetItems() {
|
|
@@ -132,9 +146,9 @@ var script = {
|
|
|
132
146
|
this.resizeDone = false;
|
|
133
147
|
this.resetItems();
|
|
134
148
|
const containerWidth = this.$el.clientWidth;
|
|
135
|
-
const buttonWidth =
|
|
149
|
+
const buttonWidth = 40; // px
|
|
136
150
|
|
|
137
|
-
if (this.totalBreadcrumbsWidth
|
|
151
|
+
if (this.totalBreadcrumbsWidth > containerWidth) {
|
|
138
152
|
// Not all breadcrumb items fit. Start moving items over to the dropdown.
|
|
139
153
|
const startSlicingAt = 0;
|
|
140
154
|
|
|
@@ -158,6 +172,18 @@ var script = {
|
|
|
158
172
|
},
|
|
159
173
|
getAriaCurrentAttr(index) {
|
|
160
174
|
return this.isLastItem(index) ? 'page' : false;
|
|
175
|
+
},
|
|
176
|
+
enableAutoResize() {
|
|
177
|
+
this.resizeObserver || (this.resizeObserver = new ResizeObserver(this.debounceMakeBreadcrumbsFit));
|
|
178
|
+
this.resizeObserver.observe(this.$el);
|
|
179
|
+
this.measureAndMakeBreadcrumbsFit();
|
|
180
|
+
},
|
|
181
|
+
disableAutoResize() {
|
|
182
|
+
if (this.resizeObserver) {
|
|
183
|
+
this.resizeObserver.unobserve(this.$el);
|
|
184
|
+
this.resizeObserver = null;
|
|
185
|
+
}
|
|
186
|
+
this.resetItems();
|
|
161
187
|
}
|
|
162
188
|
}
|
|
163
189
|
};
|
package/dist/tokens/js/tokens.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
|
|
2
2
|
// Do not edit directly
|
|
3
|
-
// Generated on Thu, 25 Apr 2024
|
|
3
|
+
// Generated on Thu, 25 Apr 2024 15:30:17 GMT
|
|
4
4
|
|
|
5
5
|
$gl-text-color-disabled: #89888d !default; // Used for disabled text.
|
|
6
6
|
$gl-text-color-link: #63a6e9 !default; // Used for default text links.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
|
|
2
2
|
// Do not edit directly
|
|
3
|
-
// Generated on Thu, 25 Apr 2024
|
|
3
|
+
// Generated on Thu, 25 Apr 2024 15:30:17 GMT
|
|
4
4
|
|
|
5
5
|
$gl-text-color-disabled: #89888d !default; // Used for disabled text.
|
|
6
6
|
$gl-text-color-success: #217645 !default; // Used for text indicating success or validity.
|
package/package.json
CHANGED
|
@@ -29,6 +29,7 @@ describe('Breadcrumb component', () => {
|
|
|
29
29
|
const findAllAvatars = () => wrapper.findAll('[data-testid="avatar"]');
|
|
30
30
|
const findBreadcrumbItems = () => wrapper.findAllComponents(GlBreadcrumbItem);
|
|
31
31
|
const findOverflowDropdown = () => wrapper.findComponent(GlDisclosureDropdown);
|
|
32
|
+
const findOverflowingItems = () => wrapper.findAllComponents(GlDisclosureDropdownItem);
|
|
32
33
|
|
|
33
34
|
const findVisibleBreadcrumbItems = () =>
|
|
34
35
|
findBreadcrumbItems().wrappers.filter((item) => item.isVisible());
|
|
@@ -43,21 +44,24 @@ describe('Breadcrumb component', () => {
|
|
|
43
44
|
});
|
|
44
45
|
};
|
|
45
46
|
|
|
46
|
-
const
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
Object.defineProperty(wrapper.element, 'clientWidth', {
|
|
47
|
+
const mockElementWidth = (element, widthInPx) => {
|
|
48
|
+
Object.defineProperty(element, 'clientWidth', {
|
|
50
49
|
get: () => widthInPx,
|
|
51
|
-
configurable: true,
|
|
52
50
|
});
|
|
53
51
|
};
|
|
54
52
|
|
|
55
53
|
const mockWideWrapperWidth = () => {
|
|
56
|
-
|
|
54
|
+
mockElementWidth(wrapper.element, 1000);
|
|
57
55
|
};
|
|
58
56
|
|
|
59
57
|
const mockSmallWrapperWidth = () => {
|
|
60
|
-
|
|
58
|
+
mockElementWidth(wrapper.element, 1);
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
const mockItemsWidths = () => {
|
|
62
|
+
findBreadcrumbItems().wrappers.forEach((item) => {
|
|
63
|
+
mockElementWidth(item.element, 100);
|
|
64
|
+
});
|
|
61
65
|
};
|
|
62
66
|
|
|
63
67
|
describe('items', () => {
|
|
@@ -88,6 +92,7 @@ describe('Breadcrumb component', () => {
|
|
|
88
92
|
beforeEach(async () => {
|
|
89
93
|
createComponent({ items, showMoreLabel: 'More...' });
|
|
90
94
|
mockSmallWrapperWidth();
|
|
95
|
+
mockItemsWidths();
|
|
91
96
|
await wrapper.vm.$nextTick();
|
|
92
97
|
});
|
|
93
98
|
|
|
@@ -100,6 +105,7 @@ describe('Breadcrumb component', () => {
|
|
|
100
105
|
beforeEach(async () => {
|
|
101
106
|
createComponent();
|
|
102
107
|
mockSmallWrapperWidth();
|
|
108
|
+
mockItemsWidths();
|
|
103
109
|
await wrapper.vm.$nextTick();
|
|
104
110
|
});
|
|
105
111
|
|
|
@@ -109,6 +115,53 @@ describe('Breadcrumb component', () => {
|
|
|
109
115
|
});
|
|
110
116
|
});
|
|
111
117
|
|
|
118
|
+
describe('autoResize', () => {
|
|
119
|
+
describe('by default', () => {
|
|
120
|
+
beforeEach(async () => {
|
|
121
|
+
createComponent();
|
|
122
|
+
mockSmallWrapperWidth();
|
|
123
|
+
mockItemsWidths();
|
|
124
|
+
await wrapper.vm.$nextTick();
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
it('moves overflowing items into dropdown', () => {
|
|
128
|
+
expect(findOverflowDropdown().exists()).toBe(true);
|
|
129
|
+
expect(findOverflowingItems().length).toBeGreaterThan(0);
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it('reacts to prop changing to false', async () => {
|
|
133
|
+
expect(findOverflowDropdown().exists()).toBe(true);
|
|
134
|
+
await wrapper.setProps({ autoResize: false });
|
|
135
|
+
await wrapper.vm.$nextTick();
|
|
136
|
+
expect(findOverflowDropdown().exists()).toBe(false);
|
|
137
|
+
expect(findBreadcrumbItems().length).toEqual(items.length);
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
describe('when set to false', () => {
|
|
142
|
+
beforeEach(async () => {
|
|
143
|
+
createComponent({ items, autoResize: false });
|
|
144
|
+
mockSmallWrapperWidth();
|
|
145
|
+
mockItemsWidths();
|
|
146
|
+
await wrapper.vm.$nextTick();
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
it('keeps all items visible', () => {
|
|
150
|
+
expect(findOverflowDropdown().exists()).toBe(false);
|
|
151
|
+
expect(findBreadcrumbItems().length).toEqual(items.length);
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
it('reacts to prop changing to true', async () => {
|
|
155
|
+
expect(findOverflowDropdown().exists()).toBe(false);
|
|
156
|
+
await wrapper.setProps({ autoResize: true });
|
|
157
|
+
await wrapper.vm.$nextTick();
|
|
158
|
+
await wrapper.vm.$nextTick(); // otherwise test fails with VUE_VERSION=3
|
|
159
|
+
expect(findOverflowDropdown().exists()).toBe(true);
|
|
160
|
+
expect(findOverflowingItems().length).toBeGreaterThan(0);
|
|
161
|
+
});
|
|
162
|
+
});
|
|
163
|
+
});
|
|
164
|
+
|
|
112
165
|
describe('avatars', () => {
|
|
113
166
|
it('renders 2 avatars when 2 avatarPaths are passed', async () => {
|
|
114
167
|
createComponent();
|
|
@@ -169,6 +222,7 @@ describe('Breadcrumb component', () => {
|
|
|
169
222
|
beforeEach(async () => {
|
|
170
223
|
createComponent();
|
|
171
224
|
mockSmallWrapperWidth();
|
|
225
|
+
mockItemsWidths();
|
|
172
226
|
await wrapper.vm.$nextTick();
|
|
173
227
|
});
|
|
174
228
|
|
|
@@ -7,6 +7,7 @@ const template = `
|
|
|
7
7
|
<gl-breadcrumb
|
|
8
8
|
:items="items"
|
|
9
9
|
:aria-label="ariaLabel"
|
|
10
|
+
:auto-resize="autoResize"
|
|
10
11
|
/>
|
|
11
12
|
`;
|
|
12
13
|
|
|
@@ -15,6 +16,7 @@ const collapsedTemplate = `
|
|
|
15
16
|
<gl-breadcrumb
|
|
16
17
|
:items="items"
|
|
17
18
|
:aria-label="ariaLabel"
|
|
19
|
+
:auto-resize="autoResize"
|
|
18
20
|
/>
|
|
19
21
|
</div>
|
|
20
22
|
`;
|
|
@@ -48,6 +48,14 @@ export default {
|
|
|
48
48
|
required: false,
|
|
49
49
|
default: () => translate('GlBreadcrumb.showMoreLabel', 'Show more breadcrumbs'),
|
|
50
50
|
},
|
|
51
|
+
/**
|
|
52
|
+
* Allows to disable auto-resize behavior. Items will then overflow their container instead of being collapsed into a dropdown.
|
|
53
|
+
*/
|
|
54
|
+
autoResize: {
|
|
55
|
+
type: Boolean,
|
|
56
|
+
required: false,
|
|
57
|
+
default: true,
|
|
58
|
+
},
|
|
51
59
|
},
|
|
52
60
|
data() {
|
|
53
61
|
return {
|
|
@@ -89,16 +97,23 @@ export default {
|
|
|
89
97
|
handler: 'measureAndMakeBreadcrumbsFit',
|
|
90
98
|
deep: true,
|
|
91
99
|
},
|
|
100
|
+
autoResize(newValue) {
|
|
101
|
+
if (newValue) this.enableAutoResize();
|
|
102
|
+
else this.disableAutoResize();
|
|
103
|
+
},
|
|
92
104
|
},
|
|
93
105
|
created() {
|
|
94
106
|
this.debounceMakeBreadcrumbsFit = debounce(this.makeBreadcrumbsFit, 25);
|
|
95
107
|
},
|
|
96
108
|
mounted() {
|
|
97
|
-
|
|
98
|
-
|
|
109
|
+
if (this.autoResize) {
|
|
110
|
+
this.enableAutoResize();
|
|
111
|
+
} else {
|
|
112
|
+
this.resizeDone = true;
|
|
113
|
+
}
|
|
99
114
|
},
|
|
100
115
|
beforeDestroy() {
|
|
101
|
-
|
|
116
|
+
this.disableAutoResize();
|
|
102
117
|
},
|
|
103
118
|
methods: {
|
|
104
119
|
resetItems() {
|
|
@@ -126,9 +141,9 @@ export default {
|
|
|
126
141
|
this.resetItems();
|
|
127
142
|
|
|
128
143
|
const containerWidth = this.$el.clientWidth;
|
|
129
|
-
const buttonWidth =
|
|
144
|
+
const buttonWidth = 40; // px
|
|
130
145
|
|
|
131
|
-
if (this.totalBreadcrumbsWidth
|
|
146
|
+
if (this.totalBreadcrumbsWidth > containerWidth) {
|
|
132
147
|
// Not all breadcrumb items fit. Start moving items over to the dropdown.
|
|
133
148
|
const startSlicingAt = 0;
|
|
134
149
|
|
|
@@ -156,6 +171,18 @@ export default {
|
|
|
156
171
|
getAriaCurrentAttr(index) {
|
|
157
172
|
return this.isLastItem(index) ? 'page' : false;
|
|
158
173
|
},
|
|
174
|
+
enableAutoResize() {
|
|
175
|
+
this.resizeObserver ||= new ResizeObserver(this.debounceMakeBreadcrumbsFit);
|
|
176
|
+
this.resizeObserver.observe(this.$el);
|
|
177
|
+
this.measureAndMakeBreadcrumbsFit();
|
|
178
|
+
},
|
|
179
|
+
disableAutoResize() {
|
|
180
|
+
if (this.resizeObserver) {
|
|
181
|
+
this.resizeObserver.unobserve(this.$el);
|
|
182
|
+
this.resizeObserver = null;
|
|
183
|
+
}
|
|
184
|
+
this.resetItems();
|
|
185
|
+
},
|
|
159
186
|
},
|
|
160
187
|
};
|
|
161
188
|
</script>
|
|
@@ -1,10 +1,13 @@
|
|
|
1
|
+
import GlFormGroup from '../form_group/form_group.vue';
|
|
1
2
|
import readme from './form_date.md';
|
|
2
3
|
import GlFormDate from './form_date.vue';
|
|
3
4
|
|
|
4
5
|
const defaultValue = (prop) => GlFormDate.props[prop].default;
|
|
5
6
|
|
|
6
7
|
const template = `
|
|
8
|
+
<gl-form-group :label="labelText" :label-for="inputId">
|
|
7
9
|
<gl-form-date
|
|
10
|
+
:id="inputId"
|
|
8
11
|
v-model="localValue"
|
|
9
12
|
:disabled="disabled"
|
|
10
13
|
:min="min"
|
|
@@ -13,9 +16,12 @@ const template = `
|
|
|
13
16
|
:max-invalid-feedback="maxInvalidFeedback"
|
|
14
17
|
:readonly="readonly"
|
|
15
18
|
:value="value"
|
|
16
|
-
|
|
19
|
+
/>
|
|
20
|
+
</gl-form-group>`;
|
|
17
21
|
|
|
18
22
|
const generateProps = ({
|
|
23
|
+
inputId = 'input-id',
|
|
24
|
+
labelText = 'Label',
|
|
19
25
|
disabled = false,
|
|
20
26
|
min = '',
|
|
21
27
|
max = '',
|
|
@@ -24,6 +30,8 @@ const generateProps = ({
|
|
|
24
30
|
readonly = false,
|
|
25
31
|
value = '',
|
|
26
32
|
} = {}) => ({
|
|
33
|
+
inputId,
|
|
34
|
+
labelText,
|
|
27
35
|
disabled,
|
|
28
36
|
min,
|
|
29
37
|
max,
|
|
@@ -34,7 +42,7 @@ const generateProps = ({
|
|
|
34
42
|
});
|
|
35
43
|
|
|
36
44
|
const Template = (args) => ({
|
|
37
|
-
components: { GlFormDate },
|
|
45
|
+
components: { GlFormDate, GlFormGroup },
|
|
38
46
|
props: Object.keys(args),
|
|
39
47
|
watch: {
|
|
40
48
|
value(newValue) {
|