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

feat(react): add CircularProgressAvatar component #31

Merged
merged 9 commits into from
Feb 15, 2023
8 changes: 6 additions & 2 deletions packages/react/.storybook/story-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,15 @@ export type Stories =
| 'ActionCard'
| 'AppBar'
| 'Avatar'
| 'UserDropdownMenu'
| 'Header'
| 'Box'
| 'Button'
| 'CircularProgressAvatar'
| 'ColorModeToggle'
| 'Colors'
| 'Divider'
| 'Drawer'
| 'Grid'
| 'Header'
| 'IconButton'
| 'Icons'
| 'Image'
Expand All @@ -55,6 +55,7 @@ export type Stories =
| 'ListItemText'
| 'Menu'
| 'MenuItem'
| 'UserDropdownMenu'
| 'SignIn'
| 'TextField'
| 'Toolbar'
Expand Down Expand Up @@ -108,6 +109,9 @@ const StoryConfig: StorybookConfig = {
Button: {
hierarchy: `${StorybookCategories.Inputs}/Button`,
},
CircularProgressAvatar: {
hierarchy: `${StorybookCategories.DataDisplay}/Circular Progress Avatar`,
},
UserDropdownMenu: {
hierarchy: `${StorybookCategories.Navigation}/User Dropdown Menu`,
},
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import {ArgsTable, Source, Story, Canvas, Meta} from '@storybook/addon-docs';
import dedent from 'ts-dedent';
import StoryConfig from '../../../.storybook/story-config.ts';
import CircularProgressAvatar from './CircularProgressAvatar.tsx';

export const meta = {
component: CircularProgressAvatar,
title: StoryConfig.CircularProgressAvatar.hierarchy,
};

<Meta title={meta.title} component={meta.component} />

export const Template = args => <CircularProgressAvatar {...args} />;

# Circular Progress Avatar

- [Overview](#overview)
- [Props](#props)
- [Usage](#usage)

## Overview

The Avatar with circular progress and badge.

<Canvas>
<Story
name="Overview"
args={{color: 'warning',
progress: 70,
badgeOptions: {color: 'primary', badgeContent: '70%'},
avatarOptions: {
src: '/assets/images/avatar-john.svg',
alt:'avatar',
}
}}
Comment on lines +28 to +35
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we move colors to the next line to make it more readable?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ack. Will send a seperate PR for this improvement.

>
{Template.bind({})}
</Story>
</Canvas>

## Props

<ArgsTable story="Overview" />

## Usage

Import and use the `CircularProgressAvatar` component in your components as follows.

<Source
language="jsx"
dark
format
code={dedent`import CircularProgressAvatar from '@oxygen-ui/react/CircularProgressAvatar';\n`}
/>
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/**
* Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). All Rights Reserved.
*
* WSO2 LLC. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

import {Badge, BadgeProps, CircularProgress, CircularProgressProps} from '@mui/material';
Copy link
Member

Choose a reason for hiding this comment

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

Wrap these components. Even if not wrapped, always better to use the tree shakable import syntax.
https://mui.com/material-ui/guides/minimizing-bundle-size/#option-one-use-path-imports

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Got it. Will wrap and do this improvement in commits seperately.

import clsx from 'clsx';
import {FC, ReactElement} from 'react';
import {WithWrapperProps} from '../../models';
import {composeComponentDisplayName} from '../../utils';
import Avatar, {AvatarProps} from '../Avatar';
import Box from '../Box';
import './circular-progress-avatar.scss';

export interface CircularProgressAvatarProps extends Omit<CircularProgressProps, 'value'> {
/**
* Props sent to the Avatar component.
*/
avatarOptions?: Omit<AvatarProps, 'variant'>;
/**
* Props sent to the Badge component.
*/
badgeOptions?: Omit<BadgeProps, 'overlap' | 'anchorOrigin' | 'showZero'>;
savindi7 marked this conversation as resolved.
Show resolved Hide resolved
/**
* Value prop sent to CircularProgress component.
*/
progress?: number;
}

const COMPONENT_NAME: string = 'CircularProgressAvatar';

const CircularProgressAvatar: FC<CircularProgressAvatarProps> & WithWrapperProps = (
props: CircularProgressAvatarProps,
): ReactElement => {
const {className, progress, badgeOptions, avatarOptions, ...rest} = props;

const classes: string = clsx('oxygen-circular-progress-avatar', className);

return (
<Box className={classes} role="presentation">
<Badge
showZero
className="oxygen-badge"
overlap="circular"
anchorOrigin={{
horizontal: 'left',
vertical: 'bottom',
}}
{...badgeOptions}
>
<Avatar {...avatarOptions} />
<CircularProgress
aria-label="progress"
size={90}
className="oxygen-circular-progress"
variant="determinate"
value={progress}
{...rest}
/>
<CircularProgress
aria-label="progress"
size={90}
className="oxygen-circular-progress frame"
variant="determinate"
value={100}
{...rest}
/>
</Badge>
</Box>
);
};

CircularProgressAvatar.displayName = composeComponentDisplayName(COMPONENT_NAME);
CircularProgressAvatar.muiName = COMPONENT_NAME;
CircularProgressAvatar.defaultProps = {};

export default CircularProgressAvatar;
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/**
* Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). All Rights Reserved.
*
* WSO2 LLC. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

import {render} from '@unit-testing';
import CircularProgressAvatar from '../CircularProgressAvatar';

describe('CircularProgressAvatar', () => {
it('should render successfully', () => {
const {baseElement} = render(<CircularProgressAvatar />);
expect(baseElement).toBeTruthy();
});

it('should match the snapshot', () => {
const {baseElement} = render(<CircularProgressAvatar />);
expect(baseElement).toMatchSnapshot();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`CircularProgressAvatar should match the snapshot 1`] = `
<body>
<div>
<div
class="oxygen-box oxygen-circular-progress-avatar MuiBox-root css-0"
role="presentation"
>
<span
class="MuiBadge-root badge MuiBadge-root css-1c32n2y-MuiBadge-root"
>
<div
class="MuiAvatar-root MuiAvatar-circular MuiAvatar-colorDefault oxygen-ui-avatar avatar css-woe6xp-MuiAvatar-root"
>
<svg
aria-hidden="true"
class="MuiSvgIcon-root MuiSvgIcon-fontSizeMedium MuiAvatar-fallback css-10mi8st-MuiSvgIcon-root-MuiAvatar-fallback"
data-testid="PersonIcon"
focusable="false"
viewBox="0 0 24 24"
>
<path
d="M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z"
/>
</svg>
</div>
<span
aria-label="progress"
aria-valuenow="0"
class="MuiCircularProgress-root MuiCircularProgress-determinate MuiCircularProgress-colorPrimary circularProfileProgress css-iq1hel-MuiCircularProgress-root"
role="progressbar"
style="width: 90px; height: 90px; transform: rotate(-90deg);"
>
<svg
class="MuiCircularProgress-svg css-1idz92c-MuiCircularProgress-svg"
viewBox="22 22 44 44"
>
<circle
class="MuiCircularProgress-circle MuiCircularProgress-circleDeterminate css-oxts8u-MuiCircularProgress-circle"
cx="44"
cy="44"
fill="none"
r="20.2"
stroke-width="3.6"
style="stroke-dasharray: 126.920; stroke-dashoffset: 126.920px;"
/>
</svg>
</span>
<span
aria-label="progress"
aria-valuenow="100"
class="MuiCircularProgress-root MuiCircularProgress-determinate MuiCircularProgress-colorPrimary circularProfileProgress frame css-iq1hel-MuiCircularProgress-root"
role="progressbar"
style="width: 90px; height: 90px; transform: rotate(-90deg);"
>
<svg
class="MuiCircularProgress-svg css-1idz92c-MuiCircularProgress-svg"
viewBox="22 22 44 44"
>
<circle
class="MuiCircularProgress-circle MuiCircularProgress-circleDeterminate css-oxts8u-MuiCircularProgress-circle"
cx="44"
cy="44"
fill="none"
r="20.2"
stroke-width="3.6"
style="stroke-dasharray: 126.920; stroke-dashoffset: 0.000px;"
/>
</svg>
</span>
<span
class="MuiBadge-badge MuiBadge-standard MuiBadge-invisible MuiBadge-anchorOriginBottomLeft MuiBadge-anchorOriginBottomLeftCircular MuiBadge-overlapCircular MuiBadge-badge css-1mktq6a-MuiBadge-badge"
/>
</span>
</div>
</div>
</body>
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/**
* Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). All Rights Reserved.
*
* WSO2 LLC. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

.oxygen-circular-progress-avatar {
padding: 1rem;

.oxygen-circular-progress {
position: absolute;
top: -6px;
left: -6px;
z-index: 1;
transform: scaleY(-1) rotate(90deg) !important;

&.frame {
color: lightgrey;
z-index: 0;
}
}

.oxygen-avatar {
width: 80px;
height: 80px;
}

.oxygen-badge {
.MuiBadge-badge {
left: 50%;
border-radius: 3px;
padding: 0.5rem 1rem;
top: 70px;
}
}
}
20 changes: 20 additions & 0 deletions packages/react/src/components/CircularProgressAvatar/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/**
* Copyright (c) 2023, WSO2 LLC. (https://www.wso2.com). All Rights Reserved.
*
* WSO2 LLC. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

export {default} from './CircularProgressAvatar';
export type {CircularProgressAvatarProps} from './CircularProgressAvatar';