Experimental lab for testing different image swapping techniques with smooth transitions.
- View Transition API: Uses the modern
document.startViewTransition()for smooth, native transitions between images - Opacity Toggle: Preloads all images and uses CSS opacity transitions for instant switching
- AI-Generated Images: All demo images generated using Google Gemini Banana 2.5
- Dual Controls: Each technique has two switches - Day/Night theme toggle and On/Off state
- Theme Switch: Toggle between Day and Night modes
- Power Switch: Toggle between On and Off states
- Responsive Design: Optimized for mobile, tablet, and desktop
- Clean UI: Minimalist design with smooth transitions
- Node.js 18+
- pnpm
# Install dependencies
pnpm install# Run development server
pnpm dev
# Open http://localhost:5173# Create production build
pnpm build
# Preview production build
pnpm preview- React 19 - Latest React with modern hooks
- TypeScript - Type-safe development
- Vite 7 - Lightning-fast build tool
- Tailwind CSS 4 - Utility-first styling
- SWC - Super-fast TypeScript/JSX compiler
- ESLint 9 - Code linting
- TypeScript ESLint 8 - TypeScript-specific linting
- React Hooks ESLint - React hooks best practices
- Prettier 3 - Code formatting
├── src/
│ ├── components/ # React components
│ │ ├── Switch.tsx # Reusable switch component
│ │ ├── ControlPanel.tsx # Control panel with switches
│ │ ├── ViewTransitionImage.tsx # View Transition technique
│ │ ├── OpacityToggleImage.tsx # Opacity toggle technique
│ │ ├── ImageSwapSection.tsx # Section wrapper
│ │ ├── Footer.tsx # Footer component
│ │ └── index.ts # Component exports
│ ├── hooks/ # Custom React hooks
│ │ ├── useViewTransition.ts # View Transition API hook
│ │ ├── useImageSwapState.ts # Image swap state management
│ │ └── index.ts # Hook exports
│ ├── types/ # TypeScript types
│ │ └── index.ts # Type definitions
│ ├── constants/ # Constants
│ │ └── images.ts # Image paths and mappings
│ ├── utils/ # Utility functions
│ │ └── getImageIndex.ts # Image index calculator
│ ├── App.tsx # Main app component
│ ├── main.tsx # App entry point
│ ├── global.css # Global styles and transitions
│ └── vite-env.d.ts # Vite type declarations
├── public/
│ ├── day-off.png # Day theme, off state
│ ├── day-on.png # Day theme, on state
│ ├── night-off.png # Night theme, off state
│ ├── night-on.png # Night theme, on state
│ └── screenshot.jpeg # Project screenshot
└── index.html # HTML entry point
- Feature Detection: Checks if browser supports
document.startViewTransition() - Graceful Fallback: Falls back to instant swap if View Transition API is unavailable
- Smooth Animation: Uses CSS view transitions for seamless image morphing
- Optimized: Only loads the currently visible image
- Preload All: Loads all 4 images upfront for instant switching
- CSS Transitions: Uses
opacityandz-indexfor smooth fades - Performance: All images stay in DOM, only opacity changes
- Duration: 600ms transition for smooth visual effect
Each technique displays one of 4 possible states:
- Day + Off →
/day-off.png - Day + On →
/day-on.png - Night + Off →
/night-off.png - Night + On →
/night-on.png
All images generated with Google Gemini Banana 2.5 for consistent style and quality.
- Chrome 111+
- Edge 111+
- Safari 18+ (iOS 18+)
- Not supported: Firefox (fallback enabled)
- Works in all modern browsers
- No polyfills required
- View Transition: Smaller initial bundle, loads images on demand
- Opacity Toggle: Larger initial load, but instant switching
- CSS Transitions: Hardware-accelerated for smooth 60fps animations
- Optimized Images: All images are optimized PNGs
Lab project by Mariano Álvarez - MIT License
