Skip to content

Commit

Permalink
feat(Avatar): allow control over alt text (#4939)
Browse files Browse the repository at this point in the history
* feat(Avatar): allow control over alt text

* Build out tests
  • Loading branch information
dougmacknz authored Aug 21, 2024
1 parent def3feb commit 9952feb
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 7 deletions.
5 changes: 5 additions & 0 deletions .changeset/silver-shirts-decide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@kaizen/components": minor
---

Avatar: allow control over alt property
63 changes: 63 additions & 0 deletions packages/components/src/Avatar/Avatar.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,67 @@ describe("<Avatar />", () => {
expect(screen.getByText("JWAVLN")).toBeInTheDocument()
})
})

describe("alt text", () => {
describe("providing alt text, overriding fullName", () => {
it("uses alt prop over full name when using initials", () => {
render(<Avatar fullName="Jane Doe" alt="alt override" />)
expect(screen.getByTitle("alt override")).toBeInTheDocument()
})

it("uses alt prop over full name when using fallback img", () => {
render(
<Avatar fullName="Jane Doe" alt="alt override" disableInitials />
)
expect(screen.getByRole("img")).toHaveAccessibleName("alt override")
})

it("uses alt prop over full name when supplying an img", () => {
render(
<Avatar
fullName="Jane Doe"
alt="alt override"
avatarSrc="https://www.cultureampcom-preview-1.usw2.wp-dev-us.cultureamp-cdn.com/assets/slices/main/assets/public/media/[email protected]"
/>
)
expect(screen.getByRole("img")).toHaveAccessibleName("alt override")
})
})

describe("providing fullName, no alt prop", () => {
it("uses the fullName when using initials", () => {
render(<Avatar fullName="Jane Doe" />)
expect(screen.getByTitle("Jane Doe")).toBeInTheDocument()
})

it("uses the fullName when using fallback img", () => {
render(<Avatar fullName="Jane Doe" disableInitials />)
expect(screen.getByRole("img")).toHaveAccessibleName("Jane Doe")
})

it("uses alt prop over full name when supplying an img", () => {
render(
<Avatar
fullName="Jane Doe"
avatarSrc="https://www.cultureampcom-preview-1.usw2.wp-dev-us.cultureamp-cdn.com/assets/slices/main/assets/public/media/[email protected]"
/>
)
expect(screen.getByRole("img")).toHaveAccessibleName("Jane Doe")
})
})

describe("not providing fullName or alt text", () => {
it("makes the img presentational on the fallback img", () => {
render(<Avatar />)
expect(screen.queryByRole("img")).not.toBeInTheDocument()
})

it("has blank alt text when img provided", () => {
render(
<Avatar avatarSrc="https://www.cultureampcom-preview-1.usw2.wp-dev-us.cultureamp-cdn.com/assets/slices/main/assets/public/media/[email protected]" />
)
expect(screen.queryByRole("img")).not.toBeInTheDocument()
})
})
})
})
22 changes: 15 additions & 7 deletions packages/components/src/Avatar/Avatar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ type BaseAvatarProps = {
* Renders Company Avatar variant - If true `fullName` and `avatarSrc` will be strictly typed.
*/
isCompany?: boolean
/**
* Control of the alt property on the img (or title when initials are rendered)
* Defaults to the fullName if provided, otherwise an empty string
*/
alt?: string
} & OverrideClassName<HTMLAttributes<HTMLSpanElement>>

export type GenericAvatarProps = BaseAvatarProps & {
Expand Down Expand Up @@ -71,16 +76,17 @@ const getMaxFontSizePixels: (size: AvatarSizes) => number = size => {
return 22
}

const fallbackIcon = (fullName: string): JSX.Element => {
if (fullName) {
return <UserIcon inheritSize role="img" aria-label={fullName} />
const fallbackIcon = (alt: string): JSX.Element => {
if (alt) {
return <UserIcon inheritSize role="img" aria-label={alt} />
}

return <UserIcon inheritSize role="presentation" />
}

const renderInitials = (
fullName = "",
alt: string,
size: AvatarSizes,
disableInitials = false
): JSX.Element => {
Expand All @@ -89,11 +95,11 @@ const renderInitials = (
const renderFallback = disableInitials || initials === ""

return renderFallback ? (
<span className={styles.fallbackIcon}>{fallbackIcon(fullName)}</span>
<span className={styles.fallbackIcon}>{fallbackIcon(alt)}</span>
) : (
<abbr
className={classnames(styles.initials, isLongName && styles.longName)}
title={fullName || ""}
title={alt}
>
{isLongName ? (
// Only called if 3 or more initials, fits text width for long names
Expand All @@ -118,6 +124,7 @@ export const Avatar = ({
disableInitials = false,
isCompany = false,
isCurrentUser = true,
alt = fullName || "",
classNameOverride,
...restProps
}: AvatarProps): JSX.Element => {
Expand Down Expand Up @@ -167,10 +174,11 @@ export const Avatar = ({
src={avatarSrc}
onError={onImageFailure}
onLoad={onImageSuccess}
alt={fullName || ""}
alt={alt}
/>
)}
{renderInitialAvatar && renderInitials(fullName, size, disableInitials)}
{renderInitialAvatar &&
renderInitials(fullName, alt, size, disableInitials)}
</span>
)
}

0 comments on commit 9952feb

Please sign in to comment.