@gitlab/ui 59.3.0 → 59.3.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.
@@ -119,11 +119,13 @@ function isDev() {
119
119
  /**
120
120
  * Prints a warning message to the console in non-test and non-production environments.
121
121
  * @param {string} message message to print to the console
122
+ * @param {HTMLElement} element component that triggered the warning
122
123
  */
123
124
  function logWarning() {
124
125
  let message = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
126
+ let element = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
125
127
  if (message.length && isDev()) {
126
- console.warn(message); // eslint-disable-line no-console
128
+ console.warn(message, element); // eslint-disable-line no-console
127
129
  }
128
130
  }
129
131
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gitlab/ui",
3
- "version": "59.3.0",
3
+ "version": "59.3.2",
4
4
  "description": "GitLab UI Components",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",
@@ -119,9 +119,9 @@
119
119
  "bootstrap": "4.6.2",
120
120
  "cypress": "^11.2.0",
121
121
  "emoji-regex": "^10.0.0",
122
- "eslint": "8.36.0",
122
+ "eslint": "8.37.0",
123
123
  "eslint-import-resolver-jest": "3.0.2",
124
- "eslint-plugin-cypress": "2.12.1",
124
+ "eslint-plugin-cypress": "2.13.2",
125
125
  "eslint-plugin-storybook": "0.6.11",
126
126
  "file-loader": "^4.2.0",
127
127
  "glob": "^7.2.0",
@@ -121,7 +121,10 @@ export default {
121
121
  mounted() {
122
122
  // eslint-disable-next-line @gitlab/vue-prefer-dollar-scopedslots
123
123
  if (!this.$slots.default && !this.$attrs['aria-label'] && !this.$props.label) {
124
- logWarning('[gl-button]: Accessible name missing. Please add inner text or aria-label.');
124
+ logWarning(
125
+ '[gl-button]: Accessible name missing. Please add inner text or aria-label.',
126
+ this.$el
127
+ );
125
128
  }
126
129
  },
127
130
  };
@@ -113,7 +113,8 @@ export default {
113
113
  mounted() {
114
114
  if (!this.ariaLabel && !this.title) {
115
115
  logWarning(
116
- '[gl-modal]: Accessible name for modal missing. Please add title prop or aria-label.'
116
+ '[gl-modal]: Accessible name for modal missing. Please add title prop or aria-label.',
117
+ this.$el
117
118
  );
118
119
  }
119
120
  },
@@ -92,6 +92,13 @@ describe('base dropdown', () => {
92
92
  wrapper.destroy();
93
93
  expect(destroyPopper).toHaveBeenCalled();
94
94
  });
95
+
96
+ it('should not destroy popper instance when component is not initiated', async () => {
97
+ buildWrapper();
98
+ wrapper.destroy();
99
+ await nextTick();
100
+ expect(destroyPopper).not.toHaveBeenCalled();
101
+ });
95
102
  });
96
103
 
97
104
  describe('renders content to the default slot', () => {
@@ -214,14 +214,15 @@ export default {
214
214
  this.checkToggleFocusable();
215
215
  },
216
216
  beforeDestroy() {
217
- this.popper.destroy();
217
+ this.popper?.destroy();
218
218
  },
219
219
  methods: {
220
220
  checkToggleFocusable() {
221
221
  if (!isElementFocusable(this.toggleElement) && !isElementTabbable(this.toggleElement)) {
222
222
  logWarning(
223
223
  `GlDisclosureDropdown/GlCollapsibleListbox: Toggle is missing a 'tabindex' and cannot be focused.
224
- Use 'a' or 'button' element instead or make sure to add 'role="button"' along with 'tabindex' otherwise.`
224
+ Use 'a' or 'button' element instead or make sure to add 'role="button"' along with 'tabindex' otherwise.`,
225
+ this.$el
225
226
  );
226
227
  }
227
228
  },
@@ -7,8 +7,15 @@ describe('GlSkeletonLoader', () => {
7
7
  const findDefaultLines = () => wrapper.findAll('clipPath rect');
8
8
  const findSvg = () => wrapper.find('svg');
9
9
 
10
- const createComponent = (options = {}) => {
11
- wrapper = shallowMount(GlSkeletonLoader, options);
10
+ const createComponent = ({ propsData, slots, reducedMotion } = {}) => {
11
+ Object.defineProperty(window, 'matchMedia', {
12
+ writable: true,
13
+ value: jest.fn().mockImplementation(() => ({
14
+ matches: reducedMotion,
15
+ })),
16
+ });
17
+
18
+ wrapper = shallowMount(GlSkeletonLoader, { propsData, slots });
12
19
  };
13
20
 
14
21
  describe('when default skeleton is used', () => {
@@ -126,4 +133,19 @@ describe('GlSkeletonLoader', () => {
126
133
  });
127
134
  });
128
135
  });
136
+
137
+ it.each`
138
+ reducedMotion | hasLinearGradient
139
+ ${false} | ${'has'}
140
+ ${true} | ${'does not have'}
141
+ `(
142
+ '$hasLinearGradient linear-gradient when reduced motion is $reducedMotion',
143
+ ({ reducedMotion }) => {
144
+ createComponent({ reducedMotion });
145
+
146
+ const gradient = wrapper.find('linearGradient');
147
+
148
+ expect(gradient.exists()).toBe(!reducedMotion);
149
+ }
150
+ );
129
151
  });
@@ -106,6 +106,8 @@ export default {
106
106
  return `${DEFAULT_LINE_WIDTH_PERCENTAGES[index % DEFAULT_LINE_WIDTH_PERCENTAGES.length]}%`;
107
107
  };
108
108
 
109
+ const reducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
110
+
109
111
  const svg = createElement(
110
112
  'svg',
111
113
  {
@@ -122,13 +124,15 @@ export default {
122
124
  [
123
125
  createElement('title', {}, ['Loading']),
124
126
  createElement('rect', {
125
- style: { fill: `url(${props.baseUrl}#${props.uniqueKey}-idGradient)` },
126
127
  attrs: {
127
128
  'clip-path': `url(${props.baseUrl}#${props.uniqueKey}-idClip)`,
128
129
  x: 0,
129
130
  y: 0,
130
131
  width: width(),
131
132
  height: height(),
133
+ ...(reducedMotion
134
+ ? { class: 'gl-fill-gray-100' }
135
+ : { fill: `url(${props.baseUrl}#${props.uniqueKey}-idGradient)` }),
132
136
  },
133
137
  }),
134
138
  createElement('defs', {}, [
@@ -153,73 +157,74 @@ export default {
153
157
  })
154
158
  )
155
159
  ),
156
- createElement(
157
- 'linearGradient',
158
- {
159
- attrs: {
160
- id: `${props.uniqueKey}-idGradient`,
161
- },
162
- },
163
- [
164
- createElement(
165
- 'stop',
166
- {
167
- class: 'primary-stop',
168
- attrs: {
169
- offset: '0%',
170
- },
160
+ !reducedMotion &&
161
+ createElement(
162
+ 'linearGradient',
163
+ {
164
+ attrs: {
165
+ id: `${props.uniqueKey}-idGradient`,
171
166
  },
172
- [
173
- createElement('animate', {
167
+ },
168
+ [
169
+ createElement(
170
+ 'stop',
171
+ {
172
+ class: 'primary-stop',
174
173
  attrs: {
175
- attributeName: 'offset',
176
- values: '-2; 1',
177
- dur: '1s',
178
- repeatCount: 'indefinite',
174
+ offset: '0%',
179
175
  },
180
- }),
181
- ]
182
- ),
183
- createElement(
184
- 'stop',
185
- {
186
- class: 'secondary-stop',
187
- attrs: {
188
- offset: '50%',
189
176
  },
190
- },
191
- [
192
- createElement('animate', {
177
+ [
178
+ createElement('animate', {
179
+ attrs: {
180
+ attributeName: 'offset',
181
+ values: '-2; 1',
182
+ dur: '1s',
183
+ repeatCount: 'indefinite',
184
+ },
185
+ }),
186
+ ]
187
+ ),
188
+ createElement(
189
+ 'stop',
190
+ {
191
+ class: 'secondary-stop',
193
192
  attrs: {
194
- attributeName: 'offset',
195
- values: '-1.5; 1.5',
196
- dur: '1s',
197
- repeatCount: 'indefinite',
193
+ offset: '50%',
198
194
  },
199
- }),
200
- ]
201
- ),
202
- createElement(
203
- 'stop',
204
- {
205
- class: 'primary-stop',
206
- attrs: {
207
- offset: '100%',
208
195
  },
209
- },
210
- [
211
- createElement('animate', {
196
+ [
197
+ createElement('animate', {
198
+ attrs: {
199
+ attributeName: 'offset',
200
+ values: '-1.5; 1.5',
201
+ dur: '1s',
202
+ repeatCount: 'indefinite',
203
+ },
204
+ }),
205
+ ]
206
+ ),
207
+ createElement(
208
+ 'stop',
209
+ {
210
+ class: 'primary-stop',
212
211
  attrs: {
213
- attributeName: 'offset',
214
- values: '-1; 2',
215
- dur: '1s',
216
- repeatCount: 'indefinite',
212
+ offset: '100%',
217
213
  },
218
- }),
219
- ]
220
- ),
221
- ]
222
- ),
214
+ },
215
+ [
216
+ createElement('animate', {
217
+ attrs: {
218
+ attributeName: 'offset',
219
+ values: '-1; 2',
220
+ dur: '1s',
221
+ repeatCount: 'indefinite',
222
+ },
223
+ }),
224
+ ]
225
+ ),
226
+ ]
227
+ ),
223
228
  ]),
224
229
  ]
225
230
  );
@@ -35,7 +35,7 @@ describe('GlTable', () => {
35
35
  factory();
36
36
  await waitForAnimationFrame();
37
37
 
38
- expect(logWarning).toHaveBeenCalledWith(glTableLiteWarning);
38
+ expect(logWarning).toHaveBeenCalledWith(glTableLiteWarning, wrapper.element);
39
39
  });
40
40
 
41
41
  it('should not log a warning when given a prop which qualifies for the usage of GlTable', async () => {
@@ -30,7 +30,7 @@ export default {
30
30
  // logWarning will call isDev before logging any message
31
31
  // this additional call to isDev is being made to exit the condition early when run in production
32
32
  if (isDev() && !shouldUseFullTable(this)) {
33
- logWarning(glTableLiteWarning);
33
+ logWarning(glTableLiteWarning, this.$el);
34
34
  }
35
35
  },
36
36
  };
@@ -7809,6 +7809,14 @@
7809
7809
  stroke: transparent !important
7810
7810
  }
7811
7811
 
7812
+ .gl-fill-gray-100 {
7813
+ fill: $gray-100
7814
+ }
7815
+
7816
+ .gl-fill-gray-100\! {
7817
+ fill: $gray-100 !important
7818
+ }
7819
+
7812
7820
  .gl-fill-gray-200 {
7813
7821
  fill: $gray-200
7814
7822
  }
@@ -46,6 +46,10 @@
46
46
  stroke: transparent;
47
47
  }
48
48
 
49
+ @mixin gl-fill-gray-100 {
50
+ fill: $gray-100;
51
+ }
52
+
49
53
  @mixin gl-fill-gray-200 {
50
54
  fill: $gray-200;
51
55
  }
@@ -130,10 +130,11 @@ export function isDev() {
130
130
  /**
131
131
  * Prints a warning message to the console in non-test and non-production environments.
132
132
  * @param {string} message message to print to the console
133
+ * @param {HTMLElement} element component that triggered the warning
133
134
  */
134
- export function logWarning(message = '') {
135
+ export function logWarning(message = '', element = '') {
135
136
  if (message.length && isDev()) {
136
- console.warn(message); // eslint-disable-line no-console
137
+ console.warn(message, element); // eslint-disable-line no-console
137
138
  }
138
139
  }
139
140