Skip to content

fix: make voicover read title and description out of the table#4288

Open
JamalAlabdullah wants to merge 4 commits into
mainfrom
19017-wcag-413-skjermleser-signingdocumentlist-leser-ikke-opp-beskrivelse
Open

fix: make voicover read title and description out of the table#4288
JamalAlabdullah wants to merge 4 commits into
mainfrom
19017-wcag-413-skjermleser-signingdocumentlist-leser-ikke-opp-beskrivelse

Conversation

@JamalAlabdullah

@JamalAlabdullah JamalAlabdullah commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

Description

after.mov

Related Issue(s)

Verification/QA

  • Manual functionality testing
    • I have tested these changes manually
    • Creator of the original issue (or service owner) has been contacted for manual testing (or will be contacted when released in alpha)
    • No testing done/necessary
  • Automated tests
    • Unit test(s) have been added/updated
    • Cypress E2E test(s) have been added/updated
    • No automatic tests are needed here (no functional changes/additions)
    • I want someone to help me make some tests
  • UU/WCAG (follow these guidelines until we have our own)
    • I have tested with a screen reader/keyboard navigation/automated wcag validator
    • No testing done/necessary (no DOM/visual changes)
    • I want someone to help me perform accessibility testing
  • User documentation @ altinn-studio-docs
    • Has been added/updated
    • No functionality has been changed/added, so no documentation is needed
    • I will do that later/have created an issue
  • Support in Altinn Studio
    • Issue(s) created for support in Studio
    • This change/feature does not require any changes to Altinn Studio
  • Sprint board
    • The original issue (or this PR itself) has been added to the Team Apps project and to the current sprint board
    • I don't have permissions to do that, please help me out
  • Labels
    • I have added a kind/* and backport* label to this PR for proper release notes grouping
    • I don't have permissions to add labels, please help me out

Summary by CodeRabbit

Summary by CodeRabbit

  • Refactor
    • Improved the signing document list’s information hierarchy with explicit heading/description and an inline, localized caption.
  • Accessibility
    • Enhanced table accessibility with consistent labeling support.
    • Updated the download column to use a localized, visually-hidden header label and consistent download link text styling.
  • Tests
    • Refined accessibility and loading-state assertions, including stronger checks for headings, table labeling, and the download column header.

@JamalAlabdullah JamalAlabdullah added kind/bug Something isn't working backport This PR should be cherry-picked onto older release branches labels Jun 16, 2026
@coderabbitai

coderabbitai Bot commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 0228fceb-2e8e-43f2-8597-15942a5ce6d7

📥 Commits

Reviewing files that changed from the base of the PR and between b745926 and 0584570.

📒 Files selected for processing (1)
  • src/layout/SigningDocumentList/SigningDocumentListComponent.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/layout/SigningDocumentList/SigningDocumentListComponent.tsx

📝 Walkthrough

Walkthrough

AppTable extends its props to accept ariaLabel and tableTestId for accessibility and testing. SigningDocumentListComponent refactors the table caption from an AppTable prop to standalone Heading, Description, and HelpTextContainer elements, changes the download column header from null with ariaLabel to a visually-hidden span with a localized label, and accepts baseComponentId to generate component identifiers. Parent component wiring passes baseComponentId through render and summary paths. Tests add setup mocks and update assertions to verify the new DOM structure and accessibility labels.

Changes

Caption rendering and table accessibility refactor

Layer / File(s) Summary
AppTable props extension for aria-label and data-testid
src/app-components/Table/Table.tsx
DataTableProps type adds optional ariaLabel and tableTestId properties. AppTable destructures and passes these to the underlying Table component as aria-label and data-testid attributes.
SigningDocumentListComponent caption and download column refactor
src/layout/SigningDocumentList/SigningDocumentListComponent.tsx, src/layout/SigningDocumentList/SigningDocumentListComponent.module.css
Component props now accept baseComponentId to generate component identifiers for caption elements. Imports new design-system components (Heading, Description, HelpTextContainer) and caption utilities; renders explicit caption block containing heading, optional description, and help elements before AppTable; removes caption prop from AppTable and passes ariaLabel instead; changes download column from header: null with ariaLabel to a visually-hidden span using localized downloadLabel. New .downloadLink CSS class provides flex layout and whitespace styling for download links.
Parent component wiring for baseComponentId
src/layout/SigningDocumentList/index.tsx
SigningDocumentList render method and renderSummary2 method now pass baseComponentId alongside textResourceBindings to SigningDocumentListComponent.
Test setup and assertions for new caption structure
src/layout/SigningDocumentList/SigningDocumentListComponent.test.tsx
Adds mock for DataModelLocation to control useIndexedId deterministically. Defines baseComponentId constant for test renders. Updates "should render correctly" test to assert heading and description presence, verify no caption role element exists, drop accessible-name matchers from table queries, assert aria-label via data-testid, and add download column header assertions. Updates "should render error message" and "should render spinner when loading" tests to pass baseComponentId and textResourceBindings, and adds heading presence assertion to the spinner test.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested labels

area/accessibility

Suggested reviewers

  • adamhaeger
  • lassopicasso
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main change: making VoiceOver (screen readers) read title and description outside the table, directly addressing the WCAG accessibility issue.
Description check ✅ Passed The description includes a video reference, linked issue (#4278), and verification checklist, but lacks detail on the technical implementation and design decisions made.
Linked Issues check ✅ Passed All code changes directly address the WCAG 4.1.3 compliance violation [#4278]: title and description are now rendered outside the table with proper semantic elements (Heading, Description, HelpTextContainer) and aria-labels for screen reader announcement.
Out of Scope Changes check ✅ Passed All changes are scoped to the SigningDocumentList component and directly support the accessibility fix: adding baseComponentId support, moving caption content outside the table, updating table aria-labels, and improving download column labeling.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch 19017-wcag-413-skjermleser-signingdocumentlist-leser-ikke-opp-beskrivelse

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/layout/SigningDocumentList/SigningDocumentListComponent.test.tsx (1)

128-133: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Loading-state test should also assert the download column header.

The render test validates the new visually-hidden download header, but the loading test still omits that assertion. Adding it keeps accessibility coverage consistent across states.

Suggested test addition
     screen.getByRole('columnheader', { name: 'signing_document_list.header_filename' });
     screen.getByRole('columnheader', { name: 'signing_document_list.header_attachment_type' });
     screen.getByRole('columnheader', { name: 'signing_document_list.header_size' });
+    screen.getByRole('columnheader', { name: 'signing_document_list.download' });
     screen.getByRole('cell', { name: /loading data.../i });
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/layout/SigningDocumentList/SigningDocumentListComponent.test.tsx` around
lines 128 - 133, The loading state test block for SigningDocumentListComponent
is missing an assertion for the download column header that is being tested in
the render test. Add a screen.getByRole assertion for the columnheader with the
download header name (following the same pattern as the existing columnheader
assertions for filename, attachment_type, and size) to ensure consistent
accessibility coverage across all component states.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/layout/SigningDocumentList/SigningDocumentListComponent.tsx`:
- Around line 22-23: The table labeling contract was dropped when the caption
was removed from AppTable in SigningDocumentListComponent.tsx. The tableLabelId
constant is defined but only used for description IDs, leaving the table without
a programmatic label. In src/app-components/Table/Table.tsx, add an
ariaLabelledBy prop to the AppTable component and forward it to the underlying
Table element as aria-labelledby to restore the accessible table naming. Then in
SigningDocumentListComponent.tsx at lines 22-23 (and the other affected
locations at lines 42-66 and 66-115), pass the tableLabelId to each AppTable
usage via the new ariaLabelledBy prop to establish the table labeling
relationship.

---

Outside diff comments:
In `@src/layout/SigningDocumentList/SigningDocumentListComponent.test.tsx`:
- Around line 128-133: The loading state test block for
SigningDocumentListComponent is missing an assertion for the download column
header that is being tested in the render test. Add a screen.getByRole assertion
for the columnheader with the download header name (following the same pattern
as the existing columnheader assertions for filename, attachment_type, and size)
to ensure consistent accessibility coverage across all component states.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: ade350aa-9c14-49ea-9ffb-812439860b4f

📥 Commits

Reviewing files that changed from the base of the PR and between 7efe316 and 444b9db.

📒 Files selected for processing (2)
  • src/layout/SigningDocumentList/SigningDocumentListComponent.test.tsx
  • src/layout/SigningDocumentList/SigningDocumentListComponent.tsx

Comment thread src/layout/SigningDocumentList/SigningDocumentListComponent.tsx Outdated
@JamalAlabdullah JamalAlabdullah moved this to 🔎 In review in Team Altinn Studio Jun 17, 2026
@JamalAlabdullah JamalAlabdullah added the squad/utforming Issues that belongs to the named squad. label Jun 17, 2026

@walldenfilippa walldenfilippa left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tested it with NVDA, and the header labels and columns are read correctly 🥳
However, the description is still being read twice. See this comment from Olav in the original issue: #4278 (comment)

return <SigningDocumentListError error={error} />;
}

const downloadLabel = langAsString('signing_document_list.download');

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider using all labels as variables, or integrating them directly into the code for consistency.

import { getSizeWithUnit } from 'src/utils/attachmentsUtils';
import type { ITextResourceBindings } from 'src/layout/layout';

const tableLabelId = 'signing-document-list';

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This id is not unique. Is their a usecase where someone would use two SigningDocumentList component?
You could pass the baseComponentId which is available trough the index.tsx, to remove that risk :)

renderCell: (_, rowData) => (
<Link
href={rowData.url}
style={{ display: 'flex', gap: '0.5rem', whiteSpace: 'nowrap', textDecoration: 'none' }}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider moving the styling into a dedicated module.

@lassopicasso lassopicasso left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Testet denne, tittel og beskrivelse blir lest korrekt.

<>
{textResourceBindings?.title && (
<div className={captionClasses.tableCaption}>
<Heading

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Vi bør ha dynamisk heading etter hvor komponenten ligger i rekkefølge, om den ligger etter en h2 så bør vel neste være h3 om den er etter en h1 så blir det h2 - eller har vi et fast mønster på dette ?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alternativt så kan vi gå for å bruke title og description - og ikke heading

Image

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed
Screenshot 2026-06-19 at 14 55 29

@olavflar olavflar self-requested a review June 19, 2026 12:49
@sonarqubecloud

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backport This PR should be cherry-picked onto older release branches kind/bug Something isn't working squad/utforming Issues that belongs to the named squad.

Projects

Status: 🔎 In review

Development

Successfully merging this pull request may close these issues.

WCAG-brudd: 4.1.3 Statusbeskjeder (AA) - Skjermleser: SigningDocumentList leser ikke opp beskrivelse

4 participants