storybook/stories/small_multiples/4_vertical_bars.story.tsx (135 lines of code) (raw):

/* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * or more contributor license agreements. Licensed under the Elastic License * 2.0 and the Server Side Public License, v 1; you may not use this file except * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ import { action } from '@storybook/addon-actions'; import { boolean } from '@storybook/addon-knobs'; import { DateTime } from 'luxon'; import React from 'react'; import { ScaleType, Position, Chart, Axis, GroupBy, SmallMultiples, Settings, BarSeries, LineAnnotation, AnnotationDomainType, LIGHT_THEME, LineSeries, } from '@elastic/charts'; import { SeededDataGenerator } from '@elastic/charts/src/mocks/utils'; import { ColorVariant } from '@elastic/charts/src/utils/common'; import type { ChartsStory } from '../../types'; import { useBaseTheme } from '../../use_base_theme'; const dg = new SeededDataGenerator(); const numOfDays = 7; function generateData(totalGroups: number, mappings: Record<string, string>) { return dg.generateGroupedSeries(numOfDays, totalGroups).map((d) => { return { ...d, x: DateTime.fromFormat(`${d.x + 1}`, 'E').toFormat('EEEE'), y: Math.floor(d.y * 10), g: mappings[d.g], }; }); } const data1 = generateData(2, { a: 'new user', b: 'existing user' }).map((d) => ({ ...d, site: 'website A' })); const data2 = generateData(2, { a: 'new user', b: 'existing user' }).map((d) => ({ ...d, site: 'website B' })); const datal1 = generateData(2, { a: 'avg new user', b: 'avg existing user' }).map((d) => ({ ...d, site: 'website A', })); const datal2 = generateData(2, { a: 'avg new user', b: 'avg existing user' }).map((d) => ({ ...d, site: 'website B', })); export const Example: ChartsStory = (_, { title, description }) => { const marker = ( <span style={{ backgroundColor: 'lightgray', padding: 2, width: 30, height: 10, margin: 'auto', fontSize: 8, borderRadius: 2, }} > MIN </span> ); const showLegend = boolean('Show Legend', true); const onElementClick = action('onElementClick'); return ( <Chart title={title} description={description}> <Settings onElementClick={onElementClick} showLegend={showLegend} baseTheme={useBaseTheme()} /> <Axis id="time" title="Day of week" position={Position.Bottom} gridLine={{ visible: false }} /> <Axis id="y" title="Count of logins" position={Position.Left} gridLine={{ visible: false }} /> <GroupBy id="h_split" by={(spec, datum) => { return datum.site; }} sort="alphaAsc" /> <SmallMultiples splitVertically="h_split" /> <LineAnnotation dataValues={[ { dataValue: 100, details: 'Minimum # of connected users', }, ]} id="threshold" domainType={AnnotationDomainType.YDomain} marker={marker} style={{ line: { dash: [5, 10], stroke: 'black', opacity: 0.8, strokeWidth: 1, }, }} /> <BarSeries id="website a" xScaleType={ScaleType.Ordinal} yScaleType={ScaleType.Linear} timeZone="local" xAccessor="x" yAccessors={['y']} stackAccessors={['x']} splitSeriesAccessors={['g']} data={[...data1, ...data2]} color={[LIGHT_THEME.colors.vizColors[0], 'lightgray']} /> <LineSeries id="avg" xScaleType={ScaleType.Ordinal} yScaleType={ScaleType.Linear} timeZone="local" xAccessor="x" yAccessors={['y']} splitSeriesAccessors={['g']} data={[...datal1, ...datal2]} lineSeriesStyle={{ point: { radius: 1, fill: ColorVariant.Series, }, }} color={['black', 'darkgray']} /> </Chart> ); }; Example.parameters = { markdown: `Similarly to the Vertical Areas example, the above chart shows an example of small multiples technique that splits our dataset into multiple sub-series horizontally positioned one aside the other. In this case, the \`<GroupBy />\` id is used to specify the horizontal split via the \`splitHorizontally\` prop. As for single charts, we can merge and handle multiple data-series together and specify a \`by\` accessor to consider the specific case. An additional property \`sort\` is available to configure the sorting order of the vertical or horizontal split. `, };