feat(grid)!: replace frozen panes with pinning and sticky docking - #1302
ghiscoding wants to merge 21 commits into
Conversation
|
@6pac I think you should close your previous PR #1238 since this is the new approach that includes Pinning and Sticky. Please note that I would ask if you can ask Claude to audit and verify the entire PR to detect any possible problem, there's a progress file written by AI and read by AI to keep it focused, you should tell Claude to read that file Side note, with the code now you can at least start testing it out (including the new Also important, the +/- 1000px that we carried from the original SlickGrid lib is officially gone in this PR, I'm pretty sure that it was in place to support legacy IE browser back in the day but there's no reason to keep such old code and approach that caused alignment issues when implementing this PR and so I told the AI to remove it all, which is a lot easier to read the DOM now |
|
OK, Claude Fable is done with the evaluation. There's a lot of it! |
Evaluation of 6pac/SlickGrid PR #1302 — "feat(grid)!: replace frozen panes with pinning and sticky docking"
1. VerdictNot mergeable as it stands. The architecture is sound and the big-ticket claims (one viewport, one row per data row with left/centre/right regions, one horizontal scroll owner, Top issues (details in §4):
Nothing found requires abandoning the design. Most items are local fixes; the largest are the row-reference model (§4.1 group B) and the hit-testing/wheel routing for docked content (group D). 2. What was verified and how
Not done: no unit tests exist in this repository (the 3. Cypress results (local run, Windows)
The one failure is
Otherwise the suite is green locally, which matches CI. Note that green CI does not cover findings 1–7 above: the spreadsheet spec asserts the wrong pinned count, no spec drags a range over pinned cells, no spec uses non-contiguous row pins, 4. FindingsSeverity: Blocker = wrong behaviour for ordinary configurations or silent regression for existing users; High = wrong behaviour for documented pinning/sticky configurations; Medium = correctness edge cases, performance, API hygiene; Low/Nit = polish. Status: Confirmed (re-verified in source or browser), Observed (seen in the browser), Reasoned (reviewer, from code only). 4.1 Blockers and HighA. Column pinning referencesA1. Blocker — Numeric index references are also matched against A2. High — Numeric shorthands count hidden columns; B. Row references (pinned and sticky rows)B1. High — B2. High — The id→index cache is never invalidated on a count-preserving DataView sort/filter. Confirmed in B3. High — Custom DataView B4. High — Bottom-pinned rows keep their natural slot in the canvas. Reasoned ( B5. High — Non-contiguous top pins break hit-testing and active-cell tracking. Reasoned. Unpinned rows render at B6. High — Sticky-row thresholds ignore the permanent top band and subtract the bottom band twice. Confirmed in B7. High — B8. Medium — C. Regressions for grids that do not use pinning at allC1. Blocker — Every C2. Blocker — Vertical wheel now scrolls one row per notch on every grid. Confirmed by diff. C3. Blocker — Ctrl/Meta+drag multi-selection regressed. Confirmed by diff. Base C4. High — Undocumented rename C5. High — C6. High — Plain grids pay O(columns) per rendered cell in C7. Medium — Keyboard/focus contract changes not listed as breaking. Reasoned. Focus sinks moved outside the container with C8. Blocker — D. Interaction with docked contentD1. High — D2. High — Wheel over a pinned/sticky row scrolls the page. Reasoned. D3. High — Column reorder throws when a sticky column is docked (LTR proxy path). Reasoned. D4. High — Forwarded chrome D5. Medium — Docked rows outside the vertical rendered range never receive new centre cells on horizontal scroll, and in-range docked rows are never cell-cleaned. Reasoned ( D6. Medium — D7. Medium — Pinning cannot be switched off at runtime; the proxy scroller and chrome regions are created lazily but never removed. Confirmed by reading D8. Medium — Lazy docking activation empties header/header-row/footer without firing the D9. Medium — Cross-band colspan fragments freeze the host's E. Legacy surface and claimsE1. High — Legacy frozen options remain declared with live JSDoc; the Grid Menu still branches on them. Confirmed. E2. High — PR description and progress file claim things that do not exist in this repository. Confirmed by grep/diff.
E3. High — Test integrity. Confirmed by diff.
4.2 MediumM1. Performance on the per-scroll path. Reasoned by two reviewers (consistent with each other):
M2. M3. Public API drift not listed as breaking. Reasoned/confirmed by call-site diff:
M4. slickgrid-universal leakage into public types. Confirmed in the model diff. M5. Dead file that ships as an empty bundle. Confirmed. M6. Docked-row overlay artifact with zero-width scrollbars. Observed only in headless Chrome with scrollbars hidden (which is what overlay-scrollbar platforms such as macOS report): the last digit of each docked sticky row's rightmost cell is painted a second time, offset down-right, in the strip between the overlay clip and the grid border ( M7. Small controller/geometry issues. M8. Examples and docs. 4.3 Low / Nits
5. Verified sound
6. Recommended actions before merge
7. Reproducing the confirmed findingsAll steps use the repository's own scripts on a clean checkout of the PR branch (
|
|
Hang on a minute, there's quite a bit of stuff in there that's specific to my computer and its environment. I'm just gonna remove that and repost. |
|
OK the evaluation has been updated |
|
wow that is a lot.... providing this to Codex, and we'll see what it's able to fix. Just curious, do you also have access to Fable 5.1? Seems like an improvement, probably more expensive though Side note I also fixed colspan just now which can now spread on both side of the column pinning and also updated data Grouping which also spreads its grouping title (see above). |
|
Yep, this review was done with Fable 5.1. It did take up about 35% of my weekly quota though! Which is fine, I usually don't use more than about 30% of it anyway. |
| const queueMicrotaskPolyfill = (callback: () => void) => typeof queueMicrotask === 'function' ? queueMicrotask(callback) : setTimeout(callback, 0); | ||
| const destroyAllElementProps = (_target: object) => undefined; | ||
| const destroyAllElementProps = (target: object): void => { | ||
| const elementProperties = [ |
There was a problem hiding this comment.
not really sure why it added all of these, this seems very overkill. Shouldn't it be able to destroy and remove whatever it needs without us having to name all functions? I assume it came from Claude report
|
@6pac ok the AI is done with the audit report, the remaining things it said was basically verifying the UI myself... can you do a final audit to make sure it fixed everything. Also, can you ask it to see if it there's any areas to decrease LOC (I usually ask the AI if it's the most minimalist it can do without regressing). I'm especially concerned about the comment I left just above, I don't understand the point of listing all function names to loop and and destroy (this seems ridiculous and not minimalist to do this way). If there's anything else, I'd prefer you let it fix the rest... having a different AI model to double-check is actually a very good exercise, this will be used for the next few years, so better be good :) ahh wait, last commit caused a few test failures, let me fix them
|
|
@6pac ok I'm done and fixed Cypress failures, so would you mind addressing what I wrote above |
|
In the middle of a very busy workday, but I'll point Claude at it and see how it goes. The destroyAllElementProps issue looks like a reversion rather than something Claude suggested (it found an issue with that function, but that's not the suggestion it made), from what I can see. I'll query it. |
|
ah yeah it might have been my old code actually, but I think we can remove that or lighten it at least. Thanks. There's no rush on it, need to make sure that we cover all angles and that the UI/UX works for you :) |
|
Here's the eval. Let me know if you're happy to go ahead and I can get Fable to do the final commits. |
Re-evaluation of 6pac/SlickGrid PR #1302 after the audit-fix commits
1. SummaryThe fix commits are substantive, not cosmetic. Of the eight blocker/high items that were demonstrated live in the first report, seven are fixed and verified on the new build (column over-pinning, autoHeight band, wheel behaviour, Ctrl+drag selection, editor placement, row-reference matching and cache invalidation, docked-cell hit-testing). The frozen option surface, the dead re-export file, the three tautological quirk specs and the missing documentation are dealt with. Two items were "fixed" in a way that needs another pass (bottom-pinned rows, Still blocking, in my view:
Worth doing before merge but not blocking: the remaining universal-fork leakage, the unrequested keyboard/focus feature carried in from slickgrid-universal, and the LOC/comment reductions in §5. 2. What was re-run
3. Status of the first report's findingsLegend: Fixed (verified) = re-demonstrated on the new build; Fixed (code) = the diff addresses it, not executed; Partial; Open. Column references
Row references
Regressions for non-pinned grids
Docked-content interaction
Legacy surface, claims, tests
Medium items
4. Review of the fix commits themselves4.1
|
| # | What | Est. saving | Effect on perf / readability |
|---|---|---|---|
| 1 | Unrequested keyboard/focus feature ported from universal: focusHeaderRowFilter (33), focusHeaderMenuOrColumn (15), focusGridMenu (12), focusHeaderColumn, focusGridCell, focusElementWithoutBubbling, stopFullBubbling, getVisibleElements, handleContainerKeyDown (20) and the F6/Tab/Shift+Tab routing inside handleGridKeyDown (~20). The selectors they target (.slick-header-menu-button[tabIndex="0"], .slick-grid-menu-button[tabIndex="0"]) have no producer in this repo. |
−130 | None on perf; removes an undocumented behaviour change (C7). Ship it as its own PR with plugin support if wanted. |
| 2 | Universal leakage in §4.3 | −120 src, −20 models | None; removes dead branches and any types. |
| 3 | Narrative comments. Many new comments are debugging history ("placed right-pinned titles at that stale edge (for example 1537px for a 1637px proxy)", "The docking POC's one horizontal scrollbar…", 10-line justifications before one-line writes). Trim to intent-level comments. |
−200 to −300 | Improves readability; the file already has 2,343 comment lines. Keep the ones that explain a non-obvious invariant (proxy translation, overlay clip, row shift). |
| 4 | destroyAllElementProps → reflective method (§4.1) |
−45 | Safer. |
| 5 | applyDockingToColumnChrome (161 lines): the four branches (sticky-transform / centre / left / right) each set position/left/right/order/transform with slightly different values; a placeChrome(element, { position, left, right, order, transform, offset }) helper and building dockingChromeByColumn from getHeaderColumn(id) instead of querySelectorAll(...).find per column |
−50 | Also removes the O(n²) header lookup on every resize step. |
| 6 | setOptions pinning/stickyRows array replacement as a loop or Utils helper |
−30 | Neutral. |
| 7 | Revert the slick-state-default rename |
−10 src, −25 scss | Removes a breaking change; nothing in this repo keys on either class. |
| 8 | applyRowTopOffset (74): the rowspan metadata scan can be computed once per row at render time and stored on the cache entry instead of on every syncDockedRowContainers pass |
−20 | Faster vertical scrolling on row-docked grids. |
| 9 | Small unused/duplicate public methods: getColumnByIdx (0 callers), getColumnHeaderByIndex (alias of getColumnByIndex), removeCellCssStylesBatch (0 external callers), getTopPanels returning the same panel twice |
−30 | Smaller public surface. |
| 10 | updateRenderedColspanFragmentGeometry host lookup fallback (querySelectorAll + find) — the host is always in cellNodesByColumnIdx |
−6 | Neutral. |
Total: roughly 650–750 lines (about a third of the net growth) without touching the docking architecture, and items 5 and 8 are also performance improvements. What should not be cut: the region-routing code in appendRowHtml/appendCellHtml/createColumnHeaders, the DockingController, the overlay/proxy sync — that is the feature.
6. Cypress
| Specs | 68 (67 + new example11-autoheight.cy.ts) |
| Passing | 710 |
| Failing | 1 — example-plugin-headermenu.cy.ts › "…Feedback->ContactUs sub-menus…": level-2 sub-menu still opens dropleft on Windows (Electron); unchanged from the first report, where the base version of the spec passed on the same machine. Nothing in the fix commits touches header layout or getGridPosition().width, so this was expected |
| Pending | 1 (example-auto-scroll-when-dragging "MAX interval", skipped in base too) |
The new and reworked specs (example11-autoheight, the three quirk-pinning-* harnesses, the spreadsheet hidden-column case, example-grouping-esm pinning cases, example-colspan pinned-colspan cases) all pass and now assert the intended behaviour rather than echoing options.
7. Recommended next steps
- Fix bottom-pin reachability (B4) — extend the scroll range or shrink the scroll viewport by the band height; add a spec that scrolls to the end with
bottom: [N-1]and asserts row N−2 is fully visible, with and withoutenableAddRow. - Replace the
destroyAllElementPropslist with the reflective method (§4.1). - Replace the
elementFromPointfallback with a geometric inverse (B5/D1) so off-screen drag coordinates resolve correctly under non-contiguous pins. - Decide the colspan-over-pinning look: the probe shows the host does paint over scrolled centre cells (§4.2). Unless that is the intended AG-Grid-style behaviour for every cross-boundary colspan, clip the host to its band and let the fragment carry the text.
- Remove the universal leakage (§4.3) and, unless the focus feature is wanted now, the focus/keyboard routing (§5 item 1).
- Address the open Ds (D3, D4, D5, D8, D9) or list them explicitly as known limitations in
docs/pinning-sticky.md. - Expand
docs/pinning-sticky.mdinto a real migration section and remove the stale narrative from the progress file (or delete the file from the PR). - Reproduce the Windows header-menu alignment failure (§6) — it is deterministic here and passes on the base.
|
@6pac so I would prefer if you ask Claude to finish the rest, I'm out of token until Saturday anyway. Thanks |
|
Can do, might be worth looking at the '5. Can the PR lose lines without hurting performance or readability?' section especially 1,7,8 - they are all optional. Would be good for you to check. eg. 7, 8 maybe should be left for legacy purposes. |
`destroy(true)` nulled a hand-maintained list of 46 property names, so every new element field (the docking overlay, proxy scroller and chrome regions among them) had to be added in two places and `dockingChromeByColumn` was missed. The element references are now cleared by content: any field holding an element, a non-empty array of elements or a plain record of elements is nulled, and the chrome map is cleared. A self-hosted spec checks single, array and record fields on a plain and a pinned grid. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…6pac Drop the options, fields and code paths that were carried over from the multi-package fork and have no implementation here: the formatted-data cache planner and its DataView hooks (`SlickDataView` implements neither), `enableGridMenu` last-column compensation, `enableRowDetailView`/`rowDetailView.renderMode`, `silenceWarnings` and the zoom warning, `selectionOptions` (the selection model's own option is authoritative again), `datasetIdPropertyName` (the DataView's id property is used), `Column.editorClass`, `exportCustomFormatter`, `exportWithFormatter`, the unread `Column.pinnable`, `EditorArguments.isCompositeEditor`, and the `FormattedDataCachePlanner`/`TrustedHTML` type stubs. `sanitizeHtmlString` is back to its 6pac signature with the `logSanitizedHtml` logging path. The two functional additions that were kept (`allowDragFromClosest`, `columnResizingDelay`) are now documented. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
`getCellFromPoint()` on a docking grid used `document.elementFromPoint()` and fell back to the natural layout when the point was off-screen or not over a cell, so drag auto-scroll and non-contiguous row pins still resolved the wrong cell. The point is now mapped geometrically: pinned/sticky rows through the overlay bands, scrolling rows through the inverse of `getRenderedRowTop()`, and columns through the left/centre/right band offsets at the current scroll position. RTL and non-docking grids keep the original calculation. With the end cell resolved correctly, dragging upward from the bottom-right of a pinned grid auto-scrolls up again, which is what the base spec asserted; the weakened `equal` assertion is restored to `greaterThan`. A self-hosted spec covers pinned columns and rows while scrolled, a row shifted by a non-contiguous pin, and a row that is not rendered. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The previous change removed bottom-pinned rows from the canvas flow by shortening the canvas by their height. The viewport and the overlay band were unchanged, so at maximum scroll the last unpinned row (or the add-new row) sat exactly under the band and could not be reached. The canvas now keeps its full height: rows after a bottom pin are still rendered one pinned height higher, so the pinned row's slot collapses to the end of the canvas where the band covers it, and every scrolling row stays visible above it. A self-hosted spec checks a pinned last row, a pinned last row with `enableAddRow`, and a pinned middle row. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ments `updateCellCssStylesOnRenderedRows()` only touched the logical host cell, so a colspan that crosses a docking boundary kept the `selected` (or any custom) class on its continuation fragment after the host lost it. Added and removed classes are now applied to the host and to every fragment of the span. The colspan spec selects a fragment, checks both pieces carry `selected`, then selects another cell and checks both are cleared. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Enabling pinning on an initialized grid (and removing it again) rebuilt the header, header-row and footer chrome through the docking region helpers, which emptied the roots before `createColumnHeaders()`/`createColumnFooter()` could fire `onBeforeHeaderCellDestroy`, `onBeforeHeaderRowCellDestroy` and `onBeforeFooterRowCellDestroy`, so plugins attached to those cells never cleaned up. The destroy events are now fired by the region set/reset helpers themselves right before they empty a root, which covers the initial build, lazy activation and deactivation from one place; the duplicated loops in the header and footer builders are removed and the header-row event now passes the cell as `node` as its type declares. A self-hosted spec counts each event per column across activation and removal. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
`cleanUpAndRenderCells()` only walked the vertical render range, so a pinned row outside it (typically a pinned last row on a long dataset) never received new centre cells when the grid scrolled right, and `cleanUpCells()` exempted every pinned row, so docked rows inside the range accumulated cells without bound. Docked rows are now appended to the rows processed against the horizontal range and cleaned like any other row; the pinned bands themselves are still always materialized. A self-hosted spec scrolls a 40-column grid with a pinned first and last row and checks that both gain the newly visible column and drop the off-screen one. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
With the docking horizontal scrollbar, the viewport and the header/header-row/footer containers stay at scrollLeft 0 while their content is translated by the proxy position. A native scroll on one of them (the browser revealing a focused filter, an integration scrolling `.slick-viewport`) is therefore a delta from the current position, but it was forwarded as an absolute position, jumping the grid back towards the left edge. It is now added to the proxy position, and `handleElementScroll()` no longer mirrors the reset-to-zero echo of those containers as an absolute position. A self-hosted spec scrolls the proxy to 400, scrolls the header-row container by 60 and expects 460. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
On the sticky transform path an active sticky column is listed in the resolved left/right band while its header stays in the centre header region. The drop handler mapped the resolved bands onto the three Sortable arrays, so a docked sticky column produced an undefined slot and the drop threw while destructuring it. Slots are now derived from the band each header actually lives in (permanent pins left/right, everything else centre in column order), and a slot/array length mismatch leaves the order unchanged instead of throwing. A self-hosted spec docks a sticky column by scrolling, drags one centre header onto another and checks the resulting column order and the reorder event. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… sub-menu alignment spec Renaming the demo command from "Freeze/Pinning" to "Pinning" made the level-0 header menu 13px narrower, which moved the drop-left level-1 menu 14px to the right. The level-2 alignment rule compares `item left + sub-menu width + item width` with the grid width; on Windows font metrics that sum went from 563 to 577 against a 575px grid, so the spec's `dropright` expectation failed there while Linux CI stayed green. The command is now "Column Pinning", the terminology used by the pinning feature, which restores the geometry. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… frozen-pane migration table `docs/pinning-sticky.md` now covers the option semantics (visible-column shorthands, index vs id references, row references), the runtime API, the docking budgets, rendering notes, the stable selectors, a migration table from the v5 frozen options/methods/classes, and the known limitations. The pinning skill and the implementation status file are rewritten to describe this flat repository only: no unit-test layer, no `Column.pinnable`, no fork-only Grid State, Header Menu or locale claims, and a verification section that lists the actual Cypress coverage. The row/column reference JSDoc states that numbers are indexes and strings are ids. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
PR #1302 — issues fixed since the first evaluationTwo rounds of fixes are covered: the PR author's commits Blockers and High
Medium
Documentation
New browser coverage added by the audit branch
Size
|
|
@ghiscoding Next is what's left that I thought you should look at before proceeding. Could you read it carefully and make calls? Assuming most of it's okay, probably just tell me what you don't want to do. |
PR #1302 — remaining issues after the audit-fix branchState: PR head 1. Behaviour and correctness
2. Performance
3. Tests
4. Size and readability (from v2 §5, not applied)
5. Examples and repo files
|
Yes sure, when I asked the AI to replicate my universal PR in here and it carried a lot of previous universal changes that you didn't have in your repo (e.g. step 1 or C7 above, is mostly about a11y that I've fixed in my repo which you didn't have, I also always display Header Menu in my grids, but in your repo it's an optional plugin). I would say, you could ask Claude to cleanup unused code but I think you should also ask it to do an a11y audit to improve it on your repo as well (that is you wish to do it) For some feedback from the last audit above:
The rest seems fine, so you could provide my feedback to Claude and let it finish accordingly. I will test the UI after work, Claude brought some very valid point, it's nice to have double AI audits, this will improve the features overall I think :) Have you had a chance to try the UI yourself? Also just to make sure you understand why it's now called Pinning and Freeze name is gone (pinning is now individual, as oppose to freeze a range, and you can even skip column pinning, e.g. Also I know we did increase LOC by more than a thousand lines of real code (excluding comments/interfaces), which I complained in your other PR, but I'm much more happy with the new UI/UX and I also based my implementation on Ag-Grid UX, which I think was also a good decision and we also gain Sticky which Ag-Grid doesn't even have (AI also said we could use Pinning & Sticky in same grid as well, which I was a bit surprised, but I haven't tried that, not sure anyone would do that anyway). So in the end, I find that this will be a big modernization improving UI/UX in a good direction :) |
|
Okay, I'll go ahead, noting those comments. In terms of the specific SlickGrid-Universal code, I'll remove it from this PR. I think it's a good idea to move as many of your SlickGrid-Universal enhancements back here as possible, but that should be separate PRs. Will look at that once we're done here. |
|
yes your approach makes sense and I like the idea you had the other day to decouple the column auto-sizing, that is the main difference with our 2 The main thing I'd like to do after all the fixes would be to do a final audit for LOC, because I find that especially ChatGPT it adds a lot extra often overcomplex logic fix things. So I often have to ask it to do a final review with a prompt like: "is that the most minimal you can do without regressing?". It often finds by itself that his logic was too complex and it could decreases LOC by a good amount... so AI is good in general but we still have to watch it sometime and avoid spaghetti code which adds LOC and we can often decrease them. I also have access to ChatGPT 6 Astra which is like Fable 5.2 but it's expensive and I only have a Pro subscriptions (25$/month), so it burns rather quickly... still I find it's important for such code because we'll use it for the years to come I'm pretty happy with the result so far (great UI/UX), it wouldn't have been possible without AI I think and I've been working on this for the past 3 weeks, which isn't too bad. |
|
Great. Happy to use Fable where possible if you want - I've just about run my Fable quota out this week but it renews every Wed. Most weeks I use 10% or less under normal use. It's funny, I've watched the AI churn - you can turn on a detailed view where you see every thought - and it seems to spend most of its time obsessing over where to store a file, or resolving some small ambiguity in the instructions that could be easily remedied in two words if it asked you. But it just eats up well defined complex problems. |
|
It's the most complex feature to work on, when that is shipped, then other tasks will be much less complex and less costly on AI usage for sure. By the way, I didn't quite understand how that works for Vitepress, does it need another CI workflow for it to publish the docs (I did look at it and it's pretty), because in comparison with the service I use which is free for open source project, it just sync it to a website but with Vitepress, do we need to do a build and the use the SlickGrid github.io link as website for the docs? I assume that part isn't done, right? Also it will need an update for current PR because I saw reference in the docs for your older 3x3 Viewport Mgr approach in the docs, will need cleanup |
|
With the docs, honestly, I wasn't paying that much attention to them. Deploying the SlickGrid VitePress docsNotes on how publishing works for the VitePress docs site (PR #1301), and why it differs from a "sync markdown to a website" service. Current state of GitHub PagesThe repo's Pages is set to "Deploy from a branch: How VitePress differs from a "just syncs" serviceA hosted docs service renders/hosts your markdown for you. VitePress is a static-site generator: the markdown + Vue components get compiled ( You don't run the build by hand each time — something automates it on every push. Two free-for-open-source ways: Option 1 — GitHub Actions → GitHub PagesThe To turn it on:
Option 2 — Netlify / Cloudflare Pages / VercelThis is the "connect the repo and it syncs" experience:
It auto-builds + hosts on every push, free for open source, on its own URL (or a custom domain/subdomain). It doesn't touch GitHub Pages at all — the examples stay exactly where they are. Is deployment done?No. The PR only contains the inert workflow file. Nothing is wired, Pages is untouched (still serving the examples), and the docs aren't hosted anywhere yet. This was deliberate — it's the outward-facing step to decide. RecommendationGiven the goal of low friction and not disturbing the examples site: Cloudflare Pages or Netlify pointed at If everything should live on Either way, |
|
It's up to you, if you want to create account on Netlify or Cloudflare, then you'll have to look into it. But option 1 would also work just as well, the main reason I went to GitBook on my side is actually because of 2 things (1. sync docs folder with website and 2. GitHub page only offers 1 live webpage per repo and I always use it for my own examples website, so I can't use it for docs). But in your case, you're not currently using it for anything since your examples aren't a separate live demo website like I do (because yours are just part of your Wiki links and that is also why we need to keep your dist folder in GitHub because without it, your examples wouldn't work). So because you're not using GitHub Page website for anything, you could use it for the docs. As for the sync, yeah sure Netlify/Cloudflare could offer you sync, but we can also do synching by adding a CI workflow to run on every commit and that would sync just the same... Personally, since you're not using the GitHub Page for anything, I would just go with Option 1, it's simple and doesn't require any new account of any kind. Feel free to go with Option 2 if you wish though, up to you really but I've never tried them myself (so can't really on that) If you go with Option 1, with GitHub Page, you can configure it through your repo Settings -> Pages, then I usually create a branch named "gh-pages" (that's the default name for it) and then have the CI update it by itself. Then I use
|
|
Okay, will investigate sometime soon. I understand what it's saying about VitePress, but honestly, I'm not across the different site areas available in GitHub and how CI interacts with them, so I'll have to check that out. |


supersede #1238
fixes #410
fixes #443
fixes #739
fixes #1219
Summary
Introduce a single-viewport docking architecture for permanent pinned columns/rows and
scroll-activated sticky columns/rows.
This is an intentional v6 breaking change. The previous multi-pane frozen implementation has
been removed from the runtime and replaced with one virtualized body viewport, one vertical
scroll owner, one horizontal scroll owner, and stable per-row left/center/right cell regions.
Why
The legacy frozen-pane implementation required multiple synchronized panes and scroll
containers. This increased complexity around scrolling, resizing, virtualization, editing,
grouping, and framework integrations.
The new architecture provides a simpler and more predictable model:
Unlike the previous freeze-until-column/row behavior, users can now pin individual columns or
rows independently. For example, columns 0 and 2 can be pinned while column 1 remains in the
center region.
Changes
GridOption.pinningsupport for:columns.left/columns.right;rows.top/rows.bottom.Column.pinnedandCurrentColumn.pinningstate support.Column.stickyandGridOption.stickyRowsfor scroll-activated docking.DockingControllerfor permanent and sticky column/row resolution.conveyor/clampoverflow strategies.
fragments.
and framework integrations.
example-sticky-financial-report.htmlColumn.pinnablesupport for controlling Header Menu pinning commands.pinningshape.is intentionally not serialized.
.slick-horizontal-scrollerand.slick-vertical-scrollerselectors.scroll branches, redundant viewport/canvas aliases, and old pane CSS classes.
-1000pxheader coordinate workaround andHEADER_WIDTH_SLACK.pinning-stickyskill as implementation and documentation guidance.Breaking changes
The old frozen-pane configuration and APIs are removed.
The canonical configuration is now:
Legacy flat pinning options and temporary aliases are no longer supported.
Sticky state is not serialized because it changes with scrolling.
The old multi-pane DOM structure and pane selectors are no longer available.
Column reordering remains within each docking band; moving a column between pinned and center
bands is an explicit pinning operation.
Legacy names and theme variables are retained only as migration documentation references.
References
Ag-Grid Column Pinning was used as key concept reference for the idea of a single horizontal scroller and single vertical scroller, also for its declaration of left/center/right cell docking regions
Validation
The following checks pass:
git diff --check.pinning/sticky, resizing, reordering, RTL, variable row heights, editing, selection,
grouping, spans, and framework parity.
The accessibility audit found no pinning/sticky-specific semantic-tree or keyboard-navigation
regressions. Automated axe/WCAG integration and manual screen-reader validation are not included
in this PR.
Implementation status
The single-viewport rewrite and legacy runtime cleanup are complete. This is no longer a POC
that runs alongside the old frozen-pane implementation.
The approximate library-only production diff is:
+3,989 / -1,550;+2,439net LOC relative to the base commit.These figures exclude demos, tests, generated output, and framework-wrapper changes.
Follow-up work
The following items are intentionally separate from the v6 implementation:
None of these requires restoring the legacy pane architecture or changing the current pinning/sticky
runtime design.
AI / LLM assistance
documentation updates, test maintenance, and validation support.
Checklist
documentation, tests, and cleanup.
Print Screens