[Bug Fix] DataTable: match dashboard-01 look (Columns trigger, badges, toolbar spacing)
Follow-up to #579 (stacked on it). It fixes the visual differences the shadcn audit still reported on DataTable against the dashboard-01 block (Base UI + vega + neutral). #579's per-page Select and CSP change is left alone.
What changed
Columns toggle (display: inline-flex vs flex).
Both buttons have the same inline-flex class. shadcn's trigger computes flex because it is a direct child of the toolbar's div.flex, and a flex item's inline-flex becomes flex. In RubyUI, DataTableColumnToggle's div.relative and the DropdownMenu root sat between the toolbar and the button, so the button stayed in block flow. Both wrappers are now display: contents. The menu is a top-layer popover anchored to the button, so it doesn't rely on either wrapper's box. Button and DropdownMenu are unchanged.
Row checkbox (block; text-align: start vs flex; text-align: left).
RubyUI's checkbox is a native <input type=checkbox> with no children; its check mark is an absolutely positioned ::before. shadcn's is a <span class="flex"> that centers its Indicator child. flex only affects children, so on the input it renders the same box as block. The text-align line comes from the select-all checkbox in the header: the browser's form-control defaults reset the input to start, while the span inherits left from TableHead. In LTR the two are the same. Both are registered in audit/divergences/data_table.yml, and Checkbox is unchanged.
"In Process" / "Done" badges look darker.
This came from the audit fixture, not Badge. RubyUI used Badge(variant: :outline, size: :sm) (h-4, text-foreground). The block uses the default size with px-1.5 text-muted-foreground, puts the type badge in a div.w-32, and shows a status icon: CircleCheckIcon with fill-green-500 dark:fill-green-400 for Done, LoaderIcon otherwise. The shadcn fixture was missing those icons too. Both fixtures now follow the block, and computed color, size, padding, border and icon fill/stroke match in light and dark.
Toolbar to table spacing.
The re-run showed one more difference: RubyUI's table sat 8px higher. DataTable uses space-y-4 (16px), while the block's Tabs root has gap-6 (24px) between the toolbar and the table (and gap-4 between the table and the pagination). DataTableToolbar now has mb-6, which overrides space-y-4's zero-specificity margin below the toolbar only.
After these changes the per-state pixel diff dropped from about 26k px (light) and 44k px (dark) to 33 px in every state (closed, open, focus, after-esc). The 33 px are the font fallback on "row(s)", the environment difference the audit already reports.
Screenshots
Each image is RubyUI on main + #579, RubyUI with this PR, and shadcn (Base UI + vega).




Audit checklists
Before (main + #579)
shadcn audit ruby-ui/ruby_ui
base 1fd93db0 head 78c4c242 shadcn 42f3bb63
⚠️ Environment font: "Inter Variable", "system-ui", -apple-system, "system-ui", "Segoe UI", Roboto, "Helvetica Neue", Arial, "sans-serif" vs "Inter Variable", sans-serif (light)
⚠️ Environment font: "Inter Variable", "system-ui", -apple-system, "system-ui", "Segoe UI", Roboto, "Helvetica Neue", Arial, "sans-serif" vs "Inter Variable", sans-serif (dark)
✅ Theme neutral tokens match shadcn
DataTable (ref: bases/base/blocks/dashboard-01/components/data-table.tsx + style-vega.css @ 42f3bb63)
❌ Look display: inline-flex
vega: display: flex
DataTableColumnToggle — closed/light, open/light, focus/light, after-esc/light, closed/dark, open/dark, focus/dark, after-esc/dark
↳ computed styles (shadcn-audit collect)
❌ Look display: block; text-align: start
vega: display: flex; text-align: left
DataTableRowCheckbox — closed/light, open/light, focus/light, after-esc/light, closed/dark, open/dark, focus/dark, after-esc/dark
↳ computed styles (shadcn-audit collect)
⏸ Look properties: font-family
DataTableColumnToggle, DropdownMenuContent, DataTablePerPageSelect, DataTableRowCheckbox — explained by environment diff: font
✅ ARIA DataTableColumnToggle, DropdownMenuContent, DataTablePerPageSelect, DataTableRowCheckbox: accessibility tree matches
↳ accessibility tree (shadcn-audit collect)
❌ Look status/type badges: Badge(variant: :outline, size: :sm) → h-4 text-foreground, no status icon
vega: Badge variant=outline className="px-1.5 text-muted-foreground" → h-5 text-muted-foreground; Done: CircleCheckIcon fill-green-500 dark:fill-green-400, otherwise LoaderIcon; type badge inside div.w-32
Fixture composition (and the shadcn fixture lacked the block's status icons): the badges read darker and shorter on RubyUI.
↳ bases/base/blocks/dashboard-01/components/data-table.tsx:194
❌ Look DataTable space-y-4: 16px between toolbar and table
vega: Tabs root gap-6: 24px between toolbar and table (16px table → pagination, gap-4)
The table sits 8px higher on RubyUI.
↳ bases/base/blocks/dashboard-01/components/data-table.tsx:434
After (this PR)
shadcn audit ruby-ui/ruby_ui
base 1fd93db0 head 6e0a3ea9 shadcn 42f3bb63
⚠️ Environment font: "Inter Variable", "system-ui", -apple-system, "system-ui", "Segoe UI", Roboto, "Helvetica Neue", Arial, "sans-serif" vs "Inter Variable", sans-serif (light)
⚠️ Environment font: "Inter Variable", "system-ui", -apple-system, "system-ui", "Segoe UI", Roboto, "Helvetica Neue", Arial, "sans-serif" vs "Inter Variable", sans-serif (dark)
✅ Theme neutral tokens match shadcn
DataTable (ref: bases/base/blocks/dashboard-01/components/data-table.tsx + style-vega.css @ 42f3bb63)
✅ Look text-align: start — intentional
DataTableRowCheckbox — In a left-to-right document start resolves to left, and the input has no text to align either way.
↳ audit/divergences/data_table.yml
✅ Look display: block — intentional
DataTableRowCheckbox — flex only lays out children, and the native input has none (its check mark is an absolutely positioned ::before), so block and flex render the same box. Adding flex to the input would change nothing on screen.
↳ audit/divergences/data_table.yml
⏸ Look properties: font-family
DataTableColumnToggle, DropdownMenuContent, DataTablePerPageSelect, DataTableRowCheckbox — explained by environment diff: font
✅ ARIA DataTableColumnToggle, DropdownMenuContent, DataTablePerPageSelect, DataTableRowCheckbox: accessibility tree matches
↳ accessibility tree (shadcn-audit collect)
✅ Look DataTableColumnToggle: wrapper and DropdownMenu root display: contents → button is a toolbar flex item, computes display: flex
inline-flex blockifies to flex in a flex container; the RubyUI wrappers had kept the button in block flow.
↳ bases/base/blocks/dashboard-01/components/data-table.tsx:475
✅ Look Badge(variant: :outline, class: "px-1.5 text-muted-foreground") + lucide circle-check (fill-green-500 dark:fill-green-400) / loader; type badge in div.w-32
Fixture only, Badge unchanged. Computed color, size, padding, border and icon fill/stroke match, light and dark.
↳ bases/base/blocks/dashboard-01/components/data-table.tsx:194
✅ Look DataTableToolbar mb-6: 24px before the table, 16px table → pagination
Pixel diff per state down from ~26k (light) / ~44k (dark) px to 33 px (font fallback on "row(s)").
↳ bases/base/blocks/dashboard-01/components/data-table.tsx:434
Test steps
cd gem && bundle exec rake(782 runs + new toolbar and toggle tests, standardrb clean).cd audit && bundle exec rake testandcd mcp && bundle exec rake test./shadcn-audit data_table: the Look lines forDataTableColumnToggleandDataTableRowCheckboxno longer fail, and the per-state pixel diff is about 33 px.- On
/docs/data_table_demo, the Columns menu still opens, toggles columns and returns focus on Esc.
The base branch pierry01/data-table-per-page-select is an unchanged copy of #579's head (78c4c242), because GitHub stacks don't take fork PRs. Merge #579 first, then retarget this PR to main.
🤖 Generated with Claude Code