Skip to content

Commit

Permalink
feat(CircularProgress): initial implementation (unstable) (#691)
Browse files Browse the repository at this point in the history
  • Loading branch information
WilliamKelley authored Apr 10, 2023
1 parent 0d5d5b4 commit 44ff745
Show file tree
Hide file tree
Showing 8 changed files with 323 additions and 17 deletions.
2 changes: 2 additions & 0 deletions libs/spark/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ The naming scheme of v2 replacement components will change from "Unstable\_\<Com

API surface:

- **CircularProgress_unstable**
- [feat] initial implementation
- **LinearProgress_unstable**
- [feat] initial implementation

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import React from 'react';
import type { Meta, Story as DefaultStory } from '@storybook/react/types-6-0';
import { CircularProgress_unstable, CircularProgressProps_unstable } from '..';

export const _retyped =
CircularProgress_unstable as typeof CircularProgress_unstable;

export default {
title: '@ps/CircularProgress',
component: _retyped,
excludeStories: ['_retyped'],
} as Meta;

const Template = (args) => <CircularProgress_unstable {...args} />;

type Story = DefaultStory<CircularProgressProps_unstable>;

export const Default: Story = Template.bind({});
Default.storyName = '(default)';

export const Value0: Story = Template.bind({});
Value0.args = { value: 0 };
Value0.storyName = 'value=0';

export const Value50: Story = Template.bind({});
Value50.args = { value: 50 };
Value50.storyName = 'value=50';

export const Value100: Story = Template.bind({});
Value100.args = { value: 100 };
Value100.storyName = 'value=100';

export const VariantDeterminateValueColorBlue: Story = Template.bind({});
VariantDeterminateValueColorBlue.args = {
color: 'blue',
value: 50,
variant: 'determinate',
};
VariantDeterminateValueColorBlue.storyName =
'variant=determinate value=50 color=blue';

export const VariantDeterminateValueColorGreen: Story = Template.bind({});
VariantDeterminateValueColorGreen.args = {
color: 'green',
value: 50,
variant: 'determinate',
};
VariantDeterminateValueColorGreen.storyName =
'variant=determinate value=50 color=green';

export const VariantDeterminateValueColorNeutral: Story = Template.bind({});
VariantDeterminateValueColorNeutral.args = {
color: 'neutral',
value: 50,
variant: 'determinate',
};
VariantDeterminateValueColorNeutral.storyName =
'variant=determinate value=50 color=neutral';

export const VariantDeterminateValueColorPurple: Story = Template.bind({});
VariantDeterminateValueColorPurple.args = {
color: 'purple',
value: 50,
variant: 'determinate',
};
VariantDeterminateValueColorPurple.storyName =
'variant=determinate value=50 color=purple';

export const VariantDeterminateValueColorRed: Story = Template.bind({});
VariantDeterminateValueColorRed.args = {
color: 'red',
value: 50,
variant: 'determinate',
};
VariantDeterminateValueColorRed.storyName =
'variant=determinate value=50 color=red';

export const VariantDeterminateValueColorTeal: Story = Template.bind({});
VariantDeterminateValueColorTeal.args = {
color: 'teal',
value: 50,
variant: 'determinate',
};
VariantDeterminateValueColorTeal.storyName =
'variant=determinate value=50 color=teal';

export const VariantDeterminateValueColorYellow: Story = Template.bind({});
VariantDeterminateValueColorYellow.args = {
color: 'yellow',
value: 50,
variant: 'determinate',
};
VariantDeterminateValueColorYellow.storyName =
'variant=determinate value=50 color=yellow';

export const VariantIndeterminate: Story = Template.bind({});
VariantIndeterminate.args = { variant: 'indeterminate' };
VariantIndeterminate.storyName = 'variant=indeterminate';

export const Value50Children: Story = Template.bind({});
Value50Children.args = {
children: <>50%</>,
value: 50,
};
Value50Children.storyName = 'children value=50';

export const Value100Children: Story = Template.bind({});
Value100Children.args = {
children: <>100%</>,
value: 100,
};
Value100Children.storyName = 'children value=100';
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { render } from '@testing-library/react';
import CircularProgress_unstable from './CircularProgress_unstable';

describe('CircularProgress_unstable', () => {
it('Can render without ThemeProvider', () => {
const { baseElement } = render(<CircularProgress_unstable />);

expect(baseElement).toBeTruthy();
});
});
185 changes: 185 additions & 0 deletions libs/spark/src/CircularProgress_unstable/CircularProgress_unstable.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
import {
default as MuiCircularProgress,
CircularProgressProps as MuiCircularProgressProps,
} from '@material-ui/core/CircularProgress';
import clsx from 'clsx';
import React, { ReactNode, forwardRef, isValidElement } from 'react';
import { StandardProps } from '../utils';
import withStyles, { Styles } from '../withStyles';

export interface CircularProgressProps_unstable
extends StandardProps<
MuiCircularProgressProps,
CircularProgressClassKey_unstable,
'classes' | 'color'
> {
/**
* The color of the circle, label (if provided).
*/
color?: 'neutral' | 'red' | 'yellow' | 'teal' | 'green' | 'blue' | 'purple';
children?: ReactNode;
/**
* The variant of the component
*/
variant?: Exclude<MuiCircularProgressProps['variant'], 'static'>;
}

export type CircularProgressClassKey_unstable =
| 'root'
| 'circle'
| 'dashed'
| 'container'
| 'label';

type PrivateClassKey =
| 'private-circle-color-neutral'
| 'private-circle-color-red'
| 'private-circle-color-yellow'
| 'private-circle-color-teal'
| 'private-circle-color-green'
| 'private-circle-color-blue'
| 'private-circle-color-purple'
| 'private-label-color-neutral'
| 'private-label-color-red'
| 'private-label-color-yellow'
| 'private-label-color-teal'
| 'private-label-color-green'
| 'private-label-color-blue'
| 'private-label-color-purple';

const styles: Styles<CircularProgressClassKey_unstable | PrivateClassKey> = (
theme
) => ({
/* Styles applied to the root element. */
root: {},
circle: {
color: 'inherit',
strokeLinecap: 'round',
},
dashed: {},
container: {
position: 'relative',
display: 'inline-flex',
},
label: {
...theme.unstable_typography.T14,
inset: 0,
position: 'absolute',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
},
'private-circle-color-neutral': {
color: theme.unstable_palette.neutral[300],
},
'private-circle-color-red': {
color: theme.unstable_palette.red[600],
},
'private-circle-color-yellow': {
color: theme.unstable_palette.yellow[500],
},
'private-circle-color-teal': {
color: theme.unstable_palette.teal[500],
},
'private-circle-color-green': {
color: theme.unstable_palette.green[600],
},
'private-circle-color-blue': {
color: theme.unstable_palette.blue[600],
},
'private-circle-color-purple': {
color: theme.unstable_palette.purple[500],
},
'private-label-color-neutral': {
color: theme.unstable_palette.neutral[500],
},
'private-label-color-red': {
color: theme.unstable_palette.red[600],
},
'private-label-color-yellow': {
color: theme.unstable_palette.yellow[500],
},
'private-label-color-teal': {
color: theme.unstable_palette.teal[500],
},
'private-label-color-green': {
color: theme.unstable_palette.green[600],
},
'private-label-color-blue': {
color: theme.unstable_palette.blue[600],
},
'private-label-color-purple': {
color: theme.unstable_palette.purple[500],
},
});

const UnstyledCircularProgress = forwardRef<
HTMLDivElement,
CircularProgressProps_unstable
>(function CircularProgress(props, ref) {
const {
children,
classes,
color = 'neutral',
size = 56,
thickness = 4,
variant = 'determinate',
value = 0,
...other
} = props;

const hasChildren = isValidElement(children);

const progressElement = (
<MuiCircularProgress
classes={{
root: classes.root,
circle: clsx(classes.circle, {
[classes['private-circle-color-neutral']]: color === 'neutral',
[classes['private-circle-color-red']]: color === 'red',
[classes['private-circle-color-yellow']]: color === 'yellow',
[classes['private-circle-color-teal']]: color === 'teal',
[classes['private-circle-color-green']]: color === 'green',
[classes['private-circle-color-blue']]: color === 'blue',
[classes['private-circle-color-purple']]: color === 'purple',
}),
}}
ref={ref}
size={size}
thickness={thickness}
value={value}
variant={variant}
{...other}
/>
);

if (!hasChildren) {
return progressElement;
}

return (
<div className={classes.container}>
{progressElement}

<span
className={clsx(classes.label, {
[classes['private-label-color-neutral']]: color === 'neutral',
[classes['private-label-color-red']]: color === 'red',
[classes['private-label-color-yellow']]: color === 'yellow',
[classes['private-label-color-teal']]: color === 'teal',
[classes['private-label-color-green']]: color === 'green',
[classes['private-label-color-blue']]: color === 'blue',
[classes['private-label-color-purple']]: color === 'purple',
})}
>
{children}
</span>
</div>
);
});

const CircularProgress_unstable = withStyles(styles, {
name: 'MuiSparkCircularProgress_unstable',
})(UnstyledCircularProgress) as typeof UnstyledCircularProgress;

export default CircularProgress_unstable;
2 changes: 2 additions & 0 deletions libs/spark/src/CircularProgress_unstable/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { default } from './CircularProgress_unstable';
export * from './CircularProgress_unstable';
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
import React from 'react';
import type { Meta, Story as DefaultStory } from '@storybook/react/types-6-0';
import {
LinearProgress_unstable,
LinearProgressProps_unstable,
Unstable_Typography,
} from '..';
import { LinearProgress_unstable, LinearProgressProps_unstable } from '..';

export const _retyped =
LinearProgress_unstable as typeof LinearProgress_unstable;
Expand Down Expand Up @@ -105,22 +101,16 @@ export const VariantQuery: Story = Template.bind({});
VariantQuery.args = { variant: 'query' };
VariantQuery.storyName = 'variant=query';

const labelElement = (
<Unstable_Typography component="span" variant="T14">
50%
</Unstable_Typography>
);

export const Value50Children: Story = Template.bind({});
Value50Children.args = {
children: labelElement,
children: <>50%</>,
value: 50,
};
Value50Children.storyName = 'children value=50';

export const Value50ChildrenLabelPlacementStart: Story = Template.bind({});
Value50ChildrenLabelPlacementStart.args = {
children: labelElement,
children: <>50%</>,
value: 50,
labelPlacement: 'start',
};
Expand All @@ -129,7 +119,7 @@ Value50ChildrenLabelPlacementStart.storyName =

export const Value50ChildrenLabelPlacementEnd: Story = Template.bind({});
Value50ChildrenLabelPlacementEnd.args = {
children: labelElement,
children: <>50%</>,
value: 50,
labelPlacement: 'end',
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export interface LinearProgressProps_unstable
'classes' | 'color' | 'variant'
> {
/**
* The color of the bar.
* The color of the bar, label (if provided).
*/
color?: 'neutral' | 'red' | 'yellow' | 'teal' | 'green' | 'blue' | 'purple';
/**
Expand Down Expand Up @@ -68,7 +68,9 @@ const styles: Styles<LinearProgressClassKey_unstable | PrivateClassKey> = (
display: 'flex',
gap: 8,
},
label: {},
label: {
...theme.unstable_typography.T14,
},
'private-root-with-label': {
width: '100%',
},
Expand All @@ -94,7 +96,7 @@ const styles: Styles<LinearProgressClassKey_unstable | PrivateClassKey> = (
backgroundColor: theme.unstable_palette.purple[500],
},
'private-label-color-neutral': {
color: theme.unstable_palette.neutral[300],
color: theme.unstable_palette.neutral[500],
},
'private-label-color-red': {
color: theme.unstable_palette.red[600],
Expand Down
Loading

0 comments on commit 44ff745

Please sign in to comment.