diff --git a/.gitignore b/.gitignore index 705f39518..fc740099e 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,5 @@ dist .DS_Store storybook-static package-lock.json -.vscode \ No newline at end of file +.vscode +yarn.lock \ No newline at end of file diff --git a/README.md b/README.md index a9b1beb09..4c7009cf4 100644 --- a/README.md +++ b/README.md @@ -1,116 +1,84 @@ -
-
-
-
- Tremor Logo -
-
-
- -
- - npm - - - Read the documentation - - - License Apache 2.0 - - - Join Slack - - - - Follow at Tremorlabs - - -
-

- Documentation • - Website -

-
+
+
+

+ + + + + Tremor Logo + + +

+
+
+
+
+ + npm + + + Read the documentation + + + License Apache 2.0 + + + Join Slack + + + Follow at Tremorlabs + +
+

+ Documentation • + Website +

+

The react library to build dashboards fast

-
-[Tremor](https://tremor.so/) lets you create simple and modular components to build insightful dashboards in a breeze. Fully open-source, made by data scientists and software engineers with a sweet spot for design. +[Tremor](https://tremor.so/) provides React components to build charts and dashboards. Fully open-source, made by data scientists and software engineers with a sweet spot for design. -
-
+
![Tremor Banner](images/banner-github-readme.png) -
-
+
## Getting Started -For new projects, we recommend using Next.js 13.4+. For other frameworks, see our [Installation Guide](https://www.tremor.so/docs/getting-started/installation). To make use of the library we also need Tailwind CSS setup in the project. For manual installation, refer to the installation guide on our website. - -
- -## Using NextJS - -In your terminal, we create a new Next project. When prompted `Would you like to use Tailwind CSS with this project?`, select `Yes`. - -```bash -npx create-next-app@latest my-project -cd my-project -``` - -### Installation using the Tremor CLI - -We recommend installing Tremor with our CLI. To do so, run this command and select Next as your framework. If you prefer a manual installation, check the [installation guide](https://www.tremor.so/docs/getting-started/installation) on our website. - -```bash -npx @tremor/cli@latest init -``` - -Now you are set and you can start the dev server. - -```bash -npm run dev -``` +See our [Installation Guide](https://www.tremor.so/docs/getting-started/installation). To make use of the library we also need Tailwind CSS setup in the project. ## Example With Tremor creating an analytical interface is easy. -
- ```jsx //Card.tsx -import { Card, Text, Metric, Flex, ProgressBar } from "@tremor/react"; +import { Card, ProgressBar } from "@tremor/react"; export default () => ( - - Sales - $ 71,465 - - 32% of annual target - $ 225,000 - - - + + Sales +

$71,465

+
+ 32% of annual target + $ 225,000 +
+ +
); ``` -
+
![Tremor Example](images/example.png) -
## Community and Contribution -We are always looking for new ideas or other ways to improve Tremor. If you have developed anything cool or found a bug, send us a pull request. -
-
+We are always looking for new ideas or other ways to improve Tremor. If you have developed anything cool or found a bug, send us a pull request. Check out our Contributor License Agreement [here](https://www.tremor.so/contributors). ## License diff --git a/images/tremor-logo-dark.svg b/images/tremor-logo-dark.svg new file mode 100644 index 000000000..79c44c29e --- /dev/null +++ b/images/tremor-logo-dark.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/images/tremor-logo-light.svg b/images/tremor-logo-light.svg new file mode 100644 index 000000000..24b1b5929 --- /dev/null +++ b/images/tremor-logo-light.svg @@ -0,0 +1,3 @@ + + + diff --git a/images/tremor-logo.svg b/images/tremor-logo.svg deleted file mode 100644 index 6772fa099..000000000 --- a/images/tremor-logo.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/components/icon-elements/Badge/Badge.tsx b/src/components/icon-elements/Badge/Badge.tsx index d9b10b864..bd0e1e52e 100644 --- a/src/components/icon-elements/Badge/Badge.tsx +++ b/src/components/icon-elements/Badge/Badge.tsx @@ -35,18 +35,22 @@ const Badge = React.forwardRef((props, ref) => { className={tremorTwMerge( makeBadgeClassName("root"), // common - "w-max flex-shrink-0 inline-flex justify-center items-center cursor-default rounded-tremor-full", + "w-max shrink-0 inline-flex justify-center items-center cursor-default rounded-tremor-small ring-1 ring-inset", color ? tremorTwMerge( getColorClassNames(color, colorPalette.background).bgColor, - getColorClassNames(color, colorPalette.text).textColor, - "bg-opacity-20 dark:bg-opacity-25", + getColorClassNames(color, colorPalette.iconText).textColor, + getColorClassNames(color, colorPalette.iconRing).ringColor, + // light + "bg-opacity-10 ring-opacity-20", + // dark + "dark:bg-opacity-5 dark:ring-opacity-60", ) : tremorTwMerge( // light - "bg-tremor-brand-muted text-tremor-brand-emphasis", + "bg-tremor-brand-faint text-tremor-brand-emphasis ring-tremor-brand/20", // dark - "dark:bg-dark-tremor-brand-muted dark:text-dark-tremor-brand-emphasis", + "dark:bg-dark-tremor-brand-muted/50 dark:text-dark-tremor-brand dark:ring-dark-tremor-subtle/20", ), badgeProportions[size].paddingX, badgeProportions[size].paddingY, @@ -67,9 +71,9 @@ const Badge = React.forwardRef((props, ref) => { )} /> ) : null} -

+ {children} -

+ ); }); diff --git a/src/components/icon-elements/BadgeDelta/BadgeDelta.tsx b/src/components/icon-elements/BadgeDelta/BadgeDelta.tsx index 30f4a9aea..af1fec726 100644 --- a/src/components/icon-elements/BadgeDelta/BadgeDelta.tsx +++ b/src/components/icon-elements/BadgeDelta/BadgeDelta.tsx @@ -50,12 +50,17 @@ const BadgeDelta = React.forwardRef((props, re className={tremorTwMerge( makeBadgeDeltaClassName("root"), // common - "w-max flex-shrink-0 inline-flex justify-center items-center cursor-default rounded-tremor-full bg-opacity-20 dark:bg-opacity-25", + "w-max shrink-0 inline-flex justify-center items-center cursor-default rounded-tremor-small ring-1 ring-inset", colors[mappedDeltaType].bgColor, colors[mappedDeltaType].textColor, + colors[mappedDeltaType].ringColor, badgeProportions[size].paddingX, badgeProportions[size].paddingY, badgeProportions[size].fontSize, + // light + "bg-opacity-10 ring-opacity-20", + // dark + "dark:bg-opacity-5 dark:ring-opacity-60", className, )} {...getReferenceProps} @@ -71,9 +76,9 @@ const BadgeDelta = React.forwardRef((props, re )} /> {children ? ( -

+ {children} -

+ ) : null} ); diff --git a/src/components/icon-elements/BadgeDelta/styles.ts b/src/components/icon-elements/BadgeDelta/styles.ts index 0c340922f..426405a11 100644 --- a/src/components/icon-elements/BadgeDelta/styles.ts +++ b/src/components/icon-elements/BadgeDelta/styles.ts @@ -105,28 +105,34 @@ export const iconSizes: { export type ColorTypes = { bgColor: string; textColor: string; + ringColor: string; }; export const colors: { [key: string]: ColorTypes } = { [DeltaTypes.Increase]: { bgColor: getColorClassNames(BaseColors.Emerald, colorPalette.background).bgColor, - textColor: getColorClassNames(BaseColors.Emerald, colorPalette.text).textColor, + textColor: getColorClassNames(BaseColors.Emerald, colorPalette.iconText).textColor, + ringColor: getColorClassNames(BaseColors.Emerald, colorPalette.iconRing).ringColor, }, [DeltaTypes.ModerateIncrease]: { bgColor: getColorClassNames(BaseColors.Emerald, colorPalette.background).bgColor, - textColor: getColorClassNames(BaseColors.Emerald, colorPalette.text).textColor, + textColor: getColorClassNames(BaseColors.Emerald, colorPalette.iconText).textColor, + ringColor: getColorClassNames(BaseColors.Emerald, colorPalette.iconRing).ringColor, }, [DeltaTypes.Decrease]: { - bgColor: getColorClassNames(BaseColors.Rose, colorPalette.background).bgColor, - textColor: getColorClassNames(BaseColors.Rose, colorPalette.text).textColor, + bgColor: getColorClassNames(BaseColors.Red, colorPalette.background).bgColor, + textColor: getColorClassNames(BaseColors.Red, colorPalette.iconText).textColor, + ringColor: getColorClassNames(BaseColors.Red, colorPalette.iconRing).ringColor, }, [DeltaTypes.ModerateDecrease]: { - bgColor: getColorClassNames(BaseColors.Rose, colorPalette.background).bgColor, - textColor: getColorClassNames(BaseColors.Rose, colorPalette.text).textColor, + bgColor: getColorClassNames(BaseColors.Red, colorPalette.background).bgColor, + textColor: getColorClassNames(BaseColors.Red, colorPalette.iconText).textColor, + ringColor: getColorClassNames(BaseColors.Red, colorPalette.iconRing).ringColor, }, [DeltaTypes.Unchanged]: { bgColor: getColorClassNames(BaseColors.Orange, colorPalette.background).bgColor, - textColor: getColorClassNames(BaseColors.Orange, colorPalette.text).textColor, + textColor: getColorClassNames(BaseColors.Orange, colorPalette.iconText).textColor, + ringColor: getColorClassNames(BaseColors.Orange, colorPalette.iconRing).ringColor, }, }; diff --git a/src/components/icon-elements/Icon/Icon.tsx b/src/components/icon-elements/Icon/Icon.tsx index 38ff29995..f2cf17cc9 100644 --- a/src/components/icon-elements/Icon/Icon.tsx +++ b/src/components/icon-elements/Icon/Icon.tsx @@ -44,7 +44,7 @@ const Icon = React.forwardRef((props, ref) => { ref={mergeRefs([ref, tooltipProps.refs.setReference])} className={tremorTwMerge( makeIconClassName("root"), - "inline-flex flex-shrink-0 items-center", + "inline-flex shrink-0 items-center justify-center", iconColorStyles.bgColor, iconColorStyles.textColor, iconColorStyles.borderColor, diff --git a/src/components/input-elements/Button/Button.tsx b/src/components/input-elements/Button/Button.tsx index 2e965a122..8cabe7e95 100644 --- a/src/components/input-elements/Button/Button.tsx +++ b/src/components/input-elements/Button/Button.tsx @@ -126,7 +126,7 @@ const Button = React.forwardRef((props, ref) => className={tremorTwMerge( makeButtonClassName("root"), // common - "flex-shrink-0 inline-flex justify-center items-center group font-medium outline-none", + "shrink-0 inline-flex justify-center items-center group font-medium outline-none", buttonShapeStyles, buttonProportionStyles.paddingX, buttonProportionStyles.paddingY, diff --git a/src/components/input-elements/DateRangePicker/DateRangePicker.tsx b/src/components/input-elements/DateRangePicker/DateRangePicker.tsx index 1904b8c79..3e505ec1a 100644 --- a/src/components/input-elements/DateRangePicker/DateRangePicker.tsx +++ b/src/components/input-elements/DateRangePicker/DateRangePicker.tsx @@ -304,9 +304,9 @@ const DateRangePicker = React.forwardRef(( // common "w-full outline-none text-left whitespace-nowrap truncate rounded-r-tremor-default transition duration-100 border px-4 py-2", // light - "border-tremor-border shadow-tremor-input text-tremor-content-emphasis focus:border-tremor-brand-subtle", + "border-tremor-border text-tremor-content-emphasis focus:border-tremor-brand-subtle", // dark - "dark:border-dark-tremor-border dark:shadow-dark-tremor-input dark:text-dark-tremor-content-emphasis dark:focus:border-dark-tremor-brand-subtle", + "dark:border-dark-tremor-border dark:text-dark-tremor-content-emphasis dark:focus:border-dark-tremor-brand-subtle", getSelectButtonColors(hasValue(value), disabled), )} > diff --git a/src/components/input-elements/SearchSelect/SearchSelect.tsx b/src/components/input-elements/SearchSelect/SearchSelect.tsx index b22ac4dc1..5d33cb27f 100644 --- a/src/components/input-elements/SearchSelect/SearchSelect.tsx +++ b/src/components/input-elements/SearchSelect/SearchSelect.tsx @@ -1,5 +1,5 @@ "use client"; -import React, { isValidElement, useMemo, useRef, useState } from "react"; +import React, { isValidElement, useMemo, useRef } from "react"; import { useInternalState } from "hooks"; import { Combobox, Transition } from "@headlessui/react"; import { ArrowDownHeadIcon, XCircleIcon } from "assets"; @@ -16,6 +16,8 @@ const makeSearchSelectClassName = makeClassName("SearchSelect"); export interface SearchSelectProps extends React.HTMLAttributes { defaultValue?: string; name?: string; + searchValue?: string; + onSearchValueChange?: (value: string) => void; value?: string; onValueChange?: (value: string) => void; placeholder?: string; @@ -33,6 +35,8 @@ const makeSelectClassName = makeClassName("SearchSelect"); const SearchSelect = React.forwardRef((props, ref) => { const { defaultValue = "", + searchValue, + onSearchValueChange, value, onValueChange, placeholder = "Select...", @@ -50,7 +54,7 @@ const SearchSelect = React.forwardRef((prop } = props; const comboboxButtonRef = useRef(null); - const [searchQuery, setSearchQuery] = useState(""); + const [searchQuery, setSearchQuery] = useInternalState("", searchValue); const [selectedValue, setSelectedValue] = useInternalState(defaultValue, value); const Icon = icon; @@ -62,7 +66,7 @@ const SearchSelect = React.forwardRef((prop }, [children]); const filteredOptions = useMemo( - () => getFilteredOptions(searchQuery, reactElementChildren), + () => getFilteredOptions(searchQuery ?? "", reactElementChildren), [searchQuery, reactElementChildren], ); @@ -70,6 +74,7 @@ const SearchSelect = React.forwardRef((prop setSelectedValue(""); setSearchQuery(""); onValueChange?.(""); + onSearchValueChange?.(""); }; return ( @@ -166,7 +171,10 @@ const SearchSelect = React.forwardRef((prop getSelectButtonColors(hasValue(value), disabled), )} placeholder={placeholder} - onChange={(event) => setSearchQuery(event.target.value)} + onChange={(event) => { + onSearchValueChange?.(event.target.value); + setSearchQuery(event.target.value); + }} displayValue={(value: string) => valueToNameMapping.get(value) ?? ""} />
diff --git a/src/components/input-elements/Switch/Switch.tsx b/src/components/input-elements/Switch/Switch.tsx index a72ff686a..fc69aae56 100644 --- a/src/components/input-elements/Switch/Switch.tsx +++ b/src/components/input-elements/Switch/Switch.tsx @@ -93,7 +93,7 @@ const Switch = React.forwardRef((props, ref) => { disabled={disabled} className={tremorTwMerge( makeSwitchClassName("switch"), - "w-10 h-5 group relative inline-flex flex-shrink-0 cursor-pointer items-center justify-center rounded-tremor-full", + "w-10 h-5 group relative inline-flex shrink-0 cursor-pointer items-center justify-center rounded-tremor-full", "focus:outline-none", disabled ? "cursor-not-allowed" : "", )} diff --git a/src/components/list-elements/Table/TableHeaderCell.tsx b/src/components/list-elements/Table/TableHeaderCell.tsx index 35da15e89..62ff8c461 100644 --- a/src/components/list-elements/Table/TableHeaderCell.tsx +++ b/src/components/list-elements/Table/TableHeaderCell.tsx @@ -17,9 +17,9 @@ const TableHeaderCell = React.forwardRef< // common "whitespace-nowrap text-left font-semibold top-0 px-4 py-3.5", // light - "text-tremor-content", + "text-tremor-content-strong", // dark - "dark:text-dark-tremor-content", + "dark:text-dark-tremor-content-strong", className, )} {...other} diff --git a/src/components/spark-elements/SparkAreaChart/SparkAreaChart.tsx b/src/components/spark-elements/SparkAreaChart/SparkAreaChart.tsx index 549f5c6b9..ebc3182f3 100644 --- a/src/components/spark-elements/SparkAreaChart/SparkAreaChart.tsx +++ b/src/components/spark-elements/SparkAreaChart/SparkAreaChart.tsx @@ -1,12 +1,13 @@ "use client"; import React from "react"; -import { Area, AreaChart as ReChartsAreaChart, ResponsiveContainer, XAxis } from "recharts"; +import { Area, AreaChart as ReChartsAreaChart, ResponsiveContainer, XAxis, YAxis } from "recharts"; import { BaseColors, colorPalette, getColorClassNames, themeColorRange, tremorTwMerge } from "lib"; import { CurveType } from "../../../lib/inputTypes"; import BaseSparkChartProps from "../common/BaseSparkChartProps"; -import { constructCategoryColors } from "components/chart-elements/common/utils"; +import { constructCategoryColors, getYAxisDomain } from "components/chart-elements/common/utils"; import NoData from "components/chart-elements/common/NoData"; +import { AxisDomain } from "recharts/types/util/types"; export interface SparkAreaChartProps extends BaseSparkChartProps { stack?: boolean; @@ -28,16 +29,21 @@ const AreaChart = React.forwardRef((props, curveType = "linear", connectNulls = false, noDataText, + autoMinValue = false, + minValue, + maxValue, className, ...other } = props; const categoryColors = constructCategoryColors(categories, colors); + const yAxisDomain = getYAxisDomain(autoMinValue, minValue, maxValue); return (
{data?.length ? ( + {categories.map((category) => { return ( diff --git a/src/components/spark-elements/SparkBarChart/SparkBarChart.tsx b/src/components/spark-elements/SparkBarChart/SparkBarChart.tsx index 7a9c2e954..4218fc324 100644 --- a/src/components/spark-elements/SparkBarChart/SparkBarChart.tsx +++ b/src/components/spark-elements/SparkBarChart/SparkBarChart.tsx @@ -2,12 +2,13 @@ import { colorPalette, getColorClassNames, tremorTwMerge } from "lib"; import React from "react"; -import { Bar, BarChart as ReChartsBarChart, ResponsiveContainer, XAxis } from "recharts"; +import { Bar, BarChart as ReChartsBarChart, ResponsiveContainer, XAxis, YAxis } from "recharts"; import { BaseColors, themeColorRange } from "lib"; import BaseSparkChartProps from "../common/BaseSparkChartProps"; -import { constructCategoryColors } from "components/chart-elements/common/utils"; +import { constructCategoryColors, getYAxisDomain } from "components/chart-elements/common/utils"; import NoData from "components/chart-elements/common/NoData"; +import { AxisDomain } from "recharts/types/util/types"; export interface SparkBarChartProps extends BaseSparkChartProps { stack?: boolean; @@ -25,10 +26,14 @@ const SparkBarChart = React.forwardRef((prop animationDuration = 900, showAnimation = false, noDataText, + autoMinValue = false, + minValue, + maxValue, className, ...other } = props; const categoryColors = constructCategoryColors(categories, colors); + const yAxisDomain = getYAxisDomain(autoMinValue, minValue, maxValue); return (
@@ -39,6 +44,7 @@ const SparkBarChart = React.forwardRef((prop stackOffset={relative ? "expand" : "none"} margin={{ top: 0, left: -1.5, right: -1.5, bottom: 0 }} > + {categories.map((category) => ( ((pr curveType = "linear", connectNulls = false, noDataText, + autoMinValue = false, + minValue, + maxValue, className, ...other } = props; const categoryColors = constructCategoryColors(categories, colors); + const yAxisDomain = getYAxisDomain(autoMinValue, minValue, maxValue); return (
{data?.length ? ( + {categories.map((category) => ( ((props, ref) "font-semibold text-tremor-metric", color ? getColorClassNames(color, colorPalette.darkText).textColor - : "text-tremor-content-emphasis dark:text-dark-tremor-content-emphasis", + : "text-tremor-content-strong dark:text-dark-tremor-content-strong", className, )} {...other} diff --git a/src/components/text-elements/Subtitle/Subtitle.tsx b/src/components/text-elements/Subtitle/Subtitle.tsx index b38ab88c7..1f5992cc9 100644 --- a/src/components/text-elements/Subtitle/Subtitle.tsx +++ b/src/components/text-elements/Subtitle/Subtitle.tsx @@ -17,7 +17,7 @@ const Subtitle = React.forwardRef((props, r className={tremorTwMerge( color ? getColorClassNames(color, colorPalette.lightText).textColor - : "text-tremor-content-subtle dark:text-dark-tremor-content-subtle", + : "text-tremor-content-emphasis dark:text-dark-tremor-content-emphasis", className, )} {...other} diff --git a/src/components/text-elements/Title/Title.tsx b/src/components/text-elements/Title/Title.tsx index e8eb42209..e40859d88 100644 --- a/src/components/text-elements/Title/Title.tsx +++ b/src/components/text-elements/Title/Title.tsx @@ -19,7 +19,7 @@ const Title = React.forwardRef((props, ref) => "font-medium text-tremor-title", color ? getColorClassNames(color, colorPalette.darkText).textColor - : "text-tremor-content-emphasis dark:text-dark-tremor-content-emphasis", + : "text-tremor-content-strong dark:text-dark-tremor-content-strong", className, )} {...other} diff --git a/src/components/vis-elements/BarList/BarList.tsx b/src/components/vis-elements/BarList/BarList.tsx index b74b233b8..f14847cac 100644 --- a/src/components/vis-elements/BarList/BarList.tsx +++ b/src/components/vis-elements/BarList/BarList.tsx @@ -11,7 +11,7 @@ import { colorPalette } from "lib/theme"; const makeBarListClassName = makeClassName("BarList"); -type Bar = { +type Bar = T & { key?: string; value: number; name: string; @@ -33,19 +33,21 @@ const getWidthsFromValues = (dataValues: number[]) => { }); }; -export interface BarListProps extends React.HTMLAttributes { - data: Bar[]; +export interface BarListProps extends React.HTMLAttributes { + data: Bar[]; valueFormatter?: ValueFormatter; color?: Color; showAnimation?: boolean; + onValueChange?: (payload: Bar) => void; } -const BarList = React.forwardRef((props, ref) => { +function BarListInner(props: BarListProps, ref: React.ForwardedRef) { const { data = [], color, valueFormatter = defaultValueFormatter, showAnimation = false, + onValueChange, className, ...other } = props; @@ -87,7 +89,15 @@ const BarList = React.forwardRef((props, ref) => { transition: showAnimation ? "all 1s" : "", }} > -
+
{ + onValueChange?.(item); + }} + > {Icon ? ( ((props, ref) => { makeBarListClassName("barLink"), // common "whitespace-nowrap hover:underline truncate text-tremor-default", + onValueChange ? "cursor-pointer" : "", // light "text-tremor-content-emphasis", // dark "dark:text-dark-tremor-content-emphasis", )} + onClick={() => { + onValueChange?.(item); + }} > {item.name} @@ -124,11 +138,15 @@ const BarList = React.forwardRef((props, ref) => { makeBarListClassName("barText"), // common "whitespace-nowrap truncate text-tremor-default", + onValueChange ? "cursor-pointer" : "", // light "text-tremor-content-emphasis", // dark "dark:text-dark-tremor-content-emphasis", )} + onClick={() => { + onValueChange?.(item); + }} > {item.name}

@@ -167,8 +185,12 @@ const BarList = React.forwardRef((props, ref) => {
); -}); +} + +BarListInner.displayName = "BarList"; -BarList.displayName = "BarList"; +const BarList = React.forwardRef(BarListInner) as ( + p: BarListProps & { ref?: React.ForwardedRef }, +) => ReturnType; export default BarList; diff --git a/src/lib/theme.ts b/src/lib/theme.ts index dd6ec3d60..c40a83a1a 100644 --- a/src/lib/theme.ts +++ b/src/lib/theme.ts @@ -16,8 +16,10 @@ export const colorPalette = { darkBorder: 700, lightRing: 200, ring: 300, + iconRing: 500, lightText: 400, text: 500, + iconText: 600, darkText: 700, darkestText: 900, icon: 500, diff --git a/src/stories/icon-elements/Icon.stories.tsx b/src/stories/icon-elements/Icon.stories.tsx index 613a432ec..8d5fde76a 100644 --- a/src/stories/icon-elements/Icon.stories.tsx +++ b/src/stories/icon-elements/Icon.stories.tsx @@ -65,6 +65,20 @@ const IconTemplateColors: Story = { }, }; +const IconShrink: Story = { + render: ({ ...args }) => { + return ( +
+ + + + + +
+ ); + }, +}; + export const Default: Story = { args: {}, }; @@ -76,3 +90,7 @@ export const Sizes: Story = { export const Colors: Story = { ...IconTemplateColors, }; + +export const Shrink: Story = { + ...IconShrink, +}; diff --git a/src/stories/input-elements/SearchSelect.stories.tsx b/src/stories/input-elements/SearchSelect.stories.tsx index 82c76ef93..0794261d9 100644 --- a/src/stories/input-elements/SearchSelect.stories.tsx +++ b/src/stories/input-elements/SearchSelect.stories.tsx @@ -6,6 +6,7 @@ import { SimpleSearchSelectControlled, SimpleSearchSelectWithStaticAndDynamicChildren, SimpleSearchSelectForm, + SimpleSearchSelectServerSideRendering, } from "./helpers/SimpleSearchSelect"; import { CalendarIcon } from "assets"; @@ -84,3 +85,10 @@ export const Form: Story = { required: true, }, }; + +export const ServerSideRendering: Story = { + render: SimpleSearchSelectServerSideRendering, + args: { + required: true, + }, +}; diff --git a/src/stories/input-elements/helpers/SimpleSearchSelect.tsx b/src/stories/input-elements/helpers/SimpleSearchSelect.tsx index 85148c22c..de9f52420 100644 --- a/src/stories/input-elements/helpers/SimpleSearchSelect.tsx +++ b/src/stories/input-elements/helpers/SimpleSearchSelect.tsx @@ -97,3 +97,58 @@ export function SimpleSearchSelectControlled() {
); } + +export function SimpleSearchSelectServerSideRendering() { + const [searchQuery, setSearchQuery] = React.useState(""); + + interface User { + id: number; + name: string; + email: string; + } + const [options, setOptions] = React.useState([]); + + const [value, setValue] = React.useState(); + + const handleSearchQueryChange = (query: string) => { + setSearchQuery(query); + }; + + const handleValueChange = (newValue: string) => { + setValue(newValue); + }; + + const handleReset = () => { + setValue(""); + }; + + React.useEffect(() => { + if (searchQuery) { + fetch("https://jsonplaceholder.typicode.com/users") + .then((response) => response.json()) + .then((data) => { + setOptions(data); + }) + .catch((error) => console.error("Error fetching user data:", error)); + } + }, [searchQuery]); + + return ( +
+ + {options.map((option) => ( + + {`${option.name} (${option.email})`} + + ))} + + +

Selected User ID: {value}

+
+ ); +} diff --git a/src/stories/list-elements/Table.stories.tsx b/src/stories/list-elements/Table.stories.tsx index 962f10c78..605e715d3 100644 --- a/src/stories/list-elements/Table.stories.tsx +++ b/src/stories/list-elements/Table.stories.tsx @@ -1,16 +1,7 @@ import React from "react"; import type { Meta, StoryObj } from "@storybook/react"; -import { - Table, - TableBody, - TableCell, - TableFoot, - TableFooterCell, - TableHead, - TableHeaderCell, - TableRow, -} from "components"; +import { Table, TableBody, TableCell, TableHead, TableHeaderCell, TableRow } from "components"; import BadgeDelta from "components/icon-elements/BadgeDelta/BadgeDelta"; import { DeltaType } from "lib"; @@ -35,7 +26,6 @@ const data = [ status: "overperforming", deltaType: "moderateIncrease", hours: 100, - productivity: "n/a", }, { id: 2, @@ -45,7 +35,6 @@ const data = [ status: "overperforming", deltaType: "moderateIncrease", hours: 110, - productivity: "n/a", }, { id: 3, @@ -55,7 +44,6 @@ const data = [ status: "underperforming", deltaType: "moderateDecrease", hours: 90, - productivity: "n/a", }, { id: 4, @@ -65,7 +53,6 @@ const data = [ status: "overperforming", deltaType: "moderateDecrease", hours: 92, - productivity: "n/a", }, { id: 5, @@ -75,7 +62,6 @@ const data = [ status: "underperforming", deltaType: "moderateDecrease", hours: 95, - productivity: "n/a", }, { id: 6, @@ -85,17 +71,15 @@ const data = [ status: "overperforming", deltaType: "moderateIncrease", hours: 98, - productivity: "n/a", }, { id: 7, name: "Employee 7", sales: "800000", region: "Region G", - status: "underperforming", - deltaType: "moderateDecrease", + status: "average", + deltaType: "unchanged", hours: 101, - productivity: "n/a", }, { id: 8, @@ -105,7 +89,6 @@ const data = [ status: "overperforming", deltaType: "moderateDecrease", hours: 104, - productivity: "n/a", }, { id: 9, @@ -115,17 +98,15 @@ const data = [ status: "underperforming", deltaType: "moderateIncrease", hours: 107, - productivity: "n/a", }, { id: 10, name: "Employee 10", sales: "1100000", region: "Region J", - status: "overperforming", - deltaType: "moderateDecrease", + status: "average", + deltaType: "unchanged", hours: 110, - productivity: "n/a", }, { id: 11, @@ -135,7 +116,6 @@ const data = [ status: "underperforming", deltaType: "moderateDecrease", hours: 113, - productivity: "n/a", }, { id: 12, @@ -145,7 +125,6 @@ const data = [ status: "overperforming", deltaType: "moderateIncrease", hours: 116, - productivity: "n/a", }, { id: 13, @@ -155,7 +134,6 @@ const data = [ status: "underperforming", deltaType: "moderateDecrease", hours: 119, - productivity: "n/a", }, ]; @@ -169,10 +147,8 @@ export const Default: Story = { Region Status Working Hours (h) - Productivity - {data.map((item) => ( @@ -180,7 +156,7 @@ export const Default: Story = { {item.sales} {item.region} - + {item.status} @@ -188,15 +164,6 @@ export const Default: Story = { ))} - - - - 4642 - - - 15h - - ), args: { diff --git a/src/stories/spark-elements/SparkAreaChart.stories.tsx b/src/stories/spark-elements/SparkAreaChart.stories.tsx index eae81515f..dd17ce9ab 100644 --- a/src/stories/spark-elements/SparkAreaChart.stories.tsx +++ b/src/stories/spark-elements/SparkAreaChart.stories.tsx @@ -10,6 +10,7 @@ import { } from "../chart-elements/helpers/testData"; import { SparkAreaChart } from "components/spark-elements"; import ExampleCard from "./helpers/ExampleCard"; +import { smallVariantionDatas } from "./helpers/testData"; const meta: Meta = { title: "Visualizations/Chart/SparkAreaChart", @@ -140,3 +141,12 @@ export const WithCard: Story = { ), ], }; + +export const WithAutoMinValue: Story = { + args: { + data: smallVariantionDatas, + index: "ts", + categories: ["avg_price"], + autoMinValue: true, + }, +}; diff --git a/src/stories/spark-elements/SparkBarChart.stories.tsx b/src/stories/spark-elements/SparkBarChart.stories.tsx index 26362b489..fea5a188a 100644 --- a/src/stories/spark-elements/SparkBarChart.stories.tsx +++ b/src/stories/spark-elements/SparkBarChart.stories.tsx @@ -10,6 +10,7 @@ import { } from "../chart-elements/helpers/testData"; import { SparkBarChart } from "components/spark-elements"; import ExampleCard from "./helpers/ExampleCard"; +import { smallVariantionDatas } from "./helpers/testData"; const meta: Meta = { title: "Visualizations/Chart/SparkBarChart", @@ -133,3 +134,12 @@ export const WithCard: Story = { ), ], }; + +export const WithAutoMinValue: Story = { + args: { + data: smallVariantionDatas, + index: "ts", + categories: ["avg_price"], + autoMinValue: true, + }, +}; diff --git a/src/stories/spark-elements/SparkLineChart.stories.tsx b/src/stories/spark-elements/SparkLineChart.stories.tsx index 3846085cd..7d618414e 100644 --- a/src/stories/spark-elements/SparkLineChart.stories.tsx +++ b/src/stories/spark-elements/SparkLineChart.stories.tsx @@ -10,6 +10,7 @@ import { } from "../chart-elements/helpers/testData"; import { SparkLineChart } from "components/spark-elements"; import ExampleCard from "./helpers/ExampleCard"; +import { smallVariantionDatas } from "./helpers/testData"; const meta: Meta = { title: "Visualizations/Chart/SparkLineChart", @@ -130,3 +131,12 @@ export const WithCard: Story = { ), ], }; + +export const WithAutoMinValue: Story = { + args: { + data: smallVariantionDatas, + index: "ts", + categories: ["avg_price"], + autoMinValue: true, + }, +}; diff --git a/src/stories/spark-elements/helpers/testData.ts b/src/stories/spark-elements/helpers/testData.ts new file mode 100644 index 000000000..86eff8c53 --- /dev/null +++ b/src/stories/spark-elements/helpers/testData.ts @@ -0,0 +1,142 @@ +export const smallVariantionDatas = [ + { ts: "2024-02-05T18:36:00.000Z", avg_price: 3112.96 }, + { ts: "2024-02-05T18:37:00.000Z", avg_price: 3112.8749999999995 }, + { ts: "2024-02-05T18:38:00.000Z", avg_price: 3112.62 }, + { ts: "2024-02-05T18:39:00.000Z", avg_price: 3113.4491666666668 }, + { ts: "2024-02-05T18:40:00.000Z", avg_price: 3113.5900000000006 }, + { ts: "2024-02-05T18:41:00.000Z", avg_price: 3113.5900000000006 }, + { ts: "2024-02-05T18:42:00.000Z", avg_price: 3113.5900000000006 }, + { ts: "2024-02-05T18:43:00.000Z", avg_price: 3113.590000000001 }, + { ts: "2024-02-05T18:44:00.000Z", avg_price: 3113.590000000001 }, + { ts: "2024-02-05T18:45:00.000Z", avg_price: 3113.590000000001 }, + { ts: "2024-02-05T18:46:00.000Z", avg_price: 3113.590000000001 }, + { ts: "2024-02-05T18:47:00.000Z", avg_price: 3113.590000000001 }, + { ts: "2024-02-05T18:48:00.000Z", avg_price: 3113.590000000001 }, + { ts: "2024-02-05T18:49:00.000Z", avg_price: 3113.882 }, + { ts: "2024-02-05T18:50:00.000Z", avg_price: 3115.05 }, + { ts: "2024-02-05T18:51:00.000Z", avg_price: 3115.0499999999997 }, + { ts: "2024-02-05T18:52:00.000Z", avg_price: 3112.694333333334 }, + { ts: "2024-02-05T18:53:00.000Z", avg_price: 3111.2300000000005 }, + { ts: "2024-02-05T18:54:00.000Z", avg_price: 3111.2300000000005 }, + { ts: "2024-02-05T18:55:00.000Z", avg_price: 3111.230000000001 }, + { ts: "2024-02-05T18:56:00.000Z", avg_price: 3111.230000000001 }, + { ts: "2024-02-05T18:57:00.000Z", avg_price: 3111.2300000000005 }, + { ts: "2024-02-05T18:58:00.000Z", avg_price: 3111.2300000000005 }, + { ts: "2024-02-05T18:59:00.000Z", avg_price: 3111.2300000000005 }, + { ts: "2024-02-05T19:00:00.000Z", avg_price: 3111.230000000001 }, + { ts: "2024-02-05T19:01:00.000Z", avg_price: 3111.958 }, + { ts: "2024-02-05T19:02:00.000Z", avg_price: 3112.01 }, + { ts: "2024-02-05T19:03:00.000Z", avg_price: 3112.0099999999998 }, + { ts: "2024-02-05T19:04:00.000Z", avg_price: 3111.989 }, + { ts: "2024-02-05T19:05:00.000Z", avg_price: 3111.8221666666664 }, + { ts: "2024-02-05T19:06:00.000Z", avg_price: 3111.87 }, + { ts: "2024-02-05T19:07:00.000Z", avg_price: 3111.87 }, + { ts: "2024-02-05T19:08:00.000Z", avg_price: 3111.87 }, + { ts: "2024-02-05T19:09:00.000Z", avg_price: 3111.87 }, + { ts: "2024-02-05T19:10:00.000Z", avg_price: 3111.8700000000003 }, + { ts: "2024-02-05T19:11:00.000Z", avg_price: 3111.8699999999994 }, + { ts: "2024-02-05T19:12:00.000Z", avg_price: 3111.8700000000003 }, + { ts: "2024-02-05T19:13:00.000Z", avg_price: 3112.026 }, + { ts: "2024-02-05T19:14:00.000Z", avg_price: 3112.2300000000005 }, + { ts: "2024-02-05T19:15:00.000Z", avg_price: 3111.4049999999997 }, + { ts: "2024-02-05T19:16:00.000Z", avg_price: 3111.252 }, + { ts: "2024-02-05T19:17:00.000Z", avg_price: 3111.846666666667 }, + { ts: "2024-02-05T19:18:00.000Z", avg_price: 3112.86 }, + { ts: "2024-02-05T19:19:00.000Z", avg_price: 3112.692 }, + { ts: "2024-02-05T19:20:00.000Z", avg_price: 3112.019999999999 }, + { ts: "2024-02-05T19:21:00.000Z", avg_price: 3112.0199999999995 }, + { ts: "2024-02-05T19:22:00.000Z", avg_price: 3112.0199999999995 }, + { ts: "2024-02-05T19:23:00.000Z", avg_price: 3113.5308333333332 }, + { ts: "2024-02-05T19:24:00.000Z", avg_price: 3114.61 }, + { ts: "2024-02-05T19:25:00.000Z", avg_price: 3114.6099999999997 }, + { ts: "2024-02-05T19:26:00.000Z", avg_price: 3114.61 }, + { ts: "2024-02-05T19:27:00.000Z", avg_price: 3114.61 }, + { ts: "2024-02-05T19:28:00.000Z", avg_price: 3114.6820000000002 }, + { ts: "2024-02-05T19:29:00.000Z", avg_price: 3114.7699999999995 }, + { ts: "2024-02-05T19:30:00.000Z", avg_price: 3114.769999999999 }, + { ts: "2024-02-05T19:31:00.000Z", avg_price: 3114.769999999999 }, + { ts: "2024-02-05T19:32:00.000Z", avg_price: 3114.7699999999995 }, + { ts: "2024-02-05T19:33:00.000Z", avg_price: 3114.7699999999995 }, + { ts: "2024-02-05T19:34:00.000Z", avg_price: 3114.7699999999995 }, + { ts: "2024-02-05T19:35:00.000Z", avg_price: 3114.769999999999 }, + { ts: "2024-02-05T19:36:00.000Z", avg_price: 3114.769999999999 }, + { ts: "2024-02-05T19:37:00.000Z", avg_price: 3114.5096666666664 }, + { ts: "2024-02-05T19:38:00.000Z", avg_price: 3113.3500000000004 }, + { ts: "2024-02-05T19:39:00.000Z", avg_price: 3113.3500000000004 }, + { ts: "2024-02-05T19:40:00.000Z", avg_price: 3113.3500000000004 }, + { ts: "2024-02-05T19:41:00.000Z", avg_price: 3113.402 }, + { ts: "2024-02-05T19:42:00.000Z", avg_price: 3113.61 }, + { ts: "2024-02-05T19:43:00.000Z", avg_price: 3113.61 }, + { ts: "2024-02-05T19:44:00.000Z", avg_price: 3113.61 }, + { ts: "2024-02-05T19:45:00.000Z", avg_price: 3113.6099999999997 }, + { ts: "2024-02-05T19:46:00.000Z", avg_price: 3113.61 }, + { ts: "2024-02-05T19:47:00.000Z", avg_price: 3113.61 }, + { ts: "2024-02-05T19:48:00.000Z", avg_price: 3113.61 }, + { ts: "2024-02-05T19:49:00.000Z", avg_price: 3113.508166666667 }, + { ts: "2024-02-05T19:50:00.000Z", avg_price: 3113.4800000000005 }, + { ts: "2024-02-05T19:51:00.000Z", avg_price: 3113.480000000001 }, + { ts: "2024-02-05T19:52:00.000Z", avg_price: 3115.1179999999995 }, + { ts: "2024-02-05T19:53:00.000Z", avg_price: 3115.2999999999997 }, + { ts: "2024-02-05T19:54:00.000Z", avg_price: 3115.564833333333 }, + { ts: "2024-02-05T19:55:00.000Z", avg_price: 3117.5700000000006 }, + { ts: "2024-02-05T19:56:00.000Z", avg_price: 3118.8389999999995 }, + { ts: "2024-02-05T19:57:00.000Z", avg_price: 3121.8 }, + { ts: "2024-02-05T19:58:00.000Z", avg_price: 3121.7999999999997 }, + { ts: "2024-02-05T19:59:00.000Z", avg_price: 3121.7999999999997 }, + { ts: "2024-02-05T20:00:00.000Z", avg_price: 3120.780333333333 }, + { ts: "2024-02-05T20:01:00.000Z", avg_price: 3117.4299999999994 }, + { ts: "2024-02-05T20:02:00.000Z", avg_price: 3117.7874999999995 }, + { ts: "2024-02-05T20:03:00.000Z", avg_price: 3116.5 }, + { ts: "2024-02-05T20:04:00.000Z", avg_price: 3115.8933333333325 }, + { ts: "2024-02-05T20:05:00.000Z", avg_price: 3114.6799999999994 }, + { ts: "2024-02-05T20:06:00.000Z", avg_price: 3114.6799999999994 }, + { ts: "2024-02-05T20:07:00.000Z", avg_price: 3117.9186666666665 }, + { ts: "2024-02-05T20:08:00.000Z", avg_price: 3120.36 }, + { ts: "2024-02-05T20:09:00.000Z", avg_price: 3120.36 }, + { ts: "2024-02-05T20:10:00.000Z", avg_price: 3120.36 }, + { ts: "2024-02-05T20:11:00.000Z", avg_price: 3120.301999999999 }, + { ts: "2024-02-05T20:12:00.000Z", avg_price: 3120.6383333333333 }, + { ts: "2024-02-05T20:13:00.000Z", avg_price: 3121.2480000000005 }, + { ts: "2024-02-05T20:14:00.000Z", avg_price: 3122.21 }, + { ts: "2024-02-05T20:15:00.000Z", avg_price: 3120.6016666666674 }, + { ts: "2024-02-05T20:16:00.000Z", avg_price: 3119.83 }, + { ts: "2024-02-05T20:17:00.000Z", avg_price: 3119.83 }, + { ts: "2024-02-05T20:18:00.000Z", avg_price: 3119.8300000000004 }, + { ts: "2024-02-05T20:19:00.000Z", avg_price: 3119.8300000000004 }, + { ts: "2024-02-05T20:20:00.000Z", avg_price: 3119.83 }, + { ts: "2024-02-05T20:21:00.000Z", avg_price: 3119.83 }, + { ts: "2024-02-05T20:22:00.000Z", avg_price: 3119.8300000000004 }, + { ts: "2024-02-05T20:23:00.000Z", avg_price: 3119.83 }, + { ts: "2024-02-05T20:24:00.000Z", avg_price: 3119.83 }, + { ts: "2024-02-05T20:25:00.000Z", avg_price: 3119.8300000000004 }, + { ts: "2024-02-05T20:26:00.000Z", avg_price: 3119.83 }, + { ts: "2024-02-05T20:27:00.000Z", avg_price: 3119.83 }, + { ts: "2024-02-05T20:28:00.000Z", avg_price: 3119.83 }, + { ts: "2024-02-05T20:29:00.000Z", avg_price: 3119.8300000000004 }, + { ts: "2024-02-05T20:30:00.000Z", avg_price: 3119.8300000000004 }, + { ts: "2024-02-05T20:31:00.000Z", avg_price: 3119.83 }, + { ts: "2024-02-05T20:32:00.000Z", avg_price: 3119.8300000000004 }, + { ts: "2024-02-05T20:33:00.000Z", avg_price: 3119.8300000000004 }, + { ts: "2024-02-05T20:34:00.000Z", avg_price: 3119.067666666667 }, + { ts: "2024-02-05T20:35:00.000Z", avg_price: 3118.343500000001 }, + { ts: "2024-02-05T20:36:00.000Z", avg_price: 3120.8791666666666 }, + { ts: "2024-02-05T20:37:00.000Z", avg_price: 3121.9400000000005 }, + { ts: "2024-02-05T20:38:00.000Z", avg_price: 3123.2384999999995 }, + { ts: "2024-02-05T20:39:00.000Z", avg_price: 3123.5299999999993 }, + { ts: "2024-02-05T20:40:00.000Z", avg_price: 3125.2688333333335 }, + { ts: "2024-02-05T20:41:00.000Z", avg_price: 3126.2200000000007 }, + { ts: "2024-02-05T20:42:00.000Z", avg_price: 3130.6138333333333 }, + { ts: "2024-02-05T20:43:00.000Z", avg_price: 3132.65 }, + { ts: "2024-02-05T20:44:00.000Z", avg_price: 3132.902833333333 }, + { ts: "2024-02-05T20:45:00.000Z", avg_price: 3133.0599999999995 }, + { ts: "2024-02-05T20:46:00.000Z", avg_price: 3132.617333333333 }, + { ts: "2024-02-05T20:47:00.000Z", avg_price: 3131.4 }, + { ts: "2024-02-05T20:48:00.000Z", avg_price: 3131.3999999999996 }, + { ts: "2024-02-05T20:49:00.000Z", avg_price: 3131.4 }, + { ts: "2024-02-05T20:50:00.000Z", avg_price: 3136.072 }, + { ts: "2024-02-05T20:51:00.000Z", avg_price: 3137.2400000000002 }, + { ts: "2024-02-05T20:52:00.000Z", avg_price: 3137.24 }, + { ts: "2024-02-05T20:53:00.000Z", avg_price: 3137.24 }, + { ts: "2024-02-05T20:54:00.000Z", avg_price: 3137.2400000000002 }, + { ts: "2024-02-05T20:55:00.000Z", avg_price: 3137.24 }, +]; diff --git a/src/stories/vis-elements/BarList.stories.tsx b/src/stories/vis-elements/BarList.stories.tsx index 7c5eef325..e8137e027 100644 --- a/src/stories/vis-elements/BarList.stories.tsx +++ b/src/stories/vis-elements/BarList.stories.tsx @@ -83,3 +83,11 @@ export const IndividualColors: Story = { valueFormatter: (value) => `${value} USD`, }, }; + +export const WithOnValueChange: Story = { + render: (args) => , + args: { + data: getData(), + onValueChange: (data) => alert(JSON.stringify(data)), + }, +};