Conversation
❌ Deploy Preview for hyprnote failed.
|
✅ Deploy Preview for hyprnote-storybook ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
apps/web/src/routes/_view/index.tsx
Outdated
There was a problem hiding this comment.
🔴 CTA button for waitlist users is broken because HeroSection (with email input) is commented out
The CTASection at the bottom of the page uses heroInputRef to scroll to and focus the hero email input when platformCTA.action === "waitlist". However, HeroSection (which contained the <input ref={heroInputRef}>) is now commented out at apps/web/src/routes/_view/index.tsx:169-172.
Root Cause and Impact
In handleCTAClick (apps/web/src/routes/_view/index.tsx:2413-2431), when the platform action is "waitlist", the code calls window.scrollTo({ top: 0 }) and then tries to focus heroInputRef.current. Since HeroSection is commented out, heroInputRef.current is always null, so the if (heroInputRef.current) guard prevents a crash but the button becomes effectively non-functional — it scrolls to the top of the page but provides no further interaction (no focus, no shake animation, no email input visible).
Impact: On non-macOS platforms where platformCTA.action === "waitlist", clicking the bottom CTA button scrolls to the top of the page with no actionable UI, creating a confusing dead-end for users.
Prompt for agents
In apps/web/src/routes/_view/index.tsx, the HeroSection is commented out (lines 169-172) but CTASection (line 192) still receives heroInputRef and tries to use it to focus an email input that no longer exists. Either: (1) Uncomment HeroSection, (2) Replace the CTASection's waitlist behavior with a new action (e.g. navigate to /auth/ or show a signup modal), or (3) Add an email input to the new HeroParagraphSection and attach heroInputRef to it. The heroInputRef, selectedFeature, featuresScrollRef, and scrollToFeature are also unused now and can be cleaned up.
Was this helpful? React with 👍 or 👎 to provide feedback.
| <MockWindow | ||
| showAudioIndicator={activeTab === "notes"} | ||
| audioIndicatorColor="#ef4444" | ||
| audioIndicatorWidth={120} |
There was a problem hiding this comment.
🟡 audioIndicatorWidth prop passed to MockWindow is silently ignored
At line 1188, audioIndicatorWidth={120} is passed to MockWindow, but this component does not accept an audioIndicatorWidth prop.
Root Cause and Impact
The MockWindow component (apps/web/src/components/mock-window.tsx:4-21) only accepts: showAudioIndicator, variant, className, title, prefixIcons, headerClassName, audioIndicatorColor, and children. There is no audioIndicatorWidth prop, so the value 120 is silently ignored.
The inner DancingSticks component uses its default width of 17px instead of the intended 120px. The developer's intent is visible at apps/web/src/routes/_view/index.tsx:1347 where DancingSticks is used directly with width={120} — the same width was intended for the MockWindow's audio indicator but isn't being forwarded.
Impact: The audio indicator in the "How it works" MockWindow renders at 17px wide instead of the intended 120px, making it visually inconsistent with the standalone DancingSticks used below it.
Prompt for agents
In apps/web/src/components/mock-window.tsx, add an optional `audioIndicatorWidth` prop (type: number) to the MockWindow component's props interface, and pass it through to the DancingSticks component as the `width` prop at line 61 (i.e. `<DancingSticks amplitude={1} height={isMobile ? 10 : 12} color={audioIndicatorColor ?? "#a3a3a3"} width={audioIndicatorWidth} />`). This will allow the caller at apps/web/src/routes/_view/index.tsx:1188 to control the width of the audio indicator.
Was this helpful? React with 👍 or 👎 to provide feedback.
|
/staging |
fa817d3 to
eb2b903
Compare
| clearInterval(interval2); | ||
|
|
||
| setTimeout(() => { | ||
| setEnhancedLines(1); | ||
| setActiveTab("summary"); | ||
|
|
||
| setTimeout(() => { | ||
| setEnhancedLines(2); | ||
| setEnhancedLines(1); | ||
| setTimeout(() => { | ||
| setEnhancedLines(3); | ||
| setEnhancedLines(2); | ||
| setTimeout(() => { | ||
| setEnhancedLines(4); | ||
| setEnhancedLines(3); | ||
| setTimeout(() => { | ||
| setEnhancedLines(5); | ||
| setEnhancedLines(4); | ||
| setTimeout(() => { | ||
| setEnhancedLines(6); | ||
| setEnhancedLines(5); | ||
| setTimeout(() => { | ||
| setEnhancedLines(7); | ||
| setTimeout(() => runAnimation(), 1000); | ||
| setEnhancedLines(6); | ||
| setTimeout(() => { | ||
| setEnhancedLines(7); | ||
| setTimeout(() => runAnimation(), 2000); | ||
| }, 800); | ||
| }, 800); | ||
| }, 800); | ||
| }, 800); | ||
| }, 800); | ||
| }, 800); | ||
| }, 800); | ||
| }, 500); | ||
| }, 300); | ||
| }, 800); | ||
| } | ||
| }, 50); | ||
| } |
There was a problem hiding this comment.
🔴 HowItWorksSection animation timers are never cleaned up on unmount
The useEffect in HowItWorksSection (line 1053) starts a recursive animation loop using deeply nested setTimeout and setInterval calls, but returns no cleanup function. When the component unmounts, all pending timers continue to fire.
Detailed Explanation
The animation at apps/web/src/routes/_view/index.tsx:1053-1111 works as follows:
runAnimation()is called, which starts asetTimeout(line 1061)- Inside, a
setIntervaltypes text1 character by character (line 1062) - When done, another
setIntervaltypes text2 (line 1070) - Then a chain of ~9 nested
setTimeoutcalls reveal summary lines (lines 1077-1101) - Finally,
setTimeout(() => runAnimation(), 2000)restarts the whole cycle (line 1094)
None of these timer IDs are tracked or cleaned up. The useEffect has no return/cleanup function. If the user navigates away mid-animation, all pending setTimeout/setInterval callbacks will fire and call setTypedText1, setTypedText2, setEnhancedLines, and setActiveTab on an unmounted component. While React suppresses the state-update-on-unmounted warning in newer versions, this still causes unnecessary work and the timers accumulate if the component is remounted (e.g. navigating away and back).
Impact: Timer/resource leak on navigation. Multiple animation cycles can stack up if the component is repeatedly mounted and unmounted.
(Refers to lines 1053-1111)
Prompt for agents
In apps/web/src/routes/_view/index.tsx, the HowItWorksSection useEffect (lines 1053-1111) starts a complex chain of setTimeout and setInterval calls in runAnimation() but has no cleanup. Add a cleanup mechanism: create a mutable ref or closure variable (e.g. let cancelled = false) and an array to collect all timer IDs. In the cleanup function returned by useEffect, set cancelled = true and clear all collected timers. Guard each setTimeout/setInterval callback with an if (!cancelled) check before calling setState or scheduling further timers. This prevents timer leaks when the component unmounts mid-animation.
Was this helpful? React with 👍 or 👎 to provide feedback.
| <MockWindow | ||
| showAudioIndicator={activeTab === "notes"} | ||
| audioIndicatorColor="#ef4444" | ||
| audioIndicatorWidth={120} |
There was a problem hiding this comment.
🚩 audioIndicatorWidth prop passed to MockWindow but not accepted
At apps/web/src/routes/_view/index.tsx:1130, the HowItWorksSection passes audioIndicatorWidth={120} to MockWindow. However, MockWindow (apps/web/src/components/mock-window.tsx) does not declare audioIndicatorWidth in its props type. In standard React with TypeScript strict mode, this would be a type error caught by the compiler. If it somehow passes type checking (e.g. due to config), the prop is silently ignored — the DancingSticks component inside MockWindow uses its own default width (17px from packages/ui/src/components/ui/dancing-sticks.tsx:86). The intended wider audio indicator (120px) is never applied in the window header. This should be caught by pnpm -r typecheck per the repo's conventions.
Was this helpful? React with 👍 or 👎 to provide feedback.
|
/staging |
mostly want to figure out how to work with staging