Skip to content

Commit

Permalink
fix(header): added bigger logo with animation (#1552)
Browse files Browse the repository at this point in the history
Co-authored-by: Alizé Debray <[email protected]>
Co-authored-by: Oliver Schürch <[email protected]>
  • Loading branch information
3 people authored Aug 11, 2023
1 parent 17db6b2 commit 2baa121
Show file tree
Hide file tree
Showing 12 changed files with 134 additions and 47 deletions.
5 changes: 5 additions & 0 deletions .changeset/stupid-pianos-rush.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@swisspost/internet-header': minor
---

Updated the logo size, the post logo now spans the meta-navigation and scales down on scroll.
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ const Template = (args: Args) => {
<swisspost-internet-header {...filteredArgs} />
<main className="container mt-huge-r">
<swisspost-internet-breadcrumbs />
<h1 className="mt-huge-r mb-big-r bold">CWF Internet Header</h1>
<h1 className="mt-huge-r mb-big-r bold">Design System Internet Header</h1>
<p className="fake-content my-big"></p>
<p className="fake-content my-big"></p>
<p className="fake-content my-big"></p>
Expand Down
4 changes: 2 additions & 2 deletions packages/internet-header/cypress/e2e/header.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ describe('header', () => {
cy.get('swisspost-internet-header').should('have.class', 'hydrated');
});

it(`has title 'CWF Internet Header'`, () => {
cy.get('h1').should('contain.text', 'CWF Internet Header');
it(`has title 'Design System Internet Header'`, () => {
cy.get('h1').should('contain.text', 'Design System Internet Header');
});

it(`has nav item 'Briefe versenden' selected`, () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
@use '../../../utils/mixins.scss';

/**
* Default position: scrolled
* Logo is being scaled up for the initial view (scrollY = 0). This enables media queries to override
* mobile behaviour without re-calculation
*/
:host {
--logo-scale: 1;

@include mixins.max(lg) {
--logo-scale: 1 !important;
}
}

post-logo {
height: var(--header-height);
transform-origin: bottom left;
transform: scale(var(--logo-scale));
}

post-main-navigation {
margin-left: calc((var(--header-height) * var(--logo-scale)) - var(--header-height));
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { debounce } from 'throttle-debounce';
import { state } from '../../../data/store';

export const registerLogoAnimationObserver = (
target: HTMLElement,
headerRef: HTMLSwisspostInternetHeaderElement,
) => {
/**
* Set intersection ratio as CSS custom property
*/
const handleScroll = () => {
const fullStickyness = state.stickyness === 'full';
let scale = 1;
// Minus 1px border at the bottom that the logo is not covering
const adjustedHeaderHeight = headerRef.clientHeight - 1;
const scrollY = fullStickyness ? 0 : window.scrollY;

// If meta navigation is not visible (mobile, not configured), scale should just be 1
if (target.clientHeight > 0) {
scale = Math.max(
(adjustedHeaderHeight - Math.max(scrollY, 0)) /
(adjustedHeaderHeight - target.clientHeight),
1,
);
}
headerRef.style.setProperty('--logo-scale', scale.toString());
};

const debounced = debounce(150, handleScroll);

/**
* Observe the meta navigation in order to not track scroll events throughout the whole page.
* This ensures that the scroll listener is only active while the meta navigation is visible.
*/
const observer = new IntersectionObserver(
entries => {
entries.forEach(entry => {
if (entry.isIntersecting && entry.intersectionRatio > 0) {
window.addEventListener('scroll', handleScroll, { passive: true });
window.addEventListener('resize', debounced);

// Ensure callback is called at least once in case main thread is too busy while scrolling up
window.requestAnimationFrame(handleScroll);
} else {
window.removeEventListener('scroll', handleScroll);
window.removeEventListener('resize', debounced);
window.requestAnimationFrame(handleScroll);
}
});
},
{
// Fires when element leaves viewport (0) and when it just about enters it (0.001)
threshold: [0, 0.001],
},
);
observer.observe(target);

return handleScroll;
};
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
@use '@swisspost/design-system-styles/variables/color';
@use '../../utils/utils.scss';
@use '../../utils/mixins.scss';
@use './logo-animation/logo-animation.scss';

:host {
display: block;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import { IAvailableLanguage } from '../../models/language.model';
import { translate } from '../../services/language.service';
import { If } from '../../utils/if.component';
import packageJson from '../../../package.json';
import { registerLogoAnimationObserver } from './logo-animation/logo-animation';

@Component({
tag: 'swisspost-internet-header',
Expand Down Expand Up @@ -123,7 +124,7 @@ export class PostInternetHeader {

@State() activeFlyout: string | null = null;
@State() activeDropdownElement: DropdownElement | null = null;
@Element() host: HTMLElement;
@Element() host: HTMLSwisspostInternetHeaderElement;

/**
* Get the currently set language as a two letter string ("de", "fr" "it" or "en")
Expand All @@ -135,10 +136,12 @@ export class PostInternetHeader {
}

private mainNav?: HTMLPostMainNavigationElement;
private metaNav?: HTMLPostMetaNavigationElement;
private lastScrollTop = window.scrollY || document.documentElement.scrollTop;
private throttledScroll: throttle<() => void>;
private debouncedResize: debounce<() => void>;
private lastWindowWidth: number = window.innerWidth;
private updateLogoAnimation: () => void;

constructor() {
if (this.project === undefined || this.project === '' || !isValidProjectId(this.project)) {
Expand Down Expand Up @@ -167,6 +170,7 @@ export class PostInternetHeader {
// Wait for the config to arrive, then render the header
try {
state.projectId = this.project;
state.stickyness = this.stickyness;
state.environment = this.environment.toLocaleLowerCase() as Environment;
if (this.language !== undefined) state.currentLanguage = this.language;
state.languageSwitchOverrides =
Expand Down Expand Up @@ -205,6 +209,9 @@ export class PostInternetHeader {
this.handleResize();
this.headerLoaded.emit();
this.host.classList.add('header-loaded');
if (this.meta && this.metaNav) {
this.updateLogoAnimation = registerLogoAnimationObserver(this.metaNav, this.host);
}
});

if (this.stickyness === 'full')
Expand Down Expand Up @@ -299,6 +306,12 @@ export class PostInternetHeader {
this.handleLanguageChange(event.detail);
}

@Watch('stickyness')
handleStickynessChange(newValue: StickynessOptions) {
state.stickyness = newValue;
this.updateLogoAnimation();
}

private handleClickOutsideBound = this.handleClickOutside.bind(this);

private handleClickOutside(event: Event) {
Expand Down Expand Up @@ -439,6 +452,7 @@ export class PostInternetHeader {
orientation="horizontal"
class="hidden-lg"
full-width={this.fullWidth}
ref={el => (this.metaNav = el)}
>
<If condition={renderLanguageSwitch === true}>
<post-language-switch
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,11 @@
align-self: stretch;

&::before {
position: relative;
content: '';
display: var(--separator-display);
height: var(--separator-height);
border-left: 1px solid color.$gray-10;
content: '';
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

:host {
display: block;
aspect-ratio: 1/1;
}

.logo {
Expand All @@ -13,7 +14,7 @@

svg {
display: block;
width: var(--header-height);
height: var(--header-height);
width: 100%;
height: 100%;
}
}
36 changes: 1 addition & 35 deletions packages/internet-header/src/components/post-logo/post-logo.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { Component, Host, h, State, Element } from '@stencil/core';
import { throttle } from 'throttle-debounce';
import { Component, Host, h, Element } from '@stencil/core';
import { state } from '../../data/store';

@Component({
Expand All @@ -8,40 +7,7 @@ import { state } from '../../data/store';
shadow: true,
})
export class PostLogo {
@State() showFaviconLogo: boolean;
@Element() host: HTMLPostLogoElement;
private throttledResize: throttle<() => void>;
private resizeObserver: ResizeObserver;

constructor() {
// Register window resize event listener and a resize observer on the mainnav controls (they change size while controls are being loaded) to display an accurately sized logo
this.throttledResize = throttle(300, () => this.handleResize());
window.addEventListener('resize', this.throttledResize, { passive: true });
this.resizeObserver = new ResizeObserver(this.handleResize.bind(this));

// Initially call the resize handler
this.handleResize();
}

componentDidLoad() {
const mainNavControls = this.host.parentElement?.querySelector('.main-navigation-controls');
if (mainNavControls) {
this.resizeObserver.observe(mainNavControls);
}
}

disconnectedCallback() {
window.removeEventListener('resize', this.throttledResize);
this.resizeObserver.disconnect();
}

handleResize() {
const mainNavControls = this.host.parentElement?.querySelector('.main-navigation-controls');
const menuButton = this.host.parentElement?.querySelector('.menu-button');
if (mainNavControls && menuButton)
this.showFaviconLogo =
window.innerWidth - (150 + mainNavControls.clientWidth + menuButton.clientWidth) <= 0;
}

render() {
if (state.localizedConfig?.header.logo === undefined) return;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
@use "@swisspost/design-system-styles/variables/color";
@use "@swisspost/design-system-styles/functions";
@use "../../utils/utils.scss";
@use "../../utils/mixins.scss";
@use '@swisspost/design-system-styles/variables/color';
@use '@swisspost/design-system-styles/functions';
@use '../../utils/utils.scss';
@use '../../utils/mixins.scss';

:host {
display: block;
background: color.$gray-background-light;
font-size: functions.px-to-rem(14px);
}

Expand All @@ -15,6 +14,8 @@
align-items: center;
min-height: functions.px-to-rem(48px);

background: color.$gray-background-light;

@media (min-width: 1441px) {
&:not(.full-width) {
margin: 0 auto;
Expand All @@ -40,11 +41,23 @@
--separator-display: block;
--separator-height: #{functions.px-to-rem(34px)};
}

&::before {
display: block;
content: '';
position: absolute;
top: 0px;
height: var(--meta-header-height);
background-color: color.$gray-background-light;
left: 50%;
width: 50%;
}
}
}

.meta-navigation {
.horizontal & {
position: relative;
padding-right: 1rem;
}
}
Expand Down
3 changes: 3 additions & 0 deletions packages/internet-header/src/data/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { createStore } from '@stencil/store';
import { Environment, ILocalizedConfig, ILocalizedCustomConfig } from '../models/general.model';
import { NavMainEntity } from '../models/header.model';
import { IAvailableLanguage } from '../models/language.model';
import { StickynessOptions } from '../components';

export interface HeaderState {
localizedConfig: ILocalizedConfig | null;
Expand All @@ -14,6 +15,7 @@ export interface HeaderState {
languageSwitchOverrides?: IAvailableLanguage[];
localizedCustomConfig?: ILocalizedCustomConfig;
osFlyoutOverrides?: NavMainEntity;
stickyness: StickynessOptions;
}

export const { state, reset, dispose } = createStore<HeaderState>({
Expand All @@ -24,4 +26,5 @@ export const { state, reset, dispose } = createStore<HeaderState>({
search: true,
login: true,
meta: true,
stickyness: 'minimal',
});

0 comments on commit 2baa121

Please sign in to comment.