Skip to content

Commit

Permalink
Merge pull request #31 from savindi7/feat-profile-overview
Browse files Browse the repository at this point in the history
feat(react): add `CircularProgressAvatar` component
  • Loading branch information
savindi7 authored Feb 15, 2023
2 parents edbae1a + 6237b92 commit 51620f8
Show file tree
Hide file tree
Showing 7 changed files with 329 additions and 2 deletions.
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,17 +34,17 @@ export type Stories =
| 'ActionCard'
| 'AppBar'
| 'Avatar'
| 'UserDropdownMenu'
| 'Header'
| 'Box'
| 'Button'
| 'CircularProgressAvatar'
| 'Chip'
| 'ColorModeToggle'
| 'Colors'
| 'Container'
| 'Divider'
| 'Drawer'
| 'Grid'
| 'Header'
| 'IconButton'
| 'Icons'
| 'Image'
Expand All @@ -57,6 +57,7 @@ export type Stories =
| 'ListItemText'
| 'Menu'
| 'MenuItem'
| 'UserDropdownMenu'
| 'Navbar'
| 'SignIn'
| 'TextField'
Expand Down Expand Up @@ -111,6 +112,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',
}
}}
>
{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';
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'>;
/**
* 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 oxygen-badge MuiBadge-root css-1c32n2y-MuiBadge-root"
>
<div
class="MuiAvatar-root MuiAvatar-circular MuiAvatar-colorDefault oxygen-ui-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 oxygen-circular-progress 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 oxygen-circular-progress 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';

0 comments on commit 51620f8

Please sign in to comment.