Skip to content

Commit

Permalink
feat: auto legend resize (#316)
Browse files Browse the repository at this point in the history
* Remove UI legend toggle. `showLegend` prop on settings unchanged.
* allow content to set size
* refactor: measure vert legend width with static buffer
* fix: legend toggle issue for top/bottom legends
* Refactor css flex styles to use grid for more shinny UI!=
* Remove legendId, fix safari max-height inheritance issue, remove uneeded legendList styles, revert empty state flex value.
* remove unused styles

BREAKING CHANGE: `theme.legend.spacingBuffer` added to `Theme` type. Controls the width buffer between the legend label and value.

#268
  • Loading branch information
nickofthyme authored Aug 21, 2019
1 parent 2b838d7 commit 659d27e
Show file tree
Hide file tree
Showing 33 changed files with 495 additions and 438 deletions.
1 change: 1 addition & 0 deletions .playground/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Charts Playground</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Document</title>
Expand Down
184 changes: 113 additions & 71 deletions .playground/playgroud.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React from 'react';
import { loremIpsum } from 'lorem-ipsum';

import {
Axis,
Expand All @@ -9,88 +10,129 @@ import {
Position,
ScaleType,
Settings,
LineSeries,
AreaSeries,
mergeWithDefaultTheme,
} from '../src';
import { KIBANA_METRICS } from '../src/utils/data_samples/test_dataset_kibana';
import { CursorEvent } from '../src/specs/settings';
import { CursorUpdateListener } from '../src/chart_types/xy_chart/store/chart_state';

export class Playground extends React.Component {
ref1 = React.createRef<Chart>();
ref2 = React.createRef<Chart>();
ref3 = React.createRef<Chart>();

onCursorUpdate: CursorUpdateListener = (event?: CursorEvent) => {
this.ref1.current!.dispatchExternalCursorEvent(event);
this.ref2.current!.dispatchExternalCursorEvent(event);
this.ref3.current!.dispatchExternalCursorEvent(event);
};

render() {
return (
<>
{renderChart(
'1',
this.ref1,
KIBANA_METRICS.metrics.kibana_os_load[0].data.slice(0, 15),
this.onCursorUpdate,
true,
)}
{renderChart(
'2',
this.ref2,
KIBANA_METRICS.metrics.kibana_os_load[1].data.slice(0, 15),
this.onCursorUpdate,
true,
)}
{renderChart('2', this.ref3, KIBANA_METRICS.metrics.kibana_os_load[1].data.slice(15, 30), this.onCursorUpdate)}
</>
);
return <>{this.renderChart(Position.Bottom)}</>;
}
}

function renderChart(
key: string,
ref: React.RefObject<Chart>,
data: any,
onCursorUpdate?: CursorUpdateListener,
timeSeries: boolean = false,
) {
return (
<div key={key} className="chart">
<Chart ref={ref}>
<Settings tooltip={{ type: 'vertical' }} debug={false} showLegend={true} onCursorUpdate={onCursorUpdate} />
<Axis
id={getAxisId('timestamp')}
title="timestamp"
position={Position.Bottom}
tickFormat={niceTimeFormatter([1555819200000, 1555905600000])}
/>
<Axis id={getAxisId('count')} title="count" position={Position.Left} tickFormat={(d) => d.toFixed(2)} />
<LineSeries
id={getSpecId('dataset A with long title')}
xScaleType={timeSeries ? ScaleType.Time : ScaleType.Linear}
renderChart(legendPosition: Position) {
const renderMore = () => {
const random = Math.floor(Math.random() * 3) + 1;
const id = loremIpsum({ count: random, units: 'words' });
return (
<AreaSeries
id={getSpecId(id)}
xScaleType={ScaleType.Time}
yScaleType={ScaleType.Linear}
data={data}
data={KIBANA_METRICS.metrics.kibana_os_load[0].data.slice(0, 15)}
xAccessor={0}
lineSeriesStyle={{
areaSeriesStyle={{
point: {
visible: true,
strokeWidth: 3,
radius: 10,
},
line: {
stroke: 'red',
opacity: 1,
strokeWidth: 10,
},
}}
yAccessors={[1]}
/>
<LineSeries
id={getSpecId('dataset B')}
xScaleType={ScaleType.Time}
yScaleType={ScaleType.Linear}
data={KIBANA_METRICS.metrics.kibana_os_load[1].data.slice(0, 15)}
xAccessor={0}
yAccessors={[1]}
stackAccessors={[0]}
/>
</Chart>
</div>
);
);
};
const theme = mergeWithDefaultTheme({
lineSeriesStyle: {
line: {
stroke: 'violet',
strokeWidth: 4,
},
point: {
fill: 'yellow',
stroke: 'black',
strokeWidth: 2,
radius: 6,
},
},
});
return (
<div className="chart">
<Chart>
<Settings debug={false} showLegend={true} legendPosition={legendPosition} rotation={0} theme={theme} />
<Axis
id={getAxisId('timestamp')}
title="timestamp"
position={Position.Bottom}
tickFormat={niceTimeFormatter([1555819200000, 1555905600000])}
/>
<Axis id={getAxisId('count')} title="count" position={Position.Left} tickFormat={(d) => d.toFixed(2)} />

<AreaSeries
id={getSpecId('dataset B')}
xScaleType={ScaleType.Time}
yScaleType={ScaleType.Linear}
data={KIBANA_METRICS.metrics.kibana_os_load[1].data.slice(0, 15)}
xAccessor={0}
yAccessors={[1]}
stackAccessors={[0]}
areaSeriesStyle={{
line: {
// opacity:1,
strokeWidth: 10,
},
point: {
visible: true,
strokeWidth: 3,
radius: 10,
},
}}
/>
<AreaSeries
id={getSpecId('dataset C')}
xScaleType={ScaleType.Time}
yScaleType={ScaleType.Linear}
data={KIBANA_METRICS.metrics.kibana_os_load[1].data.slice(0, 15)}
xAccessor={0}
yAccessors={[1]}
stackAccessors={[0]}
areaSeriesStyle={{
line: {
// opacity:1,
strokeWidth: 10,
},
point: {
visible: true,
strokeWidth: 3,
radius: 10,
},
}}
/>
<AreaSeries
id={getSpecId('dataset A')}
xScaleType={ScaleType.Time}
yScaleType={ScaleType.Linear}
data={KIBANA_METRICS.metrics.kibana_os_load[0].data.slice(0, 15)}
xAccessor={0}
areaSeriesStyle={{
point: {
visible: true,
strokeWidth: 3,
radius: 10,
},
line: {
strokeWidth: 10,
},
}}
yAccessors={[1]}
/>
{Array(10)
.fill(null)
.map(renderMore)}
</Chart>
</div>
);
}
}
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@
"husky": "^1.3.1",
"jest": "^24.1.0",
"jest-environment-jsdom-fourteen": "^0.1.0",
"lorem-ipsum": "^2.0.3",
"node-sass": "^4.11.0",
"postcss-cli": "^6.1.3",
"prettier": "1.16.4",
Expand Down
12 changes: 2 additions & 10 deletions src/chart_types/xy_chart/store/chart_state.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,14 +108,6 @@ describe('Chart Store', () => {
expect(axesTicks.get(AXIS_ID)).not.toBeUndefined();
});

test('can toggle legend visibility', () => {
store.toggleLegendCollapsed();
expect(store.legendCollapsed.get()).toBe(true);

store.toggleLegendCollapsed();
expect(store.legendCollapsed.get()).toBe(false);
});

test('can set legend visibility', () => {
store.showLegend.set(false);
store.setShowLegend(true);
Expand Down Expand Up @@ -509,7 +501,7 @@ describe('Chart Store', () => {
};

localStore.computeChart();
expect(localStore.initialized.get()).toBe(false);
expect(localStore.chartInitialized.get()).toBe(false);
});

test('only computes chart if series specs exist', () => {
Expand All @@ -524,7 +516,7 @@ describe('Chart Store', () => {

localStore.seriesSpecs = new Map();
localStore.computeChart();
expect(localStore.initialized.get()).toBe(false);
expect(localStore.chartInitialized.get()).toBe(false);
});

test('can set the color for a series', () => {
Expand Down
32 changes: 15 additions & 17 deletions src/chart_types/xy_chart/store/chart_state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,8 @@ export class ChartStore {
debug = false;
id = uuid.v4();
specsInitialized = observable.box(false);
initialized = observable.box(false);
chartInitialized = observable.box(false);
legendInitialized = observable.box(false);
enableHistogramMode = observable.box(false);

parentDimensions: Dimensions = {
Expand Down Expand Up @@ -232,15 +233,9 @@ export class ChartStore {
canDataBeAnimated = false;

showLegend = observable.box(false);
legendCollapsed = observable.box(false);
legendPosition: Position | undefined;
legendPosition = observable.box<Position>(Position.Right);
showLegendDisplayValue = observable.box(true);

toggleLegendCollapsed = action(() => {
this.legendCollapsed.set(!this.legendCollapsed.get());
this.computeChart();
});

/**
* determine if crosshair cursor should be visible based on cursor position and brush enablement
*/
Expand Down Expand Up @@ -833,7 +828,7 @@ export class ChartStore {
}

computeChart() {
this.initialized.set(false);
this.chartInitialized.set(false);
// compute only if parent dimensions are computed
if (this.parentDimensions.width === 0 || this.parentDimensions.height === 0) {
return;
Expand Down Expand Up @@ -879,6 +874,14 @@ export class ChartStore {
this.deselectedDataSeries,
);

if (!this.legendInitialized.get()) {
this.legendInitialized.set(true);

if (this.legendItems.size > 0 && this.showLegend.get()) {
return;
}
}

this.isChartEmpty = isAllSeriesDeselected(this.legendItems);

const { xDomain, yDomain, formattedDataSeries } = this.seriesDomainsAndData;
Expand Down Expand Up @@ -913,14 +916,12 @@ export class ChartStore {
});
bboxCalculator.destroy();

// // compute chart dimensions
// compute chart dimensions
const computedChartDims = computeChartDimensions(
this.parentDimensions,
this.chartTheme,
this.axesTicksDimensions,
this.axesSpecs,
this.showLegend.get() && !this.legendCollapsed.get(),
this.legendPosition,
);
this.chartDimensions = computedChartDims.chartDimensions;

Expand All @@ -940,7 +941,6 @@ export class ChartStore {
this.enableHistogramMode.get(),
);

// tslint:disable-next-line:no-console
this.geometries = seriesGeometries.geometries;
this.xScale = seriesGeometries.scales.xScale;

Expand All @@ -958,17 +958,15 @@ export class ChartStore {
computedChartDims,
this.chartTheme,
this.chartRotation,
this.showLegend.get() && !this.legendCollapsed.get(),
this.axesSpecs,
this.axesTicksDimensions,
xDomain,
yDomain,
totalBarsInCluster,
this.enableHistogramMode.get(),
this.legendPosition,
barsPadding,
);
// tslint:disable-next-line:no-console

this.axesPositions = axisTicksPositions.axisPositions;
this.axesTicks = axisTicksPositions.axisTicks;
this.axesVisibleTicks = axisTicksPositions.axisVisibleTicks;
Expand All @@ -992,6 +990,6 @@ export class ChartStore {
// temporary disabled until
// https://github.com/elastic/elastic-charts/issues/89 and https://github.com/elastic/elastic-charts/issues/41
this.canDataBeAnimated = false;
this.initialized.set(true);
this.chartInitialized.set(true);
}
}
Loading

0 comments on commit 659d27e

Please sign in to comment.