carbon-design-system / carbon-charts

:bar_chart: :chart_with_upwards_trend:⠀Robust dataviz framework implemented using D3 & typescript
https://charts.carbondesignsystem.com
Apache License 2.0
878 stars 182 forks source link

[Enhancement]: Ability to apply locale and translations to ticks, tooltips, and toolbar / Tabular representation #1635

Open nstuyvesant opened 11 months ago

nstuyvesant commented 11 months ago

User Story

As a developer, I want to apply international locales to ticks (both axes), tooltips, and the tabular data representation displayed by the toolbar. Currently, I have to write formatter functions for ticks.formatter, tooltip.valueFormatter and/or supply a date-fns localeObject for timeScaleOptions. The latter approach is limited to dates and relies on a bloated package which increases the bundle size of @carbon/charts. I also want @carbon/charts to adjust the display to my browser's navigator.language property unless the language is hard-coded by me.

Problems: I cannot change the format of numbers and dates in the Toolbar / Tabular representation or labels for Group, the title of the Tabular representation modal or exports. Also, I have to explicitly override multiple ticks and the tooltip values rather than doing it globally.

Technical Specs

For every chart type, I want a top-level property to options called locale. This property should have this interface:

interface Locale {
  code?: string // BCP 47 language tag 
  number?: (value: number) => string
  date?: (value: Date) => string
  translations?: {
    group?: string // used by Tooltip and Toolbar / Tabular Representation
    total? string // ditto
    toolbarTabularModalTitle?: string
    toolbarExportAsCSV?: string
    toolbarExportAsJPG?: string
    toolbarExportAsPNG?: string
  }
}

Defaults for optional properties would be as follows:

const locale: Locale = {
  code: navigator.language, // read from browser's navigator.language
  number:  (value) => value.toLocaleString(navigator.language), // based on code property if specified
  date: (value) => value.toLocaleDateString(navigator.language), // based on code property if specified
  translations: {
    group: 'Group',
    total: 'Total',
    toolbarTabularModalTitle: 'Tabular representation',
    toolbarExportAsCSV: 'Export to CSV',
    toolbarExportAsJPG: 'Export to JPG',
    toolbarExportAsPNG: 'Export to PNG'
  }
}

Example of setting options for a chart the old way...

const options = {
  title: 'Line (time series) - Time interval monthly with French locale',
  axes: {
    left: {
      ticks: {
        formatter: e => e.toLocaleString('fr-FR')
      }
    },
    bottom: {
      scaleType: 'time',
      ticks: {
        formatter: e => e.toLocaleDateString('fr-FR', { month: 'short', day: 'numeric' })
      }
    }
  },
  tooltip: {
    valueFormatter: e => e.toLocaleDateString('fr-FR', { month: 'long', day: 'numeric' })
  },
  legend: {
    clickable: false
  },
  height: '400px'
}

Example of the same thing with the new locale property...

const options = {
  title: 'Line (time series) - Time interval monthly with French locale',
  locale: {
    code: 'fr-FR',
    number: (value) => value.toLocaleString('fr-FR'), // could be omitted as this would be the default value
    date: (value) => value.toLocaleDateString('fr-FR', { month: 'short', 'day': 'numeric' }), // omitting would leave out the options
    translations: {
      group: 'Groupe',
      toolbarTabularModalTitle: 'Représentation tabulaire',
      toolbarExportAsCSV: 'Exporter vers CSV',
      toolbarExportAsJPG: 'Exporter vers JPG',
      toolbarExportAsPNG: 'Exporter vers PNG'
    }
  },
  axes: {
    left: {},
    bottom: {
      scaleType: 'time'
    }
  },
  legend: {
    clickable: false
  },
  height: '400px'
}

Justification

  1. Currently no way to override certain UI element labels.
  2. Currently no way to set date and number formats for Tabular representation modal
  3. You can set a localeObject based on date-fns but it only applies to TimeScaleOptions which only affects one axis's ticks. Also, many consider date-fns to be the equivalent of using a bazooka to swat a fly.
  4. If you want to set locale formats for something other than dates like for numbers on the y-axis or anything in the tooltip, you have to supply formatter functions for each axis and valueFormatter functions for tooltips. Some of these will invariably be the same function. For example, if you want a number on the y-axis tick to be formatted for France, you probably also want the number formatted that way in the tooltip and in the tabular representation.
  5. This issue: https://github.com/carbon-design-system/carbon-charts/issues/1596
  6. This issue: https://github.com/carbon-design-system/carbon-charts/issues/1577
  7. This issue: https://github.com/carbon-design-system/carbon-charts/issues/1393
  8. This issue: https://github.com/carbon-design-system/carbon-charts/issues/1362
  9. This issue: https://github.com/carbon-design-system/carbon-charts/issues/797
  10. This issue: https://github.com/carbon-design-system/carbon-charts/issues/260
  11. This issue: https://github.com/carbon-design-system/carbon-charts/issues/1400

What priority level would this issue be in your opinion?

P1 because it would close 7 issues.

theiliad commented 11 months ago

removing the valueFormatters would be a breaking change. what if we introduce a new central formatter that'd currently override all your specific formatters if you use it... and we can drop the valueFormatters in a major version release down the road?

nstuyvesant commented 11 months ago

I was thinking if a valueFormatter is provided, then it dictates the output; otherwise, it uses the global locale settings. This would avoid a breaking change. Thoughts?

theiliad commented 11 months ago

yeah that could be it too, and potentially adding console logs to warn user of the fact that those would be removed in a the next major version

nstuyvesant commented 11 months ago

One use case for continuing to support valueFormatters (in additional to a chart-wide locale) would be if you want to add some kind of additional information like a badge to go with the value like in a tooltip.