Skip to content

Commit

Permalink
fix: refine timeline callback to match header styles
Browse files Browse the repository at this point in the history
  • Loading branch information
fbuireu committed Dec 20, 2023
1 parent 4f12642 commit 37dfa48
Show file tree
Hide file tree
Showing 2 changed files with 156 additions and 151 deletions.
Original file line number Diff line number Diff line change
@@ -1,53 +1,56 @@
const SELECTORS = {
HEADER: '.header',
LATEST_ARTICLES: '.latest-articles__wrapper',
SITE_LOGO_SVG: '.site__logo svg',
HEADER_MENU_TEXT: '.header',
HEADER_MENU_OUTLINES: '.header__menu-button__outline',
HEADER: '.header',
LATEST_ARTICLES: '.latest-articles__wrapper',
SITE_LOGO_SVG: '.site__logo svg',
SITE_LOGO: '.site__logo',
HEADER_MENU_TEXT: '.header__menu-text',
HEADER_MENU_OUTLINES: '.header__menu-button__outline',
};

const getComputedStyleValue = (property: string): string =>
getComputedStyle(document.documentElement).getPropertyValue(property);
getComputedStyle(document.documentElement).getPropertyValue(property);

function isIntersecting(element: HTMLElement): boolean {
const { HEADER: HEADER_SELECTOR } = SELECTORS;
const headerOffsetHeight = (document.querySelector(HEADER_SELECTOR) as HTMLElement).offsetHeight / 2;
const threshold = element.offsetTop - headerOffsetHeight;
const sectionBottom = element.offsetTop + element.offsetHeight - headerOffsetHeight;
const { HEADER: HEADER_SELECTOR } = SELECTORS;
const headerOffsetHeight = (document.querySelector(HEADER_SELECTOR) as HTMLElement).offsetHeight / 2;
const threshold = element.offsetTop - headerOffsetHeight;
const sectionBottom = element.offsetTop + element.offsetHeight - headerOffsetHeight;

return window.scrollY >= threshold && window.scrollY < sectionBottom;
return window.scrollY >= threshold && window.scrollY < sectionBottom;
}

export function intersectionObserver(): void {
const WHITE = getComputedStyleValue('--white');
const BLACK = getComputedStyleValue('--neutral-main');
const {
HEADER: HEADER_SELECTOR,
LATEST_ARTICLES: LATEST_ARTICLES_SELECTOR,
SITE_LOGO_SVG: SITE_LOGO_SVG_SELECTOR,
HEADER_MENU_TEXT: HEADER_MENU_TEXT_SELECTOR,
HEADER_MENU_OUTLINES: HEADER_MENU_OUTLINES_SELECTOR,
} = SELECTORS;

const HEADER = document.querySelector(HEADER_SELECTOR) as HTMLElement;
const LATEST_ARTICLES = document.querySelector(LATEST_ARTICLES_SELECTOR) as HTMLElement;
const SITE_LOGO_SVG = document.querySelector(SITE_LOGO_SVG_SELECTOR) as HTMLElement;
const HEADER_MENU_TEXT = document.querySelector(HEADER_MENU_TEXT_SELECTOR) as HTMLElement;
const HEADER_MENU_OUTLINES = document.querySelectorAll(HEADER_MENU_OUTLINES_SELECTOR) as unknown as HTMLElement[];

if (!HEADER || !LATEST_ARTICLES) return;

const hasIntersected = isIntersecting(LATEST_ARTICLES);

if (hasIntersected) {
SITE_LOGO_SVG.style.fill = WHITE;
HEADER_MENU_TEXT.style.color = WHITE;
HEADER_MENU_OUTLINES.forEach((element) => (element.style.borderColor = WHITE));
} else {
SITE_LOGO_SVG.style.fill = BLACK;
HEADER_MENU_TEXT.style.color = BLACK;
HEADER_MENU_OUTLINES.forEach((element) => (element.style.borderColor = BLACK));
}
const WHITE = getComputedStyleValue('--white');
const BLACK = getComputedStyleValue('--neutral-main');
const {
HEADER: HEADER_SELECTOR,
LATEST_ARTICLES: LATEST_ARTICLES_SELECTOR,
SITE_LOGO: SITE_LOGO_SELECTOR,
SITE_LOGO_SVG: SITE_LOGO_SVG_SELECTOR,
HEADER_MENU_TEXT: HEADER_MENU_TEXT_SELECTOR,
HEADER_MENU_OUTLINES: HEADER_MENU_OUTLINES_SELECTOR,
} = SELECTORS;

const HEADER = document.querySelector(HEADER_SELECTOR) as HTMLElement;
const LATEST_ARTICLES = document.querySelector(LATEST_ARTICLES_SELECTOR) as HTMLElement;
const SITE_LOGO_SVG = document.querySelector(SITE_LOGO_SVG_SELECTOR) as HTMLElement;
const SITE_LOGO = document.querySelector(SITE_LOGO_SELECTOR) as HTMLElement;
const HEADER_MENU_TEXT = document.querySelector(HEADER_MENU_TEXT_SELECTOR) as HTMLElement;
const HEADER_MENU_OUTLINES = document.querySelectorAll(HEADER_MENU_OUTLINES_SELECTOR) as unknown as HTMLElement[];
const isMenuOpen = SITE_LOGO.classList.contains('--is-menu-open');

if (!HEADER || !LATEST_ARTICLES || isMenuOpen) return;
const hasIntersected = isIntersecting(LATEST_ARTICLES);

if (hasIntersected) {
SITE_LOGO_SVG.style.fill = WHITE;
HEADER_MENU_TEXT.style.color = WHITE;
HEADER_MENU_OUTLINES.forEach((element) => (element.style.borderColor = WHITE));
} else {
SITE_LOGO_SVG.style.fill = BLACK;
HEADER_MENU_TEXT.style.color = BLACK;
HEADER_MENU_OUTLINES.forEach((element) => (element.style.borderColor = BLACK));
}
}

window.addEventListener('scroll', intersectionObserver);
224 changes: 113 additions & 111 deletions src/ui/components/organisms/header/utils/toggleMenu/toggleMenu.ts
Original file line number Diff line number Diff line change
@@ -1,130 +1,132 @@
import { gsap, Power2, Power3, Power4 } from 'gsap';
import { intersectionObserver } from '@components/organisms/header/utils/intersectionObserver';

const ANIMATION_CONFIG = {
POWER4_IN_OUT: Power4.easeInOut,
POWER2_EASE_OUT: Power2.easeOut,
POWER3_OUT: Power3.easeOut,
WHITE: getComputedStyle(document.documentElement).getPropertyValue('--white') ?? 'var(--white)',
PATH_START: 'M0 502S175 272 500 272s500 230 500 230V0H0Z',
PATH_END: 'M0,1005S175,995,500,995s500,5,500,5V0H0Z',
POWER4_IN_OUT: Power4.easeInOut,
POWER2_EASE_OUT: Power2.easeOut,
POWER3_OUT: Power3.easeOut,
WHITE: getComputedStyle(document.documentElement).getPropertyValue('--white') ?? 'var(--white)',
PATH_START: 'M0 502S175 272 500 272s500 230 500 230V0H0Z',
PATH_END: 'M0,1005S175,995,500,995s500,5,500,5V0H0Z',
};

const SELECTORS = {
BODY: 'body',
HTML: 'html',
TOGGLE_MENU_BUTTON: '.header__menu-button',
MENU_OVERLAY: '.header__menu-overlay__wrapper',
OVERLAY_PATH: '.header__menu-overlay__wrapper path',
HEADER_MENU_TEXT: '.header__menu-text',
BUTTON_OUTLINE: '.header__menu-button__outline',
SITE_LOGO: '.site__logo',
SITE_LOGO_SVG: '.site__logo svg',
HEADER_MENU: '.header__menu',
NAVIGATION_DIVIDER: '.navigation__menu__divider',
NAVIGATION_ITEMS: '.navigation__menu__item > *',
QUOTE: '.navigation__menu__quote > *',
BODY: 'body',
HTML: 'html',
TOGGLE_MENU_BUTTON: '.header__menu-button',
MENU_OVERLAY: '.header__menu-overlay__wrapper',
OVERLAY_PATH: '.header__menu-overlay__wrapper path',
HEADER_MENU_TEXT: '.header__menu-text',
BUTTON_OUTLINE: '.header__menu-button__outline',
SITE_LOGO: '.site__logo',
SITE_LOGO_SVG: '.site__logo svg',
HEADER_MENU: '.header__menu',
NAVIGATION_DIVIDER: '.navigation__menu__divider',
NAVIGATION_ITEMS: '.navigation__menu__item > *',
QUOTE: '.navigation__menu__quote > *',
};

export function toggleMenu() {
let isMenuOpen = false;
let toggleMenuText = 'Menu';
const timeline = gsap.timeline({ paused: true });
let isMenuOpen = false;
let toggleMenuText = 'Menu';
const timeline = gsap.timeline({ paused: true });
timeline.eventCallback('onReverseComplete', () => intersectionObserver());

const {
BODY: BODY_SELECTOR,
HTML: HTML_SELECTOR,
TOGGLE_MENU_BUTTON: TOGGLE_MENU_BUTTON_SELECTOR,
MENU_OVERLAY,
OVERLAY_PATH,
BUTTON_OUTLINE,
SITE_LOGO,
SITE_LOGO_SVG,
NAVIGATION_DIVIDER,
HEADER_MENU,
NAVIGATION_ITEMS,
QUOTE,
HEADER_MENU_TEXT,
} = SELECTORS;
const {
BODY: BODY_SELECTOR,
HTML: HTML_SELECTOR,
TOGGLE_MENU_BUTTON: TOGGLE_MENU_BUTTON_SELECTOR,
MENU_OVERLAY,
OVERLAY_PATH,
BUTTON_OUTLINE,
SITE_LOGO,
SITE_LOGO_SVG,
NAVIGATION_DIVIDER,
HEADER_MENU,
NAVIGATION_ITEMS,
QUOTE,
HEADER_MENU_TEXT,
} = SELECTORS;

const BODY = document.querySelector(BODY_SELECTOR)!;
const HTML = document.querySelector(HTML_SELECTOR)!;
const LOGO = document.querySelector(SITE_LOGO)!;
const TOGGLE_MENU_BUTTON = document.querySelector(TOGGLE_MENU_BUTTON_SELECTOR)!;
const MENU_DIVIDER = document.querySelector(NAVIGATION_DIVIDER)!;
const MENU_TEXT = document.querySelector(HEADER_MENU_TEXT)!;
const BODY = document.querySelector(BODY_SELECTOR)!;
const HTML = document.querySelector(HTML_SELECTOR)!;
const LOGO = document.querySelector(SITE_LOGO)!;
const TOGGLE_MENU_BUTTON = document.querySelector(TOGGLE_MENU_BUTTON_SELECTOR)!;
const MENU_DIVIDER = document.querySelector(NAVIGATION_DIVIDER)!;
const MENU_TEXT = document.querySelector(HEADER_MENU_TEXT)!;

const ELEMENTS_TO_TOGGLE = [BODY, HTML, LOGO, MENU_DIVIDER];
const ELEMENTS_TO_TOGGLE = [BODY, HTML, LOGO, MENU_DIVIDER];

toggleMenuItems();
toggleMenuItems();

function updateButtonContent() {
if (!MENU_TEXT) return;
toggleMenuText = isMenuOpen ? 'Close' : 'Menu';
const timeout = isMenuOpen ? 300 : 0;
setTimeout(() => (MENU_TEXT.textContent = toggleMenuText), timeout);
}
function updateButtonContent() {
if (!MENU_TEXT) return;
toggleMenuText = isMenuOpen ? 'Close' : 'Menu';
const timeout = isMenuOpen ? 300 : 0;
setTimeout(() => (MENU_TEXT.textContent = toggleMenuText), timeout);
}

function toggleMenuItems() {
const { POWER4_IN_OUT, POWER2_EASE_OUT, POWER3_OUT, WHITE, PATH_START, PATH_END } = ANIMATION_CONFIG;
function toggleMenuItems() {
const { POWER4_IN_OUT, POWER2_EASE_OUT, POWER3_OUT, WHITE, PATH_START, PATH_END } = ANIMATION_CONFIG;

timeline.to(MENU_OVERLAY, { display: 'block' });
timeline.to(MENU_TEXT, {
top: '1.5rem',
left: '1rem',
fontSize: '1.5rem',
color: WHITE,
x: 0,
y: 0,
ease: POWER4_IN_OUT,
duration: 1,
});
timeline.add(() => updateButtonContent(), '<');
timeline.to(
BUTTON_OUTLINE,
{
width: '90px',
height: '90px',
border: `1px solid ${WHITE}`,
x: 0,
y: 0,
ease: POWER4_IN_OUT,
duration: 1,
},
'<'
);
timeline.to(SITE_LOGO, { y: '3rem', duration: 0.25 }, '<');
timeline.to(SITE_LOGO_SVG, { fill: WHITE, duration: 0.25 }, '<');
timeline
.to(OVERLAY_PATH, { attr: { d: PATH_START }, ease: POWER2_EASE_OUT, duration: 1 }, '<')
.to(OVERLAY_PATH, { attr: { d: PATH_END }, ease: POWER2_EASE_OUT, duration: 1 }, '-=.5');
timeline.to(HEADER_MENU, { visibility: 'visible', duration: 1 }, '-=.5');
timeline
.to(
NAVIGATION_ITEMS,
{
top: 0,
ease: POWER3_OUT,
stagger: { amount: 0.5 },
duration: 0.75,
},
'<'
)
.reverse();
timeline.to(
QUOTE,
{
top: 0,
ease: POWER3_OUT,
duration: 0.75,
},
'<'
);
}
timeline.to(MENU_OVERLAY, { display: 'block' });
timeline.to(MENU_TEXT, {
top: '1.5rem',
left: '1rem',
fontSize: '1.5rem',
color: WHITE,
x: 0,
y: 0,
ease: POWER4_IN_OUT,
duration: 1,
});
timeline.add(() => updateButtonContent(), '<');
timeline.to(
BUTTON_OUTLINE,
{
width: '90px',
height: '90px',
border: `1px solid ${WHITE}`,
x: 0,
y: 0,
ease: POWER4_IN_OUT,
duration: 1,
},
'<'
);
timeline.to(SITE_LOGO, { y: '3rem', duration: 0.25 }, '<');
timeline.to(SITE_LOGO_SVG, { fill: WHITE, duration: 0.25 }, '<');
timeline
.to(OVERLAY_PATH, { attr: { d: PATH_START }, ease: POWER2_EASE_OUT, duration: 1 }, '<')
.to(OVERLAY_PATH, { attr: { d: PATH_END }, ease: POWER2_EASE_OUT, duration: 1 }, '-=.5');
timeline.to(HEADER_MENU, { visibility: 'visible', duration: 1 }, '-=.5');
timeline
.to(
NAVIGATION_ITEMS,
{
top: 0,
ease: POWER3_OUT,
stagger: { amount: 0.5 },
duration: 0.75,
},
'<'
)
.reverse();
timeline.to(
QUOTE,
{
top: 0,
ease: POWER3_OUT,
duration: 0.75,
},
'<'
);
}

TOGGLE_MENU_BUTTON.addEventListener('click', () => {
isMenuOpen = !isMenuOpen;
timeline.reversed(!timeline.reversed());
TOGGLE_MENU_BUTTON.addEventListener('click', () => {
isMenuOpen = !isMenuOpen;
timeline.reversed(!timeline.reversed());

ELEMENTS_TO_TOGGLE.forEach((element) => element.classList.toggle('--is-menu-open'));
});
ELEMENTS_TO_TOGGLE.forEach((element) => element.classList.toggle('--is-menu-open'));
});
}

0 comments on commit 37dfa48

Please sign in to comment.