Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
8114ed0
Feature Request:
JExcellence Apr 7, 2025
3bc3a70
feat(components): add customizable ProgressRing component
JExcellence May 15, 2025
6c84e14
Add data-viz modules, add components to index, add recharts to packag…
lightyfr Mar 27, 2025
529ecef
Data-viz sizing changes (fill)
lightyfr Mar 28, 2025
70323ff
feat: add axis title props and adjust padding/margins in graph compon…
lightyfr Mar 28, 2025
e2a3e97
feat: extend barWidth prop to accept number and string types in graph…
lightyfr Mar 28, 2025
646a907
feat: enhance tooltip styling and improve axis label visibility in gr…
lightyfr Mar 28, 2025
4af50f9
fix: update tooltip text styling in MultiBarGraph component
lightyfr Mar 28, 2025
c06cce1
feat: enhance tooltip styling and add MultiBarGraph component styles
lightyfr Mar 28, 2025
e6d0af1
feat: add dashed line support to LineBarGraph and LineGraph components
lightyfr Mar 28, 2025
a8544dd
feat: update tooltip formatting to use locale string representation i…
lightyfr Mar 29, 2025
ddd165a
feat: add PieChart component with customizable options and tooltip
lightyfr Mar 29, 2025
e2c5d55
migrate to 0.6 and remove data-viz imports from barrel
lorant-one Apr 1, 2025
7af3221
move data-viz components to new data module
lorant-one Apr 1, 2025
5ec161d
clutched up and saved time sequence + curve type commits
lightyfr Apr 1, 2025
0c10943
Remove Unused Imports
lightyfr Apr 1, 2025
eb61f1d
add color tokens for categorical charts, simplify BarGraph styling + …
lorant-one Apr 1, 2025
ce46118
Alter MultiBarGraph and LineBarGraph to conform to BarGraph Styles
lightyfr Apr 3, 2025
b56bf97
Refactor LineBarGraph and MultiBarGraph for improved styling and layo…
lightyfr Apr 3, 2025
381c37e
Enhance graph components with improved titles, descriptions, and layo…
lightyfr Apr 3, 2025
1b1bd7d
Refactor tooltip components in LineBarGraph and LineGraph for consist…
lightyfr Apr 3, 2025
3ec937b
Refactor color tokens in LineBarGraph, LineGraph, and MultiBarGraph f…
lightyfr Apr 3, 2025
2e623fb
Make LineGraph use data vars for stroke color
lightyfr Apr 3, 2025
676cefa
Make PieChart use data-viz token colors
lightyfr Apr 3, 2025
4102abc
update colors
lorant-one Apr 3, 2025
f73a23e
minor adjustments to linechart
lorant-one Apr 3, 2025
161429e
more styling
lorant-one Apr 3, 2025
208f687
refact bar + line chart style + props
lorant-one Apr 6, 2025
fe8cda8
soimplify key handling in LineChart
lorant-one Apr 7, 2025
1e5af67
refactor linebargraph to align to new chart styles
lightyfr Apr 9, 2025
0aa6447
fix: Linebargraph tooltip label on x hide bug
lightyfr Apr 10, 2025
af798a4
fix GroupedBarChart Colors and Styles
lightyfr Apr 10, 2025
3cb6e7b
feat: fix axis labeling and legend rendering on BarChart and GroupedB…
lightyfr Apr 10, 2025
2d39dd0
refactor PieChart
lightyfr Apr 10, 2025
de6e310
refactor: improve ProgressRing and SVG components for style, performa…
JExcellence May 19, 2025
634d275
Merge branch 'main' into feat-progress-ring
JExcellence May 19, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
368 changes: 367 additions & 1 deletion package-lock.json

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,15 @@
"@floating-ui/react-dom": "^2.1.1",
"classnames": "^2.5.1",
"compressorjs": "^1.2.1",
"moment": "^2.30.1",
"next": "15.3.1",
"postcss": "^8.4.39",
"postcss-preset-env": "^9.5.15",
"prismjs": "^1.30.0",
"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"
},
Expand Down
2 changes: 1 addition & 1 deletion src/once-ui/components/Badge.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import styles from "./Badge.module.scss";
import { IconName } from "../icons";
import classNames from "classnames";

interface BadgeProps extends React.ComponentProps<typeof Flex> {
export interface BadgeProps extends React.ComponentProps<typeof Flex> {
title?: string;
icon?: IconName;
arrow?: boolean;
Expand Down
43 changes: 43 additions & 0 deletions src/once-ui/components/ProgressRing.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
.container {
--progress-color: var(--accent-alpha-strong);

position: relative;
display: inline-flex;
align-items: center;
justify-content: center;

&.size-s { width: 6rem; height: 6rem; }
&.size-m { width: 8rem; height: 8rem; }
&.size-l { width: 10rem; height: 10rem; }

&.tone-warning { --progress-color: var(--warning-alpha-strong); }
&.tone-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: none;
stroke: var(--progress-color);
stroke-linecap: round;
transition: stroke-dashoffset 0.6s cubic-bezier(0.4, 0, 0.2, 1);
}

.label {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: var(--foreground-strong);
font-weight: 600;
}
61 changes: 61 additions & 0 deletions src/once-ui/components/ProgressRing.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
"use client";

import styles from "./ProgressRing.module.scss";
import { Column, Text } from "@/once-ui/components";
import classNames from "classnames";
import { SVG } from "./SVG";

interface ProgressRingProps {
value: number;
size?: "s" | "m" | "l";
tone?: "primary" | "warning" | "success";
label?: string;
}

const ProgressRing = ({
value,
size = "s",
tone = "primary",
label
}: ProgressRingProps) => {
const strokeWidth = 4;
const radiusMap = { s: 30, m: 45, l: 60 };
const radius = radiusMap[size];

const normalizedRadius = radius - strokeWidth;
const circumference = normalizedRadius * 2 * Math.PI;
const strokeDashoffset = circumference * (1 - value / 100);

return (
<Column className={classNames(styles.container, styles[`size-${size}`], styles[`tone-${tone}`])}>
<SVG className={styles.svg} viewBox={`0 0 ${radius * 2} ${radius * 2}`}>
<circle
className={styles.background}
cx={radius}
cy={radius}
r={normalizedRadius}
strokeWidth={strokeWidth}
/>
<circle
className={styles.progress}
cx={radius}
cy={radius}
r={normalizedRadius}
strokeWidth={strokeWidth}
strokeDasharray={`${circumference} ${circumference}`}
style={{ strokeDashoffset }}
/>
</SVG>

{label && (
<Text variant="body-strong-m" className={styles.label}>
{label}
</Text>
)}
</Column>
);
};

ProgressRing.displayName = "ProgressRing";

export { ProgressRing };
77 changes: 77 additions & 0 deletions src/once-ui/components/SVG.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@

"use client";

import React, { ElementType, ComponentPropsWithoutRef, ReactNode, forwardRef } from "react";
import classNames from "classnames";
import { CommonProps, SpacingProps } from "@/once-ui/interfaces";
import { ColorScheme, ColorWeight, SpacingToken } from "@/once-ui/types";

type SVGProps<T extends ElementType> =
ComponentPropsWithoutRef<"svg"> &
CommonProps &
SpacingProps & {
as?: T;
colorScheme?: ColorScheme;
colorWeight?: ColorWeight;
strokeScheme?: ColorScheme;
strokeWeight?: ColorWeight;
interactive?: boolean;
size?: "x" | "s" | "m" | "l" | "xl";
children?: ReactNode;
};

function getColorClass(type: "fill" | "stroke", scheme?: ColorScheme, weight?: ColorWeight) {
return scheme ? `${type}-${scheme}-${weight}` : "";
}

function getSpacingClass(prefix: string, token?: SpacingToken) {
return token ? `${prefix}-${token}` : "";
}

const SVG = forwardRef<SVGSVGElement, SVGProps<ElementType>>(function SVG(
{
as,
colorScheme = "neutral",
colorWeight = "weak",
strokeScheme,
strokeWeight = "weak",
interactive = false,
size = "m",
padding,
margin,
className,
style,
children,
...rest
},
ref
) {
const Component = as || "svg";
const classes = classNames(
"transition-colors",
getColorClass("fill", colorScheme, colorWeight),
getColorClass("stroke", strokeScheme, strokeWeight),
getSpacingClass("p", padding),
getSpacingClass("m", margin),
{
"cursor-pointer hover:scale-105": interactive,
"opacity-hoverable": interactive,
},
className
);

return (
<Component
ref={ref}
className={classes}
style={{ width: size, height: size, ...style }}
{...rest}
>
{children}
</Component>
);
});

SVG.displayName = "SVG";

export { SVG };
8 changes: 8 additions & 0 deletions src/once-ui/components/TechCarousel.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
.marqueeContent {
animation: marquee 20s linear infinite;
}

@keyframes marquee {
0% { transform: translateX(0%); }
100% { transform: translateX(-50%); }
}
89 changes: 89 additions & 0 deletions src/once-ui/components/TechCarousel.tsx
Original file line number Diff line number Diff line change
@@ -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<string, IconName> = {
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<string, IconName>;
} & Partial<BadgeProps>;

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 (
<Row position="relative" overflow="hidden" fillWidth padding="l">
<Flex gap={spacing} className={styles.marqueeContent}>
{[...normalizedItems, ...normalizedItems].map((item, i) => {
const iconName = item.icon || mergedIconMap[item.name.toLowerCase()];

return (
<RevealFx
key={`${item.name}-${i}`}
delay={0.7 + (i % items.length) * 0.1}
translateY={5}
>
<Badge
background="transparent"
border="transparent"
shadow="xs"
textVariant={textVariant}
icon={iconName}
title={item.name}
{...badgeProps}
/>
</RevealFx>
);
})}
</Flex>
</Row>
);
};

export { TechCarousel, defaultIconMap };
52 changes: 51 additions & 1 deletion src/once-ui/icons.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,37 @@ import {
HiOutlineDocumentDuplicate,
} from "react-icons/hi2";

import { RiVisaLine } from "react-icons/ri";

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<string, IconType> = {
chevronUp: HiChevronUp,
chevronDown: HiChevronDown,
Expand Down Expand Up @@ -61,7 +92,26 @@ export const iconLibrary: Record<string, IconType> = {
search: HiOutlineMagnifyingGlass,
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;
Expand Down
Loading