diff --git a/packages/terra-avatar/CHANGELOG.md b/packages/terra-avatar/CHANGELOG.md index 4462174c7ef..2a347212c8b 100644 --- a/packages/terra-avatar/CHANGELOG.md +++ b/packages/terra-avatar/CHANGELOG.md @@ -4,6 +4,7 @@ ChangeLog Unreleased ---------- ### Breaking Changes +* Changed the fallback behavior of Avatar. Such that if the image fails to load, the avatar falls back to the initials display instead of default user icon. * To Make all User avatars available in same variant `generic` subcomponent has been added. * `generic` subcomponent replaces the `sharedUser` subcomponent. * `generic` subcomponent contains a `variant` prop that toggles between `single-user`, `shared-user`, and `provider` user avatar. diff --git a/packages/terra-avatar/src/common/AvatarUtils.jsx b/packages/terra-avatar/src/common/AvatarUtils.jsx index 8d2080b7c4d..9476c1fad22 100644 --- a/packages/terra-avatar/src/common/AvatarUtils.jsx +++ b/packages/terra-avatar/src/common/AvatarUtils.jsx @@ -60,17 +60,33 @@ const getColorVariant = (hashValue) => { /** * Render placeholder. */ -const generateImagePlaceholder = (alt, isAriaHidden, variant) => { +const generateImagePlaceholder = (avatarParams) => { + const { + alt, variant, isAriaHidden, + } = avatarParams; const avatarIconClassNames = cx(['icon', variant]); - return ; }; +/** + * Render placeholder. + */ +const generateInitials = (avatarParams) => { + const { + alt, initials, isAriaHidden, + } = avatarParams; + const avatarTextClassNames = cx('initials'); + return {initials.toUpperCase()}; +}; + /** * Render image with placeholder. */ -const generateImage = (image, alt, isAriaHidden, variant, handleFallback) => { - const icon = generateImagePlaceholder(alt, isAriaHidden, variant); +const generateImage = (avatarParams) => { + const { + alt, image, variant, handleFallback, + } = avatarParams; + const icon = (variant === AVATAR_VARIANTS.USER) ? generateInitials(avatarParams) : generateImagePlaceholder(avatarParams); return ; }; @@ -110,6 +126,7 @@ export { getColorVariant, generateImagePlaceholder, generateImage, + generateInitials, validateColor, setColor, }; diff --git a/packages/terra-avatar/src/terra-dev-site/doc/avatar/Avatar.2.doc.mdx b/packages/terra-avatar/src/terra-dev-site/doc/avatar/Avatar.2.doc.mdx index cc819bc1517..67d8b54ec88 100644 --- a/packages/terra-avatar/src/terra-dev-site/doc/avatar/Avatar.2.doc.mdx +++ b/packages/terra-avatar/src/terra-dev-site/doc/avatar/Avatar.2.doc.mdx @@ -14,7 +14,7 @@ import AvatarPropsTable from 'terra-avatar/src/variants/Avatar?dev-site-props-ta # Terra Avatar -The `Avatar` variant represents a person - it displays an image or initials in a circular frame. If neither are provided, a fallback user icon displays. This is the default export of the `terra-avatar` package. +The `Avatar` variant represents a person - it displays an image or initials in a circular frame. If a valid image is not provided then the avatar falls back to displaying initials. This is the default export of the `terra-avatar` package. ## Getting Started diff --git a/packages/terra-avatar/src/terra-dev-site/doc/avatar/UpgradeGuide.5.doc.mdx b/packages/terra-avatar/src/terra-dev-site/doc/avatar/UpgradeGuide.5.doc.mdx index a9db3d41a55..75a4734f564 100644 --- a/packages/terra-avatar/src/terra-dev-site/doc/avatar/UpgradeGuide.5.doc.mdx +++ b/packages/terra-avatar/src/terra-dev-site/doc/avatar/UpgradeGuide.5.doc.mdx @@ -8,14 +8,17 @@ import { Badge } from 'terra-avatar/package.json?dev-site-package'; ### Reason for upgrade * To group all user avatars in single variant `shared-user` has been replaced with `generic` sub-component * To keep adding new user avatars like `provider` easier new `generic` sub-component has been added with all user avatars as variants. +* Providing more standard fallbacks ### Removed * `Shared User` subcomponent From Avatar +* Default `user` icon as fallback icon for Avatar ### Added * The `generic` subcomponent that replaces the `sharedUser` subcomponent with a new `variant` prop that can be `single-user`, `shared-user`, or `provider`. * `variant` prop will take values for sub-variants `single-user`, `shared-user` and `provider`. * `user` avatar has been moved into `generic` sub-comopnent with varaint name `single-user`. +* the `initials` as fallback display for Avatar when image fails to load. ### Steps to uplift to V3 1. Use a named export for Generic variant. diff --git a/packages/terra-avatar/src/terra-dev-site/doc/example/avatar/AvatarColorVariants.jsx b/packages/terra-avatar/src/terra-dev-site/doc/example/avatar/AvatarColorVariants.jsx index 6313d7e261c..f5202823967 100644 --- a/packages/terra-avatar/src/terra-dev-site/doc/example/avatar/AvatarColorVariants.jsx +++ b/packages/terra-avatar/src/terra-dev-site/doc/example/avatar/AvatarColorVariants.jsx @@ -8,7 +8,7 @@ const propTypes = { color: PropTypes.string }; const AvatarColorVariants = ({ ...props }) => ( - + ); AvatarColorVariants.propTypes = propTypes; diff --git a/packages/terra-avatar/src/terra-dev-site/doc/example/avatar/AvatarImage.jsx b/packages/terra-avatar/src/terra-dev-site/doc/example/avatar/AvatarImage.jsx index e97b50fac11..e2cc8550f7d 100644 --- a/packages/terra-avatar/src/terra-dev-site/doc/example/avatar/AvatarImage.jsx +++ b/packages/terra-avatar/src/terra-dev-site/doc/example/avatar/AvatarImage.jsx @@ -3,7 +3,7 @@ import Avatar from 'terra-avatar'; import exampleAvatarImage from '../../../assets/150x150.jpg'; const AvatarImage = () => ( - + ); export default AvatarImage; diff --git a/packages/terra-avatar/src/terra-dev-site/doc/example/avatar/AvatarIsDeceased.jsx b/packages/terra-avatar/src/terra-dev-site/doc/example/avatar/AvatarIsDeceased.jsx index 75653b248f2..bf75ad39fcf 100644 --- a/packages/terra-avatar/src/terra-dev-site/doc/example/avatar/AvatarIsDeceased.jsx +++ b/packages/terra-avatar/src/terra-dev-site/doc/example/avatar/AvatarIsDeceased.jsx @@ -2,7 +2,7 @@ import React from 'react'; import Avatar from 'terra-avatar'; const AvatarImage = () => ( - + ); export default AvatarImage; diff --git a/packages/terra-avatar/src/terra-dev-site/doc/example/avatar/AvatarSize.jsx b/packages/terra-avatar/src/terra-dev-site/doc/example/avatar/AvatarSize.jsx index 40fc0284206..8a4f7dfdcc7 100644 --- a/packages/terra-avatar/src/terra-dev-site/doc/example/avatar/AvatarSize.jsx +++ b/packages/terra-avatar/src/terra-dev-site/doc/example/avatar/AvatarSize.jsx @@ -3,7 +3,7 @@ import Avatar from 'terra-avatar'; import exampleAvatarImage from '../../../assets/150x150.jpg'; const AvatarSize = () => ( - + ); export default AvatarSize; diff --git a/packages/terra-avatar/src/terra-dev-site/doc/example/avatar/AvatarUser.jsx b/packages/terra-avatar/src/terra-dev-site/doc/example/avatar/AvatarUser.jsx index c0633b8d86c..d764f82d0c3 100644 --- a/packages/terra-avatar/src/terra-dev-site/doc/example/avatar/AvatarUser.jsx +++ b/packages/terra-avatar/src/terra-dev-site/doc/example/avatar/AvatarUser.jsx @@ -2,7 +2,7 @@ import React from 'react'; import Avatar from 'terra-avatar'; const AvatarUser = () => ( - + ); export default AvatarUser; diff --git a/packages/terra-avatar/src/terra-dev-site/test/avatar/avatar/ImageAvatar.test.jsx b/packages/terra-avatar/src/terra-dev-site/test/avatar/avatar/ImageAvatar.test.jsx index 688bb1d46a0..1e654d6857f 100644 --- a/packages/terra-avatar/src/terra-dev-site/test/avatar/avatar/ImageAvatar.test.jsx +++ b/packages/terra-avatar/src/terra-dev-site/test/avatar/avatar/ImageAvatar.test.jsx @@ -2,4 +2,4 @@ import React from 'react'; import Avatar from '../../../../index'; import exampleAvatarImage from '../../../assets/150x150.jpg'; -export default () => ; +export default () => ; diff --git a/packages/terra-avatar/src/terra-dev-site/test/avatar/avatar/ImageAvatarShortAndWide.test.jsx b/packages/terra-avatar/src/terra-dev-site/test/avatar/avatar/ImageAvatarShortAndWide.test.jsx index 6b30dfbf3a9..022d08abf28 100644 --- a/packages/terra-avatar/src/terra-dev-site/test/avatar/avatar/ImageAvatarShortAndWide.test.jsx +++ b/packages/terra-avatar/src/terra-dev-site/test/avatar/avatar/ImageAvatarShortAndWide.test.jsx @@ -2,4 +2,4 @@ import React from 'react'; import Avatar from '../../../../index'; import exampleAvatarImage from '../../../assets/200x133.jpg'; -export default () => ; +export default () => ; diff --git a/packages/terra-avatar/src/terra-dev-site/test/avatar/avatar/ImageAvatarTallAndNarrow.test.jsx b/packages/terra-avatar/src/terra-dev-site/test/avatar/avatar/ImageAvatarTallAndNarrow.test.jsx index a07211513ea..3c3bc988f42 100644 --- a/packages/terra-avatar/src/terra-dev-site/test/avatar/avatar/ImageAvatarTallAndNarrow.test.jsx +++ b/packages/terra-avatar/src/terra-dev-site/test/avatar/avatar/ImageAvatarTallAndNarrow.test.jsx @@ -2,4 +2,4 @@ import React from 'react'; import Avatar from '../../../../index'; import exampleAvatarImage from '../../../assets/170x251.jpg'; -export default () => ; +export default () => ; diff --git a/packages/terra-avatar/src/terra-dev-site/test/avatar/avatar/ImageGap.test.jsx b/packages/terra-avatar/src/terra-dev-site/test/avatar/avatar/ImageGap.test.jsx index c36b2db2cdb..bbdfd11570c 100644 --- a/packages/terra-avatar/src/terra-dev-site/test/avatar/avatar/ImageGap.test.jsx +++ b/packages/terra-avatar/src/terra-dev-site/test/avatar/avatar/ImageGap.test.jsx @@ -9,7 +9,7 @@ const cx = classNames.bind(styles); export default () => (
- +
diff --git a/packages/terra-avatar/src/terra-dev-site/test/avatar/avatar/InvalidImageAvatar.test.jsx b/packages/terra-avatar/src/terra-dev-site/test/avatar/avatar/InvalidImageAvatar.test.jsx deleted file mode 100644 index 41b5c6d01f5..00000000000 --- a/packages/terra-avatar/src/terra-dev-site/test/avatar/avatar/InvalidImageAvatar.test.jsx +++ /dev/null @@ -1,4 +0,0 @@ -import React from 'react'; -import Avatar from '../../../../index'; - -export default () => ; diff --git a/packages/terra-avatar/src/terra-dev-site/test/avatar/avatar/InvalidImageAvatarWithInitials.test.jsx b/packages/terra-avatar/src/terra-dev-site/test/avatar/avatar/InvalidImageAvatarWithInitials.test.jsx new file mode 100644 index 00000000000..9f35722dfae --- /dev/null +++ b/packages/terra-avatar/src/terra-dev-site/test/avatar/avatar/InvalidImageAvatarWithInitials.test.jsx @@ -0,0 +1,4 @@ +import React from 'react'; +import Avatar from '../../../../index'; + +export default () => ; diff --git a/packages/terra-avatar/src/terra-dev-site/test/avatar/avatar/IsDeceasedAvatar.test.jsx b/packages/terra-avatar/src/terra-dev-site/test/avatar/avatar/IsDeceasedAvatar.test.jsx index 43f1db4f6fe..ffcdc904e4d 100644 --- a/packages/terra-avatar/src/terra-dev-site/test/avatar/avatar/IsDeceasedAvatar.test.jsx +++ b/packages/terra-avatar/src/terra-dev-site/test/avatar/avatar/IsDeceasedAvatar.test.jsx @@ -1,4 +1,4 @@ import React from 'react'; import Avatar from '../../../../index'; -export default () => ; +export default () => ; diff --git a/packages/terra-avatar/src/terra-dev-site/test/avatar/avatar/IsDeceasedImageAvatar.test.jsx b/packages/terra-avatar/src/terra-dev-site/test/avatar/avatar/IsDeceasedImageAvatar.test.jsx index f9191cad428..47037f2ad6a 100644 --- a/packages/terra-avatar/src/terra-dev-site/test/avatar/avatar/IsDeceasedImageAvatar.test.jsx +++ b/packages/terra-avatar/src/terra-dev-site/test/avatar/avatar/IsDeceasedImageAvatar.test.jsx @@ -2,4 +2,4 @@ import React from 'react'; import Avatar from '../../../../index'; import exampleAvatarImage from '../../../assets/150x150.jpg'; -export default () => ; +export default () => ; diff --git a/packages/terra-avatar/src/terra-dev-site/test/avatar/avatar/OneInitialAvatar.test.jsx b/packages/terra-avatar/src/terra-dev-site/test/avatar/avatar/OneInitialAvatar.test.jsx index 125722dfad1..a57d41d89cd 100644 --- a/packages/terra-avatar/src/terra-dev-site/test/avatar/avatar/OneInitialAvatar.test.jsx +++ b/packages/terra-avatar/src/terra-dev-site/test/avatar/avatar/OneInitialAvatar.test.jsx @@ -1,4 +1,4 @@ import React from 'react'; import Avatar from '../../../../index'; -export default () => ; +export default () => ; diff --git a/packages/terra-avatar/src/terra-dev-site/test/avatar/avatar/TwoInitialsAvatar.test.jsx b/packages/terra-avatar/src/terra-dev-site/test/avatar/avatar/TwoInitialsAvatar.test.jsx index e1f8b95f0dc..aeba06a2e34 100644 --- a/packages/terra-avatar/src/terra-dev-site/test/avatar/avatar/TwoInitialsAvatar.test.jsx +++ b/packages/terra-avatar/src/terra-dev-site/test/avatar/avatar/TwoInitialsAvatar.test.jsx @@ -1,4 +1,4 @@ import React from 'react'; import Avatar from '../../../../index'; -export default () => ; +export default () => ; diff --git a/packages/terra-avatar/src/terra-dev-site/test/avatar/avatar/UserAvatar.test.jsx b/packages/terra-avatar/src/terra-dev-site/test/avatar/avatar/UserAvatar.test.jsx deleted file mode 100644 index 7332758ffa8..00000000000 --- a/packages/terra-avatar/src/terra-dev-site/test/avatar/avatar/UserAvatar.test.jsx +++ /dev/null @@ -1,4 +0,0 @@ -import React from 'react'; -import Avatar from '../../../../index'; - -export default () => ; diff --git a/packages/terra-avatar/src/variants/Avatar.jsx b/packages/terra-avatar/src/variants/Avatar.jsx index 6bad5a3fd11..7288f2d4eae 100644 --- a/packages/terra-avatar/src/variants/Avatar.jsx +++ b/packages/terra-avatar/src/variants/Avatar.jsx @@ -3,7 +3,7 @@ import PropTypes from 'prop-types'; import classNames from 'classnames/bind'; import styles from '../common/Avatar.module.scss'; import { - AVATAR_VARIANTS, generateImagePlaceholder, generateImage, setColor, + AVATAR_VARIANTS, generateInitials, generateImage, setColor, } from '../common/AvatarUtils'; const cx = classNames.bind(styles); @@ -30,7 +30,7 @@ const propTypes = { /** * One or two letters to display. */ - initials: PropTypes.string, + initials: PropTypes.string.isRequired, /** * Whether to hide avatar from the accessibility tree. */ @@ -49,7 +49,6 @@ const defaultProps = { color: 'auto', hashValue: undefined, image: undefined, - initials: undefined, isAriaHidden: false, isDeceased: false, size: undefined, @@ -84,14 +83,19 @@ class Avatar extends React.Component { } = this.props; let avatarContent; + const avatarParams = { + image, + alt, + isAriaHidden, + variant: AVATAR_VARIANTS.USER, + handleFallback: this.handleFallback, + initials: (initials.length > 2) ? initials.slice(0, 2) : initials, + }; if (image) { - avatarContent = generateImage(image, alt, isAriaHidden, AVATAR_VARIANTS.USER, this.handleFallback); - } else if (initials && (initials.length === 1 || initials.length === 2)) { - const avatarTextClassNames = cx('initials'); - avatarContent = {initials.toUpperCase()}; + avatarContent = generateImage(avatarParams); } else { - avatarContent = generateImagePlaceholder(alt, isAriaHidden, AVATAR_VARIANTS.USER); + avatarContent = generateInitials(avatarParams); } const attributes = { ...customProps }; diff --git a/packages/terra-avatar/src/variants/Facility.jsx b/packages/terra-avatar/src/variants/Facility.jsx index 32c982981ec..2cbc116d6d7 100644 --- a/packages/terra-avatar/src/variants/Facility.jsx +++ b/packages/terra-avatar/src/variants/Facility.jsx @@ -73,10 +73,18 @@ class Facility extends React.Component { let facilityContent; + const facilityParams = { + image, + alt, + isAriaHidden, + variant: AVATAR_VARIANTS.FACILITY, + handleFallback: this.handleFallback, + }; + if (image) { - facilityContent = generateImage(image, alt, isAriaHidden, AVATAR_VARIANTS.FACILITY, this.handleFallback); + facilityContent = generateImage(facilityParams); } else { - facilityContent = generateImagePlaceholder(alt, isAriaHidden, AVATAR_VARIANTS.FACILITY); + facilityContent = generateImagePlaceholder(facilityParams); } const attributes = { ...customProps }; const customStyles = size ? ({ fontSize: size, ...attributes.style }) : attributes.style; diff --git a/packages/terra-avatar/tests/jest/Avatar.test.jsx b/packages/terra-avatar/tests/jest/Avatar.test.jsx index e57a993c73d..042c4e8f00b 100644 --- a/packages/terra-avatar/tests/jest/Avatar.test.jsx +++ b/packages/terra-avatar/tests/jest/Avatar.test.jsx @@ -5,7 +5,7 @@ import exampleProfilePhoto from '../../src/terra-dev-site/assets/150x150.jpg'; describe('Avatar', () => { // Snapshot Tests it('should render a default avatar', () => { - const avatar = ; + const avatar = ; const wrapper = render(avatar); expect(wrapper).toMatchSnapshot(); }); @@ -22,26 +22,26 @@ describe('Avatar', () => { expect(wrapper).toMatchSnapshot(); }); - it('should render fallback user avatar when more than two initials are passed in', () => { + it('should render two initials avatar when more than two initials are passed in', () => { const avatar = ; const wrapper = render(avatar); expect(wrapper).toMatchSnapshot(); }); it('should render image avatar when image is passed in', () => { - const avatar = ; + const avatar = ; const wrapper = render(avatar); expect(wrapper).toMatchSnapshot(); }); - it('should render fallback user avatar when invalid image is passed in', () => { - const avatar = ; + it('should render fallback initials when invalid image is passed in with initials', () => { + const avatar = ; const wrapper = render(avatar); expect(wrapper).toMatchSnapshot(); }); it('should render an avatar with provided size', () => { - const avatar = ; + const avatar = ; const wrapper = render(avatar); expect(wrapper).toMatchSnapshot(); }); @@ -53,31 +53,31 @@ describe('Avatar', () => { }); it('should render an avatar with color variant one', () => { - const avatar = ; + const avatar = ; const wrapper = render(avatar); expect(wrapper).toMatchSnapshot(); }); it('should render an avatar with color variant netural', () => { - const avatar = ; + const avatar = ; const wrapper = render(avatar); expect(wrapper).toMatchSnapshot(); }); it('should render an avatar with an automated color variant, based on a hashValue', () => { - const avatar = ; + const avatar = ; const wrapper = render(avatar); expect(wrapper).toMatchSnapshot(); }); it('should render an isDeceased avatar', () => { - const avatar = ; + const avatar = ; const wrapper = render(avatar); expect(wrapper).toMatchSnapshot(); }); it('should render an avatar with custom props', () => { - const avatar = ; + const avatar = ; const wrapper = render(avatar); expect(wrapper).toMatchSnapshot(); }); diff --git a/packages/terra-avatar/tests/jest/__snapshots__/Avatar.test.jsx.snap b/packages/terra-avatar/tests/jest/__snapshots__/Avatar.test.jsx.snap index 609db4b7409..a69b0de6d9e 100644 --- a/packages/terra-avatar/tests/jest/__snapshots__/Avatar.test.jsx.snap +++ b/packages/terra-avatar/tests/jest/__snapshots__/Avatar.test.jsx.snap @@ -8,9 +8,11 @@ exports[`Avatar should render a default avatar 1`] = ` alt="user" aria-hidden="false" aria-label="user" - class="icon user" + class="initials" role="img" - /> + > + JS +
`; @@ -22,9 +24,11 @@ exports[`Avatar should render an avatar with an automated color variant, based o alt="user" aria-hidden="false" aria-label="user" - class="icon user" + class="initials" role="img" - /> + > + JS +
`; @@ -36,9 +40,11 @@ exports[`Avatar should render an avatar with color variant netural 1`] = ` alt="user" aria-hidden="false" aria-label="user" - class="icon user" + class="initials" role="img" - /> + > + JS +
`; @@ -50,9 +56,11 @@ exports[`Avatar should render an avatar with color variant one 1`] = ` alt="user" aria-hidden="false" aria-label="user" - class="icon user" + class="initials" role="img" - /> + > + JS + `; @@ -65,9 +73,11 @@ exports[`Avatar should render an avatar with custom props 1`] = ` alt="user" aria-hidden="false" aria-label="user" - class="icon user" + class="initials" role="img" - /> + > + JS + `; @@ -80,6 +90,7 @@ exports[`Avatar should render an avatar with initials and aria hidden 1`] = ` aria-hidden="true" aria-label="user" class="initials" + role="img" > JJ @@ -95,9 +106,11 @@ exports[`Avatar should render an avatar with provided size 1`] = ` alt="user" aria-hidden="false" aria-label="user" - class="icon user" + class="initials" role="img" - /> + > + JS + `; @@ -109,13 +122,15 @@ exports[`Avatar should render an isDeceased avatar 1`] = ` alt="user" aria-hidden="false" aria-label="user" - class="icon user" + class="initials" role="img" - /> + > + JS + `; -exports[`Avatar should render fallback user avatar when invalid image is passed in 1`] = ` +exports[`Avatar should render fallback initials when invalid image is passed in with initials 1`] = `
@@ -128,23 +143,11 @@ exports[`Avatar should render fallback user avatar when invalid image is passed alt="placeholder" aria-hidden="false" aria-label="placeholder" - class="icon user" - role="img" - /> -
-`; - -exports[`Avatar should render fallback user avatar when more than two initials are passed in 1`] = ` -
- + > + JD +
`; @@ -161,9 +164,11 @@ exports[`Avatar should render image avatar when image is passed in 1`] = ` alt="placeholder" aria-hidden="false" aria-label="placeholder" - class="icon user" + class="initials" role="img" - /> + > + JS + `; @@ -176,12 +181,29 @@ exports[`Avatar should render one initial avatar when one initial is passed in 1 aria-hidden="false" aria-label="user" class="initials" + role="img" > J `; +exports[`Avatar should render two initials avatar when more than two initials are passed in 1`] = ` +
+ + JJ + +
+`; + exports[`Avatar should render two initials avatar when two initials are passed in 1`] = `