Skip to content

fix: polish mobile history lightbox swipe UX#41

Merged
Simplereally merged 1 commit intomainfrom
feature/mobile-lightbox-swipe-ux
Mar 10, 2026
Merged

fix: polish mobile history lightbox swipe UX#41
Simplereally merged 1 commit intomainfrom
feature/mobile-lightbox-swipe-ux

Conversation

@Simplereally
Copy link
Copy Markdown
Owner

@Simplereally Simplereally commented Mar 10, 2026

Summary

  • make the mobile history lightbox follow the finger during vertical swipes, with snap-back and enter/exit motion tuned for a reels-style feel
  • harden mobile video playback after swipe navigation by combining native autoplay, repeated play recovery, and broader ready-state handling so the next video renders reliably
  • expand swipe and media-player coverage for drag motion, boundary behavior, horizontal gesture rejection, and refreshed video URLs

Testing

  • /home/josh/.bun/bin/bun run test components/images/image-lightbox.test.tsx hooks/use-media-player.test.ts components/ui/media-player.test.tsx components/studio/layout/studio-shell.test.tsx
  • /home/josh/.bun/bin/bun x eslint components/images/image-lightbox.tsx components/images/image-lightbox.test.tsx components/ui/media-player.tsx components/ui/media-player.test.tsx hooks/use-media-player.ts hooks/use-media-player.test.ts hooks/use-vertical-swipe-navigation.ts components/studio/layout/studio-shell.tsx
  • /home/josh/.bun/bin/bun x tsc --noEmit

Summary by CodeRabbit

Release Notes

New Features

  • Added vertical swipe navigation for media galleries with smooth animations and improved gesture detection.
  • Enhanced video autoplay with robust error recovery.
  • Expanded video event lifecycle support for better playback control.

Bug Fixes

  • Improved suppression of unintended backdrop clicks during active swipe interactions.
  • Better UI responsiveness by hiding overlays during swipe gestures.

Tests

  • Comprehensive test coverage for swipe navigation, video playback, and gesture handling.

@Simplereally Simplereally merged commit 08d95e8 into main Mar 10, 2026
1 check passed
@Simplereally Simplereally deleted the feature/mobile-lightbox-swipe-ux branch March 10, 2026 16:54
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 10, 2026

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 2b6819e4-28b8-4acf-bb4a-6612da42d838

📥 Commits

Reviewing files that changed from the base of the PR and between a4dd462 and 353113f.

📒 Files selected for processing (7)
  • components/images/image-lightbox.test.tsx
  • components/images/image-lightbox.tsx
  • components/ui/media-player.test.tsx
  • components/ui/media-player.tsx
  • hooks/use-media-player.test.ts
  • hooks/use-media-player.ts
  • hooks/use-vertical-swipe-navigation.ts

📝 Walkthrough

Walkthrough

The PR enhances the image lightbox with time-based backdrop click suppression, integrates vertical swipe navigation with visual feedback styling, expands video lifecycle event handling (canplay, loadedmetadata, playing), and introduces autoplay resilience with retry logic. Comprehensive test coverage for swipe gestures and media player lifecycle events is added.

Changes

Cohort / File(s) Summary
Image Lightbox Components
components/images/image-lightbox.tsx, components/images/image-lightbox.test.tsx
Introduced time-based backdrop click suppression mechanism (timestamp-based instead of boolean flag). Integrated swipe navigation with overlay and media styling, opacity/scale transforms, and gesture-aware UI overlay logic. Added comprehensive swipe gesture tests covering drag tracking, boundary detection, horizontal drag ignoring, and transform verification.
Media Player Components
components/ui/media-player.tsx, components/ui/media-player.test.tsx
Wired additional video event handlers (onLoadedMetadata, onCanPlay, onPlaying) to video element. Enabled autoPlay attribute with muted behavior alignment. Added test coverage for autoplay attribute presence and loading spinner removal on canplay event.
Media Player Hook
hooks/use-media-player.ts, hooks/use-media-player.test.ts
Introduced robust autoplay resilience with retry logic, URL normalization, and stale-event guards. Expanded public API with three new handlers (handleVideoLoadedMetadata, handleVideoCanPlay, handleVideoPlaying) for granular lifecycle control. Replaced readyState-based logic with event-driven autoplay and improved error handling. Added extensive test coverage for URL refreshes, loading state, memoization, and playback error scenarios.
Swipe Navigation Hook
hooks/use-vertical-swipe-navigation.ts
Extended public API with itemKey tracking and onSwipeIntent callback. Added visual styling outputs (overlayStyle, mediaStyle) with drag-driven opacity, scale, and transform updates. Implemented multi-stage gesture lifecycle including direction detection, axis-locking, velocity-based commit logic, and composite animation handling (entry/exit/snap-back).

Sequence Diagram

sequenceDiagram
    participant User
    participant Lightbox as ImageLightbox
    participant Swipe as useVerticalSwipeNavigation
    participant Player as MediaPlayer
    participant Hook as useMediaPlayer

    User->>Swipe: Pointer Down
    Swipe->>Swipe: Initialize drag tracking
    User->>Swipe: Pointer Move (vertical)
    Swipe->>Swipe: Calculate offset & direction
    Swipe->>Swipe: Update overlayStyle & mediaStyle
    Swipe->>Lightbox: Call onSwipeIntent()
    Lightbox->>Lightbox: suppressBackdropClick (180ms)
    User->>Swipe: Pointer Up
    Swipe->>Swipe: Calculate velocity & distance
    Swipe->>Lightbox: Trigger onNext or onPrevious
    Lightbox->>Player: Render next/previous media
    Player->>Hook: Video lifecycle events
    Hook->>Hook: handleCanPlay (clear loading)
    Hook->>Hook: handlePlaying (confirm playback)
    Swipe->>Swipe: Snap animation or reset
    Lightbox->>Lightbox: Update overlayStyle (final)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Poem

🐰 A swipe, a glide, a finger's dance,
The lightbox springs with new panache!
With backdrop clicks now timed just right,
And videos that load delight,
Through gestures smooth, the scenes advance!

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/mobile-lightbox-swipe-ux

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@vercel
Copy link
Copy Markdown
Contributor

vercel Bot commented Mar 10, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
bloomstudio Ignored Ignored Mar 10, 2026 4:54pm

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 353113f431

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +493 to +495
<div
className="relative w-full h-full flex items-center justify-center p-4"
style={swipeMediaStyle}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Keep video backdrop close button clickable

In video lightbox mode, the full-screen swipe-motion container now sits above the absolute close button, so taps on the backdrop hit the motion layer instead of the button. This effectively breaks tap-to-close for videos when swipe navigation is enabled, forcing users to rely on alternate dismissal paths.

Useful? React with 👍 / 👎.

Comment on lines +227 to +229
clearScheduledWork();
setTransition("none");
setIsAnimating(false);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve pending swipe navigation on new pointerdown

Calling clearScheduledWork() at the start of onPointerDown also clears the timeout that dispatches onSwipeUp/onSwipeDown after a committed swipe exit animation. If a user touches again during that 220ms window (for example, a quick second swipe/tap), the navigation callback is canceled and the swipe never advances, producing inconsistent or stuck navigation.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant