Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
75c446b
First draft new layout table page
PerIngeVaaje Mar 5, 2026
172e927
Sticky also for xlarge and xxlarge
PerIngeVaaje Mar 5, 2026
64bf8ec
Try to fix z-index problem
PerIngeVaaje Mar 5, 2026
ba6b413
refactor: New wrapper in TableViewer for handling centered main conte…
MikaelNordberg Mar 6, 2026
a72116b
Prettier code
MikaelNordberg Mar 6, 2026
65f17a9
fix: Adjust NavigationDrawer layout on medium devices
MikaelNordberg Mar 6, 2026
dea6a6a
Changed comment
MikaelNordberg Mar 6, 2026
bd93aea
Removed padding-top in main container to stabalize navigation drawer
MikaelNordberg Mar 6, 2026
87b6ac0
refactor: Simplify padding in NavigationDrawer and update Header comp…
MikaelNordberg Mar 9, 2026
4477751
Prettier code
MikaelNordberg Mar 9, 2026
a41218a
Remove page scrollbar when side sheet is open
PerIngeVaaje Mar 9, 2026
e2fa85e
feat: Enhance scrollbar management with new context properties for se…
SjurSutterudSagen Mar 10, 2026
7d9f42d
refactor: Adjust dimensions and background color in Navigation compon…
SjurSutterudSagen Mar 10, 2026
368bc43
Use simpler scrollToTop in footer on tableview
SjurSutterudSagen Mar 10, 2026
8edb248
Remove commented out code
SjurSutterudSagen Mar 10, 2026
83276f0
Make header sticy on large screens only
SjurSutterudSagen Mar 10, 2026
2e13ca2
fix: Remove unnecessary border-top from NavigationDrawer styles
SjurSutterudSagen Mar 10, 2026
b0d7642
Merge branch 'main' into feature/PXWEB-896-new-layout-table-page
Mar 10, 2026
0902f2b
Moved GlobalAlert from RootLayout to TableViewer and StartPage.
PerIngeVaaje Mar 11, 2026
0fe06ae
set position fixed for large breakpoint in NavigationDrawer
PerIngeVaaje Mar 11, 2026
fa829f3
feat: add sticky header offset to SkipToMain and update TableViewer i…
SjurSutterudSagen Mar 11, 2026
1c2c8e8
refactor: update refs in Footer, Presentation, and TableViewer compon…
SjurSutterudSagen Mar 11, 2026
a8f889c
hange base color in NavigationItem for NavBar
SjurSutterudSagen Mar 12, 2026
f8d267c
fix: increase padding-top in NavigationDrawer for improved layout
SjurSutterudSagen Mar 12, 2026
2045734
refactor: simplify media query breakpoints and remove unused small ta…
SjurSutterudSagen Mar 12, 2026
02f462c
fix: update max-width in contentAndFooterContainer for improved layout
SjurSutterudSagen Mar 12, 2026
fbe97ca
Merge branch 'main' into feature/PxWeb2-806-new-layout-with-virtualiz…
SjurSutterudSagen Mar 12, 2026
0891a1b
Add virtualized table with outer scroll
SjurSutterudSagen Mar 12, 2026
a06d25b
Merge branch 'main' into feature/PxWeb2-896-new-layout-with-virtualiz…
SjurSutterudSagen Mar 13, 2026
f944c24
refactor: update Table component virtualization to work at table leve…
MikaelNordberg Mar 16, 2026
590e5aa
Prettier code
MikaelNordberg Mar 16, 2026
201ed03
Merge branch 'feature/PxWeb2-896-new-layout-with-virtualized-table' o…
MikaelNordberg Mar 16, 2026
a8c4c8a
refactor: enhance table virtualization logic by separating window and…
MikaelNordberg Mar 17, 2026
674f3a9
Add comment about mobile performance
SjurSutterudSagen Mar 18, 2026
009c60e
refactor: enhance Table component with improved virtualization for mo…
SjurSutterudSagen Mar 18, 2026
18b34e6
refactor: split into virtualized table components for mobile and desk…
SjurSutterudSagen Mar 18, 2026
3e31807
-- BIG Refactoring of Table --
MikaelNordberg Mar 19, 2026
f9b08d4
Prettier code
MikaelNordberg Mar 19, 2026
38fff2b
refactor: remove unused MemoizedTable component code
MikaelNordberg Mar 19, 2026
7edfeda
fix: ensure overflow is hidden in SideSheet component
MikaelNordberg Mar 20, 2026
eca179f
fix: add mobile header id for second-last stub in Table component
MikaelNordberg Mar 20, 2026
3d5b80c
fix: update virtualization thresholds for desktop and row in Table co…
MikaelNordberg Mar 23, 2026
5a3ddcf
fix: remove play function from Default story and update pxTable testd…
MikaelNordberg Mar 23, 2026
69613b0
fix: remove unused import from Table stories and correct formatting i…
MikaelNordberg Mar 23, 2026
a8726e3
Merge branch 'main' into feature/PxWeb2-896-new-layout-with-virtualiz…
MikaelNordberg Mar 23, 2026
1c7eae6
feat: add tests for desktop and mobile virtualized table components
MikaelNordberg Mar 24, 2026
b8f2bc5
feat: Refactored useBodyRowVirtualizationWindow to improve Cognitive …
MikaelNordberg Mar 24, 2026
e5ac823
feat: rename padding properties in ColumnWindow to improve clarity fo…
SjurSutterudSagen Mar 26, 2026
4544ee4
fix: clean up Table types/interfaces and constants
SjurSutterudSagen Mar 26, 2026
028f489
feat: -- Another BIG refactoring of Table --
MikaelNordberg Mar 27, 2026
cdafdaa
feat: Commented code
MikaelNordberg Mar 27, 2026
84ff252
feat: Enhance desktop header layout with responsive text wrapping and…
MikaelNordberg Mar 30, 2026
a894027
fix: Remove debug console log from calculateHeadingLevelLines function
MikaelNordberg Mar 30, 2026
ea3272a
fix: Update MOBILE_ROW_OVERSCAN constant to improve virtualization pe…
MikaelNordberg Mar 31, 2026
974225a
fix: Update MOBILE_ROW_OVERSCAN constant to improve virtualization pe…
MikaelNordberg Mar 31, 2026
d2b767a
feat: Update mobile row overscan and enhance desktop header layout fo…
MikaelNordberg Apr 1, 2026
8fad2b3
Prettier code
MikaelNordberg Apr 1, 2026
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
28 changes: 28 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions packages/pxweb2-ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"author": "",
"license": "MIT",
"dependencies": {
"@tanstack/react-virtual": "^3.13.21",
"@vitejs/plugin-react": "^5.2.0",
"clsx": "^2.1.1",
"hast-util-to-jsx-runtime": "^2.3.6",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
padding: 0px 0px 0px 0px;
border-style: none;
max-height: 100vh; // Override default margins at top and bottom for <dialog>
overflow: hidden;
}

.sideSheet::backdrop {
Expand Down
53 changes: 53 additions & 0 deletions packages/pxweb2-ui/src/lib/components/Table/Table.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,41 @@
thead th {
font-family: PxWeb-font, sans-serif;
font-weight: 700;

@media screen and (min-width: fixed.$breakpoints-small-min-width) {
min-width: 200px;
}
}

.desktopHeaderLabelWrapper {
@media screen and (min-width: fixed.$breakpoints-small-min-width) {
display: flex;
align-items: center;
justify-content: center;
min-height: calc(1.25em * var(--desktop-header-lines, 3));
}
}
.desktopHeaderLabel {
@media screen and (min-width: fixed.$breakpoints-small-min-width) {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: var(--desktop-header-lines, 3);
line-clamp: var(--desktop-header-lines, 3);
overflow: hidden;
text-overflow: ellipsis;
white-space: normal;
line-height: 1.25;
word-break: break-word;
}
}

thead tr:last-child th {
text-align: end;
border-bottom-width: 2px;

@media screen and (min-width: fixed.$breakpoints-small-min-width) {
text-align: center;
}
}
th.stub {
text-align: left;
Expand Down Expand Up @@ -255,4 +286,26 @@
background: var(--px-color-surface-moderate);
border: none;
}

.virtualPaddingCell {
padding: 0;
border: none;
background: none;
}
}

.virtualizedWrapper {
max-height: 70vh;
overflow-x: auto;
overflow-y: auto;
}

.virtualizedWrapperUseParentScroll {
max-height: none;
overflow-y: visible;
}

.virtualizedTable {
width: max-content;
min-width: 100%;
}
119 changes: 86 additions & 33 deletions packages/pxweb2-ui/src/lib/components/Table/Table.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,48 +1,101 @@
import { render } from '@testing-library/react';
import { describe, it, expect } from 'vitest';
import { render, screen } from '@testing-library/react';
import { describe, it, expect, vi, beforeEach } from 'vitest';

const childMocks = vi.hoisted(() => ({
desktopRender: vi.fn(),
mobileRender: vi.fn(),
}));

vi.mock('./TableDesktopVirtualized', () => ({
DesktopVirtualizedTable: ({
className,
getVerticalScrollElement,
}: {
className?: string;
getVerticalScrollElement?: () => HTMLElement | null;
}) => {
childMocks.desktopRender({ className, getVerticalScrollElement });
return <div data-testid="desktop-virtualized-table" />;
},
}));

vi.mock('./TableMobileVirtualized', () => ({
MobileVirtualizedTable: ({
className,
getVerticalScrollElement,
}: {
className?: string;
getVerticalScrollElement?: () => HTMLElement | null;
}) => {
childMocks.mobileRender({ className, getVerticalScrollElement });
return <div data-testid="mobile-virtualized-table" />;
},
}));

import Table from './Table';
import { pxTable } from './testData';

describe('Table', () => {
it('should render successfully desktop', () => {
const { baseElement } = render(
<Table pxtable={pxTable} isMobile={false} />,
);
expect(baseElement).toBeTruthy();
beforeEach(() => {
childMocks.desktopRender.mockClear();
childMocks.mobileRender.mockClear();
});

it('renders desktop component when isMobile is false', () => {
render(<Table pxtable={pxTable} isMobile={false} />);

expect(screen.getByTestId('desktop-virtualized-table')).toBeTruthy();
expect(screen.queryByTestId('mobile-virtualized-table')).toBeNull();
expect(childMocks.desktopRender).toHaveBeenCalledTimes(1);
expect(childMocks.mobileRender).not.toHaveBeenCalled();
});

it('should render successfully mobile', () => {
const { baseElement } = render(<Table pxtable={pxTable} isMobile={true} />);
expect(baseElement).toBeTruthy();
it('renders mobile component when isMobile is true', () => {
render(<Table pxtable={pxTable} isMobile={true} />);

expect(screen.getByTestId('mobile-virtualized-table')).toBeTruthy();
expect(screen.queryByTestId('desktop-virtualized-table')).toBeNull();
expect(childMocks.mobileRender).toHaveBeenCalledTimes(1);
expect(childMocks.desktopRender).not.toHaveBeenCalled();
});

it('should have a th header named 1968', () => {
const { baseElement } = render(
<Table pxtable={pxTable} isMobile={false} />,
it('forwards className and getVerticalScrollElement to desktop component', () => {
const getVerticalScrollElement = vi.fn(() => null);

render(
<Table
pxtable={pxTable}
isMobile={false}
className="custom-table-class"
getVerticalScrollElement={getVerticalScrollElement}
/>,
);

expect(childMocks.desktopRender).toHaveBeenCalledWith(
expect.objectContaining({
className: 'custom-table-class',
getVerticalScrollElement,
}),
);
const ths = baseElement.querySelectorAll('th');
let found = false;
ths.forEach((th) => {
if (th.innerHTML === '1968') {
found = true;
}
});
expect(found).toBe(true);
expect(ths.length).toBeGreaterThan(0);
});

it('should NOT have a th header named 1967', () => {
const { baseElement } = render(
<Table pxtable={pxTable} isMobile={false} />,
it('forwards className and getVerticalScrollElement to mobile component', () => {
const getVerticalScrollElement = vi.fn(() => null);

render(
<Table
pxtable={pxTable}
isMobile={true}
className="mobile-table-class"
getVerticalScrollElement={getVerticalScrollElement}
/>,
);

expect(childMocks.mobileRender).toHaveBeenCalledWith(
expect.objectContaining({
className: 'mobile-table-class',
getVerticalScrollElement,
}),
);
const ths = baseElement.querySelectorAll('th');
let found = false;
ths.forEach((th) => {
if (th.innerHTML === '1967') {
found = true;
}
});
expect(found).toBe(false);
});
});
14 changes: 0 additions & 14 deletions packages/pxweb2-ui/src/lib/components/Table/Table.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import type { Meta, StoryObj } from '@storybook/react-vite';
import { expect, within } from 'storybook/test';

import { Table } from './Table';
import { pxTable } from './testData';
Expand All @@ -15,17 +14,4 @@ export const Default: Story = {
args: {
pxtable: pxTable,
},
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);

expect(canvas.getByText(/region_1/i)).toBeTruthy();
expect(canvas.getByText(/region_2/i)).toBeTruthy();
expect(canvas.getByText(/region_3/i)).toBeTruthy();
expect(canvas.getByText(/region_4/i)).toBeTruthy();
expect(canvas.getByText(/CS_1/i)).toBeTruthy();
expect(canvas.getByText(/CS_2/i)).toBeTruthy();
expect(canvas.getByText(/CS_3/i)).toBeTruthy();
expect(canvas.getByText(/CS_4/i)).toBeTruthy();
expect(canvas.getByText(/CS_5/i)).toBeTruthy();
},
};
Loading
Loading