vtex / shoreline

Design System for the VTEX Admin, previously called Admin UI
https://shoreline.vtex.com
15 stars 0 forks source link

Charts #1636

Open natanfernandes opened 1 month ago

natanfernandes commented 1 month ago

Problem

Some of our admin applications currently utilize the same chart library (Recharts), but each application has implemented it differently. This fragmentation in implementation can affect our development process, user experience, and overall system efficiency (RFC). By addressing these problems, we can achieve a more cohesive and maintainable charting solution across all applications.

Solution

We've evaluated popular chart libraries to identify the one that best meets our needs in terms of features, performance, and ease of use, all of these points are in a RFC. At the final, we've decided that Echarts is the one that match our needs.

The main solution, consists in make a wrapper for Echarts lib, adding base styles for most used charts (Bar, Line for ex), in order to make a ready to use chart without any setup or customization, following the patterns and foundations of the chart library Figma made by our Design team, this would allow us to focus on mastering one tool, increasing efficiency and reducing learning curves.

Explain

At the final, what we're actually doing is:

defaultTheme: {... bar: { itemStyle: { borderRadius: [4, 4, 0, 0], }, }, }

chart.tsx <ReactECharts theme={defaultTheme} />

* Accept the options (same as the original `echarts` props), so the implementer can edit and override
* Create variants and default series styles, because some of styles are only changed in the series object (eg: horizontal bar chart):

```js
theme/defaultStyles.ts

horizontal: {
  xAxis: {
    type: 'value',
  },
  yAxis: {
    type: 'category',
  },
  series: {
    type: 'bar',
    itemStyle: {
      borderRadius: [0, 4, 4, 0],
    },
  },
},

export const buildDefaultSerie = ( serie: SeriesOption | SeriesOption[], type: ChartTypes, variant: ChartVariants ): SeriesOption => { const seriesClone = structuredClone(serie) const defaultStylesClone = structuredClone(CHART_STYLES[type][variant].series) const serieMerged = merge(defaultStylesClone, seriesClone) as SeriesOption

return serieMerged }

export const formatSeries = ( series: SeriesOption | SeriesOption[] | undefined, type: ChartTypes, variant: ChartVariants ) => { if (!series) return if (Array.isArray(series)) { return series.map((serie) => buildDefaultSerie(serie, type, variant)) }

return buildDefaultSerie(series, type, variant) }

export const getChartOptions = ( options: EChartsOption, type: ChartTypes, variant: ChartVariants ): EChartsOption | undefined => { if (!options) return const { series, ...rest } = options

const { series: defaultSeries, ...defaulRest } = CHART_STYLES[type][variant]

const formattedSeries = formatSeries(series, type, variant)

const mergedOptions = merge(defaulRest, rest)

return { ...mergedOptions, series: formattedSeries } }

chart.tsx

const chartOptions: EChartsOption = useMemo(() => { return getChartOptions(option, type, variant) || option }, [option, type, variant])

<ReactECharts theme={defaultTheme} option={chartOptions} />

### Usage examples

At the bottom level, we'll have a base chart component, that wraps the base setup and functionalities of Echarts for any chart, [which is already open](https://github.com/vtex/shoreline/pull/1648).

And, we can use the base chart component to create the others and add their default styles:

```js
<Chart 
  option={{
    xAxis: {
      data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
    },
    series: {
      data: [1, 2, 3, 4, 5, 6, 7]
    }
  }} 
  type="bar" 
  style={{
    height: 550
  }} 
/>

With this basic component setup, we can create the base chart passing just the data for the xAxis and the data itself: Captura de Tela 2024-06-11 às 16 20 11

But, the final user can decide to edit the chart on your own:

<Chart option={{
    xAxis: {
      data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
    },
    series: [{
      data: [1, 2, 3, 4, 5, 6, 7]
    }, {
      data: [1, 4, 2, 1, 4, 3, 5],
      type: 'line'
    }]
  }} type="bar" variant="default" style={{
    height: 550
  }} />

Captura de Tela 2024-06-11 às 16 32 53

Dependencies

As main dependency we have Echarts, which is the library that we're wrapping for our charts

References

RFC about charting library choose for Healthmonitor Figma presentation

natanfernandes commented 1 month ago

TODO: explore a little bit more themes, setting the default values for each chart type in themes

beatrizmilhomem commented 2 weeks ago

Hello, @natanfernandes ! In a discussion with the maintainers, we've decided it would be better to block this issue for now. We understand that the initiative has advanced a lot and the design is in the final stages, but the approval from the maintainers is still pending on the design side. We are aligning with the designers so that can happen and everything is ready for you to move on. If you have any questions, please contact any of the maintainers!