tremor icon indicating copy to clipboard operation
tremor copied to clipboard

[Feature]: Allow active bar/category/legend to be controlled via props, not only as uncontrolled internal state

Open BenJenkinson opened this issue 1 year ago • 4 comments

What problem does this feature solve?

Many of the charts provide an onValueChanged callback which is called when different pieces of the chart are clicked on, usually "selecting" that piece of data and storing the selection in state.

The chart components do not provide a way to control this "selected" data from outside the component, via props.

Example Scenario 1

I have multiple charts on a page. All charts have the same categories of data.

When I click on the legend for the first chart "selecting" a category of data I would want to set all charts on the page to reflect the same category.

Example Scenario 2

I want to let users link to a page that displays a chart, including their current selection of data.

I want to derive the currently selected category from URL search params, and then pass that category to the charts.

What does the proposed API look like?

Using the BarChart as an example, there are four possible selection states:

  • All bars for a single category (clicking the legend)
  • A single bar, of a single category (clicking the bar)
  • All bars, of a single group/index (clicking the label on the x-axis)
  • Nothing

Which could be represented by a single object:

type ChartSelection = {
    type: "category";
    category: string;
    index: never;
} | {
    type: "index";
    category: never;
    index: string;
} | {
    type: "bar"; // To make this work for non-bar charts (where you use "bubble" and others), you could use "datum"
    category: string;
    index: string;
}

I'm not sure whether this would be more useful as a single prop which expected a matching object (e.g. selected), or with one prop for each aspect (e.g. selectedCategory/selectedIndex)

// With a single prop
type Props = {
  // ...
  selected: { category?: string; index?: string } | null | undefined;
}

// With one prop per aspect
type Props = {
  // ...
  selectedCategory?: string | null | undefined;
  selectedIndex?: string | null | undefined;
}
function Example() {
  const [selectedCategory, setSelectedCategory] = useState<string>();
  const categories = ["2022", "2023"];

  return (
    <div>
      <BarChart
        data={firstChartData}
        categories={categories}
        onValueChange={(value) => {
          setSelectedCategory(value?.categoryClicked);
        }}
        selectedCategory={selectedCategory}
      />
      <BarChart
        data={secondChartData}
        categories={categories}
        onValueChange={(value) => {
          setSelectedCategory(value?.categoryClicked);
        }}
        selectedCategory={selectedCategory}
      />
    </div>
  );
}

BenJenkinson avatar Mar 23 '24 22:03 BenJenkinson

Related issues:

  • https://github.com/tremorlabs/tremor/issues/897
    • request to allow multiple-select via controlled props; even if the default uncontrolled behaviour remains single-select.
  • https://github.com/tremorlabs/tremor/issues/876
    • similar feature request, except for DonutChart

BenJenkinson avatar Mar 24 '24 13:03 BenJenkinson

great

Erasmus001 avatar Mar 26 '24 09:03 Erasmus001

Hi! I would like to work on this. Can I be assigned to the issue?

orinamio avatar Apr 19 '24 23:04 orinamio

Any update?

deepchandra02 avatar Aug 17 '24 02:08 deepchandra02