Skip to content

fix(ui): the pinned seam runs through the header, not just the body - #575

Merged
blove merged 1 commit into
mainfrom
blove/pinned-header-seam
Sep 4, 2026
Merged

fix(ui): the pinned seam runs through the header, not just the body#575
blove merged 1 commit into
mainfrom
blove/pinned-header-seam

Conversation

@blove

@blove blove commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

The gap in the pinned column's shadow on the hero grid. Reported against the deployed site and confirmed there before touching anything.

What it is

The frozen edge is one boundary meant to run the height of the grid, and only the body drew it. [data-pretable-cell][data-pretable-pinned="left"|"right"] carried the --pretable-seam-color shadow; the pinned header cells took the opaque --pretable-bg-header fill and nothing else. So the seam started 51px down — a header-tall gap at the top of it, on any grid with a pinned column and somewhere to scroll sideways.

Measured on production (pretable.ai) before the fix, with the hero grid scrolled 280px sideways:

element box-shadow
[data-pretable-cell][data-pretable-pinned="left"] rgba(16,17,26,0.2) 8px 0 8px -8px
[data-pretable-header-cell][data-pretable-pinned="left"] (right beside it) none

The fix

The header's single two-selector rule is split per side, each carrying the mirrored offset its body counterpart already has — the same reason --pretable-seam-color holds a colour rather than a whole shadow: one shadow value cannot be reversed.

Nothing else changes. Pinned siblings share z-index: 1, so each paints over the shadow the one before it cast and only the outermost seam is ever seen — verified in the body, where the checkbox column's seam is invisible under the Symbol column beside it, and now true of the header for the same reason.

Why the guard didn't catch it

Same shape as the last round. "the pinned seam is wired, mirrored, and outlives the group-row band" named [data-pretable-cell] alone, so the half that was missing was the half it could not see. It now checks both header rules for the mirrored offsets, and that the seam did not cost the opaque fill.

Mutation-tested — each of these makes the guard fail, then restored:

FAILS (good)  left header loses its seam
FAILS (good)  right header seam is not mirrored
FAILS (good)  header seam costs the opaque fill

Splitting the rule also tripped the existing "pinned header cells get an opaque background, both sides" guard, which is now written per side rather than against the combined selector.

Verification

pnpm format, pnpm lint, pnpm typecheck and pnpm test pass; 38 Playwright smoke specs pass against a local production build, including the right-pin and column-reorder cases.

Checked at the pixel in Chrome on that build, not just in the stylesheet:

  • Hero grid scrolled 280px sideways — the seam is continuous from the top of the header band down through the rows. Toggling the new declaration off in the live page reproduces the reported gap exactly, which is the before/after pair.
  • Both pinned header cells compute rgba(16,17,26,0.2) 8px 0 8px -8px and keep rgb(239,240,244).
  • The column-layout showcase's right-pinned note column mirrors it at -8px.

🤖 Generated with Claude Code

The frozen edge is one boundary running the height of the grid, and only the
body drew it. `[data-pretable-cell][data-pretable-pinned="left"|"right"]`
carried the --pretable-seam-color shadow; the pinned HEADER cells took the
opaque --pretable-bg-header fill and nothing else. So the seam started 51px
down — a header-tall gap at the top of it, on any grid with a pinned column
and somewhere to scroll sideways. Measured on the deployed hero grid before
the fix: the pinned body cell computed
`rgba(16,17,26,0.2) 8px 0 8px -8px` while the pinned header cell beside it
computed `none`.

Split the header's one two-selector rule in two, each side carrying the
mirrored offset its body counterpart already has — the same reason
--pretable-seam-color holds a colour rather than a whole shadow. Nothing
else changes: pinned siblings share z-index 1, so each paints over the
shadow the one before it cast and only the OUTERMOST seam is ever seen,
exactly as in the body.

The guard is the same story as last time: "the pinned seam is wired,
mirrored, and outlives the group-row band" named [data-pretable-cell] alone,
so the half that was missing was the half it could not see. It now checks
both header rules for the mirrored offsets and for the fill the seam must
not have cost. Mutation-tested: dropping the left header's seam, giving the
right header the unmirrored offset, and trading the fill for the seam each
make it fail. Splitting the rule also tripped the existing opaque-background
guard, which is now written per side.

Verified in Chrome on a production build, at the pixel: with the hero grid
scrolled 280px sideways the seam is continuous from the top of the header
band down through the rows, and the showcase's right-pinned column mirrors
it at -8px. `pnpm format`, `lint`, `typecheck` and `test` pass, as do 38
Playwright smoke specs including the right-pin and column-reorder cases.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@blove
blove enabled auto-merge (squash) September 4, 2026 03:28
@vercel

vercel Bot commented Sep 4, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated
pretable Ignored Ignored Sep 4, 2026 3:28am UTC

Request Review

@github-actions

github-actions Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Vercel preview ready

Preview: https://pretable-1i80y035s-cacheplane.vercel.app
Commit: f6c0b6975534d1f87829ad2e68ed561a0e05f7e5

Updated automatically by the deploy-preview job.

@blove
blove merged commit 3a5ba25 into main Sep 4, 2026
37 of 38 checks passed
@blove
blove deleted the blove/pinned-header-seam branch September 4, 2026 04:41
@blove blove mentioned this pull request Sep 4, 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