Skip to content

Commit

Permalink
feat: Implement default avatar based on user name
Browse files Browse the repository at this point in the history
  • Loading branch information
COSMO-EMI committed Aug 4, 2022
1 parent 1cd1d66 commit 5ad2630
Show file tree
Hide file tree
Showing 6 changed files with 88 additions and 43 deletions.
28 changes: 28 additions & 0 deletions doc/src/misc/DefaultAvatar.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
---
name: DefaultAvatar
route: /DefaultAvatar
menu: Misc
---

import { Playground, Props } from 'docz';
import { DefaultAvatar } from '@cosmotech/ui';

# Help Menu

The aim of this component is to display an avatar for users that didn't define one, while offering a specific one, whose color is based on the user's name.

## Props

<Props of={DefaultAvatar} />

## Basic Usage

<Playground>
<div>
<DefaultAvatar userName="Emma Michelet" />
<DefaultAvatar userName="Elena Sasova" />
<DefaultAvatar userName="Tristan Huet" />
<DefaultAvatar userName="Nicolas Borde" />
<DefaultAvatar userName="Jérémy Reynard" />
</div>
</Playground>
20 changes: 5 additions & 15 deletions src/menus/UserInfo/UserInfo.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,8 @@
import React, { useState } from 'react';
import PropTypes from 'prop-types';
import { Box, Menu, MenuItem, ClickAwayListener, IconButton, Tooltip } from '@material-ui/core';
import {
ArrowRight as ArrowRightIcon,
AccountCircle as AccountCircleIcon,
Check as CheckIcon,
} from '@material-ui/icons';

import { ArrowRight as ArrowRightIcon, Check as CheckIcon } from '@material-ui/icons';
import { DefaultAvatar } from '../../misc';
import useStyles from './style';

export const UserInfo = (props) => {
Expand Down Expand Up @@ -44,19 +40,13 @@ export const UserInfo = (props) => {
return (
<ClickAwayListener onClickAway={handleClose}>
<div>
<Box
data-cy="user-profile-menu"
aria-controls="user-profile-button"
aria-haspopup="true"
onClick={handleClick}
className={`${classes.menuTrigger} ${isMenuOpen ? 'active' : ''}`}
>
<Box data-cy="user-profile-menu" aria-controls="user-profile-button" aria-haspopup="true" onClick={handleClick}>
<Tooltip key="user-name-tooltip" title={userName}>
{profilePlaceholder ? (
<img src={profilePlaceholder} />
) : (
<IconButton aria-label="account" color="inherit">
<AccountCircleIcon />
<IconButton aria-label="account">
<DefaultAvatar userName={userName} />
</IconButton>
)}
</Tooltip>
Expand Down
28 changes: 0 additions & 28 deletions src/menus/UserInfo/style.js
Original file line number Diff line number Diff line change
@@ -1,34 +1,6 @@
import { makeStyles } from '@material-ui/core';

const useStyles = makeStyles((theme) => ({
menuTrigger: {
backgroundRepeat: 'no-repeat',
minWidth: '32px',
backgroundSize: '32px',
borderRadius: '50%',
flexShrink: 0,
transition: 'box-shadow ease-in-out 0.2s',
'&:hover': {
cursor: 'pointer',
},
display: 'flex',
flexDirection: 'row',
flexWrap: 'nowrap',
justifyContent: 'center',
alignItems: 'stretch',
},
profilePic: {
width: '32px',
height: '32px',
},
userName: {
fontSize: '16px',
textAlign: 'center',
lineHeight: '32px',
height: '32px',
marginLeft: '8px',
color: theme.palette.text.primary,
},
menu: {
transform: 'translate3d(0,30px,0) !important',
},
Expand Down
53 changes: 53 additions & 0 deletions src/misc/DefaultAvatar/DefaultAvatar.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Avatar, makeStyles } from '@material-ui/core';

function stringToColor(str) {
let hash = 0;

for (let i = 0; i < str.length; ++i) {
hash = str.charCodeAt(i) + ((hash << 5) - hash);
}

let color = '#';
for (let i = 0; i < 3; ++i) {
const value = (hash >> (i * 8)) & 0xff;
color += `00${value.toString(16)}`.slice(-2);
}

return color;
}

const useStyles = makeStyles((theme) => ({
avatar: {
width: (props) => `${props.size}px`,
height: (props) => `${props.size}px`,
fontSize: (props) => theme.typography.pxToRem(props.size / 2),
backgroundColor: (props) => props.avatarBackgroundColor,
color: (props) => theme.palette.getContrastText(props.avatarBackgroundColor),
},
}));

export const DefaultAvatar = ({ userName, size }) => {
const avatarBackgroundColor = stringToColor(userName);
const letter = userName.charAt(0).toUpperCase();

const classes = useStyles({ avatarBackgroundColor, size });

return <Avatar className={classes.avatar}>{letter}</Avatar>;
};

DefaultAvatar.propTypes = {
/**
* User name to get first letter and compute avatar's color
*/
userName: PropTypes.string.isRequired,
/**
* Icon size in pixels
*/
size: PropTypes.int,
};

DefaultAvatar.defaultProps = {
size: 24,
};
1 change: 1 addition & 0 deletions src/misc/DefaultAvatar/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { DefaultAvatar } from './DefaultAvatar';
1 change: 1 addition & 0 deletions src/misc/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ export { FixedRatioContainer } from './FixedRatioContainer';
export { ScenarioValidationStatusChip } from './ScenarioValidationStatusChip';
export { LoadingLine } from './LoadingLine';
export { ErrorBanner } from './ErrorBanner';
export { DefaultAvatar } from './DefaultAvatar';

0 comments on commit 5ad2630

Please sign in to comment.