Skip to content
This repository has been archived by the owner on Aug 21, 2023. It is now read-only.

Commit

Permalink
Merge a71abc9 into d4496bc
Browse files Browse the repository at this point in the history
  • Loading branch information
Jon Quach committed Apr 15, 2019
2 parents d4496bc + a71abc9 commit 7afb6f2
Show file tree
Hide file tree
Showing 7 changed files with 165 additions and 74 deletions.
4 changes: 4 additions & 0 deletions .storybook/preview-head.html
@@ -0,0 +1,4 @@
<meta
name="viewport"
content="width=device-width, initial-scale=1, shrink-to-fit=no"
/>
32 changes: 32 additions & 0 deletions src/components/Avatar/Avatar.Crop.tsx
@@ -0,0 +1,32 @@
import * as React from 'react'
import { classNames } from '../../utilities/classNames'
import { CropUI } from './Avatar.css'

export const AvatarCrop = props => {
const { className, children, hasImage, isImageLoaded, withShadow } = props

const componentClassName = classNames(
'c-Avatar__crop',
isImageLoaded && 'is-imageLoaded',
withShadow && 'is-withShadow',
className
)

const styles = {
backgroundColor: hasImage ? 'currentColor' : null,
}

return (
<CropUI className={componentClassName} style={styles}>
{children}
</CropUI>
)
}

AvatarCrop.defaultProps = {
hasImage: false,
isImageLoaded: false,
withShadow: false,
}

export default AvatarCrop
68 changes: 68 additions & 0 deletions src/components/Avatar/Avatar.Image.tsx
@@ -0,0 +1,68 @@
import * as React from 'react'
import VisuallyHidden from '../VisuallyHidden'
import { classNames } from '../../utilities/classNames'
import { getEasingTiming } from '../../utilities/easing'
import { noop } from '../../utilities/other'
import { ImageWrapperUI, ImageUI } from './Avatar.css'

export const AvatarImage = props => {
const {
animationDuration,
animationEasing,
className,
hasImage,
image,
isImageLoaded,
onError,
onLoad,
name,
title,
} = props

const componentClassName = classNames(
'c-Avatar__imageWrapper',
isImageLoaded && 'is-herbieFullyLoaded',
className
)

const backgroundImage = isImageLoaded ? `url('${image}')` : null

const imageStyle = {
transition: `opacity ${animationDuration}ms ${getEasingTiming(
animationEasing
)}`,
}

const contentMarkup = (
<ImageWrapperUI className={componentClassName} style={imageStyle}>
<ImageUI className="c-Avatar__image" style={{ backgroundImage }}>
<div className="c-Avatar__name">
<VisuallyHidden>{name}</VisuallyHidden>
<img
alt={name}
onError={onError}
onLoad={onLoad}
src={image}
style={{ display: 'none' }}
/>
</div>
</ImageUI>
</ImageWrapperUI>
)

return hasImage ? contentMarkup : title
}

AvatarImage.defaultProps = {
animationDuration: 160,
animationEasing: 'ease',
hasImage: false,
image: null,
isImageLoaded: false,
onError: noop,
onLoad: noop,
name: null,
title: null,
}

export default AvatarImage
27 changes: 21 additions & 6 deletions src/components/Avatar/Avatar.css.ts
Expand Up @@ -7,7 +7,7 @@ import styled from '../styled'
export const config = {
borderRadius: 3,
borderWidth: 2,
boxShadow: '0 5px 8px rgb(0, 0, 0, 0.2)',
boxShadow: '0 5px 8px rgba(0, 0, 0, 0.2)',
color: getColor('blue.500'),
position: 'relative',
size: {
Expand Down Expand Up @@ -68,23 +68,38 @@ export const CropUI = styled('div')`
${getBorderRadiusStyles()};
&.is-withShadow {
box-shadow: ${config.boxShadow};
box-shadow: 0 0 0 1px rgba(255, 255, 255, 0) inset, ${config.boxShadow};
&.is-imageLoaded {
box-shadow: 0 0 0 1px rgba(255, 255, 255, 1) inset, ${config.boxShadow};
}
}
`

export const ImageUI = styled('div')`
background-position: center center;
background-size: cover;
export const ImageWrapperUI = styled('div')`
backface-visibility: hidden;
display: block;
height: 100%;
width: 100%;
opacity: 0;
overflow: hidden;
transform: translate3d(0, 0, 0) scale(1.0125);
width: 100%;
${getBorderRadiusStyles()};
&.is-herbieFullyLoaded {
opacity: 1;
}
`

export const ImageUI = styled('div')`
background-position: center center;
background-size: cover;
display: block;
height: 100%;
width: 100%;
`

export const TitleUI = styled('div')`
color: white;
line-height: 1;
Expand Down
96 changes: 31 additions & 65 deletions src/components/Avatar/Avatar.tsx
Expand Up @@ -4,16 +4,15 @@ import propConnect from '../PropProvider/propConnect'
import { StatusDotStatus } from '../StatusDot/types'
import { AvatarShape, AvatarSize } from './Avatar.types'
import StatusDot from '../StatusDot'
import VisuallyHidden from '../VisuallyHidden'
import { includes } from '../../utilities/arrays'
import { getEasingTiming } from '../../utilities/easing'
import { classNames } from '../../utilities/classNames'
import { nameToInitials } from '../../utilities/strings'
import AvatarCrop from './Avatar.Crop'
import AvatarImage from './Avatar.Image'
import {
AvatarUI,
CropUI,
CropBorderUI,
ImageUI,
OuterBorderUI,
StatusUI,
TitleUI,
Expand Down Expand Up @@ -103,36 +102,39 @@ export class Avatar extends React.PureComponent<Props, State> {
return classNames(shape && `is-${shape}`, size && `is-${size}`)
}

getCropStyles = () => {
let styles = {}

if (this.hasImage()) {
styles = {
...styles,
backgroundColor: 'currentColor',
}
}

styles = Object.keys(styles).length ? styles : {}

return styles
}

renderCrop = () => {
const { withShadow } = this.props
const contentMarkup = this.getContentMarkup()
const styles = this.getCropStyles()
const {
animationDuration,
animationEasing,
image,
name,
withShadow,
} = this.props

const componentClassName = classNames(
'c-Avatar__crop',
withShadow && 'is-withShadow',
this.getShapeClassNames()
)
const hasImage = this.hasImage()
const isImageLoaded = image && this.isImageLoaded()
const shapeClassnames = this.getShapeClassNames()

return (
<CropUI className={componentClassName} style={styles}>
{contentMarkup}
</CropUI>
<AvatarCrop
className={shapeClassnames}
hasImage={hasImage}
isImageLoaded={isImageLoaded}
withShadow={withShadow}
>
<AvatarImage
animationDuration={animationDuration}
animationEasing={animationEasing}
className={shapeClassnames}
hasImage={hasImage}
image={image}
isImageLoaded={isImageLoaded}
name={name}
title={this.getTitleMarkup()}
onError={this.onImageLoadedError}
onLoad={this.onImageLoadedSuccess}
/>
</AvatarCrop>
)
}

Expand Down Expand Up @@ -184,42 +186,6 @@ export class Avatar extends React.PureComponent<Props, State> {
return <TitleUI className={componentClassName}>{text}</TitleUI>
}

getContentMarkup = () => {
const { animationDuration, animationEasing, image, name } = this.props

const isImageLoaded = image && this.isImageLoaded()

const componentClassName = classNames(
'c-Avatar__image',
isImageLoaded && 'is-herbieFullyLoaded'
)

const imageStyle = {
backgroundImage: isImageLoaded ? `url('${image}')` : null,
transition: `opacity ${animationDuration}ms ${getEasingTiming(
animationEasing
)}`,
}

const titleMarkup = this.getTitleMarkup()
const contentMarkup = (
<ImageUI className={componentClassName} style={imageStyle}>
<div className="c-Avatar__name">
<VisuallyHidden>{name}</VisuallyHidden>
<img
alt={name}
onError={this.onImageLoadedError}
onLoad={this.onImageLoadedSuccess}
src={image}
style={{ display: 'none' }}
/>
</div>
</ImageUI>
)

return this.hasImage() ? contentMarkup : titleMarkup
}

renderCropBorder = () => {
const { borderColor, shape } = this.props
const componentClassName = classNames(
Expand Down
2 changes: 1 addition & 1 deletion src/components/Avatar/__tests__/Avatar.test.js
Expand Up @@ -132,7 +132,7 @@ describe('Image', () => {

const crop = wrapper.find(`div${ui.crop}`)

expect(crop.prop('style')).toEqual({})
expect(crop.prop('style').background).toBeFalsy()
})

test('Sets `title` attribute to the `name`', () => {
Expand Down
10 changes: 8 additions & 2 deletions stories/AvatarStackV2.stories.js
Expand Up @@ -23,12 +23,18 @@ const guides = [

const stories = storiesOf('AvatarStack', module)
stories.addDecorator(
withArtboard({ id: 'hsds-avatarstack', guides, width: 400, height: 100 })
withArtboard({
guides,
width: 400,
height: 100,
showGuides: false,
showInterface: false,
})
)
stories.addDecorator(withKnobs)

stories.add('V2/Default', () => {
const avatars = number('avatars', 1)
const avatars = number('avatars', 5)

const animationDuration = number('animationDuration', 300)
const animationEasing = text('animationEasing', 'ease')
Expand Down

0 comments on commit 7afb6f2

Please sign in to comment.