From 680a8c2a474ce0b5d95eece4f627713d43f26f8d Mon Sep 17 00:00:00 2001
From: Huyen Nguyen <25715018+huyenltnguyen@users.noreply.github.com>
Date: Fri, 30 Jan 2026 03:28:26 -0800
Subject: [PATCH] fix(client): a11y and styling issues in challenge transcript
(#65580)
---
.../components/challenge-transcript.css | 16 ++++---
.../components/challenge-transcript.test.tsx | 26 +++++++---
.../components/challenge-transcript.tsx | 24 ++++------
.../components/scene/scene-helpers.test.ts | 48 ++++++++++++-------
.../components/scene/scene-helpers.ts | 8 ++--
5 files changed, 71 insertions(+), 51 deletions(-)
diff --git a/client/src/templates/Challenges/components/challenge-transcript.css b/client/src/templates/Challenges/components/challenge-transcript.css
index 0bc2065418d..9a747a80b28 100644
--- a/client/src/templates/Challenges/components/challenge-transcript.css
+++ b/client/src/templates/Challenges/components/challenge-transcript.css
@@ -4,14 +4,16 @@
margin-top: 1.5em;
}
-#learn-app-wrapper .transcript-table {
- display: table;
- width: 100%;
- border: 1px solid var(--gray-05);
- border-collapse: collapse;
+.challenge-transcript .transcript-dialogue {
+ border: 1px solid var(--secondary-color);
}
-#learn-app-wrapper .transcript-table td {
- border: none;
+.challenge-transcript .transcript-dialogue p {
+ margin: 0;
+ padding: 6px 13px;
text-align: start;
}
+
+.challenge-transcript .transcript-dialogue p:nth-child(odd) {
+ background-color: var(--tertiary-background);
+}
diff --git a/client/src/templates/Challenges/components/challenge-transcript.test.tsx b/client/src/templates/Challenges/components/challenge-transcript.test.tsx
index 588af47d0e5..53d3c9c1876 100644
--- a/client/src/templates/Challenges/components/challenge-transcript.test.tsx
+++ b/client/src/templates/Challenges/components/challenge-transcript.test.tsx
@@ -59,21 +59,35 @@ describe('
Bob: World
'} shouldPersistExpanded={true} isDialogue={true} /> ); - const table = screen.getByRole('table'); - expect(table).toBeVisible(); - expect(screen.getByRole('cell', { name: 'Hello' })).toBeVisible(); - expect(screen.getByRole('cell', { name: 'World' })).toBeVisible(); + + /* eslint-disable testing-library/no-node-access */ + const aliceB = screen.getByText('Alice'); + expect(aliceB).toBeVisible(); + expect(aliceB.tagName).toBe('B'); + + const aliceP = aliceB.parentElement; + expect(aliceP?.tagName).toBe('P'); + expect(aliceP?.textContent).toBe('Alice: Hello'); + + const bobB = screen.getByText('Bob'); + expect(bobB).toBeVisible(); + expect(bobB.tagName).toBe('B'); + + const bobP = bobB.parentElement; + expect(bobP?.tagName).toBe('P'); + expect(bobP?.textContent).toBe('Bob: World'); + /* eslint-enable testing-library/no-node-access */ }); it('should render the transcript with PrismFormatted when isDialogue is false', () => { diff --git a/client/src/templates/Challenges/components/challenge-transcript.tsx b/client/src/templates/Challenges/components/challenge-transcript.tsx index d4670084bf4..5922e902c4e 100644 --- a/client/src/templates/Challenges/components/challenge-transcript.tsx +++ b/client/src/templates/Challenges/components/challenge-transcript.tsx @@ -36,7 +36,11 @@ function ChallengeTranscript({ return ( <> -| - |
Naomi: Hello world, I have 5 cats
'); }); it('should build transcript from multiple commands with dialogue', () => { @@ -56,9 +54,9 @@ describe('scene-helpers', () => { ]; const result = buildTranscript(commands); expect(result).toBe( - '\nNaomi: Hello\n' + - '\nQuincy: Hi there, I found 3 bugs\n' + - '\nNaomi: How are you?\n' + 'Naomi: Hello
' + + 'Quincy: Hi there, I found 3 bugs
' + + 'Naomi: How are you?
' ); }); @@ -88,8 +86,7 @@ describe('scene-helpers', () => { ]; const result = buildTranscript(commands); expect(result).toBe( - '\nNaomi: Hello\n' + - '\nNaomi: How are you?\n' + 'Naomi: Hello
' + 'Naomi: How are you?
' ); }); @@ -106,7 +103,7 @@ describe('scene-helpers', () => { ]; const result = buildTranscript(commands); expect(result).toBe( - '\nNaomi: He said "I love TypeScript!" & she replied, \'I prefer Ruby! #ruby #rubyonrails\'\n' + 'Naomi: He said "I love TypeScript!" & she replied, \'I prefer Ruby! #ruby #rubyonrails\'
' ); }); @@ -122,7 +119,7 @@ describe('scene-helpers', () => { } ]; const result = buildTranscript(commands); - expect(result).toBe('\nNaomi: \n'); + expect(result).toBe('Naomi:
'); }); it('should handle dialogue with newlines', () => { @@ -137,7 +134,7 @@ describe('scene-helpers', () => { } ]; const result = buildTranscript(commands); - expect(result).toBe('\nNaomi: Hello\nworld\n'); + expect(result).toBe('Naomi: Hello\nworld
'); }); it('should handle multiple consecutive commands from same character', () => { @@ -169,9 +166,9 @@ describe('scene-helpers', () => { ]; const result = buildTranscript(commands); expect(result).toBe( - '\nNaomi: First line\n' + - '\nNaomi: Second line\n' + - '\nNaomi: Third line\n' + 'Naomi: First line
' + + 'Naomi: Second line
' + + 'Naomi: Third line
' ); }); @@ -187,9 +184,7 @@ describe('scene-helpers', () => { } ]; const result = buildTranscript(commands); - expect(result).toBe( - '\nNaomi: UseNaomi: Use
Naomi: 你好,世界。
' ); }); + + it('should wrap dialogue lines in p tags and speakers in b tags', () => { + const commands: SceneCommand[] = [ + { + character: 'Alice', + startTime: 1, + dialogue: { + text: 'Hello', + align: 'left' + } + } + ]; + const result = buildTranscript(commands); + expect(result).toContain(''); + expect(result).toContain('
'); + expect(result).toContain('Alice'); + }); }); }); diff --git a/client/src/templates/Challenges/components/scene/scene-helpers.ts b/client/src/templates/Challenges/components/scene/scene-helpers.ts index 6902d6e9ea7..69a6042fad5 100644 --- a/client/src/templates/Challenges/components/scene/scene-helpers.ts +++ b/client/src/templates/Challenges/components/scene/scene-helpers.ts @@ -6,13 +6,11 @@ export const buildTranscript = (commands: SceneCommand[]): string => { if (command.character && command.dialogue && command.startTime) { transcriptText = transcriptText + - '\n' + - '' + + '' + command.character + - '
:' + - ' ' + + ': ' + command.dialogue.text + - '\n'; + ''; } });