Skip to content
Merged
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
70 changes: 67 additions & 3 deletions packages/components-html/src/page-header/page-header.css
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@
display: none verwijdert de sectie uit de accessibility tree.
============================================================================= */

.dsn-page-header__large-layout {
.dsn-page-header__large-layout,
.dsn-page-header__compact-layout {
display: none;
}

Expand All @@ -59,6 +60,22 @@
.dsn-page-header {
border-block-end: none;
}

/* Compact variant: verberg default large layout, toon compact layout */
.dsn-page-header--compact .dsn-page-header__large-layout {
display: none;
}

.dsn-page-header--compact .dsn-page-header__compact-layout {
display: block;
}

/* Compact: border-block-end herstellen — geen accent-1 navbar als visueel
scheidingsmiddel, dus dezelfde border als op small viewport */
.dsn-page-header--compact {
border-block-end: var(--dsn-page-header-border-block-end-width) solid
var(--dsn-page-header-border-block-end-color);
}
}

/* =============================================================================
Expand Down Expand Up @@ -110,6 +127,41 @@
inline-size: 100%;
}

/* =============================================================================
Compact layout (large viewport) — één rij: logo | primaire nav | servicemenu
CSS-grid 1fr auto 1fr centreert de primaire navigatie optisch tussen
logo (inline-start) en servicemenu + zoekknop (inline-end).
============================================================================= */

.dsn-page-header__compact-inner {
display: grid;
grid-template-columns: 1fr auto 1fr;
align-items: center;
background-color: var(--dsn-page-header-compact-background-color);
padding-block: var(--dsn-page-header-compact-padding-block);
padding-inline: var(--dsn-page-header-compact-padding-inline);
}

/* Logo in compact context links uitlijnen — niet centreren zoals in de mobile bar.
Scoped op de compact-inner zodat geen media query override nodig is. */
.dsn-page-header__compact-inner .dsn-page-header__logo {
justify-content: flex-start;
}

/* Primaire navigatie in de middelste gridkolom */
.dsn-page-header__compact-primary-nav {
display: flex;
justify-content: center;
}

/* Servicemenu + zoekknop uitgelijnd naar inline-end */
.dsn-page-header__compact-secondary {
display: flex;
justify-content: flex-end;
align-items: center;
gap: var(--dsn-page-header-secondary-nav-gap);
}

/* =============================================================================
Navbar (large viewport) — accent-1 achtergrond, primaire navigatie
============================================================================= */
Expand All @@ -133,6 +185,8 @@
position: sticky;
inset-block-start: 0;
z-index: var(--dsn-page-header-z-index);
transition: box-shadow var(--dsn-transition-duration-normal)
var(--dsn-transition-easing-default);
}

/* =============================================================================
Expand All @@ -144,14 +198,24 @@
position: sticky;
inset-block-start: 0;
z-index: var(--dsn-page-header-z-index);
transition: transform var(--dsn-transition-duration-normal)
var(--dsn-transition-easing-default);
transition:
transform var(--dsn-transition-duration-normal)
var(--dsn-transition-easing-default),
box-shadow var(--dsn-transition-duration-normal)
var(--dsn-transition-easing-default);
}

.dsn-page-header--auto-hide[data-hidden='true'] {
transform: translateY(-100%);
}

/* Drop-shadow zodra content onder de sticky/auto-hide header schuift.
JS zet data-scrolled="true" bij scrollY > 0, "false" aan de bovenkant. */
.dsn-page-header--sticky[data-scrolled='true'],
.dsn-page-header--auto-hide[data-scrolled='true'] {
box-shadow: var(--dsn-box-shadow-sm);
}

/* =============================================================================
Inner — CSS-grid centreert logo onafhankelijk van knopbreedte
============================================================================= */
Expand Down
159 changes: 159 additions & 0 deletions packages/components-react/src/PageHeader/PageHeader.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,165 @@ describe('PageHeader', () => {
expect(onSearchClose).toHaveBeenCalledOnce();
});

// ---------------------------------------------------------------------------
// initialSearchOpen
// ---------------------------------------------------------------------------

it('zoekpaneel is open bij initialSearchOpen={true}', () => {
const { container } = render(
<PageHeader logoSlot={defaultLogo} initialSearchOpen={true} />
);
const panel = container.querySelector('.dsn-page-header__search-panel');
expect(panel).not.toHaveAttribute('hidden');
});

it('zoekknop heeft aria-expanded="true" bij initialSearchOpen={true}', () => {
render(<PageHeader logoSlot={defaultLogo} initialSearchOpen={true} />);
const searchButton = screen.getByRole('button', { name: /sluiten/i });
expect(searchButton).toHaveAttribute('aria-expanded', 'true');
});

// ---------------------------------------------------------------------------
// Compact layout
// ---------------------------------------------------------------------------

it('heeft geen dsn-page-header--compact bij layout="default"', () => {
const { container } = render(
<PageHeader logoSlot={defaultLogo} layout="default" />
);
expect(container.querySelector('header')).not.toHaveClass(
'dsn-page-header--compact'
);
});

it('heeft dsn-page-header--compact bij layout="compact"', () => {
const { container } = render(
<PageHeader logoSlot={defaultLogo} layout="compact" />
);
expect(container.querySelector('header')).toHaveClass(
'dsn-page-header--compact'
);
});

it('rendert dsn-page-header__compact-layout bij layout="compact"', () => {
const { container } = render(
<PageHeader logoSlot={defaultLogo} layout="compact" />
);
expect(
container.querySelector('.dsn-page-header__compact-layout')
).toBeTruthy();
});

it('rendert geen dsn-page-header__compact-layout bij layout="default"', () => {
const { container } = render(<PageHeader logoSlot={defaultLogo} />);
expect(
container.querySelector('.dsn-page-header__compact-layout')
).toBeNull();
});

it('compact layout rendert primaire navigatie', () => {
const { container } = render(
<PageHeader
logoSlot={defaultLogo}
layout="compact"
primaryNavigation={
<ul>
<li>Home</li>
</ul>
}
/>
);
const compactLayout = container.querySelector(
'.dsn-page-header__compact-layout'
);
expect(compactLayout?.textContent).toContain('Home');
});

it('compact layout rendert servicemenu', () => {
const { container } = render(
<PageHeader
logoSlot={defaultLogo}
layout="compact"
secondaryNavigation={
<ul>
<li>Contact</li>
</ul>
}
/>
);
const compactLayout = container.querySelector(
'.dsn-page-header__compact-layout'
);
expect(compactLayout?.textContent).toContain('Contact');
});

it('compact layout heeft aria-labelledby op primaire navigatie', () => {
const { container } = render(
<PageHeader
logoSlot={defaultLogo}
layout="compact"
primaryNavigation={<span>nav</span>}
/>
);
const nav = container.querySelector(
'.dsn-page-header__compact-primary-nav nav'
);
const headingId = nav?.getAttribute('aria-labelledby');
expect(headingId).toBeTruthy();
expect(container.querySelector(`#${CSS.escape(headingId!)}`)).toBeTruthy();
});

it('compact layout heeft aria-labelledby op servicemenu', () => {
const { container } = render(
<PageHeader
logoSlot={defaultLogo}
layout="compact"
secondaryNavigation={<span>nav</span>}
/>
);
const nav = container.querySelector(
'.dsn-page-header__compact-secondary nav'
);
const headingId = nav?.getAttribute('aria-labelledby');
expect(headingId).toBeTruthy();
expect(container.querySelector(`#${CSS.escape(headingId!)}`)).toBeTruthy();
});

it('compact layout heeft een zoekpaneel', () => {
const { container } = render(
<PageHeader logoSlot={defaultLogo} layout="compact" />
);
const compactLayout = container.querySelector(
'.dsn-page-header__compact-layout'
);
expect(
compactLayout?.querySelector('.dsn-page-header__search-panel')
).toBeTruthy();
});

it('compact zoekpaneel is standaard verborgen', () => {
const { container } = render(
<PageHeader logoSlot={defaultLogo} layout="compact" />
);
const compactLayout = container.querySelector(
'.dsn-page-header__compact-layout'
);
const panel = compactLayout?.querySelector(
'.dsn-page-header__search-panel'
);
expect(panel).toHaveAttribute('hidden');
});

it('compact layout rendert het logo', () => {
const { container } = render(
<PageHeader logoSlot={defaultLogo} layout="compact" />
);
const compactLayout = container.querySelector(
'.dsn-page-header__compact-layout'
);
expect(compactLayout?.querySelector('.dsn-page-header__logo')).toBeTruthy();
});

// ---------------------------------------------------------------------------
// className en ref
// ---------------------------------------------------------------------------
Expand Down
Loading
Loading