Repository navigation
fix(web): wrap markdown tables in an accessible scroll region - #4605
Merged
Merged
Conversation
`.prose table` used display: block and overflow-x: auto so wide tables scroll on phones, but display: block drops the table's implicit role in Safari + VoiceOver. A shared rehype plugin now wraps each markdown table in <div class="table-scroll" role="region" aria-label="Table" tabindex="0">, which owns the horizontal scroll, and the table keeps its native display. The plugin is wired into the blog's Astro markdown pipeline and into the packages site's own unified() README renderer (after rehype-sanitize, so the region attributes survive). The landing /ai page already wraps its hand-written tables and is unchanged; Starlight sites don't use .prose. Fixes #4575 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Peter Amiri <peter@alurium.com>
This was referenced Oct 15, 2026
bpamiri
added a commit
that referenced
this pull request
Oct 19, 2026
Starlight styles markdown tables with display: block (in @layer starlight.content), which drops the table role in Safari + VoiceOver. The guides site now runs the shared rehype-table-scroll plugin (#4605), which wraps each table in an accessible scroll region, and an unlayered .sl-markdown-content .table-scroll > table rule restores native display. The API site does not use the plugin: Astro runs markdown rehype plugins before rehype-raw, so it would double-wrap the generated parameter tables, which already sit in .wd-params-table with display: table. Its one plain table, the versions list in docs/index.md, is wrapped by hand. Inline code on Starlight pages also gets overflow-wrap: anywhere, matching the blog. Fixes #4608 Signed-off-by: Peter Amiri <peter@alurium.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
.prose tableuseddisplay: block; overflow-x: autoso wide tables scroll on phones. Butdisplay: blockon a<table>drops its implicit table role in Safari + VoiceOver. This replaces that stopgap with the accessible scrollable-region pattern:@wheels-dev/ui/markdown/rehype-table-scroll.mjs: wraps each table in<div class="table-scroll" role="region" aria-label="Table" tabindex="0">. It has no dependencies, plain hast recursion likerehype-base-prefix.mjs, and never wraps a table twice.markdown.rehypePlugins. Astro's GFM and Shiki defaults are unchanged.unified()README renderer insrc/lib/markdown.ts, afterrehype-sanitizeso the region attributes survive. That page usesset:html, so anastro.configentry wouldn't reach it..prose tablerule is gone; tables get native display back..table-scrollowns the scroll and shows a:focus-visibleoutline in--color-brand.Unchanged:
/ai: its hand-written tables already sit in a scrolling.table-wrap;.prose.Fixes #4575
Testing
node --test web/packages/ui/src/markdown/rehype-table-scroll.test.mjs, 5/5. Covers a top-level table, a nested table, siblings untouched, no double wrap, and several tables.pnpm --filter ./sites/packages test, 19/19, including a new case for the wrapper around a GFM table./aiis visually unchanged at 390px and 1280px.🤖 Generated with Claude Code