diff --git a/packages/circuit-ui/components/Avatar/Avatar.stories.tsx b/packages/circuit-ui/components/Avatar/Avatar.stories.tsx index bdb6025488..201e5b7e1b 100644 --- a/packages/circuit-ui/components/Avatar/Avatar.stories.tsx +++ b/packages/circuit-ui/components/Avatar/Avatar.stories.tsx @@ -27,7 +27,8 @@ export default { docs: { page: docs }, }, argTypes: { - imageUrl: { control: 'text' }, + src: { control: 'text' }, + alt: { control: 'text' }, variant: { control: { type: 'radio', options: ['business', 'person'] } }, size: { control: { type: 'radio', options: ['yotta', 'giga'] } }, }, @@ -35,7 +36,8 @@ export default { export const base = (args: AvatarProps): JSX.Element => ; base.args = { - imageUrl: 'https://upload.wikimedia.org/wikipedia/en/8/86/Avatar_Aang.png', + src: 'https://upload.wikimedia.org/wikipedia/en/8/86/Avatar_Aang.png', + alt: '', variant: 'person', size: 'yotta', }; @@ -45,12 +47,14 @@ export const sizes = (): JSX.Element => ( ); @@ -59,9 +63,10 @@ export const identity = (): JSX.Element => ( - + ); @@ -69,8 +74,9 @@ export const object = (): JSX.Element => ( - + ); diff --git a/packages/circuit-ui/components/Avatar/Avatar.tsx b/packages/circuit-ui/components/Avatar/Avatar.tsx index 5569d3b3fb..bfbd597da4 100644 --- a/packages/circuit-ui/components/Avatar/Avatar.tsx +++ b/packages/circuit-ui/components/Avatar/Avatar.tsx @@ -13,18 +13,21 @@ * limitations under the License. */ -import { HTMLAttributes } from 'react'; +import React, { HTMLAttributes } from 'react'; import { css } from '@emotion/core'; import isPropValid from '@emotion/is-prop-valid'; import styled, { StyleProps } from '../../styles/styled'; -export interface AvatarProps - extends Omit, 'size'> { +export interface AvatarProps extends HTMLAttributes { /** - * The URL of the Avatar image + * The Avatar image source */ - imageUrl?: string; + src?: string; + /** + * Alt text for the Avatar + */ + alt: string; /** * The variant of the Avatar, either representing a person or a business */ @@ -33,15 +36,6 @@ export interface AvatarProps * The size of the Avatar */ size?: 'giga' | 'yotta'; - /** - * Alternative DOM element to render - */ - as?: 'label'; - /** - * htmlFor when the element is a label - * TODO the element should extend either a div or a label - */ - htmlFor?: string; } const avatarSizes = { @@ -54,34 +48,44 @@ const placeholders = { business: ``, }; +type StyledImageProps = Omit & { + variant: 'person' | 'business'; + size: 'giga' | 'yotta'; +}; + const baseStyles = ({ theme, - imageUrl, - variant = 'person', - size = 'yotta', -}: AvatarProps & StyleProps) => css` + variant, + size, +}: StyledImageProps & StyleProps) => css` display: block; width: ${avatarSizes[size]}; height: ${avatarSizes[size]}; - box-shadow: inset 0 0 0 ${theme.borderWidth.kilo} rgba(0, 0, 0, 0.1); + box-shadow: 0 0 0 ${theme.borderWidth.kilo} rgba(0, 0, 0, 0.1); + background-color: ${theme.colors.n300}; border-radius: ${variant === 'person' ? theme.borderRadius.circle : theme.borderRadius.tera}; - border: none; - background-color: ${theme.colors.n300}; - background-size: cover; - background-position: center; - background-image: url('data:image/svg+xml;utf8,${placeholders[variant]}'); - - ${imageUrl && - css` - background-image: url(${imageUrl}); - `}; + object-fit: cover; + object-position: center; `; +const StyledImage = styled('img', { + shouldForwardProp: (prop) => isPropValid(prop), +})(baseStyles); + /** * The Avatar component. */ -export const Avatar = styled('div', { - shouldForwardProp: (prop) => isPropValid(prop), -})(baseStyles); +export const Avatar = ({ + src: initialSrc, + alt = '', + variant = 'person', + size = 'yotta', + ...props +}: AvatarProps): JSX.Element => { + const src = initialSrc || `data:image/svg+xml;utf8,${placeholders[variant]}`; + return ( + + ); +}; diff --git a/packages/circuit-ui/components/ImageInput/ImageInput.tsx b/packages/circuit-ui/components/ImageInput/ImageInput.tsx index 7802e2932f..34e6ec5600 100644 --- a/packages/circuit-ui/components/ImageInput/ImageInput.tsx +++ b/packages/circuit-ui/components/ImageInput/ImageInput.tsx @@ -18,6 +18,7 @@ import { ChangeEvent, Fragment, InputHTMLAttributes, useState } from 'react'; import { css, jsx } from '@emotion/core'; import Avatar from '../Avatar'; +import Label from '../Label'; import styled from '../../styles/styled'; import { uniqueId } from '../../util/id'; import { focusOutline, hideVisually } from '../../styles/style-mixins'; @@ -28,6 +29,10 @@ export interface ImageInputProps * label */ label: string; + /** + * alt + */ + alt: string; /** * imageUrl */ @@ -40,12 +45,12 @@ const Input = styled.input( &:focus + label { ${focusOutline({ theme })}; - border-color: ${theme.colors.p500}; + border-radius: ${theme.borderRadius.tera}; } `, ); -const Image = styled(Avatar)` +const StyledAvatar = styled(Avatar)` :hover { filter: brightness(90%); cursor: pointer; @@ -58,6 +63,7 @@ const Image = styled(Avatar)` export const ImageInput = ({ label, imageUrl: initialImageUrl, + alt, id: customId, ...props }: ImageInputProps): JSX.Element => { @@ -74,16 +80,17 @@ export const ImageInput = ({ return ( - - + /> + ); };