tremorlabs / tremor

React components to build charts and dashboards
https://tremor.so
Apache License 2.0
15.39k stars 446 forks source link

[Feature]: Allow for `BarList` to disable sorting #1032

Open mattiaz9 opened 2 weeks ago

mattiaz9 commented 2 weeks ago

What problem does this feature solve?

I need the BarList to show elements in a specific order. This is useful for elements that must follow a specific order, for instance energy classification like A+, A, B ...., or grades, or whatever. The component should not be opinionated about this.

What does the proposed API look like?

Add the option none to the sortOrder prop.

mattiaz9 commented 2 weeks ago

Another possible solutions would be to remove the default value here: https://github.com/tremorlabs/tremor/blob/790ed0c6f58aa99c10b5f92619c6c51d964b574a/src/components/vis-elements/BarList/BarList.tsx#L42

severinlandolt commented 2 weeks ago

Hi @mattiaz9! If you need a quick solution, check out our Raw Version of the component here: https://raw.tremor.so/docs/visualizations/barlist

There you have full control over the sorting, happy coding!

severinlandolt commented 1 day ago

Note:

import React from 'react';

type BarListProps<T> = {
  data?: T[];
  color?: string;
  valueFormatter?: (value: number) => string;
  showAnimation?: boolean;
  onValueChange?: (value: T) => void;
  sortOrder?: "ascending" | "descending" | "none";
  className?: string;
  [key: string]: any;
};

const defaultValueFormatter = (value: number) => value.toString();

function BarListInner<T>(props: BarListProps<T>, ref: React.ForwardedRef<HTMLDivElement>) {
  const {
    data = [],
    color,
    valueFormatter = defaultValueFormatter,
    showAnimation = false,
    onValueChange,
    sortOrder = "descending",
    className,
    ...other
  } = props;

  const Component = onValueChange ? "button" : "div";

  const sortedData = React.useMemo(() => {
    if (sortOrder === "none") {
      return data;
    }
    return [...data].sort((a, b) => {
      return sortOrder === "ascending" ? a.value - b.value : b.value - a.value;
    });
  }, [data, sortOrder]);

  return (
    <div ref={ref} className={className} {...other}>
      {sortedData.map((item, index) => (
        <Component key={index} style={{ color }}>
          {valueFormatter(item.value)}
        </Component>
      ))}
    </div>
  );
}

export default React.forwardRef(BarListInner);