Skip to content

fix(ui-table): don't append a sort state to unsorted v1 captions - #2671

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

fix(ui-table): don't append a sort state to unsorted v1 captions#2671
balzss wants to merge 1 commit into
masterfrom
fix/ui-table-unsorted-caption-v1

Conversation

@balzss

@balzss balzss commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Summary

An unsorted v1 Table with a plain string caption renders Sorted by undefined (undefined) into both its <caption> and its accessible name:

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

getCaptionText lost its if (!sortInfo) return caption guard in aac2b17 (#2574), which restructured it around the new TableCaption function form. Shipped in v11.7.4. v2 is unaffected — caption must be a function there.

Our own docs site is affected too: the __docs__ Properties, Params, Returns and ComponentTheme tables all use v1 with string captions.

Changes

  • Restore the early return in Table/v1/index.tsx. The function-caption branch is untouched, and the as string cast matches SECURITY.3 — the value feeds aria-label, which needs a string.
  • Add Table/v1/__tests__/Table.test.tsx. v1 had no test coverage at all, which is why this shipped: the existing suite imports /latest (v2), and fix(ui-table): fix caption for table to be responsive to sorting #2574 converted its last string captions to functions.

Test Plan

  • The two unsorted tests fail on unpatched source and pass with the fix. The sorted test passes either way, guarding against over-correcting.
  • pnpm run test:vitest ui-table — 25 passed. Full unit suite — 2218 passed. build:types clean.
  • Docs app: Properties and Component-theme captions render clean with matching aria-labels, and the function-caption sort form still works.

Worth knowing for future tests: the new file imports relatively on purpose. getWorkspaceAliases() in vitest.config.mts is only wired into the browser project, so a @instructure/ui-table/* import in the web project resolves to built es/ output rather than source.

Fixes INSTUI-5138

Reported by @drakeaharper in #instui while upgrading canvas-lms onto public 11.7.4, where it broke 10 vitest files and 6 Selenium specs. Supersedes #2666.

🤖 Generated with Claude Code

`getCaptionText` lost its `if (!sortInfo) return caption` early return in
aac2b17 (#2574, INSTUI-5047), which restructured it around the new
`TableCaption` function form. Every unsorted v1 Table given a plain string
caption then rendered ' Sorted by undefined (undefined)' into both its
<caption> and its aria-label:

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

That is a real defect for screen reader users, and it contradicts the
prop's own documentation ("A plain ReactNode ... is rendered as-is and the
sort state is ignored"). It also affected our own docs site, whose
Properties/Params/Returns/ComponentTheme tables all use v1 with string
captions. First shipped in v11.7.4; reported by canvas-lms.

Restore the early return, leaving the function-caption branch untouched.

v1 had no test coverage at all — the existing suite imports
`@instructure/ui-table/latest`, which is v2, and the same commit converted
its remaining string captions to functions, so nothing guarded this path.
Add a v1 suite covering the unsorted and sorted string-caption cases. It
imports relatively on purpose: the `web` vitest project has no workspace
aliases, so a package import there resolves to built output rather than
source.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@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-2671/

Built to branch gh-pages at 2026-07-31 11:46 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 31, 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.

1 participant