Skip to content

Instantly share code, notes, and snippets.

@khasky
Created April 8, 2026 06:38
Show Gist options
  • Select an option

  • Save khasky/c00c1073c3466129c0ee510d70b6f786 to your computer and use it in GitHub Desktop.

Select an option

Save khasky/c00c1073c3466129c0ee510d70b6f786 to your computer and use it in GitHub Desktop.
useDirectionTransform React Hook
// Builds Theme UI `sx` transforms so a sticky/floating bar slides in on scroll-up or near the top
// and slides away on scroll-down; optional burger-menu attrs keep it visible while the menu is open.
import React from 'react';
import { BoxProps } from 'theme-ui';
import { useScrollDirection, ScrollDirection } from '@/hooks/useScrollDirection';
const SCROLL_Y_OFFSET_PX = 500;
interface DirectionTransformProps {
fromBottom?: boolean;
translateTop?: number;
translateBottom?: number;
minOffset?: number;
burgerMenuElementId?: string;
burgerMenuOpenAttr?: string;
}
export function useDirectionTransform({
fromBottom = false,
translateTop = 100,
translateBottom = 0,
minOffset = SCROLL_Y_OFFSET_PX,
burgerMenuElementId,
burgerMenuOpenAttr,
}: DirectionTransformProps) {
const [isVisible, setIsVisible] = React.useState(false);
const direction = useScrollDirection();
const styles: BoxProps['sx'] = {};
const checkIsMenuOpen = () => {
if (typeof window !== 'undefined' && burgerMenuElementId && burgerMenuOpenAttr) {
const menuButton = document.querySelector('#' + burgerMenuElementId);
const isMenuOpen = menuButton
? menuButton.getAttribute(burgerMenuOpenAttr) === 'true'
: false;
return isMenuOpen;
}
return false;
};
if (
checkIsMenuOpen() ||
direction === ScrollDirection.Initial ||
direction === ScrollDirection.Top
) {
styles.transform = fromBottom
? `translateY(${translateTop}%)`
: `translateY(${translateBottom})`;
} else if (direction === ScrollDirection.Bottom) {
styles.transform = fromBottom
? `translateY(${translateBottom}%)`
: `translateY(-${translateTop}%)`;
}
React.useEffect(() => {
const toggleVisibility = () => setIsVisible(window.scrollY > minOffset);
window.addEventListener('scroll', toggleVisibility);
return () => window.removeEventListener('scroll', toggleVisibility);
}, []);
return { styles, isVisible };
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment