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 */} + + + + + + + + + + + + ); +}; \ 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 + + + + + + + +