From 8114ed012ad914c644d7efd9ea843c1fad21003d Mon Sep 17 00:00:00 2001
From: Justin
Date: Mon, 7 Apr 2025 22:11:48 +0200
Subject: [PATCH 01/35] Feature Request: - TechCarousel.tsx -
TechCarousel.module.scss
Display different Tech/Specs including icons through icons.ts
usage example:
const techStack= ["Java", "React", "Java", "Spring", "Hibernate", "Vue", "MySQL", "Docker", "Git", "Angular", "Javascript"]
---
src/once-ui/components/Badge.tsx | 2 +-
.../components/TechCarousel.module.scss | 8 ++
src/once-ui/components/TechCarousel.tsx | 89 +++++++++++++++++++
src/once-ui/icons.ts | 35 +++++++-
4 files changed, 131 insertions(+), 3 deletions(-)
create mode 100644 src/once-ui/components/TechCarousel.module.scss
create mode 100644 src/once-ui/components/TechCarousel.tsx
diff --git a/src/once-ui/components/Badge.tsx b/src/once-ui/components/Badge.tsx
index 804dc2cb..7370628e 100644
--- a/src/once-ui/components/Badge.tsx
+++ b/src/once-ui/components/Badge.tsx
@@ -6,7 +6,7 @@ import { Arrow, Flex, Icon, SmartLink, Text } from ".";
import styles from "./Badge.module.scss";
import { IconName } from "../icons";
-interface BadgeProps extends React.ComponentProps {
+export interface BadgeProps extends React.ComponentProps {
title?: string;
icon?: IconName;
arrow?: boolean;
diff --git a/src/once-ui/components/TechCarousel.module.scss b/src/once-ui/components/TechCarousel.module.scss
new file mode 100644
index 00000000..59641851
--- /dev/null
+++ b/src/once-ui/components/TechCarousel.module.scss
@@ -0,0 +1,8 @@
+.marqueeContent {
+ animation: marquee 20s linear infinite;
+}
+
+@keyframes marquee {
+ 0% { transform: translateX(0%); }
+ 100% { transform: translateX(-50%); }
+}
\ No newline at end of file
diff --git a/src/once-ui/components/TechCarousel.tsx b/src/once-ui/components/TechCarousel.tsx
new file mode 100644
index 00000000..28212b50
--- /dev/null
+++ b/src/once-ui/components/TechCarousel.tsx
@@ -0,0 +1,89 @@
+import { Row, RevealFx, Flex, Badge, BadgeProps } from "@/once-ui/components";
+import styles from "./TechCarousel.module.scss";
+import { IconName } from "@/once-ui/icons";
+import React from "react";
+import {SpacingToken} from "@/once-ui/types";
+
+const defaultIconMap: Record = {
+ java: 'java',
+ typescript: 'typescript',
+ javascript: 'js',
+
+ spring: 'spring',
+ hibernate: 'hibernate',
+ react: 'react',
+ angular: 'angular',
+ vue: 'vue',
+ nodejs: 'node',
+
+ postgresql: 'postgres',
+ mysql: 'mysql',
+ mongodb: 'mongo',
+
+ docker: 'docker',
+ kubernetes: 'kubernetes',
+ aws: 'aws',
+ gcp: 'gcp',
+ git: 'git',
+
+ graphql: 'graphql',
+ redis: 'redis',
+ nginx: 'nginx'
+};
+
+type TechItem = string | {
+ name: string;
+ icon?: IconName;
+};
+
+type TechCarouselProps = {
+ items: TechItem[];
+ textVariant?: BadgeProps["textVariant"];
+ spacing?: SpacingToken | "-1" | undefined;
+ iconMap?: Record;
+} & Partial;
+
+const TechCarousel = ({
+ items,
+ textVariant = "body-default-s",
+ spacing = "s",
+ iconMap = {},
+ ...badgeProps
+ }: TechCarouselProps) => {
+
+ const mergedIconMap = { ...defaultIconMap, ...iconMap };
+
+ const normalizedItems = items.map(item =>
+ typeof item === 'string' ? { name: item } : item
+ );
+
+ return (
+
+
+ {[...normalizedItems, ...normalizedItems].map((item, i) => {
+ const iconName = item.icon || mergedIconMap[item.name.toLowerCase()];
+
+ return (
+
+
+
+ );
+ })}
+
+
+ );
+};
+
+export { TechCarousel, defaultIconMap };
\ No newline at end of file
diff --git a/src/once-ui/icons.ts b/src/once-ui/icons.ts
index 8a1e6f38..d8d511f0 100644
--- a/src/once-ui/icons.ts
+++ b/src/once-ui/icons.ts
@@ -33,9 +33,21 @@ import {
import { RiVisaLine } from "react-icons/ri";
-import { FaDiscord, FaGithub, FaGoogle } from "react-icons/fa6";
+import {FaAmazon, FaDiscord, FaGitAlt, FaGithub, FaGoogle} from "react-icons/fa6";
import { LuChevronsLeftRight } from "react-icons/lu";
+import {FaJava} from "react-icons/fa";
+import {
+ SiAngular,
+ SiDocker, SiGooglecloud, SiGraphql,
+ SiHibernate,
+ SiKubernetes,
+ SiMongodb,
+ SiMysql, SiNginx, SiNodedotjs,
+ SiPostgresql, SiReact, SiRedis,
+ SiSpring,
+ SiTypescript, SiVuedotjs
+} from "react-icons/si";
export const iconLibrary: Record = {
chevronUp: HiChevronUp,
@@ -70,7 +82,26 @@ export const iconLibrary: Record = {
visa: RiVisaLine,
security: HiOutlineShieldCheck,
sparkle: HiOutlineSparkles,
- computer: HiOutlineComputerDesktop
+ computer: HiOutlineComputerDesktop,
+ java: FaJava,
+ spring: SiSpring,
+ hibernate: SiHibernate,
+ typescript: SiTypescript,
+ postgres: SiPostgresql,
+ mysql: SiMysql,
+ mongo: SiMongodb,
+ docker: SiDocker,
+ kubernetes: SiKubernetes,
+ aws: FaAmazon,
+ gcp: SiGooglecloud,
+ react: SiReact,
+ angular: SiAngular,
+ vue: SiVuedotjs,
+ node: SiNodedotjs,
+ graphql: SiGraphql,
+ redis: SiRedis,
+ nginx: SiNginx,
+ git: FaGitAlt
};
export type IconLibrary = typeof iconLibrary;
From 3bc3a7026ad717fd1f8c53ba02fb26fa1621c666 Mon Sep 17 00:00:00 2001
From: Justin
Date: Thu, 15 May 2025 17:24:54 +0200
Subject: [PATCH 02/35] feat(components): add customizable ProgressRing
component
- Implement SVG-based circular progress indicator with dynamic rendering
- Add size variants (s/m/l) and tone options (primary/warning/success)
- Include optional text label display with responsive positioning
- Support accessibility through ARIA attribute calculations
- Add smooth transition animations for value changes
- Create CSS module styles for maintainable theming
- Export component with TypeScript interface for type safety
---
.../components/ProgressRing.module.scss | 47 +++++++++++
src/once-ui/components/ProgressRing.tsx | 71 +++++++++++++++++
src/once-ui/components/SVG.tsx | 77 +++++++++++++++++++
3 files changed, 195 insertions(+)
create mode 100644 src/once-ui/components/ProgressRing.module.scss
create mode 100644 src/once-ui/components/ProgressRing.tsx
create mode 100644 src/once-ui/components/SVG.tsx
diff --git a/src/once-ui/components/ProgressRing.module.scss b/src/once-ui/components/ProgressRing.module.scss
new file mode 100644
index 00000000..2e782f0b
--- /dev/null
+++ b/src/once-ui/components/ProgressRing.module.scss
@@ -0,0 +1,47 @@
+.container {
+ --progress-color: var(--accent-alpha-strong);
+
+ position: relative;
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+
+ &.size {
+ &-s { width: 6rem; height: 6rem; }
+ &-m { width: 8rem; height: 8rem; }
+ &-l { width: 10rem; height: 10rem; }
+ }
+
+ &.tone {
+ &-warning { --progress-color: var(--warning-alpha-strong); }
+ &-success { --progress-color: var(--success-alpha-strong); }
+ }
+}
+
+.svg {
+ width: 100%;
+ height: 100%;
+ transform: rotate(-90deg);
+}
+
+.background {
+ fill: none;
+ stroke: var(--progress-color);
+ opacity: 0.4;
+}
+
+.progress {
+ fill: var(--surface-background);
+ stroke: var(--progress-color);
+ stroke-linecap: round;
+ transition: stroke-dashoffset 1.3s cubic-bezier(0.65, 0, 0.35, 1);
+}
+
+.label {
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ color: var(--foreground-strong);
+ font-weight: 600;
+}
\ No newline at end of file
diff --git a/src/once-ui/components/ProgressRing.tsx b/src/once-ui/components/ProgressRing.tsx
new file mode 100644
index 00000000..0270b316
--- /dev/null
+++ b/src/once-ui/components/ProgressRing.tsx
@@ -0,0 +1,71 @@
+"use client";
+
+import styles from "./ProgressRing.module.scss";
+import { Column, Text } from "@/once-ui/components";
+import {SVG} from "@/once-ui/components/SVG";
+
+interface ProgressRingProps {
+ value: number;
+ size?: "s" | "m" | "l";
+ tone?: "primary" | "warning" | "success";
+ label?: string;
+}
+
+export const ProgressRing = ({
+ value,
+ size = "s",
+ tone = "primary",
+ label
+ }: ProgressRingProps) => {
+ const strokeWidth = 4;
+ const radius = {
+ s: 30,
+ m: 45,
+ l: 60
+ }[size];
+
+ const normalizedRadius = radius - strokeWidth;
+ const circumference = normalizedRadius * 2 * Math.PI;
+ const strokeDashoffset = circumference - (value / 100) * circumference;
+
+ return (
+
+
+
+ {label && (
+
+ {label}
+
+ )}
+
+ );
+};
\ No newline at end of file
diff --git a/src/once-ui/components/SVG.tsx b/src/once-ui/components/SVG.tsx
new file mode 100644
index 00000000..0dc7cae4
--- /dev/null
+++ b/src/once-ui/components/SVG.tsx
@@ -0,0 +1,77 @@
+"use client";
+
+import React, { ElementType, ComponentPropsWithoutRef } from "react";
+import classNames from "classnames";
+import {CommonProps, SpacingProps} from "@/once-ui/interfaces";
+import {ColorScheme, ColorWeight, SpacingToken} from "@/once-ui/types";
+
+type SVGProps =
+ ComponentPropsWithoutRef<"svg"> &
+ CommonProps &
+ SpacingProps & {
+ as?: T;
+ colorScheme?: ColorScheme;
+ colorWeight?: ColorWeight;
+ strokeScheme?: ColorScheme;
+ strokeWeight?: ColorWeight;
+ interactive?: boolean;
+ size?: "x" | "s" | "m" | "l" | "xl";
+};
+
+export const SVG = ({
+ as,
+ colorScheme = "neutral",
+ colorWeight = "weak",
+ strokeScheme,
+ strokeWeight = "weak",
+ interactive = false,
+ size = "m",
+ padding,
+ margin,
+ className,
+ style,
+ children,
+ ...props
+ }: SVGProps) => {
+ const Component = as || "svg";
+
+ const generateColorClass = (
+ type: "fill" | "stroke",
+ scheme?: ColorScheme,
+ weight?: ColorWeight
+ ) => {
+ if (!scheme) return "";
+ return `${type}-${scheme}-${weight}`;
+ };
+
+ const generateSpacingClass = (prefix: string, token?: SpacingToken) => {
+ return token ? `${prefix}-${token}` : "";
+ };
+
+ const classes = classNames(
+ "transition-colors",
+ generateColorClass("fill", colorScheme, colorWeight),
+ generateColorClass("stroke", strokeScheme, strokeWeight),
+ generateSpacingClass("p", padding),
+ generateSpacingClass("m", margin),
+ {
+ "cursor-pointer hover:scale-105": interactive,
+ "opacity-hoverable": interactive
+ },
+ className
+ );
+
+ return (
+
+ {children}
+
+ );
+};
\ No newline at end of file
From 6c84e140ee169578418f8453fd894410452330f6 Mon Sep 17 00:00:00 2001
From: Adhitya Nadooli <127269031+lightyfr@users.noreply.github.com>
Date: Thu, 27 Mar 2025 15:14:10 -0400
Subject: [PATCH 03/35] Add data-viz modules, add components to index, add
recharts to package.json (#39)
# Conflicts:
# src/once-ui/components/index.ts
---
package-lock.json | 359 +++++++++++++++++-
package.json | 1 +
src/once-ui/components/BarGraph.module.scss | 56 +++
src/once-ui/components/BarGraph.tsx | 241 ++++++++++++
.../components/LineBarGraph.module.scss | 53 +++
src/once-ui/components/LineBarGraph.tsx | 315 +++++++++++++++
src/once-ui/components/LineGraph.module.scss | 62 +++
src/once-ui/components/LineGraph.tsx | 261 +++++++++++++
src/once-ui/components/MultiBarGraph.tsx | 249 ++++++++++++
src/once-ui/components/index.ts | 4 +
10 files changed, 1600 insertions(+), 1 deletion(-)
create mode 100644 src/once-ui/components/BarGraph.module.scss
create mode 100644 src/once-ui/components/BarGraph.tsx
create mode 100644 src/once-ui/components/LineBarGraph.module.scss
create mode 100644 src/once-ui/components/LineBarGraph.tsx
create mode 100644 src/once-ui/components/LineGraph.module.scss
create mode 100644 src/once-ui/components/LineGraph.tsx
create mode 100644 src/once-ui/components/MultiBarGraph.tsx
diff --git a/package-lock.json b/package-lock.json
index 539710c2..9eb5d298 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -18,6 +18,7 @@
"react": "19.0.0",
"react-dom": "19.0.0",
"react-icons": "^5.2.1",
+ "recharts": "^2.15.1",
"sass": "^1.77.6",
"sharp": "^0.33.4"
},
@@ -32,6 +33,17 @@
"typescript": "5.8.2"
}
},
+ "node_modules/@babel/runtime": {
+ "version": "7.27.0",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.0.tgz",
+ "integrity": "sha512-VtPOkrdPHZsKc/clNqyi9WUA8TINkZ4cGk63UUE3u4pmB2k+ZMQRDuIOagv8UVd6j7k0T3+RRIb7beKTebNbcw==",
+ "dependencies": {
+ "regenerator-runtime": "^0.14.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
"node_modules/@biomejs/biome": {
"version": "1.9.4",
"resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-1.9.4.tgz",
@@ -2081,6 +2093,60 @@
"tslib": "^2.8.0"
}
},
+ "node_modules/@types/d3-array": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.1.tgz",
+ "integrity": "sha512-Y2Jn2idRrLzUfAKV2LyRImR+y4oa2AntrgID95SHJxuMUrkNXmanDSed71sRNZysveJVt1hLLemQZIady0FpEg=="
+ },
+ "node_modules/@types/d3-color": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.3.tgz",
+ "integrity": "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A=="
+ },
+ "node_modules/@types/d3-ease": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.2.tgz",
+ "integrity": "sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA=="
+ },
+ "node_modules/@types/d3-interpolate": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz",
+ "integrity": "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==",
+ "dependencies": {
+ "@types/d3-color": "*"
+ }
+ },
+ "node_modules/@types/d3-path": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.1.1.tgz",
+ "integrity": "sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg=="
+ },
+ "node_modules/@types/d3-scale": {
+ "version": "4.0.9",
+ "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.9.tgz",
+ "integrity": "sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw==",
+ "dependencies": {
+ "@types/d3-time": "*"
+ }
+ },
+ "node_modules/@types/d3-shape": {
+ "version": "3.1.7",
+ "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.7.tgz",
+ "integrity": "sha512-VLvUQ33C+3J+8p+Daf+nYSOsjB4GXp19/S/aGo60m9h1v6XaxjiT82lKVWJCfzhtuZ3yD7i/TPeC/fuKLLOSmg==",
+ "dependencies": {
+ "@types/d3-path": "*"
+ }
+ },
+ "node_modules/@types/d3-time": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.4.tgz",
+ "integrity": "sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g=="
+ },
+ "node_modules/@types/d3-timer": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.2.tgz",
+ "integrity": "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw=="
+ },
"node_modules/@types/node": {
"version": "20.17.23",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.17.23.tgz",
@@ -2257,6 +2323,14 @@
"integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==",
"license": "MIT"
},
+ "node_modules/clsx": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
+ "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/color": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz",
@@ -2414,9 +2488,123 @@
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
- "dev": true,
"license": "MIT"
},
+ "node_modules/d3-array": {
+ "version": "3.2.4",
+ "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz",
+ "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==",
+ "dependencies": {
+ "internmap": "1 - 2"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-color": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz",
+ "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-ease": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz",
+ "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-format": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz",
+ "integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-interpolate": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz",
+ "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==",
+ "dependencies": {
+ "d3-color": "1 - 3"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-path": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz",
+ "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-scale": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz",
+ "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==",
+ "dependencies": {
+ "d3-array": "2.10.0 - 3",
+ "d3-format": "1 - 3",
+ "d3-interpolate": "1.2.0 - 3",
+ "d3-time": "2.1.1 - 3",
+ "d3-time-format": "2 - 4"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-shape": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz",
+ "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==",
+ "dependencies": {
+ "d3-path": "^3.1.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-time": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz",
+ "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==",
+ "dependencies": {
+ "d3-array": "2 - 3"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-time-format": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz",
+ "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==",
+ "dependencies": {
+ "d3-time": "1 - 3"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-timer": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz",
+ "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/decimal.js-light": {
+ "version": "2.5.1",
+ "resolved": "https://registry.npmjs.org/decimal.js-light/-/decimal.js-light-2.5.1.tgz",
+ "integrity": "sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg=="
+ },
"node_modules/detect-libc": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz",
@@ -2430,6 +2618,15 @@
"node": ">=0.10"
}
},
+ "node_modules/dom-helpers": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz",
+ "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==",
+ "dependencies": {
+ "@babel/runtime": "^7.8.7",
+ "csstype": "^3.0.2"
+ }
+ },
"node_modules/electron-to-chromium": {
"version": "1.5.112",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.112.tgz",
@@ -2445,6 +2642,19 @@
"node": ">=6"
}
},
+ "node_modules/eventemitter3": {
+ "version": "4.0.7",
+ "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz",
+ "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw=="
+ },
+ "node_modules/fast-equals": {
+ "version": "5.2.2",
+ "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-5.2.2.tgz",
+ "integrity": "sha512-V7/RktU11J3I36Nwq2JnZEM7tNm17eBJz+u25qdxBZeCKiX6BkVSZQjwWIr+IobgnZy+ag73tTZgZi7tr0LrBw==",
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
"node_modules/fill-range": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
@@ -2477,6 +2687,14 @@
"integrity": "sha512-P8IdPQHq3lA1xVeBRi5VPqUm5HDgKnx0Ru51wZz5mjxHr5n3RWhjIpOFU7ybkUxfB+5IToy+OLaHYDBIWsv+uw==",
"license": "MIT"
},
+ "node_modules/internmap": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz",
+ "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==",
+ "engines": {
+ "node": ">=12"
+ }
+ },
"node_modules/is-arrayish": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz",
@@ -2528,6 +2746,27 @@
"node": ">=0.12.0"
}
},
+ "node_modules/js-tokens": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
+ },
+ "node_modules/lodash": {
+ "version": "4.17.21",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
+ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
+ },
+ "node_modules/loose-envify": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
+ "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
+ "dependencies": {
+ "js-tokens": "^3.0.0 || ^4.0.0"
+ },
+ "bin": {
+ "loose-envify": "cli.js"
+ }
+ },
"node_modules/micromatch": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
@@ -2664,6 +2903,14 @@
"node": ">=0.10.0"
}
},
+ "node_modules/object-assign": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+ "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/picocolors": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
@@ -3420,6 +3667,21 @@
"node": ">=6"
}
},
+ "node_modules/prop-types": {
+ "version": "15.8.1",
+ "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
+ "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
+ "dependencies": {
+ "loose-envify": "^1.4.0",
+ "object-assign": "^4.1.1",
+ "react-is": "^16.13.1"
+ }
+ },
+ "node_modules/prop-types/node_modules/react-is": {
+ "version": "16.13.1",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
+ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
+ },
"node_modules/react": {
"version": "19.0.0",
"resolved": "https://registry.npmjs.org/react/-/react-19.0.0.tgz",
@@ -3450,6 +3712,40 @@
"react": "*"
}
},
+ "node_modules/react-is": {
+ "version": "18.3.1",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz",
+ "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg=="
+ },
+ "node_modules/react-smooth": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/react-smooth/-/react-smooth-4.0.4.tgz",
+ "integrity": "sha512-gnGKTpYwqL0Iii09gHobNolvX4Kiq4PKx6eWBCYYix+8cdw+cGo3do906l1NBPKkSWx1DghC1dlWG9L2uGd61Q==",
+ "dependencies": {
+ "fast-equals": "^5.0.1",
+ "prop-types": "^15.8.1",
+ "react-transition-group": "^4.4.5"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
+ "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+ }
+ },
+ "node_modules/react-transition-group": {
+ "version": "4.4.5",
+ "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz",
+ "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==",
+ "dependencies": {
+ "@babel/runtime": "^7.5.5",
+ "dom-helpers": "^5.0.1",
+ "loose-envify": "^1.4.0",
+ "prop-types": "^15.6.2"
+ },
+ "peerDependencies": {
+ "react": ">=16.6.0",
+ "react-dom": ">=16.6.0"
+ }
+ },
"node_modules/readdirp": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz",
@@ -3463,6 +3759,41 @@
"url": "https://paulmillr.com/funding/"
}
},
+ "node_modules/recharts": {
+ "version": "2.15.1",
+ "resolved": "https://registry.npmjs.org/recharts/-/recharts-2.15.1.tgz",
+ "integrity": "sha512-v8PUTUlyiDe56qUj82w/EDVuzEFXwEHp9/xOowGAZwfLjB9uAy3GllQVIYMWF6nU+qibx85WF75zD7AjqoT54Q==",
+ "dependencies": {
+ "clsx": "^2.0.0",
+ "eventemitter3": "^4.0.1",
+ "lodash": "^4.17.21",
+ "react-is": "^18.3.1",
+ "react-smooth": "^4.0.4",
+ "recharts-scale": "^0.4.4",
+ "tiny-invariant": "^1.3.1",
+ "victory-vendor": "^36.6.8"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "react": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
+ "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+ }
+ },
+ "node_modules/recharts-scale": {
+ "version": "0.4.5",
+ "resolved": "https://registry.npmjs.org/recharts-scale/-/recharts-scale-0.4.5.tgz",
+ "integrity": "sha512-kivNFO+0OcUNu7jQquLXAxz1FIwZj8nrj+YkOKc5694NbjCvcT6aSZiIzNzd2Kul4o4rTto8QVR9lMNtxD4G1w==",
+ "dependencies": {
+ "decimal.js-light": "^2.4.1"
+ }
+ },
+ "node_modules/regenerator-runtime": {
+ "version": "0.14.1",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz",
+ "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw=="
+ },
"node_modules/sass": {
"version": "1.85.1",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.85.1.tgz",
@@ -3598,6 +3929,11 @@
}
}
},
+ "node_modules/tiny-invariant": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz",
+ "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg=="
+ },
"node_modules/to-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
@@ -3673,6 +4009,27 @@
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
"license": "MIT"
+ },
+ "node_modules/victory-vendor": {
+ "version": "36.9.2",
+ "resolved": "https://registry.npmjs.org/victory-vendor/-/victory-vendor-36.9.2.tgz",
+ "integrity": "sha512-PnpQQMuxlwYdocC8fIJqVXvkeViHYzotI+NJrCuav0ZYFoq912ZHBk3mCeuj+5/VpodOjPe1z0Fk2ihgzlXqjQ==",
+ "dependencies": {
+ "@types/d3-array": "^3.0.3",
+ "@types/d3-ease": "^3.0.0",
+ "@types/d3-interpolate": "^3.0.1",
+ "@types/d3-scale": "^4.0.2",
+ "@types/d3-shape": "^3.1.0",
+ "@types/d3-time": "^3.0.0",
+ "@types/d3-timer": "^3.0.0",
+ "d3-array": "^3.1.6",
+ "d3-ease": "^3.0.1",
+ "d3-interpolate": "^3.0.1",
+ "d3-scale": "^4.0.2",
+ "d3-shape": "^3.1.0",
+ "d3-time": "^3.0.0",
+ "d3-timer": "^3.0.1"
+ }
}
}
}
diff --git a/package.json b/package.json
index 95887803..e9ede82c 100644
--- a/package.json
+++ b/package.json
@@ -20,6 +20,7 @@
"react": "19.0.0",
"react-dom": "19.0.0",
"react-icons": "^5.2.1",
+ "recharts": "^2.15.1",
"sass": "^1.77.6",
"sharp": "^0.33.4"
},
diff --git a/src/once-ui/components/BarGraph.module.scss b/src/once-ui/components/BarGraph.module.scss
new file mode 100644
index 00000000..ec2f0669
--- /dev/null
+++ b/src/once-ui/components/BarGraph.module.scss
@@ -0,0 +1,56 @@
+.graphContainer {
+ width: 100%;
+ height: 200px;
+ border-radius: 12px;
+ padding: 24px;
+
+ :global(.recharts-bar-rectangle) {
+ filter: drop-shadow(0 0 8px rgba(4, 78, 120, 0.3));
+ }
+ }
+
+ .blur {
+ backdrop-filter: blur(12px);
+ -webkit-backdrop-filter: blur(12px);
+ }
+
+ .blur::backdrop {
+ backdrop-filter: blur(12px);
+ }
+
+ .blur::before {
+ backdrop-filter: blur(12px);
+ }
+
+ .tooltip {
+ backdrop-filter: blur(12px);
+ border: 1px solid var(--neutral-alpha-medium);
+ border-radius: var(--radius-m);
+ text-align: center;
+ justify-content: center;
+ align-items: center;
+
+ .label {
+ text-align: center;
+ margin: 0 0 10px;
+ font-size: 15px;
+ font-weight: 600;
+ color: var(--neutral-on-background-strong);
+ }
+
+ .value {
+ font-weight: 500;
+ text-align: center;
+ margin: 4px 0;
+ display: flex;
+ align-items: center;
+ }
+ }
+
+ .tooltipWrapper {
+ background-color: var(--neutral-background-strong);
+ border: 1px solid var(--neutral-border-medium);
+ border-radius: var(--radius-s);
+ color: var(--neutral-on-background-medium);
+ }
+
\ No newline at end of file
diff --git a/src/once-ui/components/BarGraph.tsx b/src/once-ui/components/BarGraph.tsx
new file mode 100644
index 00000000..64f8356c
--- /dev/null
+++ b/src/once-ui/components/BarGraph.tsx
@@ -0,0 +1,241 @@
+import React from "react";
+import {
+ BarChart,
+ Bar,
+ XAxis,
+ YAxis,
+ ResponsiveContainer,
+ CartesianGrid,
+ Tooltip,
+} from "recharts";
+
+import {
+ GridProps,
+ SpacingProps,
+ SizeProps,
+ StyleProps,
+ CommonProps,
+ DisplayProps,
+ ConditionalProps,
+} from "../interfaces";
+
+import { SpacingToken, ColorScheme, ColorWeight } from "../types";
+
+import styles from "./BarGraph.module.scss";
+import { Text, Flex, Heading, Line } from "."; // Import Text component from OnceUI
+import classNames from "classnames"; // Import classNames for conditional styling
+
+interface DataPoint {
+ name: string;
+ value: number;
+ startDate: string;
+ endDate: string;
+ color?: string; // Optional color prop, if needed
+}
+
+type BarColor = "success" | "danger" | "purple";
+
+type BarRadius = "xs" | "s" | "m" | "l" | "xl";
+
+interface BarGraphProps extends React.ComponentProps {
+ data: DataPoint[];
+ xAxisKey?: string; // Allows customization of the x-axis data key
+ yAxisKey?: string; // Allows customization of the y-axis data key
+ barColor?: BarColor; // Prop for bar color
+ /**
+ * Size of the bar graph.
+ * @default "m"
+ */
+ size?: "xs" | "s" | "m" | "l" | "xl";
+ blur?: boolean; // Controls backdrop blur effect
+ title?: string; // Title for the bar graph
+ tooltipTitle?: string; // Title for the tooltip
+ /** Hide X-axis labels */
+ hideXAxisLabels?: boolean;
+ /** Hide Y-axis labels */
+ hideYAxisLabels?: boolean;
+ /** Hide both X and Y axis labels */
+ hideLabels?: boolean;
+ /** Title for X-axis */
+ xAxisTitle?: string;
+ /** Title for Y-axis */
+ yAxisTitle?: string;
+ /** Hide X-axis title */
+ hideXAxisTitle?: boolean;
+ /** Hide Y-axis title */
+ hideYAxisTitle?: boolean;
+ /** Hide both X and Y axis titles */
+ hideAxisTitles?: boolean;
+}
+
+const CustomTooltip = ({ active, payload, tooltipTitle }: any) => {
+ if (active && payload && payload.length) {
+ const data = payload[0].payload;
+ return (
+
+
+ {`${data.startDate} - ${data.endDate}`}
+
+
+
+ {`${tooltipTitle}: ${data.value}`}
+
+
+
+ );
+ }
+ return null;
+};
+
+export const BarGraph: React.FC = ({
+ data,
+ xAxisKey = "name",
+ yAxisKey = "value",
+ barColor = "success",
+ size = "m",
+ blur = false,
+ border,
+ title,
+ radius,
+ tooltipTitle,
+ background,
+ hideXAxisLabels = false,
+ hideYAxisLabels = false,
+ hideLabels = false,
+ xAxisTitle,
+ yAxisTitle,
+ hideXAxisTitle = false,
+ hideYAxisTitle = false,
+ hideAxisTitles = false,
+}) => {
+ const height = {
+ xs: 100,
+ s: 150,
+ m: 200,
+ l: 250,
+ xl: 300,
+ }[size];
+
+ const barSize = {
+ xs: 16,
+ s: 24,
+ m: 32,
+ l: 40,
+ xl: 48,
+ }[size];
+
+ const barColorMap = {
+ success: "var(--success-solid-strong)",
+ danger: "var(--danger-solid-strong)",
+ purple: "#8a63d2",
+ };
+
+ const barSolidColor = barColorMap[barColor];
+
+ return (
+
+
+ {title}
+
+
+
+
+
+
+
+ }
+ cursor={{ fill: "rgba(255,255,255,0.05)" }}
+ wrapperClassName={styles.tooltipWrapper} // Apply styles to the tooltip wrapper
+ />
+
+
+ {[
+ { offset: "0%", opacity: 0.8 },
+ { offset: "35%", opacity: 0.6 },
+ { offset: "70%", opacity: 0.3 },
+ { offset: "95%", opacity: 0.1 },
+ { offset: "100%", opacity: 0 },
+ ].map(({ offset, opacity }) => (
+
+ ))}
+
+
+
+
+
+
+
+ );
+};
diff --git a/src/once-ui/components/LineBarGraph.module.scss b/src/once-ui/components/LineBarGraph.module.scss
new file mode 100644
index 00000000..d8dcd119
--- /dev/null
+++ b/src/once-ui/components/LineBarGraph.module.scss
@@ -0,0 +1,53 @@
+.graphContainer {
+ width: 100%;
+ height: 100%;
+ min-height: 200px;
+ border-radius: 12px;
+ padding: 24px;
+
+ :global(.recharts-bar-rectangle) {
+ filter: drop-shadow(0 0 8px rgba(4, 78, 120, 0.3));
+ }
+
+ :global(.recharts-dot) {
+ filter: drop-shadow(0 0 4px rgba(78, 114, 238, 0.6));
+ }
+ }
+
+ .blur {
+ backdrop-filter: blur(12px);
+ -webkit-backdrop-filter: blur(12px);
+ }
+
+ .tooltip {
+ backdrop-filter: blur(12px);
+ border: 1px solid var(--neutral-alpha-medium);
+ border-radius: var(--radius-m);
+ text-align: center;
+ justify-content: center;
+ align-items: center;
+ backdrop-filter: blur(12px);
+
+ .label {
+ text-align: center;
+ font-size: 15px;
+ font-weight: 600;
+ color: var(--neutral-on-background-strong);
+ }
+
+ .value {
+ font-weight: 500;
+ text-align: center;
+ margin: 4px 0;
+ display: flex;
+ align-items: center;
+ }
+ }
+
+ .tooltipWrapper {
+ background-color: var(--neutral-background-strong);
+ border: 1px solid var(--neutral-border-medium);
+ border-radius: var(--radius-s);
+ color: var(--neutral-on-background-medium);
+ padding: 8px;
+ }
\ No newline at end of file
diff --git a/src/once-ui/components/LineBarGraph.tsx b/src/once-ui/components/LineBarGraph.tsx
new file mode 100644
index 00000000..030e8c2d
--- /dev/null
+++ b/src/once-ui/components/LineBarGraph.tsx
@@ -0,0 +1,315 @@
+import React from "react";
+import {
+ ComposedChart,
+ Line,
+ Bar,
+ XAxis,
+ YAxis,
+ CartesianGrid,
+ Tooltip,
+ ResponsiveContainer,
+ Legend,
+ Area,
+} from "recharts";
+import styles from "./LineBarGraph.module.scss";
+import { Flex, Heading } from ".";
+
+interface DataPoint {
+ name: string;
+ lineValue: number;
+ barValue: number;
+ [key: string]: any; // Allow for additional properties
+}
+
+interface LineBarGraphProps extends React.ComponentProps {
+ data: DataPoint[];
+ xAxisKey?: string;
+ lineDataKey?: string;
+ barDataKey?: string;
+ lineName?: string;
+ barName?: string;
+ /**
+ * Size of the graph.
+ * @default "m"
+ */
+ size?: "xs" | "s" | "m" | "l" | "xl";
+ blur?: boolean;
+ title?: string;
+ lineColor?: string;
+ lineColorVariant?: "info" | "success" | "danger" | "purple"; // Add color variant prop
+ barColor?: string;
+ /**
+ * Show area under the line
+ * @default true
+ */
+ showArea?: boolean;
+ /**
+ * Hide X-axis labels when true
+ * @default false
+ */
+ hideXAxisLabels?: boolean;
+ /**
+ * Hide Y-axis labels when true
+ * @default false
+ */
+ hideYAxisLabels?: boolean;
+ /**
+ * Hide both X and Y axis labels when true
+ * @default false
+ */
+ hideLabels?: boolean;
+ /**
+ * Title for X-axis
+ */
+ xAxisTitle?: string;
+ /**
+ * Title for Y-axis
+ */
+ yAxisTitle?: string;
+ /**
+ * Hide X-axis title
+ * @default false
+ */
+ hideXAxisTitle?: boolean;
+ /**
+ * Hide Y-axis title
+ * @default false
+ */
+ hideYAxisTitle?: boolean;
+ /**
+ * Hide both X and Y axis titles
+ * @default false
+ */
+ hideAxisTitles?: boolean;
+ /**
+ * Hide legend
+ * @default false
+ */
+ showLegend?: boolean;
+}
+
+const CustomTooltip = ({ active, payload, label }: any) => {
+ if (active && payload && payload.length) {
+ return (
+
+
+ {label}
+
+
+ {payload.map((entry: any, index: number) => (
+
+ {`${entry.name}: ${entry.value}`}
+
+ ))}
+
+
+ );
+ }
+ return null;
+};
+
+export const LineBarGraph: React.FC = ({
+ data,
+ xAxisKey = "name",
+ lineDataKey = "lineValue",
+ barDataKey = "barValue",
+ lineName = "Line",
+ barName = "Bar",
+ size = "m",
+ blur = false,
+ border,
+ title,
+ lineColorVariant = "info", // Options: "info", "success", "danger", "purple"
+ barColor = "var(--success-solid-strong)",
+ radius,
+ background,
+ showArea = true,
+ hideXAxisLabels = false,
+ hideYAxisLabels = false,
+ hideLabels = false,
+ xAxisTitle,
+ yAxisTitle,
+ hideXAxisTitle = false,
+ hideYAxisTitle = false,
+ hideAxisTitles = false,
+ showLegend = false,
+ ...flexProps
+}) => {
+ const height = {
+ xs: 100,
+ s: 150,
+ m: 200,
+ l: 250,
+ xl: 300,
+ }[size];
+
+ const barSize = {
+ xs: 16,
+ s: 24,
+ m: 32,
+ l: 40,
+ xl: 48,
+ }[size];
+
+ // Generate a unique ID for each gradient
+ const lineGradientId = `colorLine-${Math.random().toString(36).substring(2, 9)}`;
+ const barGradientId = `barGradient-${Math.random().toString(36).substring(2, 9)}`;
+
+ const colorMap = {
+ info: "var(--info-solid-strong)",
+ success: "var(--success-solid-strong)",
+ danger: "var(--danger-solid-strong)",
+ purple: "#6c5ce7"
+ };
+
+ // Use the variant to determine the color
+ const finalLineColor = lineColorVariant ? colorMap[lineColorVariant] : "var(--info-solid-strong)";
+
+ return (
+
+ {title && (
+
+ {title}
+
+ )}
+
+
+
+
+ {/* Bar gradient */}
+
+ {[
+ { offset: "0%", opacity: 0.8 },
+ { offset: "35%", opacity: 0.6 },
+ { offset: "70%", opacity: 0.3 },
+ { offset: "95%", opacity: 0.1 },
+ { offset: "100%", opacity: 0 },
+ ].map(({ offset, opacity }) => (
+
+ ))}
+
+
+ {/* Line gradient - similar to LineGraph component */}
+
+
+
+
+
+
+
+
+
+ }
+ cursor={{ fill: "rgba(255,255,255,0.05)" }}
+ wrapperClassName={styles.tooltipWrapper}
+ />
+ {showLegend && (
+
+ )}
+
+
+ {showArea ? (
+
+ ) : (
+
+ )}
+
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/src/once-ui/components/LineGraph.module.scss b/src/once-ui/components/LineGraph.module.scss
new file mode 100644
index 00000000..9ba50274
--- /dev/null
+++ b/src/once-ui/components/LineGraph.module.scss
@@ -0,0 +1,62 @@
+.graphContainer {
+ border-radius: 12px;
+ padding: 24px;
+ width: 100%;
+ height: 100%;
+ min-height: 300px;
+ border: 1px solid rgba(255, 255, 255, 0.05);
+
+ :global(.recharts-cartesian-grid-horizontal line),
+ :global(.recharts-cartesian-grid-vertical line) {
+ stroke: var(--neutral-background-strong);
+ }
+
+ :global(.recharts-tooltip-cursor) {
+ fill: rgba(255, 255, 255, 0.02);
+ }
+
+ :global(.recharts-default-tooltip) {
+ background-color: #0f0f13 !important;
+ border: 1px solid rgba(255, 255, 255, 0.05) !important;
+ border-radius: 4px;
+ padding: 8px !important;
+ box-shadow:
+ 0 4px 6px -1px rgba(0, 0, 0, 0.2),
+ 0 2px 4px -1px rgba(0, 0, 0, 0.1);
+ }
+
+ :global(.recharts-surface) {
+ overflow: visible;
+ }
+
+ :global(.recharts-bar-rectangle) {
+ filter: drop-shadow(0 0 8px rgba(4, 78, 120, 0.3));
+ }
+ }
+
+ .tooltip {
+ backdrop-filter: blur(12px);
+ border: 1px solid var(--neutral-alpha-medium);
+ border-radius: var(--radius-m);
+ text-align: center;
+ justify-content: center;
+ background-color: none;
+ background: none;
+ align-items: center;
+
+ .label {
+ text-align: center;
+ padding: 5px;
+ font-size: 15px;
+ font-weight: 600;
+ color: var(--neutral-on-background-strong);
+ }
+
+ .value {
+ font-weight: 500;
+ text-align: center;
+ display: flex;
+ align-items: center;
+ }
+ }
+
\ No newline at end of file
diff --git a/src/once-ui/components/LineGraph.tsx b/src/once-ui/components/LineGraph.tsx
new file mode 100644
index 00000000..3bca76cf
--- /dev/null
+++ b/src/once-ui/components/LineGraph.tsx
@@ -0,0 +1,261 @@
+import React from "react";
+import {
+ AreaChart,
+ Area,
+ XAxis,
+ YAxis,
+ CartesianGrid,
+ Tooltip,
+ ResponsiveContainer,
+ TooltipProps,
+} from "recharts";
+import styles from "./LineGraph.module.scss";
+import { Flex, Heading } from ".";
+
+interface DataPoint {
+ name: string;
+ value1: number;
+ value2: number;
+ value3: number;
+}
+
+interface LineGraphProps extends React.ComponentProps {
+ data: DataPoint[];
+ xAxisKey?: string;
+ yAxisKey1?: string;
+ yAxisKey2?: string;
+ yAxisKey3?: string;
+ /**
+ * Size of the line graph.
+ * @default "m"
+ */
+ size?: "xs" | "s" | "m" | "l" | "xl";
+ blur?: boolean;
+ title?: string;
+ tooltipTitle?: string;
+ value1?: string;
+ value2?: string;
+ value3?: string;
+ /**
+ * Hide X-axis labels when true
+ * @default false
+ */
+ hideXAxisLabels?: boolean;
+ /**
+ * Hide Y-axis labels when true
+ * @default false
+ */
+ hideYAxisLabels?: boolean;
+ /**
+ * Hide both X and Y axis labels when true
+ * @default false
+ */
+ hideLabels?: boolean;
+}
+
+interface CustomTooltipProps extends TooltipProps {
+ tooltipTitle?: string;
+ key1?: string;
+ key2?: string;
+ key3?: string;
+ yAxisKey1?: string;
+ yAxisKey2?: string;
+ yAxisKey3?: string;
+}
+
+const CustomTooltip = ({
+ active,
+ payload,
+ tooltipTitle,
+ label,
+ key1,
+ key2,
+ key3,
+ yAxisKey1 = "value1",
+ yAxisKey2 = "value2",
+ yAxisKey3 = "value3",
+}: CustomTooltipProps) => {
+ if (active && payload && payload.length) {
+ return (
+
+
+ {`${tooltipTitle}`}
+
+
+
+ {`${key1}: ${payload[0].value}`}
+
+
+ {`${key2}: ${payload[1].value}`}
+
+
+ {`${key3}: ${payload[2].value}`}
+
+
+
+ );
+ }
+ return null;
+};
+
+export const LineGraph: React.FC = ({
+ data,
+ xAxisKey = "name",
+ yAxisKey1 = "value1",
+ yAxisKey2 = "value2",
+ yAxisKey3 = "value3",
+ size = "m",
+ blur = false,
+ border,
+ title,
+ value1,
+ value2,
+ value3,
+ tooltipTitle,
+ radius,
+ background,
+ hideXAxisLabels = false,
+ hideYAxisLabels = false,
+ hideLabels = false,
+ ...flexProps
+}) => {
+ const height = {
+ xs: 100,
+ s: 150,
+ m: 200,
+ l: 250,
+ xl: 300,
+ }[size];
+
+ return (
+
+
+ {title}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ }
+ contentStyle={{
+ backgroundColor: "#0f0f13",
+ border: "1px solid rgba(255,255,255,0.05)",
+ borderRadius: "4px",
+ color: "rgba(255,255,255,0.7)",
+ }}
+ />
+
+
+
+
+
+
+
+ );
+};
diff --git a/src/once-ui/components/MultiBarGraph.tsx b/src/once-ui/components/MultiBarGraph.tsx
new file mode 100644
index 00000000..89f1dcd4
--- /dev/null
+++ b/src/once-ui/components/MultiBarGraph.tsx
@@ -0,0 +1,249 @@
+import React from "react";
+import {
+ BarChart,
+ Bar,
+ XAxis,
+ YAxis,
+ ResponsiveContainer,
+ CartesianGrid,
+ Tooltip,
+ Legend,
+} from "recharts";
+
+import {
+ GridProps,
+ SpacingProps,
+ SizeProps,
+ StyleProps,
+ CommonProps,
+ DisplayProps,
+ ConditionalProps,
+} from "../interfaces";
+
+import styles from "./BarGraph.module.scss";
+import { Text, Flex, Heading } from ".";
+
+// Data structure supporting multiple values
+interface MultiBarDataPoint {
+ name: string;
+ value1?: number;
+ value2?: number;
+ value3?: number;
+ startDate?: string;
+ endDate?: string;
+}
+
+interface MultiBarGraphProps extends React.ComponentProps {
+ data: MultiBarDataPoint[];
+ xAxisKey?: string;
+ yAxisKeys?: string[]; // Keys for multiple bars
+ barLabels?: string[]; // Labels for each bar series
+ /**
+ * Size of the bar graph.
+ * @default "m"
+ */
+ size?: "xs" | "s" | "m" | "l" | "xl";
+ blur?: boolean;
+ title?: string;
+ tooltipTitle?: string;
+ /**
+ * When true, hides labels on the X axis
+ * @default false
+ */
+ hideXAxisLabels?: boolean;
+ /**
+ * When true, hides labels on the Y axis
+ * @default false
+ */
+ hideYAxisLabels?: boolean;
+ /**
+ * When true, hides all axis labels
+ * @default false
+ */
+ hideLabels?: boolean;
+}
+
+const CustomTooltip = ({ active, payload, tooltipTitle, barLabels }: any) => {
+ if (active && payload && payload.length) {
+ const data = payload[0].payload;
+ return (
+
+
+
+ {data.startDate && data.endDate
+ ? `${data.startDate} - ${data.endDate}`
+ : data.name}
+
+
+
+ {payload.map((entry: any, index: number) => (
+
+ {`${barLabels?.[index] || entry.dataKey}: ${entry.value}`}
+
+ ))}
+
+
+ );
+ }
+ return null;
+};
+
+export const MultiBarGraph: React.FC = ({
+ data,
+ xAxisKey = "name",
+ yAxisKeys = ["value1", "value2", "value3"],
+ size = "m",
+ blur = false,
+ border,
+ title,
+ radius,
+ tooltipTitle,
+ barLabels,
+ background,
+ hideXAxisLabels = false,
+ hideYAxisLabels = false,
+ hideLabels = false,
+ ...flexProps
+}) => {
+ const height = {
+ xs: 100,
+ s: 150,
+ m: 250,
+ l: 275,
+ xl: 300,
+ }[size];
+
+ const barSize = {
+ xs: 32,
+ s: 32,
+ m: 32,
+ l: 32,
+ xl: 32,
+ }[size];
+
+ // Using the same colors from LineGraph
+ const barColors = ["var(--success-solid-strong)", "var(--danger-solid-strong)", "#6c5ce7"]; // green, red, purple
+
+ return (
+
+ {title && (
+
+ {title}
+
+ )}
+
+
+
+
+
+
+
+ }
+ cursor={{ fill: "rgba(255,255,255,0.05)" }}
+ wrapperClassName={styles.tooltipWrapper}
+ />
+
+ {/* Define gradients for each bar color */}
+
+ {barColors.map((color, index) => (
+
+
+
+
+
+
+
+ ))}
+
+
+ {/* Create a Bar component for each data key */}
+ {yAxisKeys.map((key, index) => (
+
+ ))}
+
+
+
+
+ );
+};
diff --git a/src/once-ui/components/index.ts b/src/once-ui/components/index.ts
index 66bdab42..3f71fa05 100644
--- a/src/once-ui/components/index.ts
+++ b/src/once-ui/components/index.ts
@@ -5,6 +5,7 @@ export * from "./Avatar";
export * from "./AvatarGroup";
export * from "./Badge";
export * from "./Background";
+export * from "./BarGraph"
export * from "./Button";
export * from "./Carousel";
export * from "./Card";
@@ -38,9 +39,12 @@ export * from "./Kbar";
export * from "./Kbd";
export * from "./LetterFx";
export * from "./Line";
+export * from "./LineBarGraph"
+export * from "./LineGraph"
export * from "./Logo";
export * from "./LogoCloud";
export * from "./MegaMenu";
+export * from "./MultiBarGraph"
export * from "./NavIcon";
export * from "./NumberInput";
export * from "./Option";
From 529ecef447c6e69b05051f0742db520cb8481338 Mon Sep 17 00:00:00 2001
From: Adhitya Nadooli <127269031+lightyfr@users.noreply.github.com>
Date: Fri, 28 Mar 2025 15:29:44 +0000
Subject: [PATCH 04/35] Data-viz sizing changes (fill)
---
src/once-ui/components/BarGraph.tsx | 65 +++++++++---------------
src/once-ui/components/LineBarGraph.tsx | 48 +++++++++--------
src/once-ui/components/LineGraph.tsx | 16 ++----
src/once-ui/components/MultiBarGraph.tsx | 49 ++++++++----------
4 files changed, 78 insertions(+), 100 deletions(-)
diff --git a/src/once-ui/components/BarGraph.tsx b/src/once-ui/components/BarGraph.tsx
index 64f8356c..b90313c0 100644
--- a/src/once-ui/components/BarGraph.tsx
+++ b/src/once-ui/components/BarGraph.tsx
@@ -9,16 +9,6 @@ import {
Tooltip,
} from "recharts";
-import {
- GridProps,
- SpacingProps,
- SizeProps,
- StyleProps,
- CommonProps,
- DisplayProps,
- ConditionalProps,
-} from "../interfaces";
-
import { SpacingToken, ColorScheme, ColorWeight } from "../types";
import styles from "./BarGraph.module.scss";
@@ -35,8 +25,6 @@ interface DataPoint {
type BarColor = "success" | "danger" | "purple";
-type BarRadius = "xs" | "s" | "m" | "l" | "xl";
-
interface BarGraphProps extends React.ComponentProps {
data: DataPoint[];
xAxisKey?: string; // Allows customization of the x-axis data key
@@ -46,7 +34,7 @@ interface BarGraphProps extends React.ComponentProps {
* Size of the bar graph.
* @default "m"
*/
- size?: "xs" | "s" | "m" | "l" | "xl";
+ barWidth?: SpacingToken | "fill";
blur?: boolean; // Controls backdrop blur effect
title?: string; // Title for the bar graph
tooltipTitle?: string; // Title for the tooltip
@@ -76,7 +64,7 @@ const CustomTooltip = ({ active, payload, tooltipTitle }: any) => {
= ({
xAxisKey = "name",
yAxisKey = "value",
barColor = "success",
- size = "m",
+ barWidth = "fill",
blur = false,
border,
title,
@@ -117,21 +105,7 @@ export const BarGraph: React.FC = ({
hideYAxisTitle = false,
hideAxisTitles = false,
}) => {
- const height = {
- xs: 100,
- s: 150,
- m: 200,
- l: 250,
- xl: 300,
- }[size];
- const barSize = {
- xs: 16,
- s: 24,
- m: 32,
- l: 40,
- xl: 48,
- }[size];
const barColorMap = {
success: "var(--success-solid-strong)",
@@ -143,7 +117,8 @@ export const BarGraph: React.FC = ({
return (
= ({
{title}
-
+
= ({
}
@@ -230,8 +201,22 @@ export const BarGraph: React.FC = ({
fill="url(#barGradient)"
stroke={barSolidColor}
strokeWidth={1}
- radius={[6, 6, 0, 0]} // Replace with appropriate numerical values
- barSize={barSize}
+ barSize={
+ barWidth === "fill"
+ ? "100%"
+ : barWidth === "xs"
+ ? 6
+ : barWidth === "s"
+ ? 12
+ : barWidth === "m"
+ ? 20
+ : barWidth === "l"
+ ? 40
+ : barWidth === "xl"
+ ? 50
+ : barWidth
+ }
+ radius={[6, 6, 0, 0]}
/>
diff --git a/src/once-ui/components/LineBarGraph.tsx b/src/once-ui/components/LineBarGraph.tsx
index 030e8c2d..d704927a 100644
--- a/src/once-ui/components/LineBarGraph.tsx
+++ b/src/once-ui/components/LineBarGraph.tsx
@@ -13,6 +13,8 @@ import {
} from "recharts";
import styles from "./LineBarGraph.module.scss";
import { Flex, Heading } from ".";
+import { SpacingToken, ColorScheme, ColorWeight } from "../types";
+
interface DataPoint {
name: string;
@@ -32,7 +34,7 @@ interface LineBarGraphProps extends React.ComponentProps {
* Size of the graph.
* @default "m"
*/
- size?: "xs" | "s" | "m" | "l" | "xl";
+ barWidth?: SpacingToken | "fill";
blur?: boolean;
title?: string;
lineColor?: string;
@@ -124,7 +126,7 @@ export const LineBarGraph: React.FC = ({
barDataKey = "barValue",
lineName = "Line",
barName = "Bar",
- size = "m",
+ barWidth = "fill",
blur = false,
border,
title,
@@ -144,21 +146,7 @@ export const LineBarGraph: React.FC = ({
showLegend = false,
...flexProps
}) => {
- const height = {
- xs: 100,
- s: 150,
- m: 200,
- l: 250,
- xl: 300,
- }[size];
-
- const barSize = {
- xs: 16,
- s: 24,
- m: 32,
- l: 40,
- xl: 48,
- }[size];
+
// Generate a unique ID for each gradient
const lineGradientId = `colorLine-${Math.random().toString(36).substring(2, 9)}`;
@@ -176,12 +164,12 @@ export const LineBarGraph: React.FC = ({
return (
= ({
)}
-
+
= ({
hide={false}
/>
= ({
stroke={barColor}
strokeWidth={1}
radius={[4, 4, 0, 0]}
- barSize={barSize}
+ barSize={
+ barWidth === "fill"
+ ? "100%"
+ : barWidth === "xs"
+ ? 6
+ : barWidth === "s"
+ ? 12
+ : barWidth === "m"
+ ? 20
+ : barWidth === "l"
+ ? 40
+ : barWidth === "xl"
+ ? 50
+ : barWidth
+ }
/>
{showArea ? (
diff --git a/src/once-ui/components/LineGraph.tsx b/src/once-ui/components/LineGraph.tsx
index 3bca76cf..2558000d 100644
--- a/src/once-ui/components/LineGraph.tsx
+++ b/src/once-ui/components/LineGraph.tsx
@@ -29,7 +29,6 @@ interface LineGraphProps extends React.ComponentProps {
* Size of the line graph.
* @default "m"
*/
- size?: "xs" | "s" | "m" | "l" | "xl";
blur?: boolean;
title?: string;
tooltipTitle?: string;
@@ -110,7 +109,6 @@ export const LineGraph: React.FC = ({
yAxisKey1 = "value1",
yAxisKey2 = "value2",
yAxisKey3 = "value3",
- size = "m",
blur = false,
border,
title,
@@ -125,20 +123,16 @@ export const LineGraph: React.FC = ({
hideLabels = false,
...flexProps
}) => {
- const height = {
- xs: 100,
- s: 150,
- m: 200,
- l: 250,
- xl: 300,
- }[size];
+
return (
= ({
>
{title}
-
-
+
+
{
* Size of the bar graph.
* @default "m"
*/
- size?: "xs" | "s" | "m" | "l" | "xl";
+ barWidth?: SpacingToken | "fill";
blur?: boolean;
title?: string;
tooltipTitle?: string;
@@ -106,7 +99,7 @@ export const MultiBarGraph: React.FC = ({
data,
xAxisKey = "name",
yAxisKeys = ["value1", "value2", "value3"],
- size = "m",
+ barWidth = "fill",
blur = false,
border,
title,
@@ -119,28 +112,14 @@ export const MultiBarGraph: React.FC = ({
hideLabels = false,
...flexProps
}) => {
- const height = {
- xs: 100,
- s: 150,
- m: 250,
- l: 275,
- xl: 300,
- }[size];
- const barSize = {
- xs: 32,
- s: 32,
- m: 32,
- l: 32,
- xl: 32,
- }[size];
// Using the same colors from LineGraph
const barColors = ["var(--success-solid-strong)", "var(--danger-solid-strong)", "#6c5ce7"]; // green, red, purple
return (
= ({
)}
-
+
= ({
stroke={barColors[index % barColors.length]}
strokeWidth={1}
radius={[6, 6, 0, 0]}
- barSize={barSize}
+ barSize={
+ barWidth === "fill"
+ ? "98%"
+ : barWidth === "xs"
+ ? 6
+ : barWidth === "s"
+ ? 12
+ : barWidth === "m"
+ ? 20
+ : barWidth === "l"
+ ? 40
+ : barWidth === "xl"
+ ? 50
+ : barWidth
+ }
isAnimationActive={false}
/>
))}
From 70323ff82e31732fa6b2f9e689db64df4b4a0281 Mon Sep 17 00:00:00 2001
From: Adhitya Nadooli <127269031+lightyfr@users.noreply.github.com>
Date: Fri, 28 Mar 2025 17:02:14 +0000
Subject: [PATCH 05/35] feat: add axis title props and adjust padding/margins
in graph components
---
src/once-ui/components/BarGraph.tsx | 22 +++++++---
src/once-ui/components/LineBarGraph.tsx | 15 +++++--
src/once-ui/components/LineGraph.tsx | 53 ++++++++++++++++++++----
src/once-ui/components/MultiBarGraph.tsx | 53 +++++++++++++++++++++++-
4 files changed, 125 insertions(+), 18 deletions(-)
diff --git a/src/once-ui/components/BarGraph.tsx b/src/once-ui/components/BarGraph.tsx
index b90313c0..d254c4f2 100644
--- a/src/once-ui/components/BarGraph.tsx
+++ b/src/once-ui/components/BarGraph.tsx
@@ -136,11 +136,11 @@ export const BarGraph: React.FC = ({
>
{title}
-
+
= ({
fill: "var(--neutral-on-background-medium)",
fontSize: 12,
}}
+
label={
xAxisTitle && !hideXAxisTitle && !hideAxisTitles
- ? { value: xAxisTitle, position: 'bottom', offset: -2, fill: "var(--neutral-on-background-medium)" }
+ ? { value: xAxisTitle, position: 'bottom', offset: 0, fill: "var(--neutral-on-background-medium)" }
: undefined
}
/>
@@ -170,8 +171,19 @@ export const BarGraph: React.FC = ({
fill: "var(--neutral-on-background-medium)",
fontSize: 12,
}}
- width={hideYAxisLabels || hideLabels ? 0 : 30}
-
+ width={yAxisTitle ? 40 : 0}
+ label={
+ yAxisTitle && !hideYAxisTitle && !hideAxisTitles
+ ? {
+ value: yAxisTitle,
+ angle: -90, // Rotate the label 90 degrees counter-clockwise
+ position: 'left',
+ dx: 5, // Move label to the left
+ dy: -20, // Adjust vertical position
+ fill: "var(--neutral-on-background-medium)"
+ }
+ : undefined
+ }
/>
}
diff --git a/src/once-ui/components/LineBarGraph.tsx b/src/once-ui/components/LineBarGraph.tsx
index d704927a..bbfb33fc 100644
--- a/src/once-ui/components/LineBarGraph.tsx
+++ b/src/once-ui/components/LineBarGraph.tsx
@@ -185,11 +185,11 @@ export const LineBarGraph: React.FC = ({
{title}
)}
-
+
{/* Bar gradient */}
@@ -246,10 +246,17 @@ export const LineBarGraph: React.FC = ({
}}
axisLine={false}
tickLine={false}
- width={hideYAxisLabels || hideLabels ? 0 : 30}
+ width={yAxisTitle ? 50 : 0}
label={
yAxisTitle && !hideYAxisTitle && !hideAxisTitles
- ? { value: yAxisTitle, angle: -90, position: 'left', offset: -5, fill: "var(--neutral-on-background-medium)" }
+ ? {
+ value: yAxisTitle,
+ angle: -90, // Rotate the label 90 degrees counter-clockwise
+ position: 'left',
+ dx: 0, // Move label to the left
+ dy: -20, // Adjust vertical position
+ fill: "var(--neutral-on-background-medium)"
+ }
: undefined
}
// Make sure to always show the grid even if labels are hidden
diff --git a/src/once-ui/components/LineGraph.tsx b/src/once-ui/components/LineGraph.tsx
index 2558000d..64a852bc 100644
--- a/src/once-ui/components/LineGraph.tsx
+++ b/src/once-ui/components/LineGraph.tsx
@@ -21,6 +21,8 @@ interface DataPoint {
interface LineGraphProps extends React.ComponentProps {
data: DataPoint[];
+ xAxisTitle?: string;
+ yAxisTitle?: string;
xAxisKey?: string;
yAxisKey1?: string;
yAxisKey2?: string;
@@ -50,6 +52,24 @@ interface LineGraphProps extends React.ComponentProps {
* @default false
*/
hideLabels?: boolean;
+
+ /**
+ * Hide Y-axis title when true
+ * @default false
+ */
+ hideYAxisTitle?: boolean;
+ /**
+ * Hide X-axis title when true
+ * @default false
+ */
+ hideXAxisTitle?: boolean;
+ /**
+ * Hide both X and Y axis titles when true
+ * @default false
+ */
+ hideAxisTitles?: boolean;
+
+
}
interface CustomTooltipProps extends TooltipProps {
@@ -109,6 +129,11 @@ export const LineGraph: React.FC = ({
yAxisKey1 = "value1",
yAxisKey2 = "value2",
yAxisKey3 = "value3",
+ hideYAxisTitle = false,
+ hideAxisTitles = false,
+ yAxisTitle,
+ xAxisTitle,
+ hideXAxisTitle = false,
blur = false,
border,
title,
@@ -148,16 +173,11 @@ export const LineGraph: React.FC = ({
>
{title}
-
+
@@ -190,6 +210,11 @@ export const LineGraph: React.FC = ({
fontSize: 11,
fontWeight: "bold",
}}
+ label={
+ xAxisTitle && !hideXAxisTitle && !hideAxisTitles
+ ? { value: xAxisTitle, position: 'bottom', offset: 0, fill: "var(--neutral-on-background-medium)" }
+ : undefined
+ }
axisLine={false}
tickLine={false}
hide={hideXAxisLabels || hideLabels}
@@ -200,6 +225,20 @@ export const LineGraph: React.FC = ({
fill: "var(--neutral-on-background-medium)",
fontSize: 11,
}}
+ width={yAxisTitle ? 40 : 0}
+ label={
+ yAxisTitle && !hideYAxisTitle && !hideAxisTitles
+ ? {
+ value: yAxisTitle,
+ angle: -90, // Rotate the label 90 degrees counter-clockwise
+ position: 'left',
+ dx: 5, // Move label to the left
+ dy: -20, // Adjust vertical position
+ fill: "var(--neutral-on-background-medium)"
+ }
+ : undefined
+ }
+
axisLine={false}
tickLine={false}
hide={hideYAxisLabels || hideLabels}
diff --git a/src/once-ui/components/MultiBarGraph.tsx b/src/once-ui/components/MultiBarGraph.tsx
index 4ab69c51..5b559f88 100644
--- a/src/once-ui/components/MultiBarGraph.tsx
+++ b/src/once-ui/components/MultiBarGraph.tsx
@@ -54,6 +54,33 @@ interface MultiBarGraphProps extends React.ComponentProps {
* @default false
*/
hideLabels?: boolean;
+ /**
+ * When true, hides the X axis title
+ * @default false
+ */
+ hideXAxisTitle?: boolean;
+ /**
+ * When true, hides the Y axis title
+ * @default false
+ */
+ hideYAxisTitle?: boolean;
+ /**
+ * When true, hides all axis titles
+ * @default false
+ */
+ hideAxisTitles?: boolean;
+ /**
+ * Title for X-axis
+ */
+ xAxisTitle?: string;
+ /**
+ * Title for Y-axis
+ */
+ yAxisTitle?: string;
+ /**
+ * When true, hides the Y axis title
+ * @default false
+ */
}
const CustomTooltip = ({ active, payload, tooltipTitle, barLabels }: any) => {
@@ -108,7 +135,12 @@ export const MultiBarGraph: React.FC = ({
barLabels,
background,
hideXAxisLabels = false,
+ xAxisTitle,
+ hideXAxisTitle = false,
hideYAxisLabels = false,
+ yAxisTitle,
+ hideYAxisTitle = false,
+ hideAxisTitles = false,
hideLabels = false,
...flexProps
}) => {
@@ -139,7 +171,7 @@ export const MultiBarGraph: React.FC = ({
{title}
)}
-
+
= ({
fontSize: 12,
}}
hide={hideLabels || hideXAxisLabels}
+ label={
+ xAxisTitle && !hideXAxisTitle && !hideAxisTitles
+ ? { value: xAxisTitle, position: 'bottom', offset: -2, fill: "var(--neutral-on-background-medium)" }
+ : undefined
+ }
/>
= ({
fill: "var(--neutral-on-background-medium)",
fontSize: 12,
}}
- width={30}
+ width={yAxisTitle ? 40 : 0} // Adjust width based on number of bars
+ label={
+ yAxisTitle && !hideYAxisTitle && !hideAxisTitles
+ ? {
+ value: yAxisTitle,
+ angle: -90, // Rotate the label 90 degrees counter-clockwise
+ position: 'left',
+ dx: 0, // Move label to the left
+ dy: -20, // Adjust vertical position
+ fill: "var(--neutral-on-background-medium)"
+ }
+ : undefined
+ }
domain={[0, "auto"]} // Start from 0, auto-scale the upper bound
allowDataOverflow={false} // Prevent data from exceeding the domain
hide={hideLabels || hideYAxisLabels}
From e2a3e9755b44ded8e51dfa16985261e87a5471e3 Mon Sep 17 00:00:00 2001
From: Adhitya Nadooli <127269031+lightyfr@users.noreply.github.com>
Date: Fri, 28 Mar 2025 17:19:14 +0000
Subject: [PATCH 06/35] feat: extend barWidth prop to accept number and string
types in graph components
---
src/once-ui/components/BarGraph.tsx | 2 +-
src/once-ui/components/LineBarGraph.tsx | 2 +-
src/once-ui/components/MultiBarGraph.tsx | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/once-ui/components/BarGraph.tsx b/src/once-ui/components/BarGraph.tsx
index d254c4f2..19306b0e 100644
--- a/src/once-ui/components/BarGraph.tsx
+++ b/src/once-ui/components/BarGraph.tsx
@@ -34,7 +34,7 @@ interface BarGraphProps extends React.ComponentProps {
* Size of the bar graph.
* @default "m"
*/
- barWidth?: SpacingToken | "fill";
+ barWidth?: SpacingToken | "fill" | number | string;
blur?: boolean; // Controls backdrop blur effect
title?: string; // Title for the bar graph
tooltipTitle?: string; // Title for the tooltip
diff --git a/src/once-ui/components/LineBarGraph.tsx b/src/once-ui/components/LineBarGraph.tsx
index bbfb33fc..8cbeabcb 100644
--- a/src/once-ui/components/LineBarGraph.tsx
+++ b/src/once-ui/components/LineBarGraph.tsx
@@ -34,7 +34,7 @@ interface LineBarGraphProps extends React.ComponentProps {
* Size of the graph.
* @default "m"
*/
- barWidth?: SpacingToken | "fill";
+ barWidth?: SpacingToken | "fill" | number | string;
blur?: boolean;
title?: string;
lineColor?: string;
diff --git a/src/once-ui/components/MultiBarGraph.tsx b/src/once-ui/components/MultiBarGraph.tsx
index 5b559f88..7f2f3372 100644
--- a/src/once-ui/components/MultiBarGraph.tsx
+++ b/src/once-ui/components/MultiBarGraph.tsx
@@ -35,7 +35,7 @@ interface MultiBarGraphProps extends React.ComponentProps {
* Size of the bar graph.
* @default "m"
*/
- barWidth?: SpacingToken | "fill";
+ barWidth?: SpacingToken | "fill" | number | string;
blur?: boolean;
title?: string;
tooltipTitle?: string;
From 646a9073b7a62a7104e42be4d8e99e9e4e44636f Mon Sep 17 00:00:00 2001
From: Adhitya Nadooli <127269031+lightyfr@users.noreply.github.com>
Date: Fri, 28 Mar 2025 19:00:29 +0000
Subject: [PATCH 07/35] feat: enhance tooltip styling and improve axis label
visibility in graph components
---
src/once-ui/components/BarGraph.module.scss | 97 ++++++++---------
src/once-ui/components/BarGraph.tsx | 15 +--
src/once-ui/components/LineBarGraph.tsx | 9 +-
src/once-ui/components/LineGraph.module.scss | 108 +++++++++----------
src/once-ui/components/LineGraph.tsx | 32 ++++--
src/once-ui/components/MultiBarGraph.tsx | 20 ++--
6 files changed, 143 insertions(+), 138 deletions(-)
diff --git a/src/once-ui/components/BarGraph.module.scss b/src/once-ui/components/BarGraph.module.scss
index ec2f0669..cdf7d288 100644
--- a/src/once-ui/components/BarGraph.module.scss
+++ b/src/once-ui/components/BarGraph.module.scss
@@ -1,56 +1,53 @@
.graphContainer {
- width: 100%;
- height: 200px;
- border-radius: 12px;
- padding: 24px;
-
- :global(.recharts-bar-rectangle) {
- filter: drop-shadow(0 0 8px rgba(4, 78, 120, 0.3));
- }
+ width: 100%;
+ height: 200px;
+ border-radius: 12px;
+ padding: 24px;
+
+ :global(.recharts-bar-rectangle) {
+ filter: drop-shadow(0 0 8px rgba(4, 78, 120, 0.3));
}
-
- .blur {
- backdrop-filter: blur(12px);
- -webkit-backdrop-filter: blur(12px);
- }
-
- .blur::backdrop {
- backdrop-filter: blur(12px);
- }
-
- .blur::before {
- backdrop-filter: blur(12px);
+}
+
+.blur {
+ backdrop-filter: blur(12px);
+ -webkit-backdrop-filter: blur(12px);
+}
+
+.blur::backdrop {
+ backdrop-filter: blur(12px);
+}
+
+.blur::before {
+ backdrop-filter: blur(12px);
+}
+
+.tooltip {
+ border-radius: var(--radius-m);
+ text-align: center;
+ justify-content: center;
+ align-items: center;
+
+ .label {
+ text-align: center;
+ margin: 0 0 10px;
+ font-size: 15px;
+ font-weight: 600;
+ color: var(--neutral-on-background-strong);
}
-
- .tooltip {
- backdrop-filter: blur(12px);
- border: 1px solid var(--neutral-alpha-medium);
- border-radius: var(--radius-m);
+
+ .value {
+ font-weight: 500;
text-align: center;
- justify-content: center;
+ margin: 4px 0;
+ display: flex;
align-items: center;
-
- .label {
- text-align: center;
- margin: 0 0 10px;
- font-size: 15px;
- font-weight: 600;
- color: var(--neutral-on-background-strong);
- }
-
- .value {
- font-weight: 500;
- text-align: center;
- margin: 4px 0;
- display: flex;
- align-items: center;
- }
- }
-
- .tooltipWrapper {
- background-color: var(--neutral-background-strong);
- border: 1px solid var(--neutral-border-medium);
- border-radius: var(--radius-s);
- color: var(--neutral-on-background-medium);
}
-
\ No newline at end of file
+}
+
+.tooltipWrapper {
+ background-color: var(--neutral-background-strong);
+ border: 1px solid var(--neutral-border-medium);
+ border-radius: var(--radius-s);
+ color: var(--neutral-on-background-medium);
+}
diff --git a/src/once-ui/components/BarGraph.tsx b/src/once-ui/components/BarGraph.tsx
index 19306b0e..db50d251 100644
--- a/src/once-ui/components/BarGraph.tsx
+++ b/src/once-ui/components/BarGraph.tsx
@@ -56,11 +56,11 @@ interface BarGraphProps extends React.ComponentProps {
hideAxisTitles?: boolean;
}
-const CustomTooltip = ({ active, payload, tooltipTitle }: any) => {
+const CustomTooltip = ({ active, payload, tooltipTitle, xAxisTitle }: any) => {
if (active && payload && payload.length) {
const data = payload[0].payload;
return (
-
+
{
variant="body-default-s"
style={{ fontWeight: "600" }}
onBackground="neutral-strong"
- >{`${data.startDate} - ${data.endDate}`}
+ >{`${xAxisTitle}: ${data.endDate}`}
@@ -154,13 +154,13 @@ export const BarGraph: React.FC = ({
axisLine={false}
tickLine={false}
tick={hideXAxisLabels || hideLabels ? false : {
- fill: "var(--neutral-on-background-medium)",
+ fill: "var(--neutral-on-background-weak)",
fontSize: 12,
}}
label={
xAxisTitle && !hideXAxisTitle && !hideAxisTitles
- ? { value: xAxisTitle, position: 'bottom', offset: 0, fill: "var(--neutral-on-background-medium)" }
+ ? { value: xAxisTitle, fontWeight: "500", position: 'bottom', offset: 0, fill: "var(--neutral-on-background-medium)" }
: undefined
}
/>
@@ -168,7 +168,7 @@ export const BarGraph: React.FC = ({
axisLine={false}
tickLine={false}
tick={{
- fill: "var(--neutral-on-background-medium)",
+ fill: "var(--neutral-on-background-weak)",
fontSize: 12,
}}
width={yAxisTitle ? 40 : 0}
@@ -178,6 +178,7 @@ export const BarGraph: React.FC = ({
value: yAxisTitle,
angle: -90, // Rotate the label 90 degrees counter-clockwise
position: 'left',
+ fontWeight: "500",
dx: 5, // Move label to the left
dy: -20, // Adjust vertical position
fill: "var(--neutral-on-background-medium)"
@@ -186,7 +187,7 @@ export const BarGraph: React.FC = ({
}
/>
}
+ content={}
cursor={{ fill: "rgba(255,255,255,0.05)" }}
wrapperClassName={styles.tooltipWrapper} // Apply styles to the tooltip wrapper
/>
diff --git a/src/once-ui/components/LineBarGraph.tsx b/src/once-ui/components/LineBarGraph.tsx
index 8cbeabcb..a6280d27 100644
--- a/src/once-ui/components/LineBarGraph.tsx
+++ b/src/once-ui/components/LineBarGraph.tsx
@@ -93,7 +93,7 @@ interface LineBarGraphProps extends React.ComponentProps {
const CustomTooltip = ({ active, payload, label }: any) => {
if (active && payload && payload.length) {
return (
-
+
= ({
axisLine={false}
tickLine={false}
tick={hideXAxisLabels || hideLabels ? false : {
- fill: "var(--neutral-on-background-medium)",
+ fill: "var(--neutral-on-background-weak)",
fontSize: 12,
}}
label={
xAxisTitle && !hideXAxisTitle && !hideAxisTitles
- ? { value: xAxisTitle, position: 'bottom', offset: 0, fill: "var(--neutral-on-background-medium)" }
+ ? { value: xAxisTitle, fontWeight: "500", position: 'bottom', offset: 0, fill: "var(--neutral-on-background-medium)" }
: undefined
}
// Make sure to always show the grid even if labels are hidden
@@ -241,8 +241,8 @@ export const LineBarGraph: React.FC = ({
/>
= ({
value: yAxisTitle,
angle: -90, // Rotate the label 90 degrees counter-clockwise
position: 'left',
+ fontWeight: "500",
dx: 0, // Move label to the left
dy: -20, // Adjust vertical position
fill: "var(--neutral-on-background-medium)"
diff --git a/src/once-ui/components/LineGraph.module.scss b/src/once-ui/components/LineGraph.module.scss
index 9ba50274..3ba34fe5 100644
--- a/src/once-ui/components/LineGraph.module.scss
+++ b/src/once-ui/components/LineGraph.module.scss
@@ -1,62 +1,56 @@
.graphContainer {
- border-radius: 12px;
- padding: 24px;
- width: 100%;
- height: 100%;
- min-height: 300px;
- border: 1px solid rgba(255, 255, 255, 0.05);
-
- :global(.recharts-cartesian-grid-horizontal line),
- :global(.recharts-cartesian-grid-vertical line) {
- stroke: var(--neutral-background-strong);
- }
-
- :global(.recharts-tooltip-cursor) {
- fill: rgba(255, 255, 255, 0.02);
- }
-
- :global(.recharts-default-tooltip) {
- background-color: #0f0f13 !important;
- border: 1px solid rgba(255, 255, 255, 0.05) !important;
- border-radius: 4px;
- padding: 8px !important;
- box-shadow:
- 0 4px 6px -1px rgba(0, 0, 0, 0.2),
- 0 2px 4px -1px rgba(0, 0, 0, 0.1);
- }
-
- :global(.recharts-surface) {
- overflow: visible;
- }
-
- :global(.recharts-bar-rectangle) {
- filter: drop-shadow(0 0 8px rgba(4, 78, 120, 0.3));
- }
+ border-radius: 12px;
+ padding: 24px;
+ width: 100%;
+ height: 100%;
+ min-height: 300px;
+ border: 1px solid rgba(255, 255, 255, 0.05);
+
+ :global(.recharts-cartesian-grid-horizontal line),
+ :global(.recharts-cartesian-grid-vertical line) {
+ stroke: var(--neutral-background-strong);
}
-
- .tooltip {
- backdrop-filter: blur(12px);
- border: 1px solid var(--neutral-alpha-medium);
- border-radius: var(--radius-m);
+
+ :global(.recharts-tooltip-cursor) {
+ fill: rgba(255, 255, 255, 0.02);
+ }
+
+ :global(.recharts-default-tooltip) {
+ background-color: #0f0f13 !important;
+ border: 1px solid rgba(255, 255, 255, 0.05) !important;
+ border-radius: 4px;
+ padding: 8px !important;
+ box-shadow:
+ 0 4px 6px -1px rgba(0, 0, 0, 0.2),
+ 0 2px 4px -1px rgba(0, 0, 0, 0.1);
+ }
+
+ :global(.recharts-surface) {
+ overflow: visible;
+ }
+
+ :global(.recharts-bar-rectangle) {
+ filter: drop-shadow(0 0 8px rgba(4, 78, 120, 0.3));
+ }
+}
+
+.tooltip {
+ border-radius: var(--radius-m);
+ text-align: center;
+ justify-content: center;
+
+ .label {
+ text-align: center;
+ padding: 5px;
+ font-size: 15px;
+ font-weight: 600;
+ color: var(--neutral-on-background-strong);
+ }
+
+ .value {
+ font-weight: 500;
text-align: center;
- justify-content: center;
- background-color: none;
- background: none;
+ display: flex;
align-items: center;
-
- .label {
- text-align: center;
- padding: 5px;
- font-size: 15px;
- font-weight: 600;
- color: var(--neutral-on-background-strong);
- }
-
- .value {
- font-weight: 500;
- text-align: center;
- display: flex;
- align-items: center;
- }
}
-
\ No newline at end of file
+}
diff --git a/src/once-ui/components/LineGraph.tsx b/src/once-ui/components/LineGraph.tsx
index 64a852bc..83dcf9c5 100644
--- a/src/once-ui/components/LineGraph.tsx
+++ b/src/once-ui/components/LineGraph.tsx
@@ -68,8 +68,11 @@ interface LineGraphProps extends React.ComponentProps {
* @default false
*/
hideAxisTitles?: boolean;
-
-
+ fixedYRange?: [number, number]; // [min, max] for y-axis
+ /**
+ * Show tick lines on the X-axis when true
+ * @default false
+ */
}
interface CustomTooltipProps extends TooltipProps {
@@ -80,6 +83,7 @@ interface CustomTooltipProps extends TooltipProps {
yAxisKey1?: string;
yAxisKey2?: string;
yAxisKey3?: string;
+ xAxisTitle?: string; // Add this property
}
const CustomTooltip = ({
@@ -93,10 +97,11 @@ const CustomTooltip = ({
yAxisKey1 = "value1",
yAxisKey2 = "value2",
yAxisKey3 = "value3",
+ xAxisTitle = "", // Add default value
}: CustomTooltipProps) => {
if (active && payload && payload.length) {
return (
-
+
- {`${tooltipTitle}`}
+
+ {tooltipTitle ? tooltipTitle : `${xAxisTitle}: ${label}`}
+
-
+
{`${key1}: ${payload[0].value}`}
-
+
{`${key2}: ${payload[1].value}`}
@@ -146,6 +153,7 @@ export const LineGraph: React.FC = ({
hideXAxisLabels = false,
hideYAxisLabels = false,
hideLabels = false,
+ fixedYRange,
...flexProps
}) => {
@@ -206,13 +214,12 @@ export const LineGraph: React.FC = ({
dataKey={xAxisKey}
stroke="var(--neutral-background-medium)"
tick={{
- fill: "var(--neutral-on-background-medium)",
+ fill: "var(--neutral-on-background-weak)",
fontSize: 11,
- fontWeight: "bold",
}}
label={
xAxisTitle && !hideXAxisTitle && !hideAxisTitles
- ? { value: xAxisTitle, position: 'bottom', offset: 0, fill: "var(--neutral-on-background-medium)" }
+ ? { value: xAxisTitle, fontWeight: "500", position: 'bottom', offset: 0, fill: "var(--neutral-on-background-medium)" }
: undefined
}
axisLine={false}
@@ -222,14 +229,16 @@ export const LineGraph: React.FC = ({
= ({
}
axisLine={false}
- tickLine={false}
hide={hideYAxisLabels || hideLabels}
+ domain={fixedYRange ? fixedYRange : undefined}
/>
= ({
yAxisKey1={yAxisKey1}
yAxisKey2={yAxisKey2}
yAxisKey3={yAxisKey3}
+ xAxisTitle={xAxisTitle} // Add this prop
/>
}
contentStyle={{
diff --git a/src/once-ui/components/MultiBarGraph.tsx b/src/once-ui/components/MultiBarGraph.tsx
index 7f2f3372..3f011621 100644
--- a/src/once-ui/components/MultiBarGraph.tsx
+++ b/src/once-ui/components/MultiBarGraph.tsx
@@ -87,7 +87,7 @@ const CustomTooltip = ({ active, payload, tooltipTitle, barLabels }: any) => {
if (active && payload && payload.length) {
const data = payload[0].payload;
return (
-
+
= ({
margin={{ top: 10, right: 10, left: 10, bottom: 10 }}
barGap={4} // Small gap between bars in the same group
barCategoryGap={1} // Control spacing between different groups (x-axis categories)
- >
+ >
= ({
axisLine={false}
tickLine={false}
tick={{
- fill: "var(--neutral-on-background-medium)",
- fontSize: 12,
+ fill: "var(--neutral-on-background-weak)",
+ fontSize: 12,
}}
hide={hideLabels || hideXAxisLabels}
label={
- xAxisTitle && !hideXAxisTitle && !hideAxisTitles
- ? { value: xAxisTitle, position: 'bottom', offset: -2, fill: "var(--neutral-on-background-medium)" }
- : undefined
+ xAxisTitle && !hideXAxisTitle && !hideAxisTitles
+ ? { value: xAxisTitle, fontWeight: "500",
+ position: 'bottom', offset: -2, fill: "var(--neutral-on-background-medium)" }
+ : undefined
}
/>
= ({
value: yAxisTitle,
angle: -90, // Rotate the label 90 degrees counter-clockwise
position: 'left',
+ fontWeight: "500",
dx: 0, // Move label to the left
dy: -20, // Adjust vertical position
fill: "var(--neutral-on-background-medium)"
From 4af50f98e41d012ed4866b36fe000fadde5d931a Mon Sep 17 00:00:00 2001
From: Adhitya Nadooli <127269031+lightyfr@users.noreply.github.com>
Date: Fri, 28 Mar 2025 19:12:15 +0000
Subject: [PATCH 08/35] fix: update tooltip text styling in MultiBarGraph
component
---
src/once-ui/components/MultiBarGraph.tsx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/once-ui/components/MultiBarGraph.tsx b/src/once-ui/components/MultiBarGraph.tsx
index 3f011621..733d89b4 100644
--- a/src/once-ui/components/MultiBarGraph.tsx
+++ b/src/once-ui/components/MultiBarGraph.tsx
@@ -108,7 +108,7 @@ const CustomTooltip = ({ active, payload, tooltipTitle, barLabels }: any) => {
{payload.map((entry: any, index: number) => (
From c06cce148faf7c97816bc4892c24a73d2df2fd1d Mon Sep 17 00:00:00 2001
From: Adhitya Nadooli <127269031+lightyfr@users.noreply.github.com>
Date: Fri, 28 Mar 2025 19:26:57 +0000
Subject: [PATCH 09/35] feat: enhance tooltip styling and add MultiBarGraph
component styles
---
src/once-ui/components/BarGraph.tsx | 7 +-
.../components/LineBarGraph.module.scss | 92 +++++++++----------
src/once-ui/components/LineBarGraph.tsx | 2 +-
src/once-ui/components/LineGraph.module.scss | 1 +
src/once-ui/components/LineGraph.tsx | 3 +-
.../components/MultiBarGraph.module.scss | 56 +++++++++++
src/once-ui/components/MultiBarGraph.tsx | 5 +-
7 files changed, 111 insertions(+), 55 deletions(-)
create mode 100644 src/once-ui/components/MultiBarGraph.module.scss
diff --git a/src/once-ui/components/BarGraph.tsx b/src/once-ui/components/BarGraph.tsx
index db50d251..09d9ab23 100644
--- a/src/once-ui/components/BarGraph.tsx
+++ b/src/once-ui/components/BarGraph.tsx
@@ -60,7 +60,7 @@ const CustomTooltip = ({ active, payload, tooltipTitle, xAxisTitle }: any) => {
if (active && payload && payload.length) {
const data = payload[0].payload;
return (
-
+
{
padding="8"
>
{`${xAxisTitle}: ${data.endDate}`}
-
+
{`${tooltipTitle}: ${data.value}`}
diff --git a/src/once-ui/components/LineBarGraph.module.scss b/src/once-ui/components/LineBarGraph.module.scss
index d8dcd119..29ff0a3e 100644
--- a/src/once-ui/components/LineBarGraph.module.scss
+++ b/src/once-ui/components/LineBarGraph.module.scss
@@ -1,53 +1,53 @@
.graphContainer {
- width: 100%;
- height: 100%;
- min-height: 200px;
- border-radius: 12px;
- padding: 24px;
-
- :global(.recharts-bar-rectangle) {
- filter: drop-shadow(0 0 8px rgba(4, 78, 120, 0.3));
- }
-
- :global(.recharts-dot) {
- filter: drop-shadow(0 0 4px rgba(78, 114, 238, 0.6));
- }
+ width: 100%;
+ height: 100%;
+ min-height: 200px;
+ border-radius: 12px;
+ padding: 24px;
+
+ :global(.recharts-bar-rectangle) {
+ filter: drop-shadow(0 0 8px rgba(4, 78, 120, 0.3));
}
- .blur {
- backdrop-filter: blur(12px);
- -webkit-backdrop-filter: blur(12px);
+ :global(.recharts-dot) {
+ filter: drop-shadow(0 0 4px rgba(78, 114, 238, 0.6));
}
-
- .tooltip {
- backdrop-filter: blur(12px);
- border: 1px solid var(--neutral-alpha-medium);
- border-radius: var(--radius-m);
+}
+
+.blur {
+ backdrop-filter: blur(12px);
+ -webkit-backdrop-filter: blur(12px);
+}
+
+.tooltip {
+ backdrop-filter: blur(12px);
+ border: 1px solid var(--neutral-alpha-medium);
+ border-radius: var(--radius-m);
+ text-align: center;
+ justify-content: center;
+ align-items: center;
+ backdrop-filter: blur(12px);
+
+ .label {
+ text-align: center;
+ font-size: 15px;
+ font-weight: 600;
+ color: var(--neutral-on-background-strong);
+ }
+
+ .value {
+ font-weight: 500;
text-align: center;
- justify-content: center;
+ margin: 4px 0;
+ display: flex;
align-items: center;
- backdrop-filter: blur(12px);
-
- .label {
- text-align: center;
- font-size: 15px;
- font-weight: 600;
- color: var(--neutral-on-background-strong);
- }
-
- .value {
- font-weight: 500;
- text-align: center;
- margin: 4px 0;
- display: flex;
- align-items: center;
- }
}
-
- .tooltipWrapper {
- background-color: var(--neutral-background-strong);
- border: 1px solid var(--neutral-border-medium);
- border-radius: var(--radius-s);
- color: var(--neutral-on-background-medium);
- padding: 8px;
- }
\ No newline at end of file
+}
+
+.tooltipWrapper {
+ background-color: var(--neutral-background-strong);
+ border: 1px solid var(--neutral-border-medium);
+ border-radius: var(--radius-s);
+ color: var(--neutral-on-background-medium);
+ padding: 8px;
+}
\ No newline at end of file
diff --git a/src/once-ui/components/LineBarGraph.tsx b/src/once-ui/components/LineBarGraph.tsx
index a6280d27..0c839f97 100644
--- a/src/once-ui/components/LineBarGraph.tsx
+++ b/src/once-ui/components/LineBarGraph.tsx
@@ -93,7 +93,7 @@ interface LineBarGraphProps extends React.ComponentProps {
const CustomTooltip = ({ active, payload, label }: any) => {
if (active && payload && payload.length) {
return (
-
+
-
+
{`${key1}: ${payload[0].value}`}
diff --git a/src/once-ui/components/MultiBarGraph.module.scss b/src/once-ui/components/MultiBarGraph.module.scss
new file mode 100644
index 00000000..b4e1f529
--- /dev/null
+++ b/src/once-ui/components/MultiBarGraph.module.scss
@@ -0,0 +1,56 @@
+.graphContainer {
+ border-radius: 12px;
+ padding: 24px;
+ width: 100%;
+ height: 100%;
+ min-height: 300px;
+ border: 1px solid rgba(255, 255, 255, 0.05);
+
+ :global(.recharts-cartesian-grid-horizontal line),
+ :global(.recharts-cartesian-grid-vertical line) {
+ stroke: var(--neutral-background-strong);
+ }
+
+ :global(.recharts-tooltip-cursor) {
+ fill: rgba(255, 255, 255, 0.02);
+ }
+
+ :global(.recharts-default-tooltip) {
+ background-color: #0f0f13 !important;
+ border: 1px solid rgba(255, 255, 255, 0.05) !important;
+ border-radius: 4px;
+ padding: 8px !important;
+ box-shadow:
+ 0 4px 6px -1px rgba(0, 0, 0, 0.2),
+ 0 2px 4px -1px rgba(0, 0, 0, 0.1);
+ }
+
+ :global(.recharts-surface) {
+ overflow: visible;
+ }
+
+ :global(.recharts-bar-rectangle) {
+ filter: drop-shadow(0 0 8px rgba(4, 78, 120, 0.3));
+ }
+ }
+
+ .tooltip {
+ border-radius: var(--radius-m);
+ text-align: center;
+ justify-content: center;
+
+ .label {
+ text-align: center;
+ padding: 5px;
+ font-size: 15px;
+ color: var(--neutral-on-background-strong);
+ }
+
+ .value {
+ text-align: center;
+ margin: 4px 0;
+ display: flex;
+ align-items: center;
+ }
+ }
+
\ No newline at end of file
diff --git a/src/once-ui/components/MultiBarGraph.tsx b/src/once-ui/components/MultiBarGraph.tsx
index 733d89b4..bb2ac989 100644
--- a/src/once-ui/components/MultiBarGraph.tsx
+++ b/src/once-ui/components/MultiBarGraph.tsx
@@ -13,7 +13,7 @@ import {
import { SpacingToken, ColorScheme, ColorWeight } from "../types";
-import styles from "./BarGraph.module.scss";
+import styles from "./MultiBarGraph.module.scss";
import { Text, Flex, Heading } from ".";
// Data structure supporting multiple values
@@ -87,7 +87,7 @@ const CustomTooltip = ({ active, payload, tooltipTitle, barLabels }: any) => {
if (active && payload && payload.length) {
const data = payload[0].payload;
return (
-
+
{
padding="8"
>
From e6d0af14517823e276f6519f8eec8eef5841135f Mon Sep 17 00:00:00 2001
From: Adhitya Nadooli <127269031+lightyfr@users.noreply.github.com>
Date: Fri, 28 Mar 2025 20:15:01 +0000
Subject: [PATCH 10/35] feat: add dashed line support to LineBarGraph and
LineGraph components
---
src/once-ui/components/LineBarGraph.tsx | 4 ++++
src/once-ui/components/LineGraph.tsx | 15 +++++++++++++++
2 files changed, 19 insertions(+)
diff --git a/src/once-ui/components/LineBarGraph.tsx b/src/once-ui/components/LineBarGraph.tsx
index 0c839f97..997e33a7 100644
--- a/src/once-ui/components/LineBarGraph.tsx
+++ b/src/once-ui/components/LineBarGraph.tsx
@@ -50,6 +50,8 @@ interface LineBarGraphProps extends React.ComponentProps {
* @default false
*/
hideXAxisLabels?: boolean;
+
+ dashedLine?: boolean;
/**
* Hide Y-axis labels when true
* @default false
@@ -128,6 +130,7 @@ export const LineBarGraph: React.FC = ({
barName = "Bar",
barWidth = "fill",
blur = false,
+ dashedLine = false,
border,
title,
lineColorVariant = "info", // Options: "info", "success", "danger", "purple"
@@ -304,6 +307,7 @@ export const LineBarGraph: React.FC = ({
dataKey={lineDataKey}
name={lineName}
stroke={finalLineColor}
+ strokeDasharray={dashedLine ? "5 5" : "0"}
strokeWidth={2}
fillOpacity={1}
fill={`url(#${lineGradientId})`}
diff --git a/src/once-ui/components/LineGraph.tsx b/src/once-ui/components/LineGraph.tsx
index 2c9741ed..54ad2baf 100644
--- a/src/once-ui/components/LineGraph.tsx
+++ b/src/once-ui/components/LineGraph.tsx
@@ -68,6 +68,14 @@ interface LineGraphProps extends React.ComponentProps {
* @default false
*/
hideAxisTitles?: boolean;
+ firstDashed?: boolean,
+
+ secondDashed?: boolean,
+
+ thirdDashed?: boolean,
+
+ allDashed?: boolean,
+
fixedYRange?: [number, number]; // [min, max] for y-axis
/**
* Show tick lines on the X-axis when true
@@ -151,6 +159,10 @@ export const LineGraph: React.FC = ({
tooltipTitle,
radius,
background,
+ firstDashed = false,
+ secondDashed = false,
+ thirdDashed = false,
+ allDashed = false,
hideXAxisLabels = false,
hideYAxisLabels = false,
hideLabels = false,
@@ -278,12 +290,14 @@ export const LineGraph: React.FC = ({
dataKey={yAxisKey1}
stroke="#047857"
strokeWidth={1.5}
+ strokeDasharray={allDashed || firstDashed ? "5 5" : "0"}
fillOpacity={1}
fill="url(#colorValue1)"
/>
= ({
Date: Sat, 29 Mar 2025 15:11:25 +0000
Subject: [PATCH 11/35] feat: update tooltip formatting to use locale string
representation in graph components
---
src/app/page.tsx | 161 ++++++++++++++++++++++-
src/once-ui/components/BarGraph.tsx | 13 +-
src/once-ui/components/LineBarGraph.tsx | 11 +-
src/once-ui/components/LineGraph.tsx | 23 ++--
src/once-ui/components/MultiBarGraph.tsx | 9 +-
src/once-ui/components/index.ts | 4 +-
6 files changed, 200 insertions(+), 21 deletions(-)
diff --git a/src/app/page.tsx b/src/app/page.tsx
index a113b652..9bfbb5b8 100644
--- a/src/app/page.tsx
+++ b/src/app/page.tsx
@@ -38,10 +38,15 @@ import {
Row,
StyleOverlay,
CompareImage,
+ ScrollToTop,
ThemeSwitcher,
} from "@/once-ui/components";
import { CodeBlock, MediaUpload } from "@/once-ui/modules";
-import { ScrollToTop } from "@/once-ui/components/ScrollToTop";
+
+import { BarGraph } from "@/once-ui/components/BarGraph";
+import { LineGraph } from "@/once-ui/components/LineGraph";
+import { MultiBarGraph } from "@/once-ui/components/MultiBarGraph";
+import { LineBarGraph } from "@/once-ui/components/LineBarGraph";
export default function Home() {
const [selectedValue, setSelectedValue] = useState("");
@@ -915,6 +920,160 @@ export default function Home() {
+ {/* DATA VISUALIZATION */}
+
+
+
+
+
+ Data Visualization
+
+
+ Powerful, responsive charts with automatic theming support
+
+
+
+
+ {/* Bar Graph */}
+
+
+
+ Revenue
+
+
+
+
+
+ {/* Line Graph */}
+
+
+
+ User Activity
+
+
+
+
+
+
+
+ {/* Multi Bar Graph */}
+
+
+
+ Quarterly Comparison
+
+
+
+
+
+ {/* Line Bar Graph */}
+
+
+
+ Conversions vs Traffic
+
+
+
+
+
+
+
+
+
+
+
+
{
- {`${tooltipTitle}: ${data.value}`}
+ {`${tooltipTitle}: ${data.value.toLocaleString()}`}
@@ -83,7 +83,7 @@ const CustomTooltip = ({ active, payload, tooltipTitle, xAxisTitle }: any) => {
return null;
};
-export const BarGraph: React.FC = ({
+const BarGraph: React.FC = ({
data,
xAxisKey = "name",
yAxisKey = "value",
@@ -103,6 +103,7 @@ export const BarGraph: React.FC = ({
hideXAxisTitle = false,
hideYAxisTitle = false,
hideAxisTitles = false,
+ ...flexProps
}) => {
@@ -117,7 +118,7 @@ export const BarGraph: React.FC = ({
return (
= ({
vertical="center"
background={background}
className={blur ? styles.blur : undefined}
+ {...flexProps}
>
= ({
);
};
+
+BarGraph.displayName = "BarGraph";
+
+export { BarGraph };
+export type { BarGraphProps };
diff --git a/src/once-ui/components/LineBarGraph.tsx b/src/once-ui/components/LineBarGraph.tsx
index 997e33a7..1d624661 100644
--- a/src/once-ui/components/LineBarGraph.tsx
+++ b/src/once-ui/components/LineBarGraph.tsx
@@ -111,7 +111,7 @@ const CustomTooltip = ({ active, payload, label }: any) => {
className={styles.value}
style={{ color: entry.color }}
>
- {`${entry.name}: ${entry.value}`}
+ {`${entry.name.toLocaleString()}: ${entry.value.toLocaleString()}`}
))}
@@ -121,7 +121,7 @@ const CustomTooltip = ({ active, payload, label }: any) => {
return null;
};
-export const LineBarGraph: React.FC = ({
+const LineBarGraph: React.FC = ({
data,
xAxisKey = "name",
lineDataKey = "lineValue",
@@ -330,4 +330,9 @@ export const LineBarGraph: React.FC = ({
);
-};
\ No newline at end of file
+};
+
+LineBarGraph.displayName = "LineBarGraph";
+
+export { LineBarGraph };
+export type { LineBarGraphProps };
\ No newline at end of file
diff --git a/src/once-ui/components/LineGraph.tsx b/src/once-ui/components/LineGraph.tsx
index 54ad2baf..cb258d52 100644
--- a/src/once-ui/components/LineGraph.tsx
+++ b/src/once-ui/components/LineGraph.tsx
@@ -123,14 +123,14 @@ const CustomTooltip = ({
-
- {`${key1}: ${payload[0].value}`}
-
-
- {`${key2}: ${payload[1].value}`}
-
-
- {`${key3}: ${payload[2].value}`}
+
+ {`${key1}: ${Number(payload[0].value).toLocaleString()}`}
+
+
+ {`${key2}: ${Number(payload[1].value).toLocaleString()}`}
+
+
+ {`${key3}: ${Number(payload[2].value).toLocaleString()}`}
@@ -139,7 +139,7 @@ const CustomTooltip = ({
return null;
};
-export const LineGraph: React.FC = ({
+const LineGraph: React.FC = ({
data,
xAxisKey = "name",
yAxisKey1 = "value1",
@@ -318,3 +318,8 @@ export const LineGraph: React.FC = ({
);
};
+
+LineGraph.displayName = "LineGraph";
+
+export { LineGraph };
+export type { LineGraphProps };
diff --git a/src/once-ui/components/MultiBarGraph.tsx b/src/once-ui/components/MultiBarGraph.tsx
index bb2ac989..ba37893e 100644
--- a/src/once-ui/components/MultiBarGraph.tsx
+++ b/src/once-ui/components/MultiBarGraph.tsx
@@ -111,7 +111,7 @@ const CustomTooltip = ({ active, payload, tooltipTitle, barLabels }: any) => {
onBackground="neutral-strong"
style={{ color: entry.color }}
>
- {`${barLabels?.[index] || entry.dataKey}: ${entry.value}`}
+ {`${barLabels?.[index] || entry.dataKey}: ${entry.value.toLocaleString()}`}
))}
@@ -121,7 +121,7 @@ const CustomTooltip = ({ active, payload, tooltipTitle, barLabels }: any) => {
return null;
};
-export const MultiBarGraph: React.FC = ({
+const MultiBarGraph: React.FC = ({
data,
xAxisKey = "name",
yAxisKeys = ["value1", "value2", "value3"],
@@ -290,3 +290,8 @@ export const MultiBarGraph: React.FC = ({
);
};
+
+MultiBarGraph.displayName = "MultiBarGraph";
+
+export { MultiBarGraph };
+export type { MultiBarGraphProps };
\ No newline at end of file
diff --git a/src/once-ui/components/index.ts b/src/once-ui/components/index.ts
index 3f71fa05..7eccdb1c 100644
--- a/src/once-ui/components/index.ts
+++ b/src/once-ui/components/index.ts
@@ -5,7 +5,6 @@ export * from "./Avatar";
export * from "./AvatarGroup";
export * from "./Badge";
export * from "./Background";
-export * from "./BarGraph"
export * from "./Button";
export * from "./Carousel";
export * from "./Card";
@@ -39,8 +38,6 @@ export * from "./Kbar";
export * from "./Kbd";
export * from "./LetterFx";
export * from "./Line";
-export * from "./LineBarGraph"
-export * from "./LineGraph"
export * from "./Logo";
export * from "./LogoCloud";
export * from "./MegaMenu";
@@ -54,6 +51,7 @@ export * from "./RadioButton";
export * from "./RevealFx";
export * from "./Row";
export * from "./Scroller";
+export * from "./ScrollToTop";
export * from "./SegmentedControl";
export * from "./Select";
export * from "./Skeleton";
From ddd165a1eb7fe4e0b0fbc2f4a102e79c6d07d5a0 Mon Sep 17 00:00:00 2001
From: Adhitya Nadooli <127269031+lightyfr@users.noreply.github.com>
Date: Sat, 29 Mar 2025 20:21:28 +0000
Subject: [PATCH 12/35] feat: add PieChart component with customizable options
and tooltip
---
src/app/page.tsx | 44 ++++
src/once-ui/components/PieChart.module.scss | 32 +++
src/once-ui/components/PieChart.tsx | 214 ++++++++++++++++++++
src/once-ui/components/ScrollToTop.tsx | 2 +
4 files changed, 292 insertions(+)
create mode 100644 src/once-ui/components/PieChart.module.scss
create mode 100644 src/once-ui/components/PieChart.tsx
diff --git a/src/app/page.tsx b/src/app/page.tsx
index 9bfbb5b8..c666d152 100644
--- a/src/app/page.tsx
+++ b/src/app/page.tsx
@@ -47,6 +47,7 @@ import { BarGraph } from "@/once-ui/components/BarGraph";
import { LineGraph } from "@/once-ui/components/LineGraph";
import { MultiBarGraph } from "@/once-ui/components/MultiBarGraph";
import { LineBarGraph } from "@/once-ui/components/LineBarGraph";
+import { PieChart } from "@/once-ui/components/PieChart";
export default function Home() {
const [selectedValue, setSelectedValue] = useState("");
@@ -1060,6 +1061,49 @@ export default function Home() {
+
+
+ {/* Bar Graph */}
+
+
+
+ Revenue
+
+
+
+
+
+ {/* Line Graph */}
+
+
+
+ User Activity
+
+
+
+
+