diff --git a/src/Avatar.tsx b/src/Avatar.tsx index 857ad7d0984..f6018d0213a 100644 --- a/src/Avatar.tsx +++ b/src/Avatar.tsx @@ -1,9 +1,8 @@ -import styled from 'styled-components' -import {get} from './constants' -import sx, {SxProp} from './sx' -import {ComponentProps} from './utils/types' +import React from 'react' +import Box from './Box' +import {SxProp, merge, BetterSystemStyleObject} from './sx' -type StyledAvatarProps = { +export type AvatarProps = { /** Sets the width and height of the avatar. */ size?: number /** Sets the shape of the avatar to a square if true. If false, the avatar will be circular. */ @@ -12,9 +11,10 @@ type StyledAvatarProps = { src: string /** Provide alt text when the Avatar is used without the user's name next to it. */ alt?: string -} & SxProp +} & SxProp & + Omit, 'ref'> -function getBorderRadius({size, square}: StyledAvatarProps) { +function getBorderRadius({size, square}: Pick) { if (square) { return size && size <= 24 ? '4px' : '6px' } else { @@ -22,23 +22,20 @@ function getBorderRadius({size, square}: StyledAvatarProps) { } } -const Avatar = styled.img.attrs(props => ({ - height: props.size, - width: props.size -}))` - display: inline-block; - overflow: hidden; // Ensure page layout in Firefox should images fail to load - line-height: ${get('lineHeights.condensedUltra')}; - vertical-align: middle; - border-radius: ${props => getBorderRadius(props)}; - ${sx} -` +const Avatar = React.forwardRef((props, ref) => { + const {size = 20, alt = '', square = false, sx = {}, ...rest} = props -Avatar.defaultProps = { - size: 20, - alt: '', - square: false -} + const styles: BetterSystemStyleObject = { + display: 'inline-block', + overflow: 'hidden', + lineHeight: 'condensedUltra', + verticalAlign: 'middle', + width: size, + height: size, + borderRadius: getBorderRadius({size, square}) + } + return (styles, sx)} {...rest} /> +}) -export type AvatarProps = ComponentProps +Avatar.displayName = 'Avatar' export default Avatar diff --git a/src/__tests__/Avatar.test.tsx b/src/__tests__/Avatar.test.tsx index 24ce518a3be..3030bb0bc82 100644 --- a/src/__tests__/Avatar.test.tsx +++ b/src/__tests__/Avatar.test.tsx @@ -24,14 +24,16 @@ describe('Avatar', () => { it('renders small by default', () => { const size = 20 const result = render() - expect(result.props.width).toEqual(size) - expect(result.props.height).toEqual(size) + + expect(result).toHaveStyleRule('width', px(size)) + expect(result).toHaveStyleRule('height', px(size)) }) it('respects the size prop', () => { const result = render() - expect(result.props.width).toEqual(40) - expect(result.props.height).toEqual(40) + + expect(result).toHaveStyleRule('width', '40px') + expect(result).toHaveStyleRule('height', '40px') }) it('passes through the src prop', () => { diff --git a/src/__tests__/__snapshots__/Avatar.test.tsx.snap b/src/__tests__/__snapshots__/Avatar.test.tsx.snap index 6c84752e4de..5eb4cdf3a9e 100644 --- a/src/__tests__/__snapshots__/Avatar.test.tsx.snap +++ b/src/__tests__/__snapshots__/Avatar.test.tsx.snap @@ -6,14 +6,13 @@ exports[`Avatar renders consistently 1`] = ` overflow: hidden; line-height: 1; vertical-align: middle; + width: 20px; + height: 20px; border-radius: 50%; } `; diff --git a/src/__tests__/__snapshots__/Token.test.tsx.snap b/src/__tests__/__snapshots__/Token.test.tsx.snap index f16b0d27a3a..7df83c10b86 100644 --- a/src/__tests__/__snapshots__/Token.test.tsx.snap +++ b/src/__tests__/__snapshots__/Token.test.tsx.snap @@ -6,9 +6,9 @@ exports[`Token components AvatarToken renders all sizes 1`] = ` overflow: hidden; line-height: 1; vertical-align: middle; - border-radius: 50%; width: 100%; height: 100%; + border-radius: 50%; } .c5 { @@ -166,10 +166,7 @@ exports[`Token components AvatarToken renders all sizes 1`] = ` @@ -217,9 +214,9 @@ exports[`Token components AvatarToken renders all sizes 2`] = ` overflow: hidden; line-height: 1; vertical-align: middle; - border-radius: 50%; width: 100%; height: 100%; + border-radius: 50%; } .c5 { @@ -377,10 +374,7 @@ exports[`Token components AvatarToken renders all sizes 2`] = ` @@ -428,9 +422,9 @@ exports[`Token components AvatarToken renders all sizes 3`] = ` overflow: hidden; line-height: 1; vertical-align: middle; - border-radius: 50%; width: 100%; height: 100%; + border-radius: 50%; } .c5 { @@ -588,10 +582,7 @@ exports[`Token components AvatarToken renders all sizes 3`] = ` @@ -639,9 +630,9 @@ exports[`Token components AvatarToken renders all sizes 4`] = ` overflow: hidden; line-height: 1; vertical-align: middle; - border-radius: 50%; width: 100%; height: 100%; + border-radius: 50%; } .c5 { @@ -799,10 +790,7 @@ exports[`Token components AvatarToken renders all sizes 4`] = ` @@ -850,9 +838,9 @@ exports[`Token components AvatarToken renders all sizes 5`] = ` overflow: hidden; line-height: 1; vertical-align: middle; - border-radius: 50%; width: 100%; height: 100%; + border-radius: 50%; } .c5 { @@ -1010,10 +998,7 @@ exports[`Token components AvatarToken renders all sizes 5`] = ` @@ -1144,9 +1129,9 @@ exports[`Token components AvatarToken renders isSelected 1`] = ` overflow: hidden; line-height: 1; vertical-align: middle; - border-radius: 50%; width: 100%; height: 100%; + border-radius: 50%; } .c4 { @@ -1252,10 +1237,7 @@ exports[`Token components AvatarToken renders isSelected 1`] = ` @@ -1273,9 +1255,9 @@ exports[`Token components AvatarToken renders with a remove button 1`] = ` overflow: hidden; line-height: 1; vertical-align: middle; - border-radius: 50%; width: 100%; height: 100%; + border-radius: 50%; } .c5 { @@ -1433,10 +1415,7 @@ exports[`Token components AvatarToken renders with a remove button 1`] = ` diff --git a/src/stories/Avatar.stories.tsx b/src/stories/Avatar.stories.tsx new file mode 100644 index 00000000000..23760d9b050 --- /dev/null +++ b/src/stories/Avatar.stories.tsx @@ -0,0 +1,51 @@ +import Avatar from '../Avatar' +import {Meta} from '@storybook/react' +import React from 'react' +import {ThemeProvider} from '..' +import BaseStyles from '../BaseStyles' + +const meta: Meta = { + title: 'Building blocks/Avatar/fixtures', + component: Avatar, + decorators: [ + (Story: React.ComponentType): JSX.Element => ( + + + + + + ) + ] +} +export default meta + +export function SimpleAvatar(): JSX.Element { + return +} + +export function CustomSize(): JSX.Element { + return +} + +export function SquareAvatar(): JSX.Element { + return +} + +export function DefaultAltText(): JSX.Element { + return +} + +export function AcceptsRef(): JSX.Element { + const ref = React.useRef(null) + + return +} + +export function AcceptsSxProp(): JSX.Element { + return ( + <> + + text pushed to right because avatar has margin + + ) +}