From 676d297cb47f00e0c594ab384b316abc7d7af16a Mon Sep 17 00:00:00 2001 From: Danny Avila Date: Fri, 20 Mar 2026 16:53:26 -0400 Subject: [PATCH] =?UTF-8?q?=F0=9F=97=A3=EF=B8=8F=20a11y:=20Add=20Screen=20?= =?UTF-8?q?Reader=20Context=20to=20Conversation=20Date=20Group=20Headings?= =?UTF-8?q?=20(#12340)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: add screen reader-only context for convo date groupings Otherwise, the screen reader simply says something like "today" or "previous 7 days" without any other context, which is confusing (especially since this is a heading, so theoretically something you'd navigate to directly). Visually it's identical to before, but screen readers have added context now. * fix: move a11y key to com_a11y_* namespace and add DateLabel test Move screen-reader-only translation key from com_ui_* to com_a11y_* namespace where it belongs, and add test coverage to prevent silent accessibility regressions. --------- Co-authored-by: Dan Lew --- .../Conversations/Conversations.tsx | 4 ++ .../__tests__/DateLabel.test.tsx | 55 +++++++++++++++++++ client/src/locales/en/translation.json | 1 + 3 files changed, 60 insertions(+) create mode 100644 client/src/components/Conversations/__tests__/DateLabel.test.tsx diff --git a/client/src/components/Conversations/Conversations.tsx b/client/src/components/Conversations/Conversations.tsx index c7eb4d53ef..f55af35f10 100644 --- a/client/src/components/Conversations/Conversations.tsx +++ b/client/src/components/Conversations/Conversations.tsx @@ -99,6 +99,9 @@ const DateLabel: FC<{ groupName: string; isFirst?: boolean }> = memo(({ groupNam const localize = useLocalize(); return (

@@ -394,4 +397,5 @@ const Conversations: FC = ({ ); }; +export { DateLabel }; export default memo(Conversations); diff --git a/client/src/components/Conversations/__tests__/DateLabel.test.tsx b/client/src/components/Conversations/__tests__/DateLabel.test.tsx new file mode 100644 index 0000000000..ccd9bc4126 --- /dev/null +++ b/client/src/components/Conversations/__tests__/DateLabel.test.tsx @@ -0,0 +1,55 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import '@testing-library/jest-dom/extend-expect'; +import { DateLabel } from '../Conversations'; + +jest.mock('~/hooks', () => ({ + useLocalize: () => (key: string, params?: Record) => { + const translations: Record = { + com_a11y_chats_date_section: `Chats from ${params?.date ?? ''}`, + com_ui_date_today: 'Today', + com_ui_date_yesterday: 'Yesterday', + com_ui_date_previous_7_days: 'Previous 7 days', + }; + return translations[key] ?? key; + }, +})); + +describe('DateLabel', () => { + it('provides accessible heading name via aria-label', () => { + render(); + expect(screen.getByRole('heading', { level: 2, name: 'Chats from Today' })).toBeInTheDocument(); + }); + + it('renders visible text as the localized group name', () => { + render(); + expect(screen.getByText('Today')).toBeInTheDocument(); + }); + + it('sets aria-label with the full accessible phrase', () => { + const { container } = render(); + const heading = container.querySelector('h2'); + expect(heading).toHaveAttribute('aria-label', 'Chats from Yesterday'); + }); + + it('uses raw groupName for unrecognized translation keys', () => { + render(); + expect( + screen.getByRole('heading', { level: 2, name: 'Chats from Unknown Group' }), + ).toBeInTheDocument(); + }); + + it('applies mt-0 for the first date header', () => { + const { container } = render(); + const heading = container.querySelector('h2'); + expect(heading).toHaveClass('mt-0'); + expect(heading).not.toHaveClass('mt-2'); + }); + + it('applies mt-2 for non-first date headers', () => { + const { container } = render(); + const heading = container.querySelector('h2'); + expect(heading).toHaveClass('mt-2'); + expect(heading).not.toHaveClass('mt-0'); + }); +}); diff --git a/client/src/locales/en/translation.json b/client/src/locales/en/translation.json index 9f641fdb16..67111586ff 100644 --- a/client/src/locales/en/translation.json +++ b/client/src/locales/en/translation.json @@ -2,6 +2,7 @@ "chat_direction_left_to_right": "Left to Right", "chat_direction_right_to_left": "Right to Left", "com_a11y_ai_composing": "The AI is still composing.", + "com_a11y_chats_date_section": "Chats from {{date}}", "com_a11y_end": "The AI has finished their reply.", "com_a11y_selected": "selected", "com_a11y_start": "The AI has started their reply.",