Skip to content

fix(ui-table): don't describe a sort state on unsorted v1 tables - #2666

Open
drakeaharper wants to merge 1 commit into
masterfrom
fix/ui-table-unsorted-caption
Open

fix(ui-table): don't describe a sort state on unsorted v1 tables#2666
drakeaharper wants to merge 1 commit into
masterfrom
fix/ui-table-unsorted-caption

Conversation

@drakeaharper

Copy link
Copy Markdown
Collaborator

Summary

A v1 Table given a plain string caption appends " Sorted by undefined (undefined)" to both its <caption> and its accessible name whenever no column is sorted:

aria-label="Movies Sorted by undefined (undefined)"
<caption>Movies Sorted by undefined (undefined)</caption>

getCaptionText lost its early return for the unsorted case between 11.7.4-SECURITY.3 and 11.7.4:

// 11.7.4-SECURITY.3
const caption = props.caption as string
if (!sortInfo) return caption
const sortText = ` Sorted by ${sortInfo.header} (${sortInfo.direction})`

// 11.7.4 — early return gone, so sortInfo is always interpolated
const sortText = ` Sorted by ${sortInfo?.header} (${sortInfo?.direction})`
return caption ? caption + sortText : sortText.trim()

This is user-facing for screen reader users, not only a test problem. It still reproduces on 11.7.5-snapshot-14.

Changes

  • Restore the early return so an unsorted table uses its caption as given. The caption-as-function path is untouched, and the cast matches what SECURITY.3 did (props.caption as string).
  • Add packages/ui-table/src/Table/v1/__tests__/Table.test.tsx. The existing Table tests import @instructure/ui-table/latest and only ever pass a caption function, so the v1 string-caption path had no coverage — which is how this shipped. The new tests import relatively so they exercise source rather than built output.

Verification

  • New tests fail on unpatched source (2 of 3, printing the literal Movies Sorted by undefined (undefined)) and pass with the fix. The third covers the sorted case and passes either way, guarding against over-correcting.
  • pnpm run test:vitest ui-table — 25 passed.
  • pnpm run bootstrap clean, including build:types (the first draft of this fix failed type-checking; aria-label needs a string).

Context

Found upgrading canvas-lms off the Artifactory-only 11.7.4-SECURITY.3 onto public 11.7.4, where it broke 10 vitest files and 6 Selenium specs that locate tables by accessible name. Reported in #instui. Canvas is carrying a patch-package patch for this that we'll drop once a fixed release ships.

One question for reviewers

componentDidUpdate still has a commented-out condition:

if (
  sortingChanged &&
  currentSortInfo &&
  // typeof this.props.caption === 'function' &&
  this._liveRegionRef
) {

That looks like this change was mid-flight, and the accompanying comment says sort changes should only be announced for function captions. I've left it exactly as-is because I don't know the intent — if the live-region announcement is also meant to be gated, that's a follow-up (or tell me and I'll fold it in here).

`getCaptionText` lost its early return for the unsorted case, so a v1
Table given a plain string caption has ' Sorted by undefined (undefined)'
appended to both its <caption> and its accessible name whenever no
column is sorted:

    aria-label="Movies Sorted by undefined (undefined)"

That is user-facing for screen reader users. Restore the early return so
an unsorted table uses its caption as given, and keep the caption
function path untouched.

Found while upgrading canvas-lms from 11.7.4-SECURITY.3 to 11.7.4, where
it broke 10 vitest files and 6 Selenium specs that locate tables by
accessible name.

Adds a v1 test file. The existing Table tests import
`@instructure/ui-table/latest` and only ever pass a caption function, so
the v1 string-caption path had no coverage.
@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

1 similar comment
@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@github-actions

Copy link
Copy Markdown
Contributor
PR Preview Action v1.8.1

QR code for preview link

🚀 View preview at
https://instructure.design/pr-preview/pr-2666/

Built to branch gh-pages at 2026-07-29 21:12 UTC.
Preview will be ready when the GitHub Pages deployment is complete.

@github-actions

Copy link
Copy Markdown
Contributor

Visual regression report

⚠️ Changes detected.

Status Count
Unchanged 0
Changed 1
New 96
Removed 32

📊 View full report

Diff images (33)

alert.png — baseline no longer produced

avatar.png — baseline no longer produced

badge.png — baseline no longer produced

billboard.png — baseline no longer produced

breadcrumb.png — baseline no longer produced

button-and-derivatives.png — baseline no longer produced

byline.png — baseline no longer produced

calendar.png — baseline no longer produced

checkbox.png — baseline no longer produced

checkboxgroup.png — baseline no longer produced

colorpicker.png — baseline no longer produced

contextview.png — baseline no longer produced

custom-and-lucide-icons.png — baseline no longer produced

dateinput-dateinput2.png — baseline no longer produced

datetimeinput.png — baseline no longer produced

diff-demo.png — 6324 pixels differ

drilldown.png — baseline no longer produced

filedrop.png — baseline no longer produced

form-errors.png — baseline no longer produced

heading.png — baseline no longer produced

img.png — baseline no longer produced

link.png — baseline no longer produced

menu.png — baseline no longer produced

metric-pill-tag-timeselect-text.png — baseline no longer produced

options.png — baseline no longer produced

pagination.png — baseline no longer produced

progressbar.png — baseline no longer produced

select-simpleselect.png — baseline no longer produced

table.png — baseline no longer produced

tabs.png — baseline no longer produced

tooltip.png — baseline no longer produced

treebrowser.png — baseline no longer produced

view.png — baseline no longer produced

Baselines come from the visual-baselines branch. They refresh on every merge to master.

github-actions Bot pushed a commit that referenced this pull request Jul 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants