diff --git a/src/components/elements/IntersectionObserver.js b/src/components/elements/IntersectionObserver.js new file mode 100644 index 000000000..547e20137 --- /dev/null +++ b/src/components/elements/IntersectionObserver.js @@ -0,0 +1,26 @@ +/* global IntersectionObserver */ + +import React, { useState, useEffect, useRef } from 'react' + +const LazyRender = ({ onView, placeholder, options }) => { + const [isVisible, setIsVisible] = useState(false) + const ref = useRef(null) + + useEffect(() => { + const { current } = ref + + const observer = new IntersectionObserver(([entry]) => { + if (entry.isIntersecting) { + setIsVisible(true) + observer.disconnect() + } + }, options) + + if (current) observer.observe(current) + return () => current && observer.unobserve(current) + }, [options]) + + return
{isVisible ? onView() : placeholder()}
+} + +export default LazyRender diff --git a/src/components/patterns/Footer/Footer.js b/src/components/patterns/Footer/Footer.js index 8c06e430a..f175b297e 100644 --- a/src/components/patterns/Footer/Footer.js +++ b/src/components/patterns/Footer/Footer.js @@ -4,6 +4,7 @@ import { Mail } from 'react-feather' import { issueUrl } from 'helpers' import React from 'react' +import IntersectionObserver from '../../elements/IntersectionObserver' import Healthcheck from '../Healthcheck/Healthcheck' import { @@ -35,6 +36,73 @@ const DARK_THEME = { iconColor: colors.white80 } +const StatusPage = ({ isDark }) => { + return ( + + + Status Page + + + ) +} + +const Health = ({ isDark, textColor }) => ( + + {({ isHealthy, isLoading }) => { + if (isLoading) return + return ( + + + + + + All systems operational + + + + System performance degradation + + + + + ) + }} + +) + const Footer = ({ isDark, ...props }) => { const { background, textColor, inputIconColor } = isDark ? DARK_THEME @@ -209,69 +277,12 @@ const Footer = ({ isDark, ...props }) => { flexDirection: 'column' })} > - - {({ isHealthy, isLoading }) => { - if (isLoading) { - return ( - - - Status Page - - - ) - } - - return ( - - - - - - All systems operational - - - - System performance degradation - - - - - ) - }} - + } + onView={() => ( + + )} + /> @@ -328,16 +339,16 @@ const Footer = ({ isDark, ...props }) => { })} > {[ - { - href: 'https://github.com/microlinkhq', - children: 'GitHub', - title: '@microlinkhq on GitHub' - }, { href: 'https://x.com/microlinkhq', children: 'X', title: '@microlinkhq on x.com' }, + { + href: 'https://github.com/microlinkhq', + children: 'GitHub', + title: '@microlinkhq on GitHub' + }, { href: 'mailto:hello@microlink.io', children: 'Email', diff --git a/src/helpers/hoc/with-link.js b/src/helpers/hoc/with-link.js index d213a2c07..55f84da53 100644 --- a/src/helpers/hoc/with-link.js +++ b/src/helpers/hoc/with-link.js @@ -9,6 +9,8 @@ import { Link as GatsbyLink } from 'gatsby' import Flex from '../../components/elements/Flex' +const addActiveClass = isActive => (isActive ? { className: 'active' } : null) + const isInternalLink = (to = '/') => /^\/(?!\/)/.test(to) const getHash = href => href.replace('/#', '#') @@ -112,29 +114,26 @@ export const withLink = Component => { }) => { const [isIntersecting, setIsIntersecting] = useState(false) const location = useLocation() - const isInternal = isInternalLink(href) + const isInternal = !href || isInternalLink(href) const partiallyActive = actively === 'partial' useEffect(() => { - if (actively === 'observer') { + if (isInternal && actively === 'observer') { const node = document.querySelector(getHash(href)) onView(node, isBeingIntersecting => setIsIntersecting(isBeingIntersecting) ) } - }, [actively, href]) + }, [isInternal, actively, href]) - const getProps = ({ isPartiallyCurrent, isCurrent, location }) => { - if (typeof actively === 'function') { - const result = actively({ location }) - return result ? { className: 'active' } : null - } - const isActive = partiallyActive ? isPartiallyCurrent : isCurrent - if (!isActive && !isIntersecting) return null - return { className: 'active' } - } + const getProps = ({ isPartiallyCurrent, isCurrent, location }) => + typeof actively === 'function' + ? addActiveClass(actively({ location })) + : addActiveClass( + isIntersecting || partiallyActive ? isPartiallyCurrent : isCurrent + ) - if (prefetch && (!href || isInternal)) { + if (prefetch && isInternal) { return (