Skip to content
This repository is currently being migrated. It's locked while the migration is in progress.

va-table: add caption summary and focus props#1907

Draft
jamigibbs wants to merge 15 commits into
mainfrom
5099-table-focus
Draft

va-table: add caption summary and focus props#1907
jamigibbs wants to merge 15 commits into
mainfrom
5099-table-focus

Conversation

@jamigibbs
Copy link
Copy Markdown
Contributor

@jamigibbs jamigibbs commented Dec 5, 2025

Chromatic

https://5099-table-focus--65a6e2ed2314f7b8f98609d8.chromatic.com

Description

This PR will add two new props to va-table:

  1. The tableTitleSummary prop for adding additional context/summary to the caption.
    • according to this W3C tutorial, summary text can be added to a caption element for more complex tables and this seems like a good place to put something like pagination summary information.
    • Why not a slot instead of a prop? Because the caption element should only contain flow content (ie. no div, p, etc). By using a prop, we can enforce that requirement and also provide consist styling for the summary.
  2. The setCaptionFocus prop for programmatically focusing the caption as needed.
    • Because of the challenges with locating the caption element in the shadow dom along with the nature of the table component re-rending with pagination, we are hoping this will make it easier for teams to add focus to this element if it's needed.
    • The specific use-case we are seeing is focusing the caption when pagination info is updated on the table.

Accessibility note

After discussion with @jeana-adhoc, we tested focusing on the table element instead of the caption element but VO + Firefox and JAWS + Edge were not reading out the title & summary at all.

Adding sr-only text to the caption with focus was the only way that we could reliably get the screenreaders to read that text across all browsers. The downside of this is that in some screenreader + browser combinations, the caption will be read twice but we thought that would be better than not reading it at all.

Related tickets and links

related department-of-veterans-affairs/vets-design-system-documentation#5099

Screenshots

Caption with summary text and focused

Screenshot 2025-12-09 at 1 41 04 PM

Testing and review

Approvals

See the QA Checklists section below for suggested approvals. Use your best judgment if additional reviews are needed. When in doubt, request a review.

Approval groups

Add approval groups to the PR as needed:

QA checklists

Use the QA checklists below as guides, not rules. Not all checklists will apply to every PR but there could be some overlap.

In all scenarios, changes should be fully tested by the author and verified by the reviewer(s); functionality, responsiveness, etc.

✨ New Component Added
  • The PR has the minor label
  • The component matches the Figma designs.
  • All properties, custom events, and utility functions have e2e and/or unit tests
  • A new Storybook page has been added for the component
  • Tested in all VA breakpoints.
  • Chromatic UI Tests have run and snapshot changes have been accepted by the design reviewer
  • Tested in vets-website using Verdaccio
  • Engineering has approved the PR
  • Design has approved the PR
  • Accessibility has approved the PR
🌱 New Component Variation Added
  • The PR has the minor label
  • The variation matches its Figma design.
  • Any new properties, custom events, or utility functions have e2e and/or unit tests
  • A new story has been added to the component's existing Storybook page
  • Any Chromatic UI snapshot changes have been accepted by a design reviewer
  • Tested in vets-website using Verdaccio
  • Engineering has approved the PR
  • Design has approved the PR
🐞 Component Fix
  • The PR has the patch label
  • Any new properties, custom events, or utility functions have e2e and/or unit tests
  • Any markup changes are evaluated for impact on vets-website.
    • Will any vets-website tests fail from the change?
  • Any Chromatic UI snapshot changes have been reviewed and approved by a designer if necessary
  • Engineering has approved the PR
♿️ Component Fix - Accessibility
  • The PR has the patch label
  • Any new properties, custom events, or utility functions have e2e and/or unit tests
  • Any Chromatic UI snapshot changes have been reviewed and approved by a designer if necessary
  • Engineering has approved the PR
  • Accessibility has approved the PR
🚨 Component Fix - Breaking API Change
  • The PR has the major label
  • vets-website and content-build have been evaluated to determine the impact of the breaking change
  • Any new properties, custom events, or utility functions have e2e and/or unit tests
  • Any Chromatic UI snapshot changes have been reviewed and approved by a designer if necessary
  • Tested in vets-website using Verdaccio
  • Engineering has approved the PR
🔧 Component Update - Non-Breaking API Change
  • The PR has the minor label
  • Any new properties, custom events, or utility functions have e2e and/or unit tests
  • Any Chromatic UI snapshot changes have been reviewed and approved by a designer if necessary
  • Engineering has approved the PR
📖 Storybook Update
  • The PR has the ignore-for-release label
  • Any Chromatic UI snapshot changes have been reviewed and approved by a designer if necessary
  • Engineering has approved the PR
🎨 CSS-Library Update
  • The PR has the css-library label
  • vets-website and content-build have been checked to determine the impact of any breaking changes
  • Engineering has approved the PR

@jamigibbs jamigibbs added minor For a minor Semantic Version change run chromatic workflow Allows a PR to run the chromatic workflow to deploy Chromatic without "ready for review" status. labels Dec 5, 2025
@jamigibbs jamigibbs removed the run chromatic workflow Allows a PR to run the chromatic workflow to deploy Chromatic without "ready for review" status. label Dec 5, 2025
@jamigibbs jamigibbs added the run chromatic workflow Allows a PR to run the chromatic workflow to deploy Chromatic without "ready for review" status. label Dec 5, 2025
@jamigibbs jamigibbs removed the run chromatic workflow Allows a PR to run the chromatic workflow to deploy Chromatic without "ready for review" status. label Dec 9, 2025
@jamigibbs jamigibbs changed the title va-table: add table title summary prop va-table: add table title summary and focus props Dec 9, 2025
@jamigibbs jamigibbs changed the title va-table: add table title summary and focus props va-table: add caption summary and caption focus props Dec 9, 2025
@jamigibbs jamigibbs requested review from a team December 10, 2025 14:37
outline: 2px solid var(--vads-color-action-focus-on-light);
outline-offset: 2px;
z-index: 2;
} No newline at end of file
Copy link
Copy Markdown
Contributor Author

@jamigibbs jamigibbs Dec 10, 2025

Choose a reason for hiding this comment

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

note: I created this Sass mixin because the single stylesheet approach for focus style has become unwieldy. I am going to create a follow-up ticket for us to look at switching to using a direct mixin in the other places the original stylesheet is referencing.

margin-bottom: 0.75rem;
margin-top: 0.75rem;
margin-left: 0.25rem;
margin-right: 0.25rem;
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.

Hello @department-of-veterans-affairs/platform-design-system-designers reviewer! 👋🏼 I made a very small adjustment to the margin of the caption (the table title) so that the focus border would not get cut off. Without doing this, the border is not continuous.

Before

Image

After

Image

margin-right: 0.25rem;
span {
display: block;
font-weight: normal;
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.

Hi again, @department-of-veterans-affairs/platform-design-system-designers reviewer! 👋🏼

We have an opportunity here to style caption summary however we'd like. This is my best guess. Let me know if you would prefer something else.

Image

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.

@jamigibbs I think the styling is good. I'm not sure if that's the best placement for the results text though? Should it be closer to the pagination controls? 🤔 That might complicat focus order though. This is just a hunch, but I can do some research if necessary. Before doing that, I wonder if this be more of an accessibility question though. @amyleadem @jeana-adhoc Your thoughts?

Here's a quick mock up moving the results total to be near the pagination controls:

image (It will need a little more space if we go this direction.)

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 think @jamigibbs initial placement makes sense. It's similar to how we manage search results.

image

After triggering a pagination change, we need to announce that change and send focus somewhere, and we wouldn't want to focus directly above the pagination.

@amyleadem Would be curious if you have other thoughts about this.

setTimeout(() => {
const main = tableRef.current;
const vaTable = main?.querySelector('va-table');
vaTable?.setAttribute('set-caption-focus', 'true');
Copy link
Copy Markdown
Contributor Author

@jamigibbs jamigibbs Dec 10, 2025

Choose a reason for hiding this comment

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

Howdy @department-of-veterans-affairs/platform-design-system-a11y reviewer! 👋🏼 I added a prop for focusing the caption element as-needed and it appears to be functioning as intended but my VO testing resulted in some duplicate readouts when I integrated it with this pagination example in Storybook.

Is it possible that this isn't the correct a11y approach for using pagination with va-table?

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'll take a look - I heard it duplicated in VO too (but sometimes that just.. happens). I'm going to listen in NVDA & JAWS too, then come back and see if this might just be a VO quirk.

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.

Thanks @jeana-adhoc! Based on our convo, I've updated the description of the PR with a11y notes to explain our approach. Feel free to edit or add if you'd like!

@jamigibbs jamigibbs marked this pull request as ready for review December 10, 2025 14:57
@jamigibbs jamigibbs requested a review from a team as a code owner December 10, 2025 14:57
{tableTitle && <caption>{tableTitle}</caption>}
{tableTitle && <caption ref={(el) => this.captionRef = el}>
{tableTitle}
{tableTitleSummary && <span>{tableTitleSummary}</span>}
Copy link
Copy Markdown
Contributor

@RyanMunsch RyanMunsch Dec 11, 2025

Choose a reason for hiding this comment

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

The dev looks good here in general but it does look like the nested span element in this caption element leads to some browsers not announcing the text content of the span on screen readers. Note that this behavior has been observed elsewhere (i.e. department-of-veterans-affairs/vets-design-system-documentation#5101).

I tested on MacOS VoiceOver on Chrome, Safari, and Edge and found that the announcement was working as expected on all but Firefox, where only the immediate child text of the caption is being read (the tableTitle value). I pulled the branch down locally and removed the nested span so that the tableTitleSummary value was a direct child of the caption element and it was being announced as expected.

I'll let the @department-of-veterans-affairs/platform-design-system-a11y reviewer advise on how to move forward with this, but just wanted to get it on the radar here.

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.

@RyanMunsch Thanks for catching this! I'm going to update it with sr-only text and combine it with the nested elements using aria-hidden so we don't have a double readout. Like this:

<caption ref={(el) => this.captionRef = el}>
  <span class="usa-sr-only">{tableTitle}{tableTitleSummary ? ` ${tableTitleSummary}` : ''}</span>
  <span aria-hidden="true">
    {tableTitle}
    {tableTitleSummary && <span id="summary">{tableTitleSummary}</span>}
  </span>
</caption>

That seems to fix it in Firefox, etc. but curious to hear your thoughts from an engineering perspective. The only other solution that I think might work is adding aria-label on the caption element but I feel like we generally try to avoid using that if possible.

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.

No problem, @jamigibbs. That solution looks like it should work! That's the same approach that I used in this PR and that behaved as expected across browsers, operating systems, and different screen readers according to Jeana's testing.

Copy link
Copy Markdown
Contributor

@danbrady danbrady left a comment

Choose a reason for hiding this comment

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

@jamigibbs I noticed that there's a bit more top margin with this update. Is that intentional?

Original

Image

Updated

Image

@jamigibbs
Copy link
Copy Markdown
Contributor Author

jamigibbs commented Dec 15, 2025

Hello participants of this PR! After some discussion with @jeana-adhoc, I'm going to push an update that changes focus from the caption to the table element. We want to do some testing with that approach. Thank you for all the feedback so far though! 🙇🏼

@jamigibbs jamigibbs changed the title va-table: add caption summary and caption focus props va-table: add caption summary and focus props Dec 15, 2025
text-align: left;
padding: 0 0 0.313rem;
font-weight: 700;
font-size: 1.25rem;
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.

Most of these styles are carry overs from the v1 (non-USWDS) version of the component so they are now unnecessary. The caption is now styled directly from the USWDS table class .usa-table caption:

Image

@jamigibbs
Copy link
Copy Markdown
Contributor Author

@jamigibbs I noticed that there's a bit more top margin with this update. Is that intentional?

Original

Image ## Updated Image

@danbrady Thanks for noticing that! I cleaned up some old caption styles and simplified the margin CSS and it looks like that resolved this issue.

Copy link
Copy Markdown

@RMunschie92 RMunschie92 left a comment

Choose a reason for hiding this comment

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

LGTM!

@jamigibbs
Copy link
Copy Markdown
Contributor Author

We are going to split out these two features into separate PRs (title summary & title focus). I'm going to convert this PR to a draft for now and here is the new PR for just the title summary prop:

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

Labels

minor For a minor Semantic Version change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants