/** * Utility for enabling View Transitions API in the app */ /** * Check if View Transitions API is supported */ export const supportsViewTransitions = (): boolean => 'startViewTransition' in document; /** * Execute a function with view transition if supported * Falls back to immediate execution if not supported */ export const withViewTransition = async (callback: () => void | Promise): Promise => { if (!supportsViewTransitions()) { await callback(); return; } const doc = document as Document & { startViewTransition: (callback: () => void | Promise) => { finished: Promise; updateCallbackDone: Promise; ready: Promise; }; }; try { const transition = doc.startViewTransition(async () => { await callback(); }); await transition.finished; } catch (error) { // Fallback if transition fails await callback(); } }; /** * Enable view transitions for router navigation * Call this in your app initialization */ export const enableViewTransitionsForNavigation = (): void => { if (!supportsViewTransitions()) { return; } // Intercept link clicks and navigation to add view transitions const handleLinkClick = (event: MouseEvent) => { const target = (event.target as HTMLElement).closest('a'); if (!target) return; if (target.target === '_blank') return; if (target.origin !== window.location.origin) return; if (event.metaKey || event.ctrlKey || event.shiftKey) return; const url = new URL(target.href); // Only handle same-origin navigation if (url.origin === window.location.origin) { event.preventDefault(); withViewTransition(() => { window.history.pushState({}, '', target.href); window.dispatchEvent(new PopStateEvent('popstate')); }); } }; // Handle back/forward navigation const handlePopState = () => { withViewTransition(() => { // The URL has already changed, just trigger re-render }); }; window.addEventListener('click', handleLinkClick); window.addEventListener('popstate', handlePopState); };