Skip to content

Commit b6c344f

Browse files
improve flashcards for screenreaders
1 parent b13d57d commit b6c344f

File tree

2 files changed

+61
-50
lines changed

2 files changed

+61
-50
lines changed

src/bundles/AiDrawer/AiDrawerManager.test.tsx

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,6 @@ const trackingEvent = jest.fn()
6767
const assertTrackingEvent = (...data: unknown[]) => {
6868
expect(trackingEvent).toHaveBeenCalledTimes(data.length)
6969
data.forEach((eventData) => {
70-
console.log(eventData)
7170
expect(trackingEvent).toHaveBeenCalledWith(eventData)
7271
})
7372
trackingEvent.mockClear()
@@ -282,19 +281,25 @@ describe("AiDrawerManager", () => {
282281

283282
await user.click(screen.getByRole("tab", { name: "Flashcards" }))
284283

285-
await user.click(screen.getByText("Q: Test question 1?"))
284+
const q1 = screen.getByRole("button", {
285+
name: "Question: Test question 1?",
286+
})
287+
expect(q1).toHaveTextContent("Q: Test question 1?")
288+
await user.click(q1)
286289

287-
screen.getByText("Answer: Test answer 1")
290+
screen.getByRole("button", { name: "Answer: Test answer 1" })
288291

289292
await user.click(screen.getByRole("button", { name: "Next card" }))
290293

291-
await user.click(screen.getByText("Q: Test question 2?"))
294+
await user.click(
295+
screen.getByRole("button", { name: "Question: Test question 2?" }),
296+
)
292297

293-
screen.getByText("Answer: Test answer 2")
298+
screen.getByRole("button", { name: "Answer: Test answer 2" })
294299

295300
await user.click(screen.getByRole("button", { name: "Previous card" }))
296301

297-
screen.getByText("Q: Test question 1?")
302+
screen.getByRole("button", { name: "Question: Test question 1?" })
298303
}),
299304
)
300305

@@ -317,33 +322,33 @@ describe("AiDrawerManager", () => {
317322

318323
await user.click(screen.getByRole("tab", { name: "Flashcards" }))
319324

320-
screen.getByText("Q: Test question 1?")
325+
screen.getByRole("button", { name: "Question: Test question 1?" })
321326

322327
await user.keyboard("{enter}")
323328

324-
screen.getByText("Answer: Test answer 1")
329+
screen.getByRole("button", { name: "Answer: Test answer 1" })
325330

326331
await user.keyboard("{arrowright}")
327332

328-
screen.getByText("Q: Test question 2?")
333+
screen.getByRole("button", { name: "Question: Test question 2?" })
329334

330335
await user.keyboard("{enter}")
331336

332-
screen.getByText("Answer: Test answer 2")
337+
screen.getByRole("button", { name: "Answer: Test answer 2" })
333338

334339
await user.keyboard("{arrowleft}")
335340

336-
screen.getByText("Q: Test question 1?")
341+
screen.getByRole("button", { name: "Question: Test question 1?" })
337342

338343
await user.keyboard("{arrowleft}")
339344

340-
screen.getByText("Q: Test question 3?")
345+
screen.getByRole("button", { name: "Question: Test question 3?" })
341346

342347
await user.keyboard("{arrowright}")
343348
await user.keyboard("{arrowright}")
344349
await user.keyboard("{arrowright}")
345350

346-
screen.getByText("Q: Test question 3?")
351+
screen.getByRole("button", { name: "Question: Test question 3?" })
347352
}),
348353
)
349354

src/bundles/AiDrawer/FlashcardsScreen.tsx

Lines changed: 43 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,9 @@ export type Flashcard = {
1212

1313
const Container = styled.div``
1414

15-
const FlashcardContainer = styled.div(({ theme }) => ({
15+
const FlashcardContainer = styled.button(({ theme }) => ({
1616
display: "flex",
17+
width: "100%",
1718
height: 300,
1819
padding: 40,
1920
flexDirection: "column",
@@ -25,6 +26,7 @@ const FlashcardContainer = styled.div(({ theme }) => ({
2526
marginTop: "8px",
2627
cursor: "pointer",
2728
textAlign: "center",
29+
background: "none",
2830
}))
2931

3032
const Navigation = styled.div({
@@ -40,48 +42,54 @@ const Page = styled.div(({ theme }) => ({
4042
...theme.typography.body2,
4143
}))
4244

43-
const Flashcard = React.forwardRef<
44-
HTMLDivElement,
45-
{ content: Flashcard; "aria-label": string }
46-
>(({ content, "aria-label": ariaLabel }, ref) => {
47-
const [screen, setScreen] = useState<0 | 1>(0)
45+
const Flashcard = React.forwardRef<HTMLButtonElement, { content: Flashcard }>(
46+
({ content, ...others }, ref) => {
47+
const [screen, setScreen] = useState<0 | 1>(0)
4848

49-
useEffect(() => setScreen(0), [content])
49+
useEffect(() => setScreen(0), [content])
5050

51-
const handleKeyDown = (e: React.KeyboardEvent) => {
52-
if (e.key === "Enter" || e.key === " ") {
53-
setScreen(screen === 0 ? 1 : 0)
51+
const handleClick = () => {
52+
setScreen((current) => (current === 0 ? 1 : 0))
5453
}
55-
}
5654

57-
return (
58-
<FlashcardContainer
59-
ref={ref}
60-
onClick={() => setScreen(screen === 0 ? 1 : 0)}
61-
onKeyDown={handleKeyDown}
62-
tabIndex={0}
63-
aria-label={ariaLabel}
64-
role="button"
65-
>
66-
<Typography variant="h5">
67-
{screen === 0 ? `Q: ${content.question}` : `Answer: ${content.answer}`}
68-
</Typography>
69-
</FlashcardContainer>
70-
)
71-
})
55+
return (
56+
<FlashcardContainer
57+
ref={ref}
58+
type="button"
59+
onClick={handleClick}
60+
tabIndex={0}
61+
{...others}
62+
>
63+
<Typography variant="h5">
64+
{screen === 0 ? (
65+
<>
66+
<span aria-label="Question:">Q: </span>
67+
{content.question}
68+
</>
69+
) : (
70+
<>
71+
<span>Answer: </span>
72+
{content.answer}
73+
</>
74+
)}
75+
</Typography>
76+
</FlashcardContainer>
77+
)
78+
},
79+
)
7280

7381
Flashcard.displayName = "Flashcard"
7482

7583
export const FlashcardsScreen = ({
7684
flashcards,
7785
wasKeyboardFocus,
7886
}: {
79-
flashcards?: Flashcard[]
87+
flashcards: Flashcard[]
8088
wasKeyboardFocus: boolean
8189
}) => {
8290
const [cardIndex, setCardIndex] = useState(0)
8391
const containerRef = useRef<HTMLDivElement>(null)
84-
const flashcardRef = useRef<HTMLDivElement>(null)
92+
const flashcardRef = useRef<HTMLButtonElement>(null)
8593

8694
const handleKeyDown = useCallback(
8795
(e: KeyboardEvent) => {
@@ -112,17 +120,14 @@ export const FlashcardsScreen = ({
112120
return () => window.removeEventListener("keydown", handleKeyDown)
113121
}, [handleKeyDown])
114122

115-
if (!flashcards?.length) {
116-
return null
117-
}
118-
119123
return (
120124
<Container ref={containerRef}>
121-
<Flashcard
122-
ref={flashcardRef}
123-
content={flashcards[cardIndex]}
125+
<div
126+
role="region"
124127
aria-label={`Flashcard ${cardIndex + 1} of ${flashcards.length}`}
125-
/>
128+
>
129+
<Flashcard ref={flashcardRef} content={flashcards[cardIndex]} />
130+
</div>
126131
<Navigation>
127132
<ActionButton
128133
onClick={() => setCardIndex(cardIndex - 1)}
@@ -134,7 +139,8 @@ export const FlashcardsScreen = ({
134139
>
135140
<RiArrowLeftLine aria-hidden />
136141
</ActionButton>
137-
<Page>
142+
{/* Hide the index count here. It's used as a region label above. */}
143+
<Page aria-hidden>
138144
{cardIndex + 1} / {flashcards.length}
139145
</Page>
140146
<ActionButton

0 commit comments

Comments
 (0)