diff --git a/src/primitives/Indicators/CircleStat/CircleStat.mdx b/src/primitives/Indicators/CircleStat/CircleStat.mdx new file mode 100644 index 0000000..61a5339 --- /dev/null +++ b/src/primitives/Indicators/CircleStat/CircleStat.mdx @@ -0,0 +1,21 @@ +import { Meta, Title, Primary, Stories, Controls, Story } from "@storybook/blocks"; +import * as CircleStatStories from "./CircleStat.stories"; +import { CircleStat } from "./CircleStat"; + +# CircleStat + + + +The `CircleStat` component displays a circular statistic with a percentage. It supports customizable size, color, show percentage symbol and font options. + +## Example + + + +# Controls + + + +# Other Variations + + diff --git a/src/primitives/Indicators/CircleStat/CircleStat.stories.tsx b/src/primitives/Indicators/CircleStat/CircleStat.stories.tsx new file mode 100644 index 0000000..a362c98 --- /dev/null +++ b/src/primitives/Indicators/CircleStat/CircleStat.stories.tsx @@ -0,0 +1,80 @@ +import { Meta, StoryObj } from "@storybook/react"; +import { CircleStat } from "./CircleStat"; +import { colors } from "@/tokens/colors"; + +const meta: Meta = { + title: "Primitives/CircleStat", + component: CircleStat, + args: { + text: 50, + }, + argTypes: { + color: { + control: "color", + }, + size: { + control: "number", + }, + text: { + control: "number", + }, + showPercentageSymbol: { + control: "boolean", + }, + }, +} satisfies Meta; + +export default meta; + +type Story = StoryObj; + +export const Default: Story = {}; + +export const Lowtext: Story = { + args: { + text: 23, + }, +}; + +export const Midtext: Story = { + args: { + text: 54, + }, +}; + +export const Hightext: Story = { + args: { + text: 60, + }, +}; + +export const CustomColor: Story = { + args: { + color: "#ff00ff", + }, +}; + +export const CustomSize: Story = { + args: { + size: 60, + }, +}; + +export const WithoutPercentageSymbol: Story = { + args: { + text: 42, + showPercentageSymbol: false, + }, +}; + +export const CustomFont: Story = { + args: { + font: { + family: "Arial", + weight: "700", + size: "18px", + lineHeight: "28px", + color: "#8c7373", + }, + }, +}; diff --git a/src/primitives/Indicators/CircleStat/CircleStat.tsx b/src/primitives/Indicators/CircleStat/CircleStat.tsx new file mode 100644 index 0000000..6384b15 --- /dev/null +++ b/src/primitives/Indicators/CircleStat/CircleStat.tsx @@ -0,0 +1,71 @@ +import React from "react"; +import { cn } from "@/lib/utils"; +import { colors as col } from "../../../tokens/colors"; +import { ColorSet } from "@/tokens/types"; + +interface CircleStatProps { + text: number; + size?: number; + color?: string; + showPercentageSymbol?: boolean; + font?: { + family?: string; + weight?: string; + size?: string; + lineHeight?: string; + color?: string; + }; +} + +export const CircleStat: React.FC = ({ + text, + size = 48, + color, + showPercentageSymbol = true, + font = {}, +}) => { + const defaultColors = { + low: (col.orange as ColorSet)["300"], + mid: (col.yellow as ColorSet)["300"], + high: (col.green as ColorSet)["300"], + }; + + const defaultFont = { + family: "DM Sans", + weight: "400", + size: "16px", + lineHeight: "24px", + color: col.black, + }; + + const usedFont = { ...defaultFont, ...font }; + + const getColor = (text: number) => { + if (color) return color; + if (text <= 30) { + return defaultColors.low; + } else if (text < 60) { + return defaultColors.mid; + } else { + return defaultColors.high; + } + }; + + return ( +
+ {`${text}${showPercentageSymbol ? "%" : ""}`} +
+ ); +}; diff --git a/src/primitives/Indicators/index.ts b/src/primitives/Indicators/index.ts new file mode 100644 index 0000000..19f811f --- /dev/null +++ b/src/primitives/Indicators/index.ts @@ -0,0 +1 @@ +// export * from "./CircleStat/CircleStat"; diff --git a/src/tokens/colors.ts b/src/tokens/colors.ts index be6f5fa..727c1e0 100644 --- a/src/tokens/colors.ts +++ b/src/tokens/colors.ts @@ -8,4 +8,13 @@ export const colors: Colors = { }, white: "#ffffff", black: "#000000", + yellow: { + "300": "#ffea7d", + }, + orange: { + "300": "#ff9776", + }, + green: { + "300": "#c4f092", + }, };