Skip to content

Commit a9ba745

Browse files
author
Olayinka Adelakun
committed
fix(playground): add accessible names to icon-only controls and fix invalid ARIA on animated/status elements
1 parent 43f52df commit a9ba745

15 files changed

Lines changed: 548 additions & 8 deletions

File tree

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { render, screen } from "@testing-library/react";
2+
import { axe } from "jest-axe";
3+
import { ThemeButtons } from "..";
4+
5+
describe("ThemeButtons accessibility", () => {
6+
it("has no detectable axe violations", async () => {
7+
const { container } = render(<ThemeButtons />);
8+
9+
const results = await axe(container);
10+
11+
expect(results).toHaveNoViolations();
12+
});
13+
14+
it("names the light, dark, and system theme buttons", () => {
15+
render(<ThemeButtons />);
16+
17+
expect(
18+
screen.getByRole("button", { name: "Light theme" }),
19+
).toBeInTheDocument();
20+
expect(
21+
screen.getByRole("button", { name: "Dark theme" }),
22+
).toBeInTheDocument();
23+
expect(
24+
screen.getByRole("button", { name: "System theme" }),
25+
).toBeInTheDocument();
26+
});
27+
});

src/frontend/src/components/core/appHeaderComponent/components/ThemeButtons/index.tsx

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import { useEffect, useState } from "react";
2+
import { useTranslation } from "react-i18next";
23
import ForwardedIconComponent from "@/components/common/genericIconComponent";
34
import { Button } from "@/components/ui/button";
45
import useTheme from "@/customization/hooks/use-custom-theme";
56

67
export const ThemeButtons = () => {
8+
const { t } = useTranslation();
79
const { systemTheme, dark, setThemePreference } = useTheme();
810
const [selectedTheme, setSelectedTheme] = useState(
911
systemTheme ? "system" : dark ? "dark" : "light",
@@ -59,8 +61,14 @@ export const ThemeButtons = () => {
5961
onClick={() => handleThemeChange("light")}
6062
data-testid="menu_light_button"
6163
id="menu_light_button"
64+
aria-label={t("theme.light")}
6265
>
63-
<ForwardedIconComponent strokeWidth={2} name="Sun" className="w-4" />
66+
<ForwardedIconComponent
67+
strokeWidth={2}
68+
name="Sun"
69+
className="w-4"
70+
aria-hidden="true"
71+
/>
6472
</Button>
6573

6674
{/* Dark Theme Button */}
@@ -74,8 +82,14 @@ export const ThemeButtons = () => {
7482
onClick={() => handleThemeChange("dark")}
7583
data-testid="menu_dark_button"
7684
id="menu_dark_button"
85+
aria-label={t("theme.dark")}
7786
>
78-
<ForwardedIconComponent strokeWidth={2} name="Moon" className="w-4" />
87+
<ForwardedIconComponent
88+
strokeWidth={2}
89+
name="Moon"
90+
className="w-4"
91+
aria-hidden="true"
92+
/>
7993
</Button>
8094

8195
{/* System Theme Button */}
@@ -89,11 +103,13 @@ export const ThemeButtons = () => {
89103
onClick={() => handleThemeChange("system")}
90104
data-testid="menu_system_button"
91105
id="menu_system_button"
106+
aria-label={t("theme.system")}
92107
>
93108
<ForwardedIconComponent
94109
name="Monitor"
95110
className="w-4"
96111
strokeWidth={2}
112+
aria-hidden="true"
97113
/>
98114
</Button>
99115
</div>
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { render, screen } from "@testing-library/react";
2+
import { axe } from "jest-axe";
3+
import { TextEffectPerChar } from "../textAnimation";
4+
5+
describe("TextEffectPerChar accessibility", () => {
6+
it("has no detectable axe violations", async () => {
7+
const { container } = render(
8+
<TextEffectPerChar>Test your flow with a chat prompt</TextEffectPerChar>,
9+
);
10+
11+
const results = await axe(container);
12+
13+
expect(results).toHaveNoViolations();
14+
});
15+
16+
it("exposes the full string as one accessible name via role=img", () => {
17+
render(
18+
<TextEffectPerChar>Test your flow with a chat prompt</TextEffectPerChar>,
19+
);
20+
21+
expect(
22+
screen.getByRole("img", { name: "Test your flow with a chat prompt" }),
23+
).toBeInTheDocument();
24+
});
25+
});

src/frontend/src/components/ui/textAnimation.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ export function TextEffect({
197197
initial="hidden"
198198
animate="visible"
199199
exit="exit"
200-
aria-label={ariaLabel}
200+
{...(ariaLabel ? { role: "img", "aria-label": ariaLabel } : {})}
201201
variants={delayedContainerVariants}
202202
className={cn("whitespace-pre-wrap", className)}
203203
onAnimationComplete={onAnimationComplete}

src/frontend/src/locales/de.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,8 +219,10 @@
219219
"canvas.zoomTo100": "Auf 100 % vergrößern",
220220
"canvas.zoomToFit": "Auf Bildschirm anpassen",
221221
"chat.attachFileTooltip": "Datei anhängen (Bilder, PDF, CSV, DOCX, TXT, MD, JSON, YAML, XML, HTML, Quellcode-Dateien)",
222+
"chat.cancelRename": "Umbenennen abbrechen",
222223
"chat.cannotOpenDescription": "Dies ist kein Chat-Ablauf.",
223224
"chat.cannotOpenTitle": "Der Chat lässt sich nicht öffnen",
225+
"chat.confirmRename": "Umbenennen bestätigen",
224226
"chat.copied": "Kopiert!",
225227
"chat.copyCode": "Copy code",
226228
"chat.copiedCode": "Code copied",
@@ -255,6 +257,7 @@
255257
"chat.outputLabel": "Ausgabe:",
256258
"chat.outputTokens": "Ausgabe-Token:",
257259
"chat.processingAudio": "Verarbeitung läuft...",
260+
"chat.renameSessionLabel": "Sitzungsname",
258261
"chat.runningStatus": "aktiv...",
259262
"chat.secondInitialText": "um frühere Nachrichten anzusehen.",
260263
"chat.selectAll": "Alles auswählen",
@@ -1950,6 +1953,9 @@
19501953
"templatesModal.title": "Vorlagen",
19511954
"templatesModal.tryDifferentQuery": "und versuchen Sie es mit einer anderen Abfrage.",
19521955
"templatesModal.useCases": "Anwendungsfälle",
1956+
"theme.dark": "Dunkles Motiv",
1957+
"theme.light": "Helles Motiv",
1958+
"theme.system": "System-Motiv",
19531959
"toolsModal.actionDescriptionHint": "Dies ist die Beschreibung des Tools, die dem Kunden angezeigt wird.",
19541960
"toolsModal.actionSlugHint": "Wird als Funktionsname verwendet, wenn dieser Ablauf für Kunden zugänglich gemacht wird.",
19551961
"toolsModal.close": "Schließen",

src/frontend/src/locales/en.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1543,6 +1543,12 @@
15431543
"header.goToDiscord": "Go to Discord server",
15441544
"misc.addChatInputOutputPlayground": "Add a Chat Input or Chat Output to use the playground",
15451545
"chat.options": "Options",
1546+
"chat.cancelRename": "Cancel rename",
1547+
"chat.confirmRename": "Confirm rename",
1548+
"chat.renameSessionLabel": "Session name",
1549+
"theme.light": "Light theme",
1550+
"theme.dark": "Dark theme",
1551+
"theme.system": "System theme",
15461552
"chat.editMessage": "Edit message",
15471553
"chat.copied": "Copied!",
15481554
"chat.copyCode": "Copy code",

src/frontend/src/locales/es.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,8 +219,10 @@
219219
"canvas.zoomTo100": "Ampliar al 100 %",
220220
"canvas.zoomToFit": "Ajustar a la pantalla",
221221
"chat.attachFileTooltip": "Adjuntar archivo (imágenes, PDF, CSV, DOCX, TXT, MD, JSON, YAML, XML, HTML, archivos de código)",
222+
"chat.cancelRename": "Cancelar cambio de nombre",
222223
"chat.cannotOpenDescription": "Esto no es un flujo de chat.",
223224
"chat.cannotOpenTitle": "No se puede abrir el chat",
225+
"chat.confirmRename": "Confirmar cambio de nombre",
224226
"chat.copied": "Copiado",
225227
"chat.copyCode": "Copy code",
226228
"chat.copiedCode": "Code copied",
@@ -255,6 +257,7 @@
255257
"chat.outputLabel": "Salida:",
256258
"chat.outputTokens": "Tokens de salida:",
257259
"chat.processingAudio": "Procesando...",
260+
"chat.renameSessionLabel": "Nombre de la sesión",
258261
"chat.runningStatus": "En ejecución...",
259262
"chat.secondInitialText": "para consultar los mensajes anteriores.",
260263
"chat.selectAll": "Seleccionar todo",
@@ -1950,6 +1953,9 @@
19501953
"templatesModal.title": "Plantillas",
19511954
"templatesModal.tryDifferentQuery": "y prueba con otra consulta.",
19521955
"templatesModal.useCases": "Casos de uso",
1956+
"theme.dark": "Tema oscuro",
1957+
"theme.light": "Tema claro",
1958+
"theme.system": "Tema del sistema",
19531959
"toolsModal.actionDescriptionHint": "Esta es la descripción de la herramienta que se muestra al cliente.",
19541960
"toolsModal.actionSlugHint": "Se utiliza como nombre de la función cuando este flujo se pone a disposición de los clientes.",
19551961
"toolsModal.close": "Cerrar",

src/frontend/src/locales/fr.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,8 +219,10 @@
219219
"canvas.zoomTo100": "Agrandir à 100 %",
220220
"canvas.zoomToFit": "Ajustement à l'écran",
221221
"chat.attachFileTooltip": "Joindre un fichier (images, PDF, CSV, DOCX, TXT, MD, JSON, YAML, XML, HTML, fichiers de code)",
222+
"chat.cancelRename": "Annuler le renommage",
222223
"chat.cannotOpenDescription": "Ce n'est pas un flux de conversation.",
223224
"chat.cannotOpenTitle": "Impossible d'ouvrir la discussion",
225+
"chat.confirmRename": "Confirmer le renommage",
224226
"chat.copied": "Copié",
225227
"chat.copyCode": "Copy code",
226228
"chat.copiedCode": "Code copied",
@@ -255,6 +257,7 @@
255257
"chat.outputLabel": "Sortie :",
256258
"chat.outputTokens": "Jetons de sortie :",
257259
"chat.processingAudio": "Traitement en cours...",
260+
"chat.renameSessionLabel": "Nom de la session",
258261
"chat.runningStatus": "Exécution en cours...",
259262
"chat.secondInitialText": "pour consulter les messages précédents.",
260263
"chat.selectAll": "Tout sélectionner",
@@ -1950,6 +1953,9 @@
19501953
"templatesModal.title": "Modèles",
19511954
"templatesModal.tryDifferentQuery": "et essayez une autre requête.",
19521955
"templatesModal.useCases": "Cas d'usage",
1956+
"theme.dark": "Thème sombre",
1957+
"theme.light": "Thème clair",
1958+
"theme.system": "Thème système",
19531959
"toolsModal.actionDescriptionHint": "Voici la description de l'outil telle qu'elle est présentée au client.",
19541960
"toolsModal.actionSlugHint": "Utilisé comme nom de fonction lorsque ce flux est mis à la disposition des clients.",
19551961
"toolsModal.close": "Fermer",

src/frontend/src/locales/ja.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,8 +219,10 @@
219219
"canvas.zoomTo100": "100%に拡大",
220220
"canvas.zoomToFit": "画面に合わせる",
221221
"chat.attachFileTooltip": "ファイルを添付する(画像、PDF、CSV、DOCX、TXT、MD、JSON、YAML、XML、HTML、コードファイル)",
222+
"chat.cancelRename": "名前変更をキャンセル",
222223
"chat.cannotOpenDescription": "これはチャットフローではありません。",
223224
"chat.cannotOpenTitle": "チャットが開けません",
225+
"chat.confirmRename": "名前変更を確定",
224226
"chat.copied": "コピーされました",
225227
"chat.copyCode": "Copy code",
226228
"chat.copiedCode": "Code copied",
@@ -255,6 +257,7 @@
255257
"chat.outputLabel": "出力:",
256258
"chat.outputTokens": "出力トークン:",
257259
"chat.processingAudio": "処理中...",
260+
"chat.renameSessionLabel": "セッション名",
258261
"chat.runningStatus": "実行中...",
259262
"chat.secondInitialText": "過去のメッセージを確認するには。",
260263
"chat.selectAll": "すべて選択",
@@ -1950,6 +1953,9 @@
19501953
"templatesModal.title": "テンプレート",
19511954
"templatesModal.tryDifferentQuery": "別のクエリを試してみてください。",
19521955
"templatesModal.useCases": "ユースケース",
1956+
"theme.dark": "ダークテーマ",
1957+
"theme.light": "ライトテーマ",
1958+
"theme.system": "システムテーマ",
19531959
"toolsModal.actionDescriptionHint": "これは、クライアントに公開されるツールの説明です。",
19541960
"toolsModal.actionSlugHint": "このフローをクライアントに公開する際の関数名として使用されます。",
19551961
"toolsModal.close": "閉じる",

src/frontend/src/locales/pt.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,8 +219,10 @@
219219
"canvas.zoomTo100": "Ampliar para 100%",
220220
"canvas.zoomToFit": "Ajustar à tela",
221221
"chat.attachFileTooltip": "Anexar arquivo (imagens, PDF, CSV, DOCX, TXT, MD, JSON, YAML, XML, HTML, arquivos de código)",
222+
"chat.cancelRename": "Cancelar renomeação",
222223
"chat.cannotOpenDescription": "Isso não é um fluxo de chat.",
223224
"chat.cannotOpenTitle": "Não é possível abrir o chat",
225+
"chat.confirmRename": "Confirmar renomeação",
224226
"chat.copied": "Copiado!",
225227
"chat.copyCode": "Copy code",
226228
"chat.copiedCode": "Code copied",
@@ -255,6 +257,7 @@
255257
"chat.outputLabel": "Saída:",
256258
"chat.outputTokens": "Tokens de saída:",
257259
"chat.processingAudio": "Processando...",
260+
"chat.renameSessionLabel": "Nome da sessão",
258261
"chat.runningStatus": "Executando...",
259262
"chat.secondInitialText": "para verificar as mensagens anteriores.",
260263
"chat.selectAll": "Selecionar todos",
@@ -1950,6 +1953,9 @@
19501953
"templatesModal.title": "Modelos",
19511954
"templatesModal.tryDifferentQuery": "e tente uma consulta diferente.",
19521955
"templatesModal.useCases": "Casos de uso",
1956+
"theme.dark": "Tema escuro",
1957+
"theme.light": "Tema claro",
1958+
"theme.system": "Tema do sistema",
19531959
"toolsModal.actionDescriptionHint": "Esta é a descrição da ferramenta apresentada ao cliente.",
19541960
"toolsModal.actionSlugHint": "Usado como nome da função quando este fluxo é disponibilizado aos clientes.",
19551961
"toolsModal.close": "Fechar",

0 commit comments

Comments
 (0)