하단 탭바 스크롤 기반 숨김/표시 효과 구현
Facebook 스타일의 스크롤 인터랙션 적용: - 스크롤 다운 시 탭바 숨김 (translateY + opacity 애니메이션) - 스크롤 업 시 탭바 표시 - requestAnimationFrame으로 성능 최적화 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -296,6 +296,11 @@ footer {
|
||||
align-items: center;
|
||||
z-index: 1000;
|
||||
border-top: 0.1px solid var(--color-E5E5E5);
|
||||
transition: transform 0.3s ease-in-out;
|
||||
}
|
||||
|
||||
.bottom-tabbar.hidden {
|
||||
transform: translateY(100%);
|
||||
}
|
||||
|
||||
.tab-button {
|
||||
@@ -308,9 +313,14 @@ footer {
|
||||
background: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
transition: all 0.2s ease, opacity 0.3s ease-in-out;
|
||||
padding: 8px 4px;
|
||||
box-sizing: border-box;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.bottom-tabbar.hidden .tab-button {
|
||||
opacity: 0.1;
|
||||
}
|
||||
|
||||
.tab-button:hover {
|
||||
|
||||
@@ -8,13 +8,14 @@ import {
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useAppBridge } from '@/hooks';
|
||||
|
||||
export const FooterNavigation = ({
|
||||
export const FooterNavigation = ({
|
||||
setMenuOn,
|
||||
footerCurrentPage,
|
||||
setFavoriteEdit
|
||||
}: FooterProps) => {
|
||||
const { navigate } = useNavigate();
|
||||
const [isFooterOn, setIsFooterOn] = useState<boolean>(true);
|
||||
const [isFooterVisible, setIsFooterVisible] = useState<boolean>(true);
|
||||
|
||||
const onClickToNavigate = (path?: string) => {
|
||||
if(!!path){
|
||||
@@ -97,39 +98,42 @@ export const FooterNavigation = ({
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
let previousTouch: any;
|
||||
let lastScrollY = 0;
|
||||
let ticking = false;
|
||||
|
||||
const handleTouchStart = (e: TouchEvent) => {
|
||||
const touch: Touch | undefined = e.touches[0];
|
||||
previousTouch = touch;
|
||||
const handleScroll = () => {
|
||||
const currentScrollY = window.scrollY;
|
||||
|
||||
if (!ticking) {
|
||||
window.requestAnimationFrame(() => {
|
||||
// 스크롤 다운 & 일정 거리 이상 스크롤된 경우 -> 숨김
|
||||
if (currentScrollY > lastScrollY && currentScrollY > 50) {
|
||||
setIsFooterVisible(false);
|
||||
}
|
||||
// 스크롤 업 -> 표시
|
||||
else if (currentScrollY < lastScrollY) {
|
||||
setIsFooterVisible(true);
|
||||
}
|
||||
|
||||
lastScrollY = currentScrollY;
|
||||
ticking = false;
|
||||
});
|
||||
|
||||
ticking = true;
|
||||
}
|
||||
};
|
||||
const handleTouchMove = (e: TouchEvent) => {
|
||||
const touch: Touch | undefined = e.touches[0];
|
||||
let movementY: number | undefined;
|
||||
if(touch && previousTouch){
|
||||
movementY = touch.pageY - previousTouch.pageY;
|
||||
if(movementY > 0){
|
||||
setIsFooterOn(false);
|
||||
}
|
||||
else{
|
||||
setIsFooterOn(true);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
window.addEventListener('touchstart', handleTouchStart);
|
||||
window.addEventListener('touchmove', handleTouchMove);
|
||||
|
||||
window.addEventListener('scroll', handleScroll, { passive: true });
|
||||
|
||||
return () => {
|
||||
window.removeEventListener('touchstart', handleTouchStart);
|
||||
window.removeEventListener('touchmove', handleTouchMove);
|
||||
window.removeEventListener('scroll', handleScroll);
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
{ isFooterOn &&
|
||||
<nav className="bottom-tabbar">
|
||||
{ isFooterOn &&
|
||||
<nav className={`bottom-tabbar ${!isFooterVisible ? 'hidden' : ''}`}>
|
||||
{ getFooterButtonItems() }
|
||||
</nav>
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user