Skip to content

fix(navbar): eliminate auth button flash using useSyncExternalStore - #4127

Merged
waleedlatif1 merged 2 commits into
stagingfrom
fix/navbar-auth-flash
Apr 13, 2026
Merged

fix(navbar): eliminate auth button flash using useSyncExternalStore#4127
waleedlatif1 merged 2 commits into
stagingfrom
fix/navbar-auth-flash

Conversation

@waleedlatif1

Copy link
Copy Markdown
Collaborator

Summary

  • Replaced useState(false) + useEffect setMounted with useSyncExternalStore to eliminate the auth button flash on the landing page navbar
  • getServerSnapshot: () => false ensures SSR and initial hydration agree (no mismatch), then client snapshot returns true immediately — no extra render cycle on client-side navigation
  • Extracted shouldShow = mounted && !isSessionPending to unify the condition across desktop and mobile button containers
  • Swapped invisible for opacity-0 pointer-events-none + transition-opacity duration-200 so buttons fade in cleanly once auth resolves instead of snapping
  • Added aria-hidden to both button containers while hidden so invisible buttons are removed from the accessibility tree
  • Bumped GitHub star count to 27.7k

Type of Change

  • Bug fix

Testing

Tested manually — no flash on page load, buttons fade in correctly for both authenticated and unauthenticated states

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

@cursor

cursorBot commented Apr 13, 2026

Copy link
Copy Markdown

PR Summary

Low Risk
Low risk UI-only change that adjusts navbar render/visibility timing during session loading; no auth logic or data handling is modified.

Overview
Prevents landing navbar auth CTAs from briefly flashing by switching the mounted check to useSyncExternalStore and gating both desktop and mobile CTA containers behind a shared shouldShow condition.

Updates hidden-state behavior to fade CTAs in via opacity/pointer-events with aria-hidden/inert while concealed, and bumps the GitHub star fallback display from 27.6k to 27.7k.

Reviewed by Cursor Bugbot for commit 73e1256. Configure here.

@vercel

vercelBot commented Apr 13, 2026

Copy link
Copy Markdown

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

1 Skipped Deployment
ProjectDeploymentActionsUpdated (UTC)
docsSkippedSkippedApr 13, 2026 5:48pm

Request Review

@greptile-apps

greptile-appsBot commented Apr 13, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes the auth button flash on the landing page navbar by replacing the old useState(false) + useEffect mount pattern with useSyncExternalStore, which guarantees the SSR and hydration renders agree on mounted = false before transitioning to true synchronously during hydration. It also smooths the reveal with an opacity fade, improves accessibility using inert + aria-hidden, and bumps the GitHub star count to 27.7k.

Confidence Score: 5/5

Safe to merge — the useSyncExternalStore pattern is correct, previously-raised accessibility issues are resolved, and there are no P0/P1 findings.

All remaining findings are P2 or lower. The useSyncExternalStore implementation correctly uses getServerSnapshot to match SSR output and transitions synchronously to the client snapshot during hydration — eliminating the flash without an extra async render cycle. The inert+aria-hidden pairing (while slightly redundant) is harmless and improves cross-browser compatibility. Prior review concerns about aria-hidden="false" and keyboard focusability have been addressed.

No files require special attention.

Important Files Changed

FilenameOverview
apps/sim/app/(landing)/components/navbar/navbar.tsxCore fix: replaces useState+useEffect mount pattern with useSyncExternalStore for SSR-safe hydration, adds shouldShow guard, opacity transition, inert+aria-hidden on both button containers. Implementation is correct and previously-flagged issues have been addressed.
apps/sim/app/(landing)/components/navbar/components/github-stars.tsxTrivial bump of INITIAL_STARS fallback from '27.6k' to '27.7k'.

Sequence Diagram

sequenceDiagram
participant SSR as Server (SSR)
participant Hydration as Client (Hydration)
participant Client as Client (Post-Hydration)
SSR->>SSR: getServerSnapshot() → false
SSR->>SSR: mounted=false, shouldShow=false
SSR->>SSR: Renders opacity-0 button containers
Hydration->>Hydration: getServerSnapshot() → false (matches SSR)
Hydration->>Hydration: React confirms hydration parity
Hydration->>Hydration: Schedules re-render with getSnapshot()
Client->>Client: getSnapshot() → true
Client->>Client: mounted=true
alt isSessionPending = true
Client->>Client: shouldShow=false, buttons still opacity-0
Client->>Client: Session resolves, isSessionPending=false
Client->>Client: shouldShow=true, fade in 200ms transition
else isSessionPending = false
Client->>Client: shouldShow=true, fade in 200ms transition
end
Loading

Reviews (2): Last reviewed commit: "fix(navbar): add inert and fix aria-hidd..." | Re-trigger Greptile

Comment threadapps/sim/app/(landing)/components/navbar/navbar.tsx Outdated
Comment threadapps/sim/app/(landing)/components/navbar/navbar.tsx

@cursorcursorBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Autofix Details

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Hidden buttons remain keyboard-focusable, violating WCAG accessibility
    • Added inert attribute to both desktop and mobile auth button containers when hidden, preventing keyboard focus on interactive elements while maintaining the opacity transition.

Create PR

Or push these changes by commenting:

@cursor push ccfa6da7ba
Preview (ccfa6da7ba)
diff --git a/apps/sim/app/(landing)/components/navbar/navbar.tsx b/apps/sim/app/(landing)/components/navbar/navbar.tsx--- a/apps/sim/app/(landing)/components/navbar/navbar.tsx+++ b/apps/sim/app/(landing)/components/navbar/navbar.tsx@@ -215,6 +215,7 @@
<div
aria-hidden={!shouldShow}
+ inert={shouldShow ? undefined : ''}
className={cn(
'hidden items-center gap-2 pr-16 pl-5 transition-opacity duration-200 lg:flex',
shouldShow ? 'opacity-100' : 'pointer-events-none opacity-0'
@@ -336,6 +337,7 @@
<div
aria-hidden={!shouldShow}
+ inert={shouldShow ? undefined : ''}
className={cn(
'mt-auto flex flex-col gap-2.5 p-5 transition-opacity duration-200',
shouldShow ? 'opacity-100' : 'pointer-events-none opacity-0'

This Bugbot Autofix run was free. To enable autofix for future PRs, go to the Cursor dashboard.

Comment threadapps/sim/app/(landing)/components/navbar/navbar.tsx
@waleedlatif1

Copy link
Copy Markdown
CollaboratorAuthor

@greptile

@waleedlatif1

Copy link
Copy Markdown
CollaboratorAuthor

@cursor review

@cursorcursorBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 73e1256. Configure here.

@waleedlatif1
waleedlatif1 merged commit cfe5591 into stagingApr 13, 2026
12 checks passed
@waleedlatif1
waleedlatif1 deleted the fix/navbar-auth-flash branch April 13, 2026 18:05
Sign up for freeto 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

@waleedlatif1