- Notifications
You must be signed in to change notification settings - Fork1k
fix: correct markup for Abbr component#19317
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Uh oh!
There was an error while loading.Please reload this page.
Changes fromall commits
9a94037
c8f38e0
0a076c7
c69b449
2169a7b
8023039
File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading.Please reload this page.
Jump to
Uh oh!
There was an error while loading.Please reload this page.
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,34 +1,14 @@ | ||
import { render, screen } from "@testing-library/react"; | ||
import { Abbr } from "./Abbr"; | ||
type AbbreviationData = { | ||
abbreviation: string; | ||
title: string; | ||
expectedLabel: string; | ||
}; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others.Learn more. Got rid of the test helper because it felt like we were binding all our tests to a shallow abstraction | ||
describe(Abbr.name, () => { | ||
it("Omits abbreviation from screen-reader outputifit is shorthand", () => { | ||
const sampleShorthands: AbbreviationData[] = [ | ||
{ | ||
abbreviation: "ms", | ||
@@ -43,11 +23,22 @@ describe(Abbr.name, () => { | ||
]; | ||
for (const shorthand of sampleShorthands) { | ||
const { unmount } = render( | ||
<Abbr title={shorthand.title} pronunciation="shorthand"> | ||
{shorthand.abbreviation} | ||
</Abbr>, | ||
); | ||
// The <abbr> element doesn't have any ARIA role semantics baked in, | ||
// so we have to get a little bit more creative with making sure the | ||
// expected content is on screen in an accessible way | ||
const element = screen.getByTitle(shorthand.title); | ||
expect(element).toHaveTextContent(shorthand.expectedLabel); | ||
unmount(); | ||
} | ||
}); | ||
it("Adds title and 'flattened' pronunciation if abbreviation is acronym", () => { | ||
const sampleAcronyms: AbbreviationData[] = [ | ||
{ | ||
abbreviation: "NASA", | ||
@@ -67,11 +58,19 @@ describe(Abbr.name, () => { | ||
]; | ||
for (const acronym of sampleAcronyms) { | ||
const { unmount } = render( | ||
<Abbr title={acronym.title} pronunciation="acronym"> | ||
{acronym.abbreviation} | ||
</Abbr>, | ||
); | ||
const element = screen.getByTitle(acronym.title); | ||
expect(element).toHaveTextContent(acronym.expectedLabel); | ||
unmount(); | ||
} | ||
}); | ||
it("Adds title and initialized pronunciation if abbreviation is initialism", () => { | ||
const sampleInitialisms: AbbreviationData[] = [ | ||
{ | ||
abbreviation: "FBI", | ||
@@ -91,7 +90,15 @@ describe(Abbr.name, () => { | ||
]; | ||
for (const initialism of sampleInitialisms) { | ||
const { unmount } = render( | ||
<Abbr title={initialism.title} pronunciation="initialism"> | ||
{initialism.abbreviation} | ||
</Abbr>, | ||
); | ||
const element = screen.getByTitle(initialism.title); | ||
expect(element).toHaveTextContent(initialism.expectedLabel); | ||
unmount(); | ||
} | ||
}); | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,13 @@ | ||
import type { FC, HTMLAttributes } from "react"; | ||
import { cn } from "utils/cn"; | ||
type Pronunciation = "shorthand" | "acronym" | "initialism"; | ||
type AbbrProps = HTMLAttributes<HTMLElement> & { | ||
children: string; | ||
title: string; | ||
pronunciation?: Pronunciation; | ||
className?: string; | ||
}; | ||
/** | ||
@@ -22,23 +23,26 @@ export const Abbr: FC<AbbrProps> = ({ | ||
children, | ||
title, | ||
pronunciation = "shorthand", | ||
className, | ||
...delegatedProps | ||
}) => { | ||
return ( | ||
<abbr | ||
// Adding title to make things a little easier for sighted users, | ||
// but titles aren't always exposed via screen readers. Still have | ||
// to inject the actual text content inside the abbr itself | ||
title={title} | ||
className={cn( | ||
"no-underline tracking-normal", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others.Learn more. I wish we understood where the underline is coming from. these kinds of conflicts are so annoying. can we at least add a TODO to clean this up one day? MemberAuthor
| ||
children === children.toUpperCase() && "tracking-wide", | ||
className, | ||
)} | ||
{...delegatedProps} | ||
> | ||
<span aria-hidden>{children}</span> | ||
<span className="sr-only"> | ||
{getAccessibleLabel(children, title, pronunciation)} | ||
</span> | ||
</abbr> | ||
); | ||
}; | ||
Uh oh!
There was an error while loading.Please reload this page.