Skip to content

Commit

Permalink
feat: implement sizing Avatar with number & size types
Browse files Browse the repository at this point in the history
  • Loading branch information
vickonrails committed Apr 14, 2021
1 parent 97aa62a commit e48da2a
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 36 deletions.
14 changes: 7 additions & 7 deletions example/src/components/avatar.tsx
Expand Up @@ -2,17 +2,17 @@ import React from 'react'
import { Avatar, AvatarGroup } from 'avocado-ui'
import { Radio } from 'react-feather'

import AvatarImg from '../images/avatar.jpg'
// import AvatarImg from '../images/avatar.jpg'

const AvatarComponent = () => {
return (
<AvatarGroup>
<Avatar name='Mathew KE' icon={<Radio />} />
<Avatar name='Mathew KE' icon={<Radio />} />
<Avatar name='Mathew KE' src={AvatarImg} />
<Avatar name='Mathew KE' src={AvatarImg} />
<Avatar name='Mathew KE' />
<Avatar name='Mathew KE' />
<Avatar name='Mathew KE' size='xs' />
<Avatar name='Mathew KE' size='sm' />
<Avatar name='Mathew KE' size='md' />
<Avatar name='Mathew KE' size='lg' />
<Avatar name='Mathew KE' size='xl' />
<Avatar name='Mathew KE' size={200} icon={<Radio />} />
</AvatarGroup>
)
}
Expand Down
70 changes: 43 additions & 27 deletions src/components/avatar/avatar.tsx
Expand Up @@ -2,9 +2,10 @@ import React, { FC, ImgHTMLAttributes } from 'react'
import styled from '@emotion/styled'
import { css } from '@emotion/react'
import { getInitials } from '../../utils/avatar'
import { avatarTheme } from '../../components/theme/components/avatar.theme'

// Avatar component
const Avatar: FC<AvatarProps> = ({ className, ...props }) => {
const Avatar: FC<AvatarProps> = ({ className, name, ...props }) => {
// Notice the name is always rendered as the `title` of the avatar to reveal more information on hover
const _className = className
? `avocado-avatar ${className}`
Expand All @@ -13,16 +14,17 @@ const Avatar: FC<AvatarProps> = ({ className, ...props }) => {
// render an image avatar if there's a `src` prop
// return and end excution here
if (props.src)
return <StyledAvatar {...props} title={props.name} className={_className} />
return <StyledAvatar {...props} title={name} className={_className} />

// render an icon if no `src` prop but `icon` exists
if (props.icon)
return (
<StyledAvatarSpan
title={props.name}
title={name}
className={_className}
role='img'
aria-label={props.name}
aria-label={name}
{...props}
>
<span>{props.icon}</span>
</StyledAvatarSpan>
Expand All @@ -31,50 +33,60 @@ const Avatar: FC<AvatarProps> = ({ className, ...props }) => {
// finally render the initials of the name supplied
return (
<StyledAvatarInitials
title={props.name}
title={name}
className={_className}
aria-label={props.name}
aria-label={name}
{...props}
>
<span>{props.name && getInitials(props.name)}</span>
<span>{name && getInitials(name)}</span>
</StyledAvatarInitials>
)
}

type Size = string

type AvatarSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl'
export interface AvatarProps extends ImgHTMLAttributes<HTMLImageElement> {
/**
* initials of the `name` string are rendered when there are no values for `src` and `icon`
*/
name: string
name?: string

/**
* specifies the size of the avatar image or box
*/
size?: Size
size?: AvatarSize | number

/**
* specifies the icon to render when there's no value for image source (`src`)
*/
icon?: JSX.Element
}

const StyledAvatarBase = css`
margin: 0;
padding: 0;
pointer: cursor;
height: 32px;
width: 32px;
text-align: center;
border-radius: 200px;
display: flex;
background: red;
color: #fff;
cursor: pointer;
user-select: none;
font-size: 0.85em;
`
const StyledAvatarBase = ({ size }: AvatarProps) =>
size &&
css`
margin: 0;
padding: 0;
pointer: cursor;
height: ${size && typeof size === 'number'
? `${size}`
: size && avatarTheme.sizes[size]}px;
width: ${size && typeof size === 'number'
? `${size}`
: size && avatarTheme.sizes[size]}px;
text-align: center;
border-radius: 9999px;
display: flex;
background: red;
color: #fff;
cursor: pointer;
user-select: none;
font-size: ${typeof size === 'number'
? size / 2
: avatarTheme.fontSizes[size]}px;
`

const StyledAvatar = styled.img`
${StyledAvatarBase}
Expand Down Expand Up @@ -104,4 +116,8 @@ const StyledAvatarSpan = styled.span`
}
`

Avatar.defaultProps = {
size: 'md'
}

export { Avatar }
16 changes: 16 additions & 0 deletions src/components/theme/components/avatar.theme.ts
@@ -0,0 +1,16 @@
export const avatarTheme = {
sizes: {
xs: 24,
sm: 32,
md: 40,
lg: 64,
xl: 84
},
fontSizes: {
xs: 8,
sm: 14,
md: 16,
lg: 26,
xl: 40
}
}
1 change: 1 addition & 0 deletions src/components/theme/components/index.ts
@@ -1,3 +1,4 @@
export * from './button.theme'
export * from './input.theme'
export * from './select.theme'
export * from './avatar.theme'
6 changes: 4 additions & 2 deletions src/components/theme/index.ts
Expand Up @@ -2,7 +2,8 @@ import colors from './colors'
import borders from './borders'
import spacing from './spacing'
import typography from './typography'
import { buttonTheme, inputTheme } from './components'

import { buttonTheme, inputTheme, avatarTheme } from './components'

const theme = {
colors,
Expand All @@ -11,7 +12,8 @@ const theme = {
typography,
components: {
buttonTheme,
inputTheme
inputTheme,
avatarTheme
}
}

Expand Down

0 comments on commit e48da2a

Please sign in to comment.