Skip to content

Instantly share code, notes, and snippets.

@yuheiy
Created June 22, 2022 05:07
Show Gist options
  • Save yuheiy/b8d5aef06c9e5c0905f693cfcbbcebc8 to your computer and use it in GitHub Desktop.
Save yuheiy/b8d5aef06c9e5c0905f693cfcbbcebc8 to your computer and use it in GitHub Desktop.
// https://standard.shiftbrain.com/blog/default-action-for-click-event-of-a-element
import gsap from "gsap";
import ScrollToPlugin from "gsap/ScrollToPlugin";
import { forceFocus } from "./dom-utils";
gsap.registerPlugin(ScrollToPlugin);
window.addEventListener(
"click",
(event) => {
const anchorElement = (event.target as HTMLElement).closest<HTMLAnchorElement>('a[href*="#"]');
const anchorHash = anchorElement?.hash;
if (!anchorHash) {
return;
}
if (event.button === 0 && !isModifiedEvent(event)) {
if (location.hash !== anchorHash) {
history.pushState(null, "", anchorHash);
}
let target = document.querySelector<HTMLElement>(anchorHash);
if (!target && anchorHash === "#top") {
target = document.documentElement;
}
if (target) {
scrollIntoView(target);
forceFocus(target, { preventScroll: true });
event.preventDefault();
}
}
},
{ capture: true }
);
function isModifiedEvent(event: MouseEvent) {
return event.ctrlKey || event.shiftKey || event.altKey || event.metaKey;
}
function scrollIntoView(element: HTMLElement) {
const shouldReduceMotion = window.matchMedia("(prefers-reduced-motion)").matches;
const style = getComputedStyle(element);
gsap.to(window, {
duration: shouldReduceMotion ? 0 : 0.5,
scrollTo: {
...ScrollToPlugin.getOffset(element, window),
offsetX: parseFloat((style as any).scrollMarginLeft),
offsetY: parseFloat((style as any).scrollMarginTop),
},
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment