@gitlab/ui 56.2.1 → 56.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.
Files changed (60) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/dist/components/base/form/form_checkbox/form_checkbox_group.js +1 -1
  3. package/dist/components/base/form/form_radio_group/form_radio_group.js +1 -1
  4. package/dist/components/base/popover/popover.js +6 -1
  5. package/dist/components/base/table/table.js +12 -1
  6. package/dist/components/base/table_lite/table_lite.js +13 -2
  7. package/dist/components/charts/area/area.js +17 -3
  8. package/dist/components/charts/bar/bar.js +17 -3
  9. package/dist/components/charts/chart/chart.js +3 -0
  10. package/dist/components/charts/column/column.js +17 -3
  11. package/dist/components/charts/discrete_scatter/discrete_scatter.js +17 -2
  12. package/dist/components/charts/gauge/gauge.js +1 -1
  13. package/dist/components/charts/heatmap/heatmap.js +17 -3
  14. package/dist/components/charts/line/line.js +17 -3
  15. package/dist/components/charts/sparkline/sparkline.js +11 -4
  16. package/dist/components/charts/stacked_column/stacked_column.js +17 -3
  17. package/dist/index.css +2 -2
  18. package/dist/index.css.map +1 -1
  19. package/dist/utils/charts/constants.js +5 -1
  20. package/package.json +7 -7
  21. package/scss_to_js/scss_variables.js +1 -0
  22. package/scss_to_js/scss_variables.json +5 -0
  23. package/src/components/base/form/form_checkbox/form_checkbox_group.vue +1 -1
  24. package/src/components/base/form/form_input/form_input.scss +0 -5
  25. package/src/components/base/form/form_radio_group/form_radio_group.vue +1 -1
  26. package/src/components/base/form/form_select/form_select.scss +1 -6
  27. package/src/components/base/popover/popover.vue +6 -0
  28. package/src/components/base/table/table.spec.js +12 -1
  29. package/src/components/base/table/table.vue +11 -1
  30. package/src/components/base/table_lite/table_lite.spec.js +21 -0
  31. package/src/components/base/table_lite/table_lite.vue +9 -1
  32. package/src/components/charts/area/area.spec.js +9 -0
  33. package/src/components/charts/area/area.stories.js +3 -0
  34. package/src/components/charts/area/area.vue +22 -2
  35. package/src/components/charts/bar/bar.spec.js +11 -2
  36. package/src/components/charts/bar/bar.stories.js +21 -7
  37. package/src/components/charts/bar/bar.vue +22 -3
  38. package/src/components/charts/chart/chart.vue +3 -0
  39. package/src/components/charts/column/column.stories.js +3 -0
  40. package/src/components/charts/column/column.vue +26 -3
  41. package/src/components/charts/column/column_chart.spec.js +9 -0
  42. package/src/components/charts/discrete_scatter/discrete_scatter.spec.js +41 -0
  43. package/src/components/charts/discrete_scatter/discrete_scatter.stories.js +3 -0
  44. package/src/components/charts/discrete_scatter/discrete_scatter.vue +22 -2
  45. package/src/components/charts/gauge/gauge.stories.js +5 -2
  46. package/src/components/charts/gauge/gauge.vue +1 -3
  47. package/src/components/charts/heatmap/heatmap.spec.js +25 -5
  48. package/src/components/charts/heatmap/heatmap.stories.js +3 -0
  49. package/src/components/charts/heatmap/heatmap.vue +22 -3
  50. package/src/components/charts/line/line.spec.js +9 -0
  51. package/src/components/charts/line/line.stories.js +3 -0
  52. package/src/components/charts/line/line.vue +22 -2
  53. package/src/components/charts/sparkline/sparkline.spec.js +28 -1
  54. package/src/components/charts/sparkline/sparkline.stories.js +18 -10
  55. package/src/components/charts/sparkline/sparkline.vue +14 -3
  56. package/src/components/charts/stacked_column/stacked_column.spec.js +9 -0
  57. package/src/components/charts/stacked_column/stacked_column.stories.js +3 -0
  58. package/src/components/charts/stacked_column/stacked_column.vue +22 -2
  59. package/src/scss/variables.scss +1 -0
  60. package/src/utils/charts/constants.js +4 -0
@@ -0,0 +1,41 @@
1
+ import { shallowMount } from '@vue/test-utils';
2
+ import { createMockChartInstance } from '~helpers/chart_stubs';
3
+ import { expectHeightAutoClasses } from '~helpers/chart_height';
4
+ import Chart from '../chart/chart.vue';
5
+ import DiscreteScatterChart from './discrete_scatter.vue';
6
+
7
+ let mockChartInstance;
8
+
9
+ jest.mock('echarts', () => ({
10
+ getInstanceByDom: () => mockChartInstance,
11
+ }));
12
+
13
+ describe('column chart component', () => {
14
+ const defaultChartProps = {
15
+ xAxisTitle: 'x axis',
16
+ yAxisTitle: 'y axis',
17
+ xAxisType: 'category',
18
+ data: [['19 May', 6.95]],
19
+ };
20
+ let wrapper;
21
+
22
+ const findChart = () => wrapper.findComponent(Chart);
23
+
24
+ const createComponent = (props = {}) => {
25
+ wrapper = shallowMount(DiscreteScatterChart, {
26
+ propsData: { ...defaultChartProps, ...props },
27
+ });
28
+ };
29
+
30
+ beforeEach(() => {
31
+ mockChartInstance = createMockChartInstance();
32
+ });
33
+
34
+ describe('height', () => {
35
+ expectHeightAutoClasses({
36
+ createComponent,
37
+ findContainer: () => wrapper,
38
+ findChart,
39
+ });
40
+ });
41
+ });
@@ -10,6 +10,7 @@ const Template = (args, { argTypes }) => ({
10
10
  :y-axis-title="yAxisTitle"
11
11
  :x-axis-title="xAxisTitle"
12
12
  data-testid="discrete-scatter-chart"
13
+ :height="height"
13
14
  />
14
15
  `,
15
16
  });
@@ -32,11 +33,13 @@ const generateProps = ({
32
33
  option = {},
33
34
  yAxisTitle = 'Pushes per day',
34
35
  xAxisTitle = 'Date',
36
+ height = null,
35
37
  } = {}) => ({
36
38
  data,
37
39
  option,
38
40
  yAxisTitle,
39
41
  xAxisTitle,
42
+ height,
40
43
  });
41
44
 
42
45
  export const Default = Template.bind({});
@@ -8,6 +8,7 @@ import {
8
8
  } from '../../../utils/charts/config';
9
9
  import { colorFromDefaultPalette } from '../../../utils/charts/theme';
10
10
  import { debounceByAnimationFrame } from '../../../utils/utils';
11
+ import { HEIGHT_AUTO_CLASSES } from '../../../utils/charts/constants';
11
12
  import TooltipDefaultFormat from '../../shared_components/charts/tooltip_default_format.vue';
12
13
  import Chart from '../chart/chart.vue';
13
14
  import ChartTooltip from '../tooltip/tooltip.vue';
@@ -47,6 +48,14 @@ export default {
47
48
  required: false,
48
49
  default: null,
49
50
  },
51
+ /**
52
+ * Sets the chart's height in pixels. Set to `"auto"` to use the height of the container.
53
+ */
54
+ height: {
55
+ type: [Number, String],
56
+ required: false,
57
+ default: null,
58
+ },
50
59
  },
51
60
  data() {
52
61
  return {
@@ -121,6 +130,9 @@ export default {
121
130
  // needs to be handled specially
122
131
  return mergeSeriesToOptions(mergedOptions, this.series);
123
132
  },
133
+ autoHeight() {
134
+ return this.height === 'auto';
135
+ },
124
136
  },
125
137
  methods: {
126
138
  defaultFormatTooltipText(params) {
@@ -160,11 +172,19 @@ export default {
160
172
  }
161
173
  },
162
174
  },
175
+ HEIGHT_AUTO_CLASSES,
163
176
  };
164
177
  </script>
165
178
  <template>
166
- <div class="position-relative">
167
- <chart v-bind="$attrs" :options="options" v-on="$listeners" @created="onCreated" />
179
+ <div class="position-relative" :class="{ [$options.HEIGHT_AUTO_CLASSES]: autoHeight }">
180
+ <chart
181
+ v-bind="$attrs"
182
+ :class="{ 'gl-flex-grow-1': autoHeight }"
183
+ :height="height"
184
+ :options="options"
185
+ v-on="$listeners"
186
+ @created="onCreated"
187
+ />
168
188
  <chart-tooltip
169
189
  v-if="chart"
170
190
  :show="showTooltip"
@@ -3,14 +3,15 @@ import readme from './gauge.md';
3
3
  import GlGauge from './gauge.vue';
4
4
 
5
5
  const template = `
6
- <gl-gauge
6
+ <gl-gauge
7
7
  :value="value"
8
8
  :min="min"
9
9
  :max="max"
10
10
  :thresholds="thresholds"
11
11
  :text="text"
12
12
  :splitNumber="splitNumber"
13
- :option="option"
13
+ :option="option"
14
+ :height="height"
14
15
  />
15
16
  `;
16
17
 
@@ -22,6 +23,7 @@ const generateProps = ({
22
23
  option = {},
23
24
  thresholds = [38, 82],
24
25
  splitNumber = 10,
26
+ height = null,
25
27
  } = {}) => ({
26
28
  option,
27
29
  value,
@@ -30,6 +32,7 @@ const generateProps = ({
30
32
  thresholds,
31
33
  text,
32
34
  splitNumber,
35
+ height,
33
36
  });
34
37
 
35
38
  const Template = (args, { argTypes }) => ({
@@ -173,7 +173,5 @@ export default {
173
173
  </script>
174
174
 
175
175
  <template>
176
- <div>
177
- <chart v-bind="$attrs" :options="options" v-on="$listeners" @created="onCreated" />
178
- </div>
176
+ <chart v-bind="$attrs" :options="options" v-on="$listeners" @created="onCreated" />
179
177
  </template>
@@ -2,6 +2,7 @@ import { shallowMount } from '@vue/test-utils';
2
2
 
3
3
  import { TOOLTIP_LEFT_OFFSET } from '~/utils/charts/constants';
4
4
  import { createMockChartInstance } from '~helpers/chart_stubs';
5
+ import { expectHeightAutoClasses } from '~helpers/chart_height';
5
6
  import Chart from '../chart/chart.vue';
6
7
  import ChartTooltip from '../tooltip/tooltip.vue';
7
8
  import HeatMapChart from './heatmap.vue';
@@ -21,23 +22,34 @@ describe('heatmap component', () => {
21
22
 
22
23
  const emitChartCreated = () => findChart().vm.$emit('created', mockChartInstance);
23
24
 
24
- beforeEach(() => {
25
- mockChartInstance = createMockChartInstance();
26
-
25
+ const createComponent = (props = {}) => {
27
26
  wrapper = shallowMount(HeatMapChart, {
28
- propsData: { options: { series: [] }, dataSeries: [] },
27
+ propsData: {
28
+ options: { series: [] },
29
+ dataSeries: [],
30
+ ...props,
31
+ },
29
32
  });
33
+
30
34
  emitChartCreated();
35
+ };
31
36
 
32
- return wrapper.vm.$nextTick();
37
+ beforeEach(async () => {
38
+ mockChartInstance = createMockChartInstance();
33
39
  });
34
40
 
35
41
  it('emits `created`, with the chart instance', () => {
42
+ createComponent();
43
+
36
44
  expect(wrapper.emitted('created').length).toBe(1);
37
45
  expect(wrapper.emitted('created')[0][0]).toBe(mockChartInstance);
38
46
  });
39
47
 
40
48
  describe('tooltip position', () => {
49
+ beforeEach(() => {
50
+ createComponent();
51
+ });
52
+
41
53
  it('is initialized', () => {
42
54
  expect(findChartTooltip().props('left')).toBe('0');
43
55
  expect(findChartTooltip().props('top')).toBe('0');
@@ -64,4 +76,12 @@ describe('heatmap component', () => {
64
76
  });
65
77
  });
66
78
  });
79
+
80
+ describe('height', () => {
81
+ expectHeightAutoClasses({
82
+ createComponent,
83
+ findContainer: () => wrapper,
84
+ findChart,
85
+ });
86
+ });
67
87
  });
@@ -24,6 +24,7 @@ const template = `
24
24
  :x-axis-name="xAxisName"
25
25
  :y-axis-name="yAxisName"
26
26
  :options="options"
27
+ :height="height"
27
28
  />
28
29
  `;
29
30
 
@@ -34,6 +35,7 @@ const generateProps = ({
34
35
  xAxisName = 'Hour',
35
36
  yAxisName = 'Day',
36
37
  options = {},
38
+ height = null,
37
39
  } = {}) => ({
38
40
  data,
39
41
  xAxisLabels,
@@ -41,6 +43,7 @@ const generateProps = ({
41
43
  xAxisName,
42
44
  yAxisName,
43
45
  options,
46
+ height,
44
47
  });
45
48
 
46
49
  const Template = (args, { argTypes }) => ({
@@ -3,7 +3,7 @@
3
3
  import merge from 'lodash/merge';
4
4
  import { white, gray100 } from '../../../../scss_to_js/scss_variables';
5
5
  import { getDefaultTooltipContent } from '../../../utils/charts/config';
6
- import { TOOLTIP_LEFT_OFFSET } from '../../../utils/charts/constants';
6
+ import { TOOLTIP_LEFT_OFFSET, HEIGHT_AUTO_CLASSES } from '../../../utils/charts/constants';
7
7
  import { heatmapHues } from '../../../utils/charts/theme';
8
8
  import { engineeringNotation } from '../../../utils/number_utils';
9
9
  import { debounceByAnimationFrame } from '../../../utils/utils';
@@ -98,6 +98,14 @@ export default {
98
98
  required: false,
99
99
  default: true,
100
100
  },
101
+ /**
102
+ * Sets the chart's height in pixels. Set to `"auto"` to use the height of the container.
103
+ */
104
+ height: {
105
+ type: [Number, String],
106
+ required: false,
107
+ default: null,
108
+ },
101
109
  },
102
110
  data() {
103
111
  return {
@@ -210,6 +218,9 @@ export default {
210
218
  };
211
219
  });
212
220
  },
221
+ autoHeight() {
222
+ return this.height === 'auto';
223
+ },
213
224
  },
214
225
  beforeDestroy() {
215
226
  this.chart.getDom().removeEventListener('mousemove', this.debouncedShowHideTooltip);
@@ -249,12 +260,20 @@ export default {
249
260
  }
250
261
  },
251
262
  },
263
+ HEIGHT_AUTO_CLASSES,
252
264
  };
253
265
  </script>
254
266
 
255
267
  <template>
256
- <div class="gl-heatmap">
257
- <chart v-bind="$attrs" :options="computedOptions" @created="onCreated" v-on="$listeners" />
268
+ <div class="gl-heatmap" :class="{ [$options.HEIGHT_AUTO_CLASSES]: autoHeight }">
269
+ <chart
270
+ v-bind="$attrs"
271
+ :class="{ 'gl-flex-grow-1': autoHeight }"
272
+ :height="height"
273
+ :options="computedOptions"
274
+ @created="onCreated"
275
+ v-on="$listeners"
276
+ />
258
277
  <chart-tooltip
259
278
  v-if="chart"
260
279
  :show="tooltip.show"
@@ -2,6 +2,7 @@ import { shallowMount } from '@vue/test-utils';
2
2
 
3
3
  import { LEGEND_LAYOUT_INLINE, LEGEND_LAYOUT_TABLE } from '~/utils/charts/constants';
4
4
  import { createMockChartInstance, ChartTooltipStub } from '~helpers/chart_stubs';
5
+ import { expectHeightAutoClasses } from '~helpers/chart_height';
5
6
  import Chart from '../chart/chart.vue';
6
7
  import ChartLegend from '../legend/legend.vue';
7
8
  import LineChart from './line.vue';
@@ -205,4 +206,12 @@ describe('line component', () => {
205
206
  expect(findLegend().exists()).toBe(false);
206
207
  });
207
208
  });
209
+
210
+ describe('height', () => {
211
+ expectHeightAutoClasses({
212
+ createComponent: createShallowWrapper,
213
+ findContainer: () => wrapper,
214
+ findChart,
215
+ });
216
+ });
208
217
  });
@@ -63,6 +63,7 @@ const template = `<gl-line-chart
63
63
  :annotations="annotations"
64
64
  :includeLegendAvgMax="includeLegendAvgMax"
65
65
  :showLegend="showLegend"
66
+ :height="height"
66
67
  />`;
67
68
 
68
69
  const generateProps = ({
@@ -72,6 +73,7 @@ const generateProps = ({
72
73
  annotations = [],
73
74
  includeLegendAvgMax = true,
74
75
  showLegend = true,
76
+ height = null,
75
77
  } = {}) => ({
76
78
  showLegend,
77
79
  includeLegendAvgMax,
@@ -79,6 +81,7 @@ const generateProps = ({
79
81
  thresholds,
80
82
  annotations,
81
83
  data,
84
+ height,
82
85
  });
83
86
 
84
87
  const Template = (_args, { argTypes }) => ({
@@ -41,6 +41,7 @@ import {
41
41
  LEGEND_CURRENT_TEXT,
42
42
  LEGEND_MIN_TEXT,
43
43
  LEGEND_MAX_TEXT,
44
+ HEIGHT_AUTO_CLASSES,
44
45
  } from '../../../utils/charts/constants';
45
46
  import { colorFromDefaultPalette } from '../../../utils/charts/theme';
46
47
  import { seriesHasAnnotations, isDataPointAnnotation } from '../../../utils/charts/utils';
@@ -121,6 +122,14 @@ export default {
121
122
  required: false,
122
123
  default: true,
123
124
  },
125
+ /**
126
+ * Sets the chart's height in pixels. Set to `"auto"` to use the height of the container.
127
+ */
128
+ height: {
129
+ type: [Number, String],
130
+ required: false,
131
+ default: null,
132
+ },
124
133
  },
125
134
  data() {
126
135
  // Part of the tooltip related data can be
@@ -249,6 +258,9 @@ export default {
249
258
  return acc;
250
259
  }, []);
251
260
  },
261
+ autoHeight() {
262
+ return this.height === 'auto';
263
+ },
252
264
  },
253
265
  beforeDestroy() {
254
266
  this.chart.getDom().removeEventListener('mousemove', this.debouncedShowHideTooltip);
@@ -330,12 +342,20 @@ export default {
330
342
  this.selectedFormatTooltipText(params);
331
343
  },
332
344
  },
345
+ HEIGHT_AUTO_CLASSES,
333
346
  };
334
347
  </script>
335
348
 
336
349
  <template>
337
- <div class="position-relative">
338
- <chart v-bind="$attrs" :options="options" v-on="$listeners" @created="onCreated" />
350
+ <div class="position-relative" :class="{ [$options.HEIGHT_AUTO_CLASSES]: autoHeight }">
351
+ <chart
352
+ v-bind="$attrs"
353
+ :class="{ 'gl-flex-grow-1': autoHeight }"
354
+ :height="height"
355
+ :options="options"
356
+ v-on="$listeners"
357
+ @created="onCreated"
358
+ />
339
359
  <chart-tooltip
340
360
  v-if="shouldShowAnnotationsTooltip"
341
361
  id="annotationsTooltip"
@@ -1,6 +1,8 @@
1
1
  import { shallowMount } from '@vue/test-utils';
2
2
  import { waitForAnimationFrame } from '~/utils/test_utils';
3
+ import { HEIGHT_AUTO_HORIZONTAL_LAYOUT_CLASSES } from '~/utils/charts/constants';
3
4
  import { createMockChartInstance, ChartTooltipStub } from '~helpers/chart_stubs';
5
+ import { expectHeightAutoClasses } from '~helpers/chart_height';
4
6
  import Chart from '../chart/chart.vue';
5
7
  import SparklineChart from './sparkline.vue';
6
8
 
@@ -25,11 +27,12 @@ jest.mock('~/directives/resize_observer/resize_observer', () => ({
25
27
  describe('sparkline chart component', () => {
26
28
  let wrapper;
27
29
  let componentOptions;
28
- const factory = () => {
30
+ const factory = (props = {}) => {
29
31
  componentOptions = {
30
32
  propsData: {
31
33
  data: [[]],
32
34
  variant: null,
35
+ ...props,
33
36
  },
34
37
  scopedSlots: { latestSeriesEntry: jest.fn() },
35
38
  stubs: {
@@ -43,6 +46,7 @@ describe('sparkline chart component', () => {
43
46
  // helpers
44
47
  const getByTestId = (id) => wrapper.find(`[data-testid="${id}"]`);
45
48
  const getChart = () => wrapper.findComponent(Chart);
49
+ const getChartContainer = () => getByTestId('chart-container');
46
50
 
47
51
  const getTooltip = () => wrapper.findComponent(ChartTooltipStub);
48
52
  const getTooltipTitle = () => getByTestId('tooltip-title');
@@ -212,4 +216,27 @@ describe('sparkline chart component', () => {
212
216
  expect(getChartOptions().series[0].smooth).toBe(smooth);
213
217
  });
214
218
  });
219
+
220
+ describe('height', () => {
221
+ expectHeightAutoClasses({
222
+ createComponent: factory,
223
+ findContainer: getChartContainer,
224
+ findChart: getChart,
225
+ classes: HEIGHT_AUTO_HORIZONTAL_LAYOUT_CLASSES,
226
+ });
227
+
228
+ describe('sparkline root element style', () => {
229
+ it('does not set the root element style to height full', () => {
230
+ factory();
231
+
232
+ expect(wrapper.element.classList.value).not.toContain('gl-h-full');
233
+ });
234
+
235
+ it('set the root element style to height full when height is "auto"', () => {
236
+ factory({ height: 'auto' });
237
+
238
+ expect(wrapper.element.classList.value).toContain('gl-h-full');
239
+ });
240
+ });
241
+ });
215
242
  });
@@ -1,5 +1,6 @@
1
1
  import { GlSparklineChart } from '../../../charts';
2
2
  import { colorFromDefaultPalette } from '../../../utils/charts/theme';
3
+ import { makeContainer } from '../../../utils/story_decorators/container';
3
4
  import readme from './sparkline.md';
4
5
 
5
6
  const chartData = [
@@ -38,16 +39,15 @@ const Template = (args) => ({
38
39
  components: { GlSparklineChart },
39
40
  props: Object.keys(args),
40
41
  template: `
41
- <div>
42
- <gl-sparkline-chart
43
- :data="data"
44
- :height="height"
45
- :tooltip-label="tooltipLabel"
46
- :show-last-y-value="showLastYValue"
47
- :gradient="gradient"
48
- :smooth="smooth"
49
- />
50
- </div>`,
42
+ <gl-sparkline-chart
43
+ :data="data"
44
+ :height="height"
45
+ :tooltip-label="tooltipLabel"
46
+ :show-last-y-value="showLastYValue"
47
+ :gradient="gradient"
48
+ :smooth="smooth"
49
+ />
50
+ `,
51
51
  });
52
52
 
53
53
  export const Default = Template.bind({});
@@ -62,6 +62,14 @@ WithChartColorGradient.args = generateProps({ gradient: customGradient });
62
62
  export const WithSmoothing = Template.bind({});
63
63
  WithSmoothing.args = generateProps({ smooth: 0.5 });
64
64
 
65
+ export const AutoHeight = Template.bind({});
66
+ Object.assign(AutoHeight, {
67
+ args: generateProps({
68
+ height: 'auto',
69
+ }),
70
+ decorators: [makeContainer({ height: '300px' })],
71
+ });
72
+
65
73
  export default {
66
74
  title: 'charts/sparkline-chart',
67
75
  component: GlSparklineChart,
@@ -8,6 +8,7 @@ import {
8
8
  mergeSeriesToOptions,
9
9
  symbolSize,
10
10
  } from '../../../utils/charts/config';
11
+ import { HEIGHT_AUTO_HORIZONTAL_LAYOUT_CLASSES } from '../../../utils/charts/constants';
11
12
  import Chart from '../chart/chart.vue';
12
13
  import ChartTooltip from '../tooltip/tooltip.vue';
13
14
 
@@ -49,10 +50,10 @@ export default {
49
50
  default: '',
50
51
  },
51
52
  /**
52
- * Sets the chart's height in pixel.
53
+ * Sets the chart's height in pixels. Set to `"auto"` to use the height of the container.
53
54
  */
54
55
  height: {
55
- type: Number,
56
+ type: [Number, String],
56
57
  required: false,
57
58
  default: 50,
58
59
  },
@@ -169,6 +170,9 @@ export default {
169
170
 
170
171
  return latestEntry[1];
171
172
  },
173
+ autoHeight() {
174
+ return this.height === 'auto';
175
+ },
172
176
  },
173
177
  methods: {
174
178
  onChartCreated(chartInstance) {
@@ -215,6 +219,7 @@ export default {
215
219
  }
216
220
  },
217
221
  },
222
+ HEIGHT_AUTO_HORIZONTAL_LAYOUT_CLASSES,
218
223
  };
219
224
  </script>
220
225
 
@@ -222,12 +227,18 @@ export default {
222
227
  <div
223
228
  v-resize-observer="handleResize"
224
229
  class="gl-display-flex gl-align-items-center"
230
+ :class="{ 'gl-h-full': autoHeight }"
225
231
  @mouseleave="hideTooltip"
226
232
  >
227
233
  <slot name="default"></slot>
228
- <div class="gl-flex-grow-1 gl-relative">
234
+ <div
235
+ data-testid="chart-container"
236
+ class="gl-flex-grow-1 gl-relative"
237
+ :class="{ [$options.HEIGHT_AUTO_HORIZONTAL_LAYOUT_CLASSES]: autoHeight }"
238
+ >
229
239
  <chart
230
240
  v-bind="$attrs"
241
+ :class="{ 'gl-flex-grow-1': autoHeight }"
231
242
  :height="height"
232
243
  :options="options"
233
244
  @created="onChartCreated"
@@ -2,6 +2,7 @@ import { shallowMount } from '@vue/test-utils';
2
2
 
3
3
  import TooltipDefaultFormat from '~/components/shared_components/charts/tooltip_default_format.vue';
4
4
  import { createMockChartInstance, ChartTooltipStub } from '~helpers/chart_stubs';
5
+ import { expectHeightAutoClasses } from '~helpers/chart_height';
5
6
  import { LEGEND_LAYOUT_INLINE, LEGEND_LAYOUT_TABLE } from '~/utils/charts/constants';
6
7
  import {
7
8
  mockDefaultStackedLineData,
@@ -279,4 +280,12 @@ describe('stacked column chart component', () => {
279
280
  });
280
281
  });
281
282
  });
283
+
284
+ describe('height', () => {
285
+ expectHeightAutoClasses({
286
+ createComponent: (props) => createShallowWrapper({ props }),
287
+ findContainer: () => wrapper,
288
+ findChart,
289
+ });
290
+ });
282
291
  });
@@ -20,6 +20,7 @@ const template = `
20
20
  :y-axis-title="yAxisTitle"
21
21
  :secondary-data="secondaryData"
22
22
  :secondary-data-title="secondaryDataTitle"
23
+ :height="height"
23
24
  />
24
25
  `;
25
26
 
@@ -36,6 +37,7 @@ const generateProps = ({
36
37
  presentation = columnOptions.stacked,
37
38
  secondaryData = [],
38
39
  secondaryDataTitle = '',
40
+ height = null,
39
41
  } = {}) => ({
40
42
  bars,
41
43
  lines,
@@ -47,6 +49,7 @@ const generateProps = ({
47
49
  yAxisTitle,
48
50
  secondaryDataTitle,
49
51
  secondaryData,
52
+ height,
50
53
  });
51
54
 
52
55
  const Template = (args, { argTypes }) => ({
@@ -19,6 +19,7 @@ import {
19
19
  LEGEND_MAX_TEXT,
20
20
  CHART_TYPE_LINE,
21
21
  ANNOTATION_TOOLTIP_TOP_OFFSET,
22
+ HEIGHT_AUTO_CLASSES,
22
23
  } from '../../../utils/charts/constants';
23
24
  import { colorFromDefaultPalette } from '../../../utils/charts/theme';
24
25
  import { columnOptions } from '../../../utils/constants';
@@ -136,6 +137,14 @@ export default {
136
137
  required: false,
137
138
  default: null,
138
139
  },
140
+ /**
141
+ * Sets the chart's height in pixels. Set to `"auto"` to use the height of the container.
142
+ */
143
+ height: {
144
+ type: [Number, String],
145
+ required: false,
146
+ default: null,
147
+ },
139
148
  },
140
149
  data() {
141
150
  return {
@@ -246,6 +255,9 @@ export default {
246
255
  return acc;
247
256
  }, []);
248
257
  },
258
+ autoHeight() {
259
+ return this.height === 'auto';
260
+ },
249
261
  },
250
262
  beforeDestroy() {
251
263
  this.chart.getDom().removeEventListener('mousemove', this.debouncedMoveShowTooltip);
@@ -295,11 +307,19 @@ export default {
295
307
  }
296
308
  },
297
309
  },
310
+ HEIGHT_AUTO_CLASSES,
298
311
  };
299
312
  </script>
300
313
  <template>
301
- <div class="position-relative">
302
- <chart v-bind="$attrs" :options="options" v-on="$listeners" @created="onCreated" />
314
+ <div class="position-relative" :class="{ [$options.HEIGHT_AUTO_CLASSES]: autoHeight }">
315
+ <chart
316
+ v-bind="$attrs"
317
+ :class="{ 'gl-flex-grow-1': autoHeight }"
318
+ :height="height"
319
+ :options="options"
320
+ v-on="$listeners"
321
+ @created="onCreated"
322
+ />
303
323
  <chart-tooltip
304
324
  v-if="chart"
305
325
  :show="showTooltip"
@@ -484,6 +484,7 @@ $modal-backdrop-opacity: 0.64;
484
484
  // these should ideally be moved further up in the file to the compoent-relevant sections
485
485
  // but they can wait here for now
486
486
  $body-color: $gl-text-color !default;
487
+ $enable-validation-icons: false;
487
488
 
488
489
  $secondary: $gray-50;
489
490
  $success: $green-500;