Skip to content

fix: reset progress bar on mobile scroll and pause on coming soon items#2036

Merged
ComputelessComputer merged 1 commit intomainfrom
devin/1764563046-fix-mobile-progress-reset
Dec 1, 2025
Merged

fix: reset progress bar on mobile scroll and pause on coming soon items#2036
ComputelessComputer merged 1 commit intomainfrom
devin/1764563046-fix-mobile-progress-reset

Conversation

@ComputelessComputer
Copy link
Collaborator

@ComputelessComputer ComputelessComputer commented Dec 1, 2025

fix: reset progress bar on mobile scroll and pause on coming soon items

Summary

Fixes mobile carousel progress bar behavior in the landing page features/details sections and the ai-notetaking floating panel section:

  1. Progress resets when scrolling to other cards - Previously, scrolling to a different card would continue the progress from where it was. Now it resets to 0.

  2. Progress pauses on "coming soon" items - When scrolling to a card marked as comingSoon, the auto-advance timer pauses until the user scrolls back to a non-coming-soon card.

Changes made:

  • Added centralized handleFeatureIndexChange / handleDetailIndexChange / handleTabIndexChange callbacks that reset progress and manage pause state
  • Updated mobile carousel onScroll handlers to only trigger when the index actually changes (prevents excessive calls during scroll)
  • Added isPaused state to MainFeaturesSection (DetailsSection already had it for tablet hover)

Review & Testing Checklist for Human

  • Test on mobile viewport: Swipe through the features carousel on the landing page (/) and verify progress resets when changing cards
  • Test coming soon pause: Swipe to "Floating Panel" or "Daily Note" (coming soon items) and verify the progress bar pauses, then resumes when swiping back
  • Test details section: Same behavior should work in the details section below features
  • Test ai-notetaking page: Visit /product/ai-notetaking and test the floating panel mobile carousel
  • Verify tablet hover still works: On tablet breakpoint (800-1200px), hovering over the selected tab should still pause progress in DetailsSection

Notes

  • The implementation resets progress to 0 when returning from a coming soon card (rather than resuming from previous position). If resume behavior is desired instead, please let me know.
  • DetailsSection uses the same isPaused state for both mobile scroll pause and tablet hover pause - these shouldn't conflict but worth verifying.

Link to Devin run: https://app.devin.ai/sessions/dc377cd439c14488bea6ade1d5604a64
Requested by: john@hyprnote.com (@ComputelessComputer)

- Add handleFeatureIndexChange in MainFeaturesSection to reset progress and pause on coming soon items
- Add handleDetailIndexChange in DetailsSection with same behavior
- Add handleTabIndexChange in FloatingPanelContent to reset progress on scroll
- Update mobile carousels to use new handlers with index change check

Co-Authored-By: john@hyprnote.com <john@hyprnote.com>
@devin-ai-integration
Copy link
Contributor

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR that start with 'DevinAI' or '@devin'.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

@netlify
Copy link

netlify bot commented Dec 1, 2025

Deploy Preview for hyprnote ready!

Name Link
🔨 Latest commit b1bd799
🔍 Latest deploy log https://app.netlify.com/projects/hyprnote/deploys/692d1a2a76d99100084776f0
😎 Deploy Preview https://deploy-preview-2036--hyprnote.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@netlify
Copy link

netlify bot commented Dec 1, 2025

Deploy Preview for hyprnote-storybook ready!

Name Link
🔨 Latest commit b1bd799
🔍 Latest deploy log https://app.netlify.com/projects/hyprnote-storybook/deploys/692d1a2a51be9200081bb8a2
😎 Deploy Preview https://deploy-preview-2036--hyprnote-storybook.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 1, 2025

📝 Walkthrough

Walkthrough

Introduces a pause-aware auto-advance mechanism for carousel components by replacing setter callbacks with onIndexChange handlers. When a feature/detail marked as comingSoon is active, auto-advance timer pauses. Parent components now handle index changes centrally, resetting progress and managing pause state based on the selected item's status.

Changes

Cohort / File(s) Change Summary
Carousel callback pattern refactoring
apps/web/src/routes/_view/index.tsx, apps/web/src/routes/_view/product/ai-notetaking.tsx
Replaced direct setter callbacks (setSelectedFeature, setSelectedDetail, setSelectedTab) with onIndexChange pattern. Mobile carousel components now invoke onIndexChange(index) when users scroll or select items, enabling parent-level control flow.
Pause-aware auto-advance implementation
apps/web/src/routes/_view/index.tsx
Added pause-aware auto-advance logic to MainFeaturesSection and DetailsSection. Introduced handleFeatureIndexChange and handleDetailIndexChange handlers that reset progress counters and apply pause state based on comingSoon flag. Progress animation short-circuits when isPaused is true.
FloatingPanelContent index management
apps/web/src/routes/_view/product/ai-notetaking.tsx
Added handleTabIndexChange callback and useCallback hook to FloatingPanelContent, wiring onIndexChange to FloatingPanelMobile for centralized tab index handling.

Sequence Diagram

sequenceDiagram
    actor User
    participant Parent as MainFeaturesSection
    participant Mobile as FeaturesMobileCarousel
    participant Progress as Auto-advance Loop

    User->>Mobile: Scroll/Select Item
    Mobile->>Mobile: Compute new index
    alt Index changed
        Mobile->>Parent: onIndexChange(newIndex)
        Parent->>Parent: resetProgress()
        Parent->>Parent: Check item.comingSoon
        alt Item is coming soon
            Parent->>Parent: setPaused(true)
        else Item is available
            Parent->>Parent: setPaused(false)
        end
    end

    loop Progress animation
        Progress->>Parent: Check isPaused
        alt isPaused = false
            Progress->>Progress: Increment progress
            Note over Progress: Normal auto-advance
        else isPaused = true
            Progress->>Progress: Skip frame
            Note over Progress: Hold at current index
        end
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Callback pattern consistency: Verify onIndexChange is correctly wired across all carousel components and that scroll handlers only invoke callbacks when index actually changes.
  • Pause state transitions: Ensure pause logic correctly reflects comingSoon status and that progress animation properly short-circuits when paused.
  • Progress reset logic: Confirm handleFeatureIndexChange and handleDetailIndexChange correctly reset progress counters and don't introduce race conditions with the animation loop.

Possibly related PRs

Suggested reviewers

  • yujonglee

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main changes: resetting progress bars on mobile scroll and pausing them for coming-soon items.
Description check ✅ Passed The description is directly related to the changeset, providing clear context about the fixes to mobile carousel progress bar behavior and the specific changes made.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch devin/1764563046-fix-mobile-progress-reset

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

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/web/src/routes/_view/index.tsx (1)

1208-1216: Critical race condition between programmatic scroll and onScroll handler.

The onScroll handler fires continuously during smooth scroll animations. When programmatic scrolling occurs (from clicking dots at line 1256 or auto-advance at lines 1135-1139), the following race condition can occur:

  1. setSelectedFeature(targetIndex) is called and smooth scroll begins
  2. During animation, scrollLeft is at an intermediate position
  3. onScroll fires, computes intermediate index from scrollLeft
  4. Calls onIndexChange(intermediateIndex), which resets selectedFeature
  5. This interrupts the scroll, causing the carousel to jump to the wrong index

The same issue exists in DetailsSection at lines 1503-1511.

Suggested fixes:

  1. Use the scrollend event instead of scroll (cleanest, but check browser support):
-onScroll={(e) => {
+onScrollEnd={(e) => {
  1. Track programmatic scrolls with a ref and ignore onScroll during those:
const isProgrammaticScroll = useRef(false);

// In scrollToFeature and auto-advance:
isProgrammaticScroll.current = true;
container.scrollTo({ left: scrollLeft, behavior: "smooth" });
setTimeout(() => isProgrammaticScroll.current = false, 500);

// In onScroll:
if (isProgrammaticScroll.current) return;
  1. Debounce the onScroll handler to only fire after scrolling settles.
🧹 Nitpick comments (2)
apps/web/src/routes/_view/product/ai-notetaking.tsx (1)

2218-2222: Centralized tab-index change handler correctly resets progress

Wiring handleTabIndexChange through onIndexChange so that every index change also zeroes progress and progressRef solves the “stale progress after manual change” problem while keeping the auto‑advance effect logic unchanged. Looks solid.

If you find more callers that need the same reset semantics (scrollToTab, handleTabClick), you could optionally factor the reset logic into a tiny helper (e.g. resetForIndex(index)) to keep those invariants DRY, but not required for this PR.

Also applies to: 2281-2284

apps/web/src/routes/_view/index.tsx (1)

1098-1108: Optional: Consider extracting duplicated pause state logic.

The logic to set isPaused based on the comingSoon flag is duplicated across multiple handlers. While the duplication is minor (2 lines), you could extract it to reduce repetition:

const getIsPaused = (index: number, features: typeof mainFeatures) => {
  return !!features[index]?.comingSoon;
};

// Then in handlers:
setIsPaused(getIsPaused(nextIndex, mainFeatures));

However, given the simplicity, the current inline approach is also acceptable.

Also applies to: 1149-1155, 1384-1394, 1434-1440, 1442-1448

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0c97fe1 and b1bd799.

📒 Files selected for processing (2)
  • apps/web/src/routes/_view/index.tsx (10 hunks)
  • apps/web/src/routes/_view/product/ai-notetaking.tsx (5 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: Avoid creating a bunch of types/interfaces if they are not shared. Especially for function props, just inline them instead.
Never do manual state management for form/mutation. Use useForm (from tanstack-form) and useQuery/useMutation (from tanstack-query) instead for 99% of cases. Avoid patterns like setError.
If there are many classNames with conditional logic, use cn (import from @hypr/utils). It is similar to clsx. Always pass an array and split by logical grouping.
Use motion/react instead of framer-motion.

Files:

  • apps/web/src/routes/_view/product/ai-notetaking.tsx
  • apps/web/src/routes/_view/index.tsx
🧠 Learnings (1)
📚 Learning: 2025-11-24T16:32:23.055Z
Learnt from: CR
Repo: fastrepl/hyprnote PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-24T16:32:23.055Z
Learning: Applies to **/*.{ts,tsx} : Use `motion/react` instead of `framer-motion`.

Applied to files:

  • apps/web/src/routes/_view/product/ai-notetaking.tsx
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
  • GitHub Check: Redirect rules - hyprnote
  • GitHub Check: Header rules - hyprnote
  • GitHub Check: Pages changed - hyprnote
  • GitHub Check: ci
  • GitHub Check: fmt
  • GitHub Check: Devin
🔇 Additional comments (5)
apps/web/src/routes/_view/product/ai-notetaking.tsx (2)

10-10: React import update matches new hook usage

Adding useCallback here is correct and used below in handleTabIndexChange; no issues.


2455-2464: Mobile scroll handler now keeps selectedTab and progress in sync

Passing onIndexChange and calling it only when the computed index differs from selectedTab ensures that horizontal swipes update the parent state and reset the auto‑advance progress without spamming updates. The offsetWidth‑based index calculation is reasonable for full‑width slides.

Please sanity‑check this on real devices (especially with momentum scrolling) to confirm we don’t hit any off‑by‑one behavior when a slide is partially visible.

Also applies to: 2475-2477

apps/web/src/routes/_view/index.tsx (3)

1095-1108: LGTM: Pause-aware index change handler is well-structured.

The new handleFeatureIndexChange callback properly centralizes the logic for index changes by resetting progress and managing pause state based on the comingSoon flag. The useCallback dependencies are correct.


1110-1147: Auto-advance logic correctly pauses for "coming soon" items.

The early return when isPaused is true properly halts the animation. Using activeFeatureIndices ensures auto-advance only navigates between non-comingSoon items, so not updating isPaused during auto-advance is correct.

Note: Auto-advance is also affected by the race condition flagged in the previous comment regarding programmatic scrolling.


1384-1394: DetailsSection follows the same pattern as MainFeaturesSection.

The implementation is consistent with MainFeaturesSection, properly centralizing index changes through handleDetailIndexChange with pause state management.

Note: The same race condition between programmatic scroll and onScroll handler applies here (lines 1508-1510), as already flagged for the features carousel.

Also applies to: 1508-1510

@ComputelessComputer ComputelessComputer merged commit e02cdea into main Dec 1, 2025
13 of 14 checks passed
@ComputelessComputer ComputelessComputer deleted the devin/1764563046-fix-mobile-progress-reset branch December 1, 2025 07:07
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

Comments