Skip to content

fix: three UX polish fixes — modal auto-close, waitlist persistence, skeleton flash - #207

Merged
ayoub3bidi merged 4 commits into
developfrom
fix/auto-close-signin-modal-after-auth
Jul 22, 2026
Merged

fix: three UX polish fixes — modal auto-close, waitlist persistence, skeleton flash#207
ayoub3bidi merged 4 commits into
developfrom
fix/auto-close-signin-modal-after-auth

Conversation

@ayoub3bidi

@ayoub3bidi ayoub3bidi commented Jul 22, 2026

Copy link
Copy Markdown
Owner

Contribution workflow

  • Base branch is develop: This PR targets develop, not `main**.
  • Guidelines and docs: I have read CONTRIBUTING.md and the docs relevant to my change.
  • This template: I kept the PR template structure and filled in the sections below.

Description

Three small UX polish fixes that address annoyances for signed-in and returning users:

  1. SignInPromptModal stays open after Google sign-in — The modal failed to auto-close when the triggering feature path did not set pendingFeatureRef.current (e.g. session_limit, algorithm_lock, speed_control).
  2. Waitlist banner reappears after tab close — Dismissal flag and enrollment email were stored in sessionStorage, which clears when the tab closes. Migrated to localStorage with backward-compatible migration fallback.
  3. Avatar skeleton flash on landing page — Returning authenticated users briefly saw a pulsing skeleton circle in the header during auth hydration, even though the avatar is hidden on the landing page.

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • Test addition or improvement

Related Issues

None (polish fixes identified during UX review).

Changes Made

  • Auto-close SignInPromptModal on successful auth regardless of whether pendingFeatureRef.current is set
  • Migrate persistWaitlistEmail / readStoredWaitlistEmail from sessionStorage to localStorage with migration fallback
  • Migrate banner dismissal flag from sessionStorage to localStorage with migration fallback
  • Add "Pro Plan" link to footer bottom bar (en/fr/ar)
  • Suppress avatar skeleton on landing page by adding !hideAvatar to skeleton condition in UserMenu
  • Add migration fallback tests for banner and service
  • Add test for skeleton suppression with hideAvatar
  • Add test for footer /pro link navigation

Testing

  • All existing tests pass
  • New tests added for new functionality
  • Manual testing completed

Test Results

ProWaitlistBanner (9), waitlistService (10), Footer (5), UserMenu (11), SignInPromptModal (13), VisualizerApp (27) — all passing.

Code Quality

  • Code follows the project's coding standards
  • ESLint passes
  • No console errors or warnings

Breaking Changes

  • None

Checklist

  • I have completed the Contribution workflow checklist
  • My code follows the project's style guidelines
  • I have performed a self-review of my code
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective
  • New and existing unit tests pass locally with my changes

Summary by CodeRabbit

  • New Features
    • Added a localized Pro Plan link to the footer, linking to the Pro Plan page.
    • Improved Pro waitlist persistence across visits by storing enrollment and dismissal preferences locally, while preserving existing preferences.
  • Bug Fixes
    • Loading placeholders no longer appear when avatars are intentionally hidden.
    • Gated features now open and close more reliably after authentication.
  • Localization
    • Added Pro Plan translations in English, Arabic, and French.
    • Standardized Pro Plan branding across related English waitlist content.

When anonymous users triggered the sign-in modal via gated features
like session_limit, algorithm_lock, or category_controls, the modal
stayed open after successful Google authentication because those
trigger paths did not set pendingFeatureRef.current.

The auto-close effect now unconditionally dismisses the modal when
isAuthenticated becomes true, while still auto-opening the
pending feature (sound, fullscreen, export, code, insight) when
one was set.
…r link

Migrate waitlist banner dismissal and enrollment flags from
sessionStorage to localStorage so they persist across browser
sessions. Users who dismissed the banner or joined the waitlist
will no longer see it reappear after closing the tab.

Also adds a 'Pro Plan' link in the footer bottom bar alongside
Privacy Policy and Terms of Use, giving users a persistent
way to navigate to the /pro page.

- waitlistService: persistWaitlistEmail/readStoredWaitlistEmail
  now use localStorage with sessionStorage migration fallback
- ProWaitlistBanner: dismissal flag reads/writes to localStorage
  with sessionStorage migration fallback
- Footer: new 'Pro Plan' link in bottom bar (en/fr/ar)
- Tests: updated assertions to localStorage, added migration
  fallback tests for both banner and service
When an authenticated user visits the landing page, the auth
hydration window briefly shows a pulsing skeleton circle in the
header before hideAvatar hides it. Adding !hideAvatar to the
skeleton condition prevents this flash on pages that don't
display the avatar.
@github-actions github-actions Bot added style Improve styling, design, and animation tests labels Jul 22, 2026
@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@ayoub3bidi, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 45 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 9c50d98a-2f52-4870-9f9c-5ef6d649a83d

📥 Commits

Reviewing files that changed from the base of the PR and between 4216787 and 93858c2.

📒 Files selected for processing (4)
  • src/components/Footer.jsx
  • src/components/Footer.test.jsx
  • src/components/ProWaitlistBanner.jsx
  • src/services/waitlistService.js
📝 Walkthrough

Walkthrough

The PR adds a localized Pro Plan footer link, migrates waitlist state from sessionStorage to localStorage with fallback migration, suppresses a UserMenu loading skeleton when avatars are hidden, and refines authenticated gated-feature handling.

Changes

Pro waitlist and navigation

Layer / File(s) Summary
Waitlist storage migration
src/services/waitlistService.js, src/components/ProWaitlistBanner.jsx, src/services/waitlistService.test.js, src/components/ProWaitlistBanner.test.jsx
Waitlist emails and banner dismissal flags now use localStorage, while legacy sessionStorage values are migrated and covered by tests.
Pro Plan footer entry
src/components/Footer.jsx, src/i18n/locales/*/translation.json, src/components/Footer.test.jsx
The footer adds a localized Pro Plan button linking to /pro; English Pro Plan copy capitalization is standardized and navigation is tested.

User menu loading behavior

Layer / File(s) Summary
Hide avatar loading condition
src/components/UserMenu.jsx, src/components/UserMenu.test.jsx
The loading skeleton is omitted when hideAvatar is enabled.

Visualizer authentication gating

Layer / File(s) Summary
Authenticated gated-feature flow
src/pages/VisualizerApp.jsx
Pending gated features are opened and cleared, and the gated-feature UI is closed only within the authenticated branch.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

Suggested labels: tests

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main UX fixes in the changeset: modal auto-close, waitlist persistence, and skeleton flash removal.
Docstring Coverage ✅ Passed Docstring coverage is 83.33% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/auto-close-signin-modal-after-auth

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.

@github-actions

github-actions Bot commented Jul 22, 2026

Copy link
Copy Markdown

Preview for Bayan Flow Staging ready!

Name Link
🔨 Latest commit 93858c2
🔍 Latest deploy log https://github.com/ayoub3bidi/bayan-flow/actions/runs/29945739652
😎 Deploy Preview https://pr-207-bayan-flow-staging.ayoub3bidi.workers.dev
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

Preview alias pr-207 on the staging worker. Updates automatically with new commits.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 2

🧹 Nitpick comments (1)
src/components/UserMenu.test.jsx (1)

55-68: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Also assert the unauthenticated fallback is rendered.

This test would still pass if UserMenu incorrectly returned null; assert the expected sign-in button alongside the skeleton’s absence so the loading-path behavior remains covered.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/UserMenu.test.jsx` around lines 55 - 68, Add an assertion in
the “does not show loading skeleton when hideAvatar is true” test that verifies
the unauthenticated sign-in button is rendered, while retaining the existing
assertion that no loading skeleton appears.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/components/Footer.jsx`:
- Around line 291-299: Replace the Pro Plan motion button in Footer.jsx with the
project’s router link element targeting /pro, preserving its existing visual
styling and click behavior. In Footer.test.jsx, render and assert the entry
using getByRole('link', { name: i18n.t('footer.proPlan') }) and perform click
assertions through that link role.

In `@src/services/waitlistService.js`:
- Around line 46-51: Preserve sessionStorage fallback across all four storage
paths: in src/services/waitlistService.js lines 46-51, update
persistWaitlistEmail to write to sessionStorage when localStorage fails; in
lines 57-70, isolate localStorage and sessionStorage errors and return the
legacy value even when migration cannot write; in
src/components/ProWaitlistBanner.jsx lines 26-45, continue reading
sessionStorage after localStorage access fails; and in lines 59-66, fall back to
sessionStorage when dismissal persistence fails. Keep localStorage as the
primary store.

---

Nitpick comments:
In `@src/components/UserMenu.test.jsx`:
- Around line 55-68: Add an assertion in the “does not show loading skeleton
when hideAvatar is true” test that verifies the unauthenticated sign-in button
is rendered, while retaining the existing assertion that no loading skeleton
appears.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: b08c75c0-2f1a-4c75-af7b-b081c2e26c24

📥 Commits

Reviewing files that changed from the base of the PR and between 9e35997 and 4216787.

📒 Files selected for processing (12)
  • src/components/Footer.jsx
  • src/components/Footer.test.jsx
  • src/components/ProWaitlistBanner.jsx
  • src/components/ProWaitlistBanner.test.jsx
  • src/components/UserMenu.jsx
  • src/components/UserMenu.test.jsx
  • src/i18n/locales/ar/translation.json
  • src/i18n/locales/en/translation.json
  • src/i18n/locales/fr/translation.json
  • src/pages/VisualizerApp.jsx
  • src/services/waitlistService.js
  • src/services/waitlistService.test.js

Comment thread src/components/Footer.jsx Outdated
Comment thread src/services/waitlistService.js
@ayoub3bidi
ayoub3bidi merged commit 0b804d9 into develop Jul 22, 2026
14 checks passed
@ayoub3bidi
ayoub3bidi deleted the fix/auto-close-signin-modal-after-auth branch July 22, 2026 18:28
@codecov

codecov Bot commented Jul 22, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

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

Labels

style Improve styling, design, and animation tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant