Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
196 changes: 196 additions & 0 deletions packages/pluggableWidgets/datagrid-web/AGENTS.md

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions packages/pluggableWidgets/datagrid-web/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),

## [Unreleased]

### Fixed

- We fixed an issue where the scrollbar disappeared in virtual scrolling mode after hiding a column.

## [3.9.0] - 2026-03-23

### Changed
Expand Down
6 changes: 6 additions & 0 deletions packages/pluggableWidgets/datagrid-web/CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Datagrid Web — Claude Code

See @AGENTS.md for full architecture, DI wiring, component tree, and routing map.

This file exists as a Claude Code proxy. All datagrid-web context lives in AGENTS.md
so it is available to any AI agent, not just Claude Code.
26 changes: 26 additions & 0 deletions packages/pluggableWidgets/datagrid-web/e2e/DataGrid.spec.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
import AxeBuilder from "@axe-core/playwright";
import { expect, test } from "@playwright/test";
import path from "path";
Expand Down Expand Up @@ -195,6 +195,32 @@
});
});

test.describe("virtual scrolling + column hiding", () => {
test("scrollbar remains after hiding a column", async ({ page }) => {
await page.goto("/p/filtering-multi");
await page.waitForLoadState("networkidle");

const grid = page.locator(".mx-name-dataGrid21");
await grid.waitFor({ state: "visible", timeout: 15000 });

const gridBody = grid.locator(".widget-datagrid-grid-body");

const before = await gridBody.evaluate(el => ({
hasScrollbar: el.scrollHeight > el.clientHeight
}));
expect(before.hasScrollbar).toBe(true);

await grid.locator(".column-selector-button").click();
await page.locator(".column-selectors > li").first().click();
await page.waitForTimeout(300);

const after = await gridBody.evaluate(el => ({
hasScrollbar: el.scrollHeight > el.clientHeight
}));
expect(after.hasScrollbar).toBe(true);
});
});

test.describe("a11y testing:", () => {
test("checks accessibility violations", async ({ page }) => {
await page.goto("/");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@ export const Pagination = observer(function Pagination(): ReactNode {
canNextPage={paging.hasMoreItems}
canPreviousPage={paging.currentPage !== 0}
gotoPage={page => paging.setPage(page)}
nextPage={() => paging.setPage(n => n + 1)}
nextPage={() => paging.setPage((n: number) => n + 1)}
numberOfItems={paging.totalCount}
page={paging.currentPage}
pageSize={paging.pageSize}
showPagingButtons={paging.showPagingButtons}
previousPage={() => paging.setPage(n => n - 1)}
previousPage={() => paging.setPage((n: number) => n - 1)}
pagination={paging.pagination}
/>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export const WidgetFooter = observer(function WidgetFooter(): ReactElement | nul
<div className="widget-datagrid-pb-middle">
<button
className="btn btn-primary widget-datagrid-load-more"
onClick={() => paging.setPage(n => n + 1)}
onClick={() => paging.setPage((n: number) => n + 1)}
tabIndex={0}
>
{loadMoreButtonCaption}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,14 @@ const _01_coreBindings: BindingGroup = {
DG.exportProgressService,
SA_TOKENS.selectionDialogVM
);
injected(GridSizeStore, CORE.atoms.hasMoreItems, DG.paginationConfig, DG.setPageAction, DG.pageSize);
injected(
GridSizeStore,
CORE.atoms.hasMoreItems,
DG.paginationConfig,
DG.setPageAction,
DG.pageSize,
CORE.atoms.visibleColumnsCount
);
},
define(container: Container) {
container.bind(DG.basicDate).toInstance(GridBasicData).inSingletonScope();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,21 @@ export class GridSizeStore {
columnSizes?: number[];

private lockedAtPageSize?: number;
private lockedAtColumnCount?: number;

constructor(
private readonly hasMoreItemsAtom: ComputedAtom<boolean | undefined>,
private readonly paginationConfig: PaginationConfig,
private readonly setPageAction: SetPageAction,
private readonly pageSizeAtom: ComputedAtom<number>
private readonly pageSizeAtom: ComputedAtom<number>,
private readonly visibleColumnsCountAtom: ComputedAtom<number>
) {
makeAutoObservable<GridSizeStore, "lockedAtPageSize">(this, {
makeAutoObservable<GridSizeStore, "lockedAtPageSize" | "lockedAtColumnCount">(this, {
gridContainerRef: false,
gridBodyRef: false,
gridHeaderRef: false,
lockedAtPageSize: false,
lockedAtColumnCount: false,

scrollBarSize: observable,
setScrollBarSize: action,
Expand Down Expand Up @@ -114,6 +117,14 @@ export class GridSizeStore {
this.lockedAtPageSize = undefined;
}

// Reset the locked height when visible column count changes so layout
// is recomputed for the new column widths (rows may reflow).
const currentColumnCount = this.visibleColumnsCountAtom.get();
if (this.gridBodyHeight !== undefined && this.lockedAtColumnCount !== currentColumnCount) {
this.gridBodyHeight = undefined;
this.lockedAtColumnCount = undefined;
}

const gridBody = this.gridBodyRef.current;
if (!gridBody || this.gridBodyHeight !== undefined) {
return;
Expand All @@ -135,5 +146,6 @@ export class GridSizeStore {
const overflows = gridBody.scrollHeight > viewportHeight;
this.gridBodyHeight = viewportHeight - (overflows ? 0 : VIRTUAL_SCROLLING_OFFSET);
this.lockedAtPageSize = currentPageSize;
this.lockedAtColumnCount = this.visibleColumnsCountAtom.get();
}
}
Loading