Add juicy on-load animation to logo in app header

This commit is contained in:
Frank Noirot
2024-08-27 23:04:06 +02:00
parent 59252b1e66
commit c167569d7e
2 changed files with 51 additions and 19 deletions

View File

@ -10,11 +10,18 @@ Please do not fill this up with junk.
interface AppState {
isStreamReady: boolean
/**
* Saves if the app has loaded already across route navigations.
* Used by the ProjectSidebarMenu component to determine if it should
* perform a fancy animation, which is only on the first render.
*/
hasRenderedOnce: boolean
setAppState: (newAppState: Partial<AppState>) => void
}
const AppStateContext = createContext<AppState>({
isStreamReady: false,
hasRenderedOnce: false,
setAppState: () => {},
})
@ -23,6 +30,7 @@ export const useAppState = () => useContext(AppStateContext)
export const AppStateProvider = ({ children }: { children: ReactNode }) => {
const [appState, _setAppState] = useState<AppState>({
isStreamReady: false,
hasRenderedOnce: false,
setAppState: () => {},
})
const setAppState = (newAppState: Partial<AppState>) =>
@ -32,6 +40,7 @@ export const AppStateProvider = ({ children }: { children: ReactNode }) => {
<AppStateContext.Provider
value={{
isStreamReady: appState.isStreamReady,
hasRenderedOnce: appState.hasRenderedOnce,
setAppState,
}}
>

View File

@ -4,7 +4,7 @@ import { type IndexLoaderData } from 'lib/types'
import { PATHS } from 'lib/paths'
import { isDesktop } from '../lib/isDesktop'
import { Link, useLocation, useNavigate } from 'react-router-dom'
import { Fragment, useMemo } from 'react'
import { Fragment, useEffect, useMemo } from 'react'
import { Logo } from './Logo'
import { APP_NAME } from 'lib/constants'
import { useCommandsContext } from 'hooks/useCommandsContext'
@ -15,6 +15,7 @@ import { machineManager } from 'lib/machineManager'
import usePlatform from 'hooks/usePlatform'
import { useAbsoluteFilePath } from 'hooks/useAbsoluteFilePath'
import Tooltip from './Tooltip'
import { useAppState } from 'AppState'
const ProjectSidebarMenu = ({
project,
@ -54,34 +55,56 @@ const ProjectSidebarMenu = ({
function AppLogoLink({
project,
file,
className = '',
}: {
project?: IndexLoaderData['project']
file?: IndexLoaderData['file']
className?: string
}) {
const { hasRenderedOnce, setAppState } = useAppState()
const { onProjectClose } = useLspContext()
const wrapperClassName =
"relative h-full grid place-content-center group p-1.5 before:block before:content-[''] before:absolute before:inset-0 before:bottom-2.5 before:z-[-1] before:bg-primary before:rounded-b-sm"
const logoClassName = 'w-auto h-4 text-chalkboard-10'
return isDesktop() ? (
<Link
data-testid="app-logo"
onClick={() => {
onProjectClose(file || null, project?.path || null, false)
// Clear the scene and end the session.
engineCommandManager.endSession()
}}
to={PATHS.HOME}
className={wrapperClassName + ' hover:before:brightness-110'}
useEffect(() => {
if (!hasRenderedOnce) {
setAppState({ hasRenderedOnce: true })
}
}, [])
return (
<Transition
show={true}
appear={!hasRenderedOnce}
as={Fragment}
enter="transition-transform ease-out duration-500 delay-200"
enterFrom="-translate-y-12"
enterTo="translate-y-0"
>
<Logo className={logoClassName} />
<span className="sr-only">{APP_NAME}</span>
</Link>
) : (
<div className={wrapperClassName} data-testid="app-logo">
<Logo className={logoClassName} />
<span className="sr-only">{APP_NAME}</span>
</div>
{isDesktop() ? (
<Link
data-testid="app-logo"
onClick={() => {
onProjectClose(file || null, project?.path || null, false)
// Clear the scene and end the session.
engineCommandManager.endSession()
}}
to={PATHS.HOME}
className={
wrapperClassName + ' hover:before:brightness-110 ' + className
}
>
<Logo className={logoClassName} />
<span className="sr-only">{APP_NAME}</span>
</Link>
) : (
<div className={wrapperClassName} data-testid="app-logo">
<Logo className={logoClassName} />
<span className="sr-only">{APP_NAME}</span>
</div>
)}
</Transition>
)
}