Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Components/progress bar #1756

Merged
merged 13 commits into from
May 6, 2024
24 changes: 24 additions & 0 deletions packages/UI/src/assets/icons/Clock.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import * as React from 'react';

function Clock(props: React.SVGProps<SVGSVGElement>) {
return (
<svg
width="22"
height="22"
viewBox="0 0 22 22"
fill="none"
xmlns="http://www.w3.org/2000/svg"
{...props}
>
<path
d="M11 5V11L15 13M21 11C21 16.5228 16.5228 21 11 21C5.47715 21 1 16.5228 1 11C1 5.47715 5.47715 1 11 1C16.5228 1 21 5.47715 21 11Z"
stroke="black"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
);
}

export default Clock;
23 changes: 23 additions & 0 deletions packages/UI/src/assets/icons/Done.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import * as React from 'react';
function Done(props: React.SVGProps<SVGSVGElement>) {
return (
<svg
width="22"
height="22"
viewBox="0 0 22 22"
fill="none"
xmlns="http://www.w3.org/2000/svg"
{...props}
>
<path
d="M8 11L10 13L14 9M21 11C21 16.5228 16.5228 21 11 21C5.47715 21 1 16.5228 1 11C1 5.47715 5.47715 1 11 1C16.5228 1 21 5.47715 21 11Z"
stroke="black"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
);
}

export default Done;
30 changes: 30 additions & 0 deletions packages/UI/src/components/progressBar/Progress.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { Progress } from './Progress.tsx';
import * as ProgressStories from './Progress.stories.tsx';
import {
Meta,
Stories,
Description,
Story,
ArgTypes,
Canvas,
Controls,
} from '@storybook/blocks';

<Meta of={ProgressStories} />
<div className="gap-14">
<h1>Progress Bar</h1>
<p className="text-[#8A8D97]">
Component with all the variants, states, etc.
</p>
</div>
<div className="flex flex-col items-start gap-3 rounded-lg p-4 outline-dashed outline-2 outline-brand-alt-nebula-500 w-96">
<Story of={ProgressStories.Primary} />
<Story of={ProgressStories.Secondary} />
<Story of={ProgressStories.Tertiary} />
<Story of={ProgressStories.Quartary} />
</div>
<Canvas />
<Controls
of={ProgressStories.Primary}
exclude={['asChild', 'value', 'max', 'getValueLabel']}
/>
65 changes: 65 additions & 0 deletions packages/UI/src/components/progressBar/Progress.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import type { Meta, StoryObj } from '@storybook/react';
import { Progress } from './Progress';
import '@devlaunchers/tailwind/tailwind.css';

const meta: Meta<typeof Progress> = {
component: Progress,
parameters: {
layout: 'centered',
docs: {
// Customize the args table by excluding certain arg types
argTypes: {
exclude: ['asChild', 'value', 'max', 'getValueLabel'],
},
},
design: {
type: 'figma',
url: 'https://www.figma.com/file/EwzuhhvTulvFRMvhTD5VAh/DL-Universal-Design-System?type=design&node-id=11653-23398&mode=design&t=pKeXByjq7arsjXYv-0',
},
},
argTypes: {
progress: {
control: {
type: 'range',
min: 25,
max: 100,
step: 25,
},
defaultValue: 25,
},
toggleClock: {
control: 'boolean',
defaultValue: true,
},
},
} as Meta<typeof Progress>;

export default meta;
type Story = StoryObj<typeof Progress>;

export const Primary: Story = {
args: {
progress: 25,
fileName: 'File name',
toggleClock: true,
},
};

export const Secondary: Story = {
args: {
...Primary.args,
progress: 50,
},
};
export const Tertiary: Story = {
args: {
...Primary.args,
progress: 75,
},
};
export const Quartary: Story = {
args: {
...Primary.args,
progress: 100,
},
};
95 changes: 95 additions & 0 deletions packages/UI/src/components/progressBar/Progress.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import * as ProgressPrimitive from '@radix-ui/react-progress';
import * as React from 'react';
import { cn } from '../../utils/classesMerger';
import Clock from './../../assets/icons/Clock';
import Done from './../../assets/icons/Done';

const styles = {
startColor: 'bg-brand-alt-cosmic-500',
endColor: 'bg-brand-alt-nebula-500',
backgroundColor: 'bg-grayscale-100',
width: 'w-80',
height: 'h-6',
textColor: 'text-grayscale-900',
font: 'font-normal',
fontStyle: 'not-italic',
flex: 'flex',
flexDirection: 'flex-col',
alignItems: 'items-start',
justifyContent: 'justify-between',
indigo: 'bg-indigo-500',
};

interface ProgressProps
extends React.ComponentPropsWithoutRef<typeof ProgressPrimitive.Root> {
/**
* Progress value passed as a prop
*/
progress: number;
/**
* It is used to uniquely identify the name of the file
*/
fileName: string;
/**
* You can choose whether to show the clock or not
*/
toggleClock: boolean; // This prop now controls both icons.
}

const Progress = React.forwardRef<
React.ElementRef<typeof ProgressPrimitive.Root>,
ProgressProps
>(
(
{ className, fileName = 'name your file', progress, toggleClock, ...props },
ref
) => {
const isComplete = progress === 100;
const currentColor = isComplete ? styles.endColor : styles.startColor;
const progressPercentage = `${progress}%`;
const icon = toggleClock ? isComplete ? <Done /> : <Clock /> : null;

return (
<div
className={`${styles.flex} ${styles.flexDirection} ${styles.alignItems} gap-14 rounded-lg p-4`}
>
<div
className={`${styles.flex} ${styles.width} ${styles.flexDirection} ${styles.alignItems} gap-3`}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think styles.flex,styles.width, styles.flexDirection , styles.alignItems can be used directly instead

ls there a reason why you made it in an object?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah simply for code readability and the DRY principle which made the lines shorter.

>
<div className={`${styles.flex} w-full ${styles.justifyContent}`}>
<p
className={`text-base ${styles.font} ${styles.fontStyle} leading-6 ${styles.textColor}`}
>
{fileName}
</p>
<div className={`${styles.flex} ${styles.justifyContent} gap-2`}>
<p
className={`text-xs ${styles.font} ${styles.fontStyle} leading-5 ${styles.textColor}`}
>
{progressPercentage}
</p>
{icon}
</div>
</div>
<ProgressPrimitive.Root
ref={ref}
className={cn(
`relative ${styles.width} ${styles.height} overflow-hidden rounded-full ${styles.backgroundColor} border-solid border-2 border-brand-alt-cosmic-500`,
className
)}
{...props}
>
<ProgressPrimitive.Indicator
className={`h-full w-full flex-1 ${currentColor} transition-all`}
style={{ transform: `translateX(-${100 - progress}%)` }}
/>
</ProgressPrimitive.Root>
</div>
</div>
);
}
);

Progress.displayName = ProgressPrimitive.Root.displayName;

export { Progress };
Loading