Refactor UI folder (#2016)

* Added Overview page

* Revised Getting Started page

* Minor revision

* Edited readme, minor modifications to docs

* Removed sweep.yaml, .devcontainer, .ergomake

* Moved security.md to .github, added contributing.md

* changes as per code review

* updated contributing.md

* fixed broken links & added missing links in doc, improved structure

* fixed link in wsl setup

* fixed server link, added https cloning in yarn-setup

* removed package-lock.json

* added doc card, admonitions

* removed underline from nav buttons

* refactoring modules/ui

* refactoring modules/ui

* Change folder case

* Fix theme location

* Fix case 2

* Fix storybook

---------

Co-authored-by: Nimra Ahmed <nimra1408@gmail.com>
Co-authored-by: Nimra Ahmed <50912134+nimraahmed@users.noreply.github.com>
This commit is contained in:
Charles Bochet
2023-10-14 00:04:29 +02:00
committed by GitHub
parent a35ea5e8f9
commit 258685467b
732 changed files with 1106 additions and 1010 deletions

View File

@ -0,0 +1,71 @@
import React, { useEffect, useMemo } from 'react';
import { motion, useAnimation } from 'framer-motion';
interface CircularProgressBarProps {
size?: number;
barWidth?: number;
barColor?: string;
}
export const CircularProgressBar = ({
size = 50,
barWidth = 5,
barColor = 'currentColor',
}: CircularProgressBarProps) => {
const controls = useAnimation();
const circumference = useMemo(
() => 2 * Math.PI * (size / 2 - barWidth),
[size, barWidth],
);
useEffect(() => {
const animateIndeterminate = async () => {
const baseSegment = Math.max(5, circumference / 10); // Adjusting for smaller values
// Adjusted sequence based on baseSegment
const dashSequences = [
`${baseSegment} ${circumference - baseSegment}`,
`${baseSegment * 2} ${circumference - baseSegment * 2}`,
`${baseSegment * 3} ${circumference - baseSegment * 3}`,
`${baseSegment * 2} ${circumference - baseSegment * 2}`,
`${baseSegment} ${circumference - baseSegment}`,
];
await controls.start({
strokeDasharray: dashSequences,
rotate: [0, 720],
transition: {
strokeDasharray: {
duration: 2,
ease: 'linear',
repeat: Infinity,
repeatType: 'loop',
},
rotate: {
duration: 2,
ease: 'linear',
repeat: Infinity,
repeatType: 'loop',
},
},
});
};
animateIndeterminate();
}, [circumference, controls]);
return (
<motion.svg width={size} height={size} animate={controls}>
<motion.circle
cx={size / 2}
cy={size / 2}
r={size / 2 - barWidth}
fill="none"
stroke={barColor}
strokeWidth={barWidth}
strokeLinecap="round"
/>
</motion.svg>
);
};

View File

@ -0,0 +1,101 @@
import {
forwardRef,
useCallback,
useEffect,
useImperativeHandle,
useRef,
} from 'react';
import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
import { AnimationControls, motion, useAnimation } from 'framer-motion';
export type ProgressBarProps = {
duration?: number;
delay?: number;
easing?: string;
barHeight?: number;
barColor?: string;
autoStart?: boolean;
};
export type ProgressBarControls = AnimationControls & {
start: () => Promise<any>;
pause: () => Promise<any>;
};
const StyledBar = styled.div<Pick<ProgressBarProps, 'barHeight'>>`
height: ${({ barHeight }) => barHeight}px;
overflow: hidden;
width: 100%;
`;
const StyledBarFilling = styled(motion.div)`
height: 100%;
width: 100%;
`;
export const ProgressBar = forwardRef<ProgressBarControls, ProgressBarProps>(
(
{
duration = 3,
delay = 0,
easing = 'easeInOut',
barHeight = 24,
barColor,
autoStart = true,
},
ref,
) => {
const theme = useTheme();
const controls = useAnimation();
const startTimestamp = useRef<number>(0);
const remainingTime = useRef<number>(duration);
const start = useCallback(async () => {
startTimestamp.current = Date.now();
return controls.start({
scaleX: 0,
transition: {
duration: remainingTime.current / 1000, // convert ms to s for framer-motion
delay: delay / 1000, // likewise
ease: easing,
},
});
}, [controls, delay, easing]);
useImperativeHandle(ref, () => ({
...controls,
start: async () => {
return start();
},
pause: async () => {
const elapsed = Date.now() - startTimestamp.current;
remainingTime.current = remainingTime.current - elapsed;
return controls.stop();
},
}));
useEffect(() => {
if (autoStart) {
start();
}
}, [controls, delay, duration, easing, autoStart, start]);
return (
<StyledBar barHeight={barHeight}>
<StyledBarFilling
style={{
originX: 0,
// Seems like custom props are not well handled by react when used with framer-motion and emotion styled
backgroundColor: barColor ?? theme.color.gray80,
}}
initial={{ scaleX: 1 }}
animate={controls}
exit={{ scaleX: 0 }}
/>
</StyledBar>
);
},
);

View File

@ -0,0 +1,56 @@
import { Meta, StoryObj } from '@storybook/react';
import { CatalogDecorator } from '~/testing/decorators/CatalogDecorator';
import { ComponentDecorator } from '~/testing/decorators/ComponentDecorator';
import { CatalogStory } from '~/testing/types';
import { CircularProgressBar } from '../CircularProgressBar';
const meta: Meta<typeof CircularProgressBar> = {
title: 'UI/CircularProgressBar/CircularProgressBar',
component: CircularProgressBar,
args: {
size: 50,
},
parameters: {
chromatic: { disableSnapshot: true },
},
};
export default meta;
type Story = StoryObj<typeof CircularProgressBar>;
export const Default: Story = {
decorators: [ComponentDecorator],
};
export const Catalog: CatalogStory<Story, typeof CircularProgressBar> = {
argTypes: {},
parameters: {
catalog: {
dimensions: [
{
name: 'barColor',
values: [undefined, 'red'],
props: (barColor: string) => ({ barColor }),
labels: (color: string) => `Segment Color: ${color ?? 'default'}`,
},
{
name: 'barWidth',
values: [undefined, 5, 10],
props: (barWidth: number) => ({ barWidth }),
labels: (width: number) =>
`Stroke Width: ${width ? width + ' px' : 'default'}`,
},
{
name: 'size',
values: [undefined, 80, 30],
props: (size: number) => ({ size }),
labels: (size: number) => `Size: ${size ? size + ' px' : 'default'}`,
},
],
},
},
decorators: [CatalogDecorator],
};

View File

@ -0,0 +1,63 @@
import { Meta, StoryObj } from '@storybook/react';
import { CatalogDecorator } from '~/testing/decorators/CatalogDecorator';
import { ComponentDecorator } from '~/testing/decorators/ComponentDecorator';
import { CatalogStory } from '~/testing/types';
import { ProgressBar } from '../ProgressBar';
const meta: Meta<typeof ProgressBar> = {
title: 'UI/ProgressBar/ProgressBar',
component: ProgressBar,
args: {
duration: 10000,
},
};
export default meta;
type Story = StoryObj<typeof ProgressBar>;
const args = {};
const defaultArgTypes = {
control: false,
};
export const Default: Story = {
args,
decorators: [ComponentDecorator],
};
export const Catalog: CatalogStory<Story, typeof ProgressBar> = {
args: {
...args,
},
argTypes: {
barHeight: defaultArgTypes,
barColor: defaultArgTypes,
autoStart: defaultArgTypes,
},
parameters: {
catalog: {
dimensions: [
{
name: 'animation',
values: [true, false],
props: (autoStart: string) => ({ autoStart: Boolean(autoStart) }),
labels: (autoStart: string) => `AutoStart: ${autoStart}`,
},
{
name: 'colors',
values: [undefined, 'blue'],
props: (barColor: string) => ({ barColor }),
labels: (color: string) => `Color: ${color ?? 'default'}`,
},
{
name: 'sizes',
values: [undefined, 10],
props: (barHeight: number) => ({ barHeight }),
labels: (size: number) => `Size: ${size ? size + ' px' : 'default'}`,
},
],
},
},
decorators: [CatalogDecorator],
};