Finesse navbar search animation
This commit is contained in:
parent
05b8a9c9f0
commit
a2745068e8
@ -33,11 +33,11 @@ const GAP_CLASS = 'mr-1.5 sm:mr-2';
|
|||||||
export default function AppViewSwitcher({
|
export default function AppViewSwitcher({
|
||||||
currentSelection,
|
currentSelection,
|
||||||
className,
|
className,
|
||||||
animateSearch = true,
|
animate = true,
|
||||||
}: {
|
}: {
|
||||||
currentSelection?: SwitcherSelection
|
currentSelection?: SwitcherSelection
|
||||||
className?: string
|
className?: string
|
||||||
animateSearch?: boolean
|
animate?: boolean
|
||||||
}) {
|
}) {
|
||||||
const pathname = usePathname();
|
const pathname = usePathname();
|
||||||
|
|
||||||
@ -151,10 +151,10 @@ export default function AppViewSwitcher({
|
|||||||
</Switcher>
|
</Switcher>
|
||||||
{showSortControl &&
|
{showSortControl &&
|
||||||
<motion.div
|
<motion.div
|
||||||
initial={{ opacity: 0, scale: 0.5 }}
|
initial={animate ? { opacity: 0, scale: 0.5 } : false}
|
||||||
animate={{ opacity: 1, scale: 1 }}
|
animate={{ opacity: 1, scale: 1 }}
|
||||||
exit={{ opacity: 0, scale: 0.5 }}
|
exit={{ opacity: 0, scale: 0.5 }}
|
||||||
transition={{ duration: 0.3, ease: 'easeInOut' }}
|
transition={{ duration: 0.2, ease: 'easeInOut' }}
|
||||||
className={GAP_CLASS}
|
className={GAP_CLASS}
|
||||||
>
|
>
|
||||||
<Switcher className="max-sm:hidden">
|
<Switcher className="max-sm:hidden">
|
||||||
@ -172,7 +172,12 @@ export default function AppViewSwitcher({
|
|||||||
/>
|
/>
|
||||||
</Switcher>
|
</Switcher>
|
||||||
</motion.div>}
|
</motion.div>}
|
||||||
<motion.div layout={animateSearch}>
|
<motion.div
|
||||||
|
// Conditional key necessary to halt/resume layout animations
|
||||||
|
key={animate ? 'search' : 'search-no-animate'}
|
||||||
|
layout={animate}
|
||||||
|
transition={{ duration: 0.2, ease: 'easeInOut' }}
|
||||||
|
>
|
||||||
<Switcher type="borderless">
|
<Switcher type="borderless">
|
||||||
<SwitcherItem
|
<SwitcherItem
|
||||||
icon={<IconSearch includeTitle={false} />}
|
icon={<IconSearch includeTitle={false} />}
|
||||||
|
|||||||
@ -20,6 +20,7 @@ import {
|
|||||||
} from './config';
|
} from './config';
|
||||||
import { useRef } from 'react';
|
import { useRef } from 'react';
|
||||||
import useStickyNav from './useStickyNav';
|
import useStickyNav from './useStickyNav';
|
||||||
|
import { useAppState } from '@/state/AppState';
|
||||||
|
|
||||||
const NAV_HEIGHT_CLASS = NAV_CAPTION
|
const NAV_HEIGHT_CLASS = NAV_CAPTION
|
||||||
? 'min-h-[4rem] sm:min-h-[5rem]'
|
? 'min-h-[4rem] sm:min-h-[5rem]'
|
||||||
@ -37,6 +38,10 @@ export default function Nav({
|
|||||||
const pathname = usePathname();
|
const pathname = usePathname();
|
||||||
const showNav = !isPathSignIn(pathname);
|
const showNav = !isPathSignIn(pathname);
|
||||||
|
|
||||||
|
const {
|
||||||
|
hasLoadedWithAnimations,
|
||||||
|
} = useAppState();
|
||||||
|
|
||||||
const {
|
const {
|
||||||
classNameStickyContainer,
|
classNameStickyContainer,
|
||||||
classNameStickyNav,
|
classNameStickyNav,
|
||||||
@ -86,7 +91,7 @@ export default function Nav({
|
|||||||
<AppViewSwitcher
|
<AppViewSwitcher
|
||||||
currentSelection={switcherSelectionForPath()}
|
currentSelection={switcherSelectionForPath()}
|
||||||
className="translate-x-[-1px]"
|
className="translate-x-[-1px]"
|
||||||
animateSearch={isNavVisible}
|
animate={hasLoadedWithAnimations && isNavVisible}
|
||||||
/>
|
/>
|
||||||
<div className={clsx(
|
<div className={clsx(
|
||||||
'grow text-right min-w-0',
|
'grow text-right min-w-0',
|
||||||
|
|||||||
@ -19,7 +19,7 @@ export type AppStateContextType = {
|
|||||||
// CORE
|
// CORE
|
||||||
previousPathname?: string
|
previousPathname?: string
|
||||||
hasLoaded?: boolean
|
hasLoaded?: boolean
|
||||||
setHasLoaded?: Dispatch<SetStateAction<boolean>>
|
hasLoadedWithAnimations?: boolean
|
||||||
swrTimestamp?: number
|
swrTimestamp?: number
|
||||||
invalidateSwr?: () => void
|
invalidateSwr?: () => void
|
||||||
nextPhotoAnimation?: AnimationConfig
|
nextPhotoAnimation?: AnimationConfig
|
||||||
|
|||||||
@ -50,6 +50,8 @@ export default function AppStateProvider({
|
|||||||
// CORE
|
// CORE
|
||||||
const [hasLoaded, setHasLoaded] =
|
const [hasLoaded, setHasLoaded] =
|
||||||
useState(false);
|
useState(false);
|
||||||
|
const [hasLoadedWithAnimations, setHasLoadedWithAnimations] =
|
||||||
|
useState(false);
|
||||||
const [swrTimestamp, setSwrTimestamp] =
|
const [swrTimestamp, setSwrTimestamp] =
|
||||||
useState(Date.now());
|
useState(Date.now());
|
||||||
const [nextPhotoAnimation, _setNextPhotoAnimation] =
|
const [nextPhotoAnimation, _setNextPhotoAnimation] =
|
||||||
@ -112,8 +114,13 @@ export default function AppStateProvider({
|
|||||||
useState(false);
|
useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setHasLoaded?.(true);
|
setHasLoaded(true);
|
||||||
storeTimezoneCookie();
|
storeTimezoneCookie();
|
||||||
|
setUserEmailEager(getAuthEmailCookie());
|
||||||
|
const timeout = setTimeout(() => {
|
||||||
|
setHasLoadedWithAnimations(true);
|
||||||
|
}, 1000);
|
||||||
|
return () => clearTimeout(timeout);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const invalidateSwr = useCallback(() => setSwrTimestamp(Date.now()), []);
|
const invalidateSwr = useCallback(() => setSwrTimestamp(Date.now()), []);
|
||||||
@ -128,9 +135,6 @@ export default function AppStateProvider({
|
|||||||
error: authError,
|
error: authError,
|
||||||
isLoading: isCheckingAuth,
|
isLoading: isCheckingAuth,
|
||||||
} = useSWR('getAuth', getAuthAction);
|
} = useSWR('getAuth', getAuthAction);
|
||||||
useEffect(() => {
|
|
||||||
setUserEmailEager(getAuthEmailCookie());
|
|
||||||
}, []);
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (auth === null || authError) {
|
if (auth === null || authError) {
|
||||||
setUserEmail(undefined);
|
setUserEmail(undefined);
|
||||||
@ -207,7 +211,7 @@ export default function AppStateProvider({
|
|||||||
// CORE
|
// CORE
|
||||||
previousPathname,
|
previousPathname,
|
||||||
hasLoaded,
|
hasLoaded,
|
||||||
setHasLoaded,
|
hasLoadedWithAnimations,
|
||||||
swrTimestamp,
|
swrTimestamp,
|
||||||
invalidateSwr,
|
invalidateSwr,
|
||||||
nextPhotoAnimation,
|
nextPhotoAnimation,
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user