mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-26 12:27:01 -05:00
Add breadcrumb and transitions
Introduce breadcrumb navigation component and integrate into detail pages with hover previews; add PageTransition to App for smooth navigations and loading animations.
This commit is contained in:
34
src/components/layout/PageTransition.tsx
Normal file
34
src/components/layout/PageTransition.tsx
Normal file
@@ -0,0 +1,34 @@
|
||||
import { ReactNode, useEffect, useState } from 'react';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
|
||||
interface PageTransitionProps {
|
||||
children: ReactNode;
|
||||
}
|
||||
|
||||
export function PageTransition({ children }: PageTransitionProps) {
|
||||
const location = useLocation();
|
||||
const [displayLocation, setDisplayLocation] = useState(location);
|
||||
const [transitionStage, setTransitionStage] = useState<'fade-in' | 'fade-out'>('fade-in');
|
||||
|
||||
useEffect(() => {
|
||||
if (location !== displayLocation) {
|
||||
setTransitionStage('fade-out');
|
||||
}
|
||||
}, [location, displayLocation]);
|
||||
|
||||
const onAnimationEnd = () => {
|
||||
if (transitionStage === 'fade-out') {
|
||||
setTransitionStage('fade-in');
|
||||
setDisplayLocation(location);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`${transitionStage === 'fade-out' ? 'animate-fade-out' : 'animate-fade-in'}`}
|
||||
onAnimationEnd={onAnimationEnd}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
87
src/components/navigation/EntityBreadcrumb.tsx
Normal file
87
src/components/navigation/EntityBreadcrumb.tsx
Normal file
@@ -0,0 +1,87 @@
|
||||
import { Link } from 'react-router-dom';
|
||||
import { Home } from 'lucide-react';
|
||||
import {
|
||||
Breadcrumb,
|
||||
BreadcrumbList,
|
||||
BreadcrumbItem,
|
||||
BreadcrumbLink,
|
||||
BreadcrumbPage,
|
||||
BreadcrumbSeparator,
|
||||
} from '@/components/ui/breadcrumb';
|
||||
import { HoverCard, HoverCardContent, HoverCardTrigger } from '@/components/ui/hover-card';
|
||||
import { ParkPreviewCard } from '@/components/preview/ParkPreviewCard';
|
||||
import { CompanyPreviewCard } from '@/components/preview/CompanyPreviewCard';
|
||||
|
||||
interface BreadcrumbSegment {
|
||||
label: string;
|
||||
href?: string;
|
||||
showPreview?: boolean;
|
||||
previewType?: 'park' | 'company';
|
||||
previewSlug?: string;
|
||||
}
|
||||
|
||||
interface EntityBreadcrumbProps {
|
||||
segments: BreadcrumbSegment[];
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export function EntityBreadcrumb({ segments, className }: EntityBreadcrumbProps) {
|
||||
return (
|
||||
<Breadcrumb className={className}>
|
||||
<BreadcrumbList>
|
||||
{/* Home link */}
|
||||
<BreadcrumbItem>
|
||||
<BreadcrumbLink asChild>
|
||||
<Link to="/" className="flex items-center gap-1 hover:text-primary transition-colors">
|
||||
<Home className="w-3.5 h-3.5" />
|
||||
<span>Home</span>
|
||||
</Link>
|
||||
</BreadcrumbLink>
|
||||
</BreadcrumbItem>
|
||||
|
||||
{segments.map((segment, index) => {
|
||||
const isLast = index === segments.length - 1;
|
||||
|
||||
return (
|
||||
<BreadcrumbItem key={index}>
|
||||
<BreadcrumbSeparator />
|
||||
{isLast ? (
|
||||
<BreadcrumbPage>{segment.label}</BreadcrumbPage>
|
||||
) : segment.showPreview && segment.previewSlug ? (
|
||||
<HoverCard openDelay={300}>
|
||||
<HoverCardTrigger asChild>
|
||||
<BreadcrumbLink asChild>
|
||||
<Link
|
||||
to={segment.href || '#'}
|
||||
className="hover:text-primary transition-colors"
|
||||
>
|
||||
{segment.label}
|
||||
</Link>
|
||||
</BreadcrumbLink>
|
||||
</HoverCardTrigger>
|
||||
<HoverCardContent side="bottom" align="start" className="w-auto">
|
||||
{segment.previewType === 'park' && (
|
||||
<ParkPreviewCard slug={segment.previewSlug} />
|
||||
)}
|
||||
{segment.previewType === 'company' && (
|
||||
<CompanyPreviewCard slug={segment.previewSlug} />
|
||||
)}
|
||||
</HoverCardContent>
|
||||
</HoverCard>
|
||||
) : (
|
||||
<BreadcrumbLink asChild>
|
||||
<Link
|
||||
to={segment.href || '#'}
|
||||
className="hover:text-primary transition-colors"
|
||||
>
|
||||
{segment.label}
|
||||
</Link>
|
||||
</BreadcrumbLink>
|
||||
)}
|
||||
</BreadcrumbItem>
|
||||
);
|
||||
})}
|
||||
</BreadcrumbList>
|
||||
</Breadcrumb>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user