Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 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
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
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@
align-items: flex-start;
gap: fixed.$spacing-4;
align-self: stretch;

// Offset anchor jump only for desktop widths where TableViewer header is sticky.
@media (min-width: fixed.$breakpoints-large-min-width) {
scroll-margin-top: var(--px-skip-to-main-sticky-offset, 0px);
}
}
.information {
display: flex;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -321,9 +321,13 @@ let mockIsXXLargeDesktop = true;
vi.mock('../../context/useApp', () => ({
default: () => ({
isXXLargeDesktop: mockIsXXLargeDesktop,
isTablet: false,
setTitle: () => {
vi.fn();
},
setTableInformationWantsToHidePageScrollbar: () => {
vi.fn();
},
}),
}));

Expand Down
16 changes: 15 additions & 1 deletion packages/pxweb2/src/app/components/ContentTop/ContentTop.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,12 @@ export function ContentTop({
const { pxTableMetadata, selectedVBValues } = useVariables();
const selectedMetadata = useTableData().data?.metadata;
const buildTableTitle = useTableData().buildTableTitle;
const { setTitle, isXXLargeDesktop, isTablet } = useApp();
const {
setTitle,
isXXLargeDesktop,
isTablet,
setTableInformationWantsToHidePageScrollbar,
} = useApp();

const openInformationButtonRef = useRef<HTMLButtonElement>(null);
const openInformationLinkRef = useRef<HTMLAnchorElement>(null);
Expand All @@ -128,6 +133,7 @@ export function ContentTop({
setActiveTab(selectedTab);
}
setIsTableInformationOpen(true);
setTableInformationWantsToHidePageScrollbar(true);
};

const noteInfo =
Expand Down Expand Up @@ -166,6 +172,13 @@ export function ContentTop({
});
}, [isTableInformationOpen, tableInformationOpener, accessibility]);

// Release table info lock on unmount.
useEffect(() => {
return () => {
setTableInformationWantsToHidePageScrollbar(false);
};
}, [setTableInformationWantsToHidePageScrollbar]);

let tableTitle = '';
if (selectedMetadata) {
const titleBy = t('presentation_page.common.table_title_by');
Expand Down Expand Up @@ -279,6 +292,7 @@ export function ContentTop({
selectedTab={activeTab}
onClose={() => {
setIsTableInformationOpen(false);
setTableInformationWantsToHidePageScrollbar(false);
}}
></TableInformation>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ vi.mock('@pxweb2/pxweb2-ui', () => ({
</div>
),
BreakpointsXsmallMaxWidth: '575px',
BreakpointsSmallMaxWidth: '600px',
BreakpointsMediumMaxWidth: '767px',
BreakpointsLargeMaxWidth: '991px',
BreakpointsXlargeMaxWidth: '1199px',
Expand Down
4 changes: 2 additions & 2 deletions packages/pxweb2/src/app/components/Footer/Footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,12 @@ function useSafeLocation(): { pathname: string } {
}

type FooterProps = {
containerRef?: React.RefObject<HTMLDivElement | null>;
containerRef?: React.RefObject<HTMLElement | null>;
variant?: 'generic' | 'tableview';
enableWindowScroll?: boolean;
};

export function scrollToTop(ref?: React.RefObject<HTMLDivElement | null>) {
export function scrollToTop(ref?: React.RefObject<HTMLElement | null>) {
if (ref?.current) {
const container = ref.current;
const start = container.scrollTop;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,74 +18,68 @@

@media ((min-width: fixed.$breakpoints-small-min-width) and (max-width: fixed.$breakpoints-medium-max-width)) {
width: 428px;
padding-left: fixed.$spacing-8;
padding-right: fixed.$spacing-8;
padding-top: fixed.$spacing-6;
padding-bottom: fixed.$spacing-6;
padding: fixed.$spacing-6 fixed.$spacing-8;
}

// xsmall, small and medium
@media (min-width: fixed.$breakpoints-xsmall-min-width) and (max-width: fixed.$breakpoints-small-max-width) {
@media (min-width: fixed.$breakpoints-xsmall-min-width) and (max-width: fixed.$breakpoints-medium-max-width) {
height: 100vh;
// Handle rtl languages
border-start-start-radius: var(--px-border-radius-none);
border-start-end-radius: var(--px-border-radius-xlarge);
border-end-end-radius: var(--px-border-radius-xlarge);
border-end-start-radius: var(--px-border-radius-none);

// Not from Figma
position: absolute;
top: 0;
z-index: 999;
}

@media (min-width: fixed.$breakpoints-medium-min-width) and (max-width: fixed.$breakpoints-medium-max-width) {
height: calc(100vh - 80px);
// Handle rtl languages
border-start-start-radius: var(--px-border-radius-none);
border-start-end-radius: var(--px-border-radius-xlarge);
border-end-end-radius: var(--px-border-radius-xlarge);
border-end-start-radius: var(--px-border-radius-none);

// Not from Figma
position: absolute;
position: fixed;
top: 0;
z-index: 999;
z-index: 70;
}

// large
@media (min-width: fixed.$breakpoints-large-min-width) and (max-width: fixed.$breakpoints-large-max-width) {
width: 428px;
padding: fixed.$spacing-8;
padding-inline-start: fixed.$spacing-8;
padding-inline-end: fixed.$spacing-8;
padding-top: fixed.$spacing-5;
padding-bottom: fixed.$spacing-8;

// Calculate height of main container, minus the header height
height: calc(100vh - fixed.$spacing-22);
height: calc(100vh - fixed.$spacing-20);

// Handle rtl languages
border-start-start-radius: var(--px-border-radius-xlarge);
border-start-end-radius: var(--px-border-radius-xlarge);
border-end-end-radius: var(--px-border-radius-xlarge);
border-end-start-radius: var(--px-border-radius-none);

// Not from Figma
position: absolute;
inset-inline-start: 120px; // Instead of "left" to handle rtl languages
z-index: 999;

// Position NavigationDrawer below the header
top: fixed.$spacing-22;
position: fixed;
top: fixed.$spacing-20;
inset-inline-start: 100px; // Instead of "left" to handle rtl languages
z-index: 60;

&.skipToMainContentVisible {
// Calculate position of NavigationDrawer below the header and SkipToMainContent
top: calc(fixed.$spacing-22 + var(--skip-to-main-content-height));
top: calc(fixed.$spacing-20 + var(--skip-to-main-content-height));
}
}

// xlarge and xxlarge
@media ((min-width: fixed.$breakpoints-xlarge-min-width) and (max-width: fixed.$breakpoints-xlarge-max-width)) or ((min-width: fixed.$breakpoints-xxlarge-min-width)) {
width: 396px;
padding: 0px fixed.$spacing-8 fixed.$spacing-8 0px;
border-radius: var(--px-border-radius-none);
width: 428px;
padding-inline-start: fixed.$spacing-8;
padding-inline-end: fixed.$spacing-8;
padding-top: fixed.$spacing-5;
padding-bottom: fixed.$spacing-8;

// Calculate height of main container, minus the header height
height: calc(100vh - fixed.$spacing-20);
position: sticky;
top: fixed.$spacing-20;
z-index: 60;

&.skipToMainContentVisible {
// Calculate position of NavigationDrawer below the header and SkipToMainContent
top: calc(fixed.$spacing-20 + var(--skip-to-main-content-height));
}
}
}

Expand Down Expand Up @@ -151,14 +145,14 @@

// Not from Figma
.backdrop {
@media (min-width: fixed.$breakpoints-xsmall-min-width) and (max-width: fixed.$breakpoints-small-max-width) {
@media (min-width: fixed.$breakpoints-xsmall-min-width) and (max-width: fixed.$breakpoints-medium-max-width) {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: var(--px-color-surface-scrim);
z-index: 999;
z-index: 50;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@
align-items: center;
gap: fixed.$spacing-2;
flex-shrink: 0;
background-color: var(--px-color-surface-subtle);
background-color: var(--px-color-surface-default);

// fix the navigation bar to the bottom of the screen
position: fixed;
bottom: 0;
z-index: 2; // 2 to fix gradient issue with table
z-index: 40;
border-top: 1px solid var(--px-color-border-subtle);

// xsmall, small and medium
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import cl from 'clsx';
import { m } from 'motion/react';
import { m, type Transition, type Variants } from 'motion/react';
import { forwardRef, MouseEvent } from 'react';

import { Icon, IconProps, Label } from '@pxweb2/pxweb2-ui';
Expand All @@ -11,7 +11,7 @@ const springConfig = {
mass: 1,
stiffness: 200,
damping: 30,
};
} satisfies Transition;

interface ItemProps {
label: string;
Expand All @@ -24,10 +24,7 @@ interface ItemProps {
export const Item = forwardRef<HTMLButtonElement, ItemProps>(
({ label, parentName, selected, icon, onClick }, ref) => {
const btnId = 'px-' + parentName + '-' + label;
const initialBaseBackgroundColor =
parentName === 'navBar'
? 'var(--px-color-surface-subtle)'
: 'var(--px-color-surface-default)';
const initialBaseBackgroundColor = 'var(--px-color-surface-default)';
const initialBackgroundColor = selected
? 'var(--px-color-surface-action-subtle-active)'
: initialBaseBackgroundColor;
Expand All @@ -50,7 +47,7 @@ export const Item = forwardRef<HTMLButtonElement, ItemProps>(
],
transition: springConfig,
},
};
} satisfies Variants;

return (
<li className={cl(styles.navigationBarListItem, styles.fadein)}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,24 @@
}

.navigationRail {
width: 120px;
width: 100px;
height: 100%;
padding: fixed.$spacing-8 0px fixed.$spacing-14 0px;
padding: fixed.$spacing-6 0px fixed.$spacing-14 0px;
flex-direction: column;
align-items: center;
flex-shrink: 0;
background: var(--px-color-surface-default);
border-inline-end: 1px solid var(--px-color-border-subtle);
gap: 24px;

// large, xlarge and xxlarge
@media ((min-width: fixed.$breakpoints-large-min-width) and (max-width: fixed.$breakpoints-xlarge-max-width)) or ((min-width: fixed.$breakpoints-xxlarge-min-width)) {
display: flex;
position: sticky;
top: fixed.$spacing-20;
height: calc(100vh - fixed.$spacing-20);
z-index: 10;
align-self: flex-start;
}

&:focus-visible {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { getConfig } from '../../util/config/getConfig';

type propsType = {
readonly selectedTabId: string;
readonly scrollRef?: React.Ref<HTMLDivElement>;
readonly scrollRef?: React.RefObject<HTMLElement | null>;
isExpanded: boolean;
setIsExpanded: (expanded: boolean) => void;
};
Expand Down
2 changes: 0 additions & 2 deletions packages/pxweb2/src/app/components/RootLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,12 @@ import { Outlet } from 'react-router';
import useLocalizeDocumentAttributes from '../../i18n/useLocalizeDocumentAttributes';
import { Title, CanonicalUrl, HrefLang } from '../util/seo/headTags';
import ErrorBoundary from './ErrorBoundary/ErrorBoundary';
import WipStatusMessage from '../components/Banners/WipStatusMessage';

export default function RootLayout() {
useLocalizeDocumentAttributes();

return (
<>
<WipStatusMessage />
<Title />
<CanonicalUrl />
<HrefLang />
Expand Down
22 changes: 21 additions & 1 deletion packages/pxweb2/src/app/components/Selection/Selection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ export function Selection({
}: SelectionProps) {
const variables = useVariables();
const app = useApp();
const { isTablet } = useApp();
const { isTablet, isMobile, setSelectionWantsToHidePageScrollbar } = useApp();
const {
selectedVBValues,
setSelectedVBValues,
Expand Down Expand Up @@ -590,6 +590,26 @@ export function Selection({
/>
);

useEffect(() => {
if (selectedNavigationView !== 'none' && (isTablet || isMobile)) {
setSelectionWantsToHidePageScrollbar(true);
} else {
setSelectionWantsToHidePageScrollbar(false);
}
}, [
selectedNavigationView,
isTablet,
isMobile,
setSelectionWantsToHidePageScrollbar,
]);

// Release selection lock on unmount.
useEffect(() => {
return () => {
setSelectionWantsToHidePageScrollbar(false);
};
}, [setSelectionWantsToHidePageScrollbar]);

return (
selectedNavigationView !== 'none' && (
<NavigationDrawer
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from 'react';
import { HTMLAttributes, Ref } from 'react';
import cl from 'clsx';
import { useLocation, useSearchParams } from 'react-router';
import { useTranslation } from 'react-i18next';
Expand All @@ -8,18 +8,22 @@ import { Link } from '@pxweb2/pxweb2-ui';
import { getConfig } from '../../util/config/getConfig';
import { getLanguagePath } from '../../util/language/getLanguagePath';

export type SkipToContentProps = React.HTMLAttributes<HTMLDivElement> & {
export type SkipToContentProps = HTMLAttributes<HTMLDivElement> & {
// Jump to
targetId?: string;

// label for the link
label?: string;

containerRef?: React.Ref<HTMLDivElement>;
containerRef?: Ref<HTMLDivElement>;
};

export function SkipToContent(props: SkipToContentProps) {
const { targetId, label, containerRef, ...rest } = props;
export function SkipToContent({
targetId,
label,
containerRef,
...rest
}: SkipToContentProps) {
const { i18n } = useTranslation();
const config = getConfig();
const location = useLocation().pathname;
Expand Down
Loading
Loading