From 2ec8e43bd1cdfe16990e9f55469dcff8e4ce3aa5 Mon Sep 17 00:00:00 2001 From: codecalm Date: Tue, 22 Sep 2026 21:04:57 +0200 Subject: [PATCH] Restyle markdown tables in the docs - wrap-tables hast plugin puts each table in a scrolling .docs-table box - bordered grid with a tinted, tighter header row --- .changeset/docs-markdown-tables.md | 5 ++ docs/astro.config.mjs | 7 ++- docs/lib/satteri-wrap-tables.mjs | 23 +++++++++ docs/scss/docs.scss | 79 +++++++++++++++++++++++++++++- 4 files changed, 112 insertions(+), 2 deletions(-) create mode 100644 .changeset/docs-markdown-tables.md create mode 100644 docs/lib/satteri-wrap-tables.mjs diff --git a/.changeset/docs-markdown-tables.md b/.changeset/docs-markdown-tables.md new file mode 100644 index 000000000..b071001e3 --- /dev/null +++ b/.changeset/docs-markdown-tables.md @@ -0,0 +1,5 @@ +--- +"@tabler/docs": patch +--- + +Updated markdown tables in the docs with a bordered, scrollable `.docs-table` box and a tighter header row. diff --git a/docs/astro.config.mjs b/docs/astro.config.mjs index 095b79f09..5e92ac37d 100644 --- a/docs/astro.config.mjs +++ b/docs/astro.config.mjs @@ -4,6 +4,7 @@ import vercel from '@astrojs/vercel' import mdx from '@astrojs/mdx' import { satteri } from '@astrojs/markdown-satteri' import { unwrapJsxParagraphs } from './lib/satteri-unwrap-jsx-paragraphs.mjs' +import { wrapTables } from './lib/satteri-wrap-tables.mjs' import { fileURLToPath } from 'node:url' import { copyAssets } from '../.build/copy-assets' import { redirects } from './lib/redirects.ts' @@ -111,7 +112,11 @@ export default defineConfig({ ], markdown: { // No typographic quote rewriting. - processor: satteri({ features: { smartPunctuation: false }, mdastPlugins: [unwrapJsxParagraphs] }), + processor: satteri({ + features: { smartPunctuation: false }, + mdastPlugins: [unwrapJsxParagraphs], + hastPlugins: [wrapTables], + }), shikiConfig: { theme: 'github-dark', }, diff --git a/docs/lib/satteri-wrap-tables.mjs b/docs/lib/satteri-wrap-tables.mjs new file mode 100644 index 000000000..db562bd1f --- /dev/null +++ b/docs/lib/satteri-wrap-tables.mjs @@ -0,0 +1,23 @@ +// A markdown table is only as wide as the prose column, so an options table +// with four columns either squeezes its description or, on a phone, pushes the +// whole page sideways. Every docs system (Starlight, VitePress, GitHub) puts +// the table in a scrolling box instead; this does the same with a wrapper +// element, which keeps the `` semantics that `display: block` on the +// table itself would throw away. Only markdown tables are elements here — +// literal `
` markup inside an is JSX and is left alone. +export function wrapTables() { + return { + name: 'wrap-tables', + element: { + filter: ['table'], + visit(node, ctx) { + ctx.wrapNode(node, { + type: 'element', + tagName: 'div', + properties: { className: ['docs-table'] }, + children: [], + }) + }, + }, + } +} diff --git a/docs/scss/docs.scss b/docs/scss/docs.scss index a1fa8cb89..c97b8a81b 100644 --- a/docs/scss/docs.scss +++ b/docs/scss/docs.scss @@ -316,7 +316,7 @@ header > .navbar { // Prose links keep the primary color but gain a quiet underline, so they // are findable when scanning and do not rely on color alone (WCAG 1.4.1). - > :is(p, ul, ol, table) a:not(.btn) { + > :is(p, ul, ol, .docs-table) a:not(.btn) { text-decoration: underline; text-decoration-color: color-mix(in srgb, var(--tblr-primary) 40%, transparent); text-underline-offset: 3px; @@ -326,6 +326,83 @@ header > .navbar { } } + // Markdown tables. The wrap-tables hast plugin (lib/satteri-wrap-tables.mjs) + // puts each one in a .docs-table box, so a wide table scrolls inside the + // column instead of pushing the page out. The wrapper also takes the table + // out of core's `.prose > table` rule, so the whole look is defined here: + // a bordered grid with a tinted header row (as on GitHub and VitePress), + // full width, tighter rows, and a first column that never wraps — the + // option or method name is what the reader scans for, and the description + // gets whatever is left. The border sits on the box, not the table, so the + // rounded corners survive a sideways scroll. + > .docs-table { + margin-bottom: 1.5rem; + overflow-x: auto; + border: 1px solid var(--tblr-border-color); + border-radius: var(--tblr-border-radius); + + > table { + width: 100%; + margin: 0; + font-size: 0.875rem; + line-height: 1.5; + border-collapse: collapse; + } + + th, + td { + padding: 0.5rem 0.75rem; + text-align: start; + vertical-align: top; + border: 1px solid var(--tblr-border-color); + } + + // The box already draws the outer edge. + tr > :first-child { + border-inline-start: 0; + } + + tr > :last-child { + border-inline-end: 0; + } + + thead tr:first-child > * { + border-top: 0; + } + + tbody tr:last-child > * { + border-bottom: 0; + } + + th { + padding-top: 0.25rem; + padding-bottom: 0.25rem; + font-size: 0.8125rem; + font-weight: var(--tblr-font-weight-semibold); + color: var(--tblr-body-color); + white-space: nowrap; + background: var(--tblr-bg-surface-tertiary); + } + + // Names, types and defaults stay on one line; only the last column wraps. + // Every middle cell in the docs is a short label, so the browser's even + // split would only spread wrapped fragments across the row. + td:not(:last-child) { + white-space: nowrap; + } + + // On a phone the box scrolls sideways; without a floor the description + // column would be the one squeezed into a tall sliver instead. + th:last-child, + td:last-child { + min-width: 18rem; + } + + td > p:last-child { + margin-bottom: 0; + } + } + // `pretty` only optimises the tail of a block, so it stays cheap on long // text; `balance` evens out all lines and suits short headings. > :is(p, li, blockquote, dd),