Skip to content

Conversation

@zonetecde
Copy link
Collaborator

@zonetecde zonetecde commented Nov 1, 2025

…mprove website's performance

Summary

Refactored all the mobile-only conditionals to use our useIsMobile hook with a desktop-first default, so we don’t flip markup between SSR and hydration.
We keep the layout stable during hydration, so CLS drops, and we skip extra client re-renders, which helps TBT (both boost lighthouse score).
Replaced the checkmark emoji with its Unicode escape \u2713

Type of change

  • Bug fix (non-breaking change which fixes an issue)

Test plan

I've checked with MCP Playwright that the changes took effect on the site.

Checklist

  • My code follows the style guidelines of this project
  • I have performed a self-review of my code
  • My changes generate no new warnings
  • Any dependent changes have been merged and published in downstream modules
  • I have commented on my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes

Summary by CodeRabbit

  • Refactor
    • Unified mobile detection across the app to improve consistency and responsiveness of layouts and controls.
  • New Behavior
    • Onboarding and several homepage/reader components now adapt more reliably to mobile vs. desktop, improving layout and button/label presentation on small screens.

@zonetecde zonetecde changed the title Refactor mobile detection to keep SSR and client markup aligned and i… Perf - Fix mobile detection hydration mismatch Nov 1, 2025
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 1, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

This PR replaces direct runtime isMobile() checks with a React hook useIsMobile() across many components and updates the useIsMobile implementation to initialize via an effect and a shared resize handler. It also threads a new isDeviceMobile argument into onboarding steps and adds a few ActionButtons props.

Changes

Cohort / File(s) Summary
Mobile Detection Hook
src/hooks/useIsMobile.ts
Simplifies initialization: initial state false, effect-based immediate update on mount, shared updateView handler for resize, removes SSR-lazy init path; public hook signature unchanged.
HomePage / Reading
src/pages/index.tsx, src/components/HomePage/ReadingSection/index.tsx, src/components/HomePage/ReadingSection/ChapterCard/index.tsx
Import and use useIsMobile()isMobileView; replace isMobile() checks with isMobileView for conditional render branches.
Onboarding
src/components/Onboarding/OnboardingProvider.tsx, src/components/Onboarding/steps.ts
checklistIndexToOnboardingSteps gains optional isDeviceMobile parameter (default false); OnboardingProvider passes isMobileView into steps and includes it in memo deps; internal isMobile() removed.
QuranReader Context Menu
src/components/QuranReader/ContextMenu/index.tsx, src/components/QuranReader/ContextMenu/hooks/useContextMenuState.ts
Replace isMobile() with useIsMobile() (isMobileView) for scrolled-view and sidebar toggle visibility logic.
Sidebar Navigation
src/components/QuranReader/SidebarNavigation/SidebarNavigation.tsx, src/components/QuranReader/SidebarNavigation/SidebarNavigationSelections.tsx
Replace isMobile() with useIsMobile() in outside-click and post-navigation sidebar-close logic; adjust imports accordingly.
QuranicCalendar
src/components/QuranicCalendar/MyProgress/index.tsx, src/components/QuranicCalendar/QuranicCalendarHero/ActionButtons.tsx, src/components/QuranicCalendar/WeeklyVerses/ActionButtons.tsx
Replace isMobile() with useIsMobile() for layout/label decisions; WeeklyVerses/ActionButtons adds props: isCompleted, shouldShowLoading, pdfUrl?, onHelpClick.
Search
src/components/Search/SearchInput/index.tsx
Use useIsMobile() (isMobileView) instead of isMobile() to decide mobile drawer rendering.
Other small components
src/components/HomePage/..., other listed files in raw summary
Consistent replacement of isMobile() with useIsMobile() and minor import adjustments; no public API signature regressions except onboarding steps and WeeklyVerses props addition.

Sequence Diagram(s)

sequenceDiagram
    participant Component as UI Component
    participant Hook as useIsMobile()
    participant Window as window

    Component->>Hook: call useIsMobile()
    Hook->>Hook: init state = false
    Hook->>Window: add resize listener (updateView)
    Hook-->>Component: return isMobileView (initial false, then updated)
    Note right of Hook: on mount/update -> compute and set isMobileView\non resize -> updateView -> set state
Loading
sequenceDiagram
    participant OnboardingProvider
    participant Steps as checklistIndexToOnboardingSteps

    OnboardingProvider->>Steps: call (t, Component, isMobileView)
    Steps-->>OnboardingProvider: steps configured using isDeviceMobile
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Changes are widespread but follow a consistent pattern (hook import + replace checks).
  • Areas needing extra attention:
    • src/hooks/useIsMobile.ts — confirm SSR/hydration implications and resize handler correctness.
    • src/components/Onboarding/steps.ts — verify callers and default behavior remain compatible.
    • src/components/QuranicCalendar/WeeklyVerses/ActionButtons.tsx — review additions to ActionButtonsProps and downstream usages.

Poem

🐰 I hopped through code with curious eyes,

Swapped functions for hooks beneath the skies,
Mobile now listens and tells me true,
Resize and mount — it updates the view,
A little rabbit clap for the new cue ✨

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 PR title "Perf - Fix mobile detection hydration mismatch" directly and specifically describes the main objective of the changeset. The changes consistently refactor mobile detection logic by replacing runtime isMobile() function calls with a useIsMobile() hook that has a desktop-first default to prevent hydration mismatches. This aligns perfectly with the title's focus on fixing the hydration mismatch issue for performance improvement, making it clear and actionable for someone reviewing the repository history.
Description Check ✅ Passed The PR description covers all major required sections from the template: it includes a clear summary explaining the refactoring and its performance benefits (CLS and TBT improvements), marks the appropriate type of change (bug fix), provides a test plan (MCP Playwright verification), and includes a checklist with multiple items marked as complete. While the description omits the JIRA ticket reference and the screenshots/videos section, these are non-critical omissions and the core content is comprehensive and well-documented, explaining both what was changed and why.
✨ 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 perf/hydration-mismatch-mobile-detection

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 90487ee and fb060b5.

📒 Files selected for processing (1)
  • src/components/QuranicCalendar/WeeklyVerses/ActionButtons.tsx (4 hunks)
🧰 Additional context used
📓 Path-based instructions (13)
**/*.*

📄 CodeRabbit inference engine (.cursor/rules/bug-handling-with-todo-comments.mdc)

If you encounter a bug in existing code, or the instructions lead to suboptimal or buggy code, add comments starting with "TODO:" outlining the problems.

**/*.*: Utilize Early Returns: Use early returns to avoid nested conditions and improve readability.
Conditional Classes: Prefer conditional classes over ternary operators for class attributes.

**/*.*: Use comments sparingly, and when you do, make them meaningful.
Don't comment on obvious things. Excessive or unclear comments can clutter the codebase and become outdated.
Use comments to convey the 'why' behind specific actions or explain unusual behavior and potential pitfalls.
Provide meaningful information about the function's behavior and explain unusual behavior and potential pitfalls.

**/*.*: Write short functions that only do one thing.
Follow the single responsibility principle (SRP), which means that a function should have one purpose and perform it effectively.
If a function becomes too long or complex, consider breaking it into smaller, more manageable functions.

Order functions with those that are composing other functions appearing earlier in the file. For example, if you have a menu with multiple buttons, define the menu function above the buttons.

**/*.*: Always add helpful comments to the code explaining what you are doing.
Never delete old comments, unless they are no longer relevant because the code has been rewritten or deleted.

**/*.*: Choose names for variables, functions, and classes that reflect their purpose and behavior.
A name should tell you why it exists, what it does, and how it is used. If a name requires a comment, then the name does not reveal its intent.
Use specific names that provide a clearer understanding of what the variables represent and how they are used.

Files:

  • src/components/QuranicCalendar/WeeklyVerses/ActionButtons.tsx
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/next-js-conventions.mdc)

**/*.{js,jsx,ts,tsx}: Rely on Next.js Pages Router for state changes.
Minimize 'use client' usage: Prefer server components and Next.js SSR features.
Minimize 'use client' usage: Use 'use client' only for Web API access in small components.
Minimize 'use client' usage: Avoid using 'use client' for data fetching or state management.

**/*.{js,jsx,ts,tsx}: Optimize Web Vitals (LCP, CLS, FID)
Use dynamic loading for non-critical components using @src/components/dls/Spinner/Spinner.tsx

Files:

  • src/components/QuranicCalendar/WeeklyVerses/ActionButtons.tsx
src/components/**/*.tsx

📄 CodeRabbit inference engine (.cursor/rules/react-functional-components.mdc)

src/components/**/*.tsx: Always use React functional components with hooks.
Use React.FC for functional components with props.

Files:

  • src/components/QuranicCalendar/WeeklyVerses/ActionButtons.tsx
**/*.{tsx,jsx}

📄 CodeRabbit inference engine (.cursor/rules/react.mdc)

**/*.{tsx,jsx}: Use functional components over class components
Keep components small and focused
Extract reusable logic into custom hooks
Use composition over inheritance
Split large components into smaller, focused ones
Follow the Rules of Hooks
Use custom hooks for reusable logic
Use appropriate dependency arrays in useEffect
Implement cleanup in useEffect when needed
Avoid nested hooks
Use useState for local component state
Avoid prop drilling through proper state management
Implement proper memoization (useMemo, useCallback)
Use React.memo for expensive components
Avoid unnecessary re-renders
Implement proper lazy loading
Use proper key props in lists
Profile and optimize render performance
Show appropriate loading and error states
Handle async errors properly
Show user-friendly error messages
Implement proper fallback UI
Log errors appropriately
Handle edge cases gracefully
Use semantic HTML elements
Implement proper ARIA attributes
Ensure keyboard navigation
Handle focus management
Provide proper alt text for images
Use proper imports/exports
Document complex component logic

Files:

  • src/components/QuranicCalendar/WeeklyVerses/ActionButtons.tsx
**/*.tsx

📄 CodeRabbit inference engine (.cursor/rules/react.mdc)

Implement proper prop types with TypeScript

**/*.tsx: Prefix interfaces for React props with 'Props' (e.g., ButtonProps)
Implement proper error boundaries

React: use functional components only; extract reusable logic into custom hooks; apply proper memoization (React.memo/useMemo/useCallback)

Files:

  • src/components/QuranicCalendar/WeeklyVerses/ActionButtons.tsx
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/react.mdc)

Use xstate for complex state logic

**/*.{ts,tsx}: TypeScript: prefer interfaces over type aliases for object shapes; avoid any; add explicit return types for public functions
Error handling: define and use custom error types; use async/await correctly; show user-friendly error messages
Use Redux Toolkit for state management and XState for complex state machines
Implement i18n with next-translate in components and utilities

Files:

  • src/components/QuranicCalendar/WeeklyVerses/ActionButtons.tsx
**/*.{ts,tsx,d.ts}

📄 CodeRabbit inference engine (.cursor/rules/typescript.mdc)

**/*.{ts,tsx,d.ts}: Prefer interfaces over types for object definitions
Use type for unions, intersections, and mapped types
Avoid using any, prefer unknown for unknown types
Leverage TypeScript's built-in utility types
Use generics for reusable type patterns
Use PascalCase for type names and interfaces
Use camelCase for variables and functions
Use UPPER_CASE for constants
Use descriptive names with auxiliary verbs (e.g., isLoading, hasError)
Use explicit return types for public functions
Use arrow functions for callbacks and methods
Implement proper error handling with custom error types
Use function overloads for complex type scenarios
Prefer async/await over Promises
Use readonly for immutable properties
Leverage discriminated unions for type safety
Use type guards for runtime type checking
Implement proper null checking
Avoid type assertions unless necessary
Create custom error types for domain-specific errors
Use Result types for operations that can fail
Use try-catch blocks with typed catch clauses
Handle Promise rejections properly

Files:

  • src/components/QuranicCalendar/WeeklyVerses/ActionButtons.tsx
{src,types}/**/*.ts?(x)

📄 CodeRabbit inference engine (CLAUDE.md)

Use TypeScript throughout the codebase with strict configuration

Files:

  • src/components/QuranicCalendar/WeeklyVerses/ActionButtons.tsx
src/**/*.tsx

📄 CodeRabbit inference engine (CLAUDE.md)

Prefer React functional components for UI implementation

Files:

  • src/components/QuranicCalendar/WeeklyVerses/ActionButtons.tsx
{src,types}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Use path aliases @/ for src and @/dls/* for design system imports

Files:

  • src/components/QuranicCalendar/WeeklyVerses/ActionButtons.tsx
src/components/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Organize React components by feature and place DLS components under src/components/dls

Files:

  • src/components/QuranicCalendar/WeeklyVerses/ActionButtons.tsx
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx,js,jsx}: Order imports: React first, then external, then internal; alphabetize within groups with blank lines between groups
Naming: camelCase for variables/functions; PascalCase for types, interfaces, and React components; UPPER_CASE for constants
Functions should be <= 30 lines, prefer early returns, single responsibility, and descriptive names

Files:

  • src/components/QuranicCalendar/WeeklyVerses/ActionButtons.tsx
**/*.{ts,tsx,js,jsx,scss}

📄 CodeRabbit inference engine (AGENTS.md)

Use Prettier formatting: single quotes, 2-space indentation, 100-character line width, and trailing commas

Files:

  • src/components/QuranicCalendar/WeeklyVerses/ActionButtons.tsx
🧠 Learnings (3)
📓 Common learnings
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .cursor/rules/react.mdc:0-0
Timestamp: 2025-08-01T08:50:54.518Z
Learning: Applies to **/*.{tsx,jsx} : Use custom hooks for reusable logic
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .cursor/rules/react.mdc:0-0
Timestamp: 2025-08-01T08:50:54.518Z
Learning: Applies to **/use*.{tsx,jsx} : Keep hooks focused and simple
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-10-07T08:38:28.343Z
Learning: Applies to **/*.tsx : React: use functional components only; extract reusable logic into custom hooks; apply proper memoization (React.memo/useMemo/useCallback)
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .cursor/rules/react.mdc:0-0
Timestamp: 2025-08-01T08:50:54.518Z
Learning: Applies to **/*.{tsx,jsx} : Extract reusable logic into custom hooks
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .cursor/rules/react-functional-components.mdc:0-0
Timestamp: 2025-08-01T08:50:22.602Z
Learning: Applies to src/components/**/*.tsx : Always use React functional components with hooks.
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-07T08:37:58.213Z
Learning: Applies to src/**/*.tsx : Prefer React functional components for UI implementation
📚 Learning: 2025-10-22T20:33:55.176Z
Learnt from: yousefdergham
Repo: quran/quran.com-frontend-next PR: 2547
File: src/components/Course/CourseDetails/Tabs/Syllabus/index.tsx:44-49
Timestamp: 2025-10-22T20:33:55.176Z
Learning: Preference: In quran.com-frontend-next, keep concise “why” comments for analytics/UX decision points (e.g., guest vs enrolled click handlers) but avoid verbose JSDoc that repeats params/types. Convert multi-line JSDoc to brief inline rationale comments, especially in src/components/Course/CourseDetails/Tabs/Syllabus/index.tsx and similar analytics handlers.

Applied to files:

  • src/components/QuranicCalendar/WeeklyVerses/ActionButtons.tsx
📚 Learning: 2025-10-26T10:22:52.381Z
Learnt from: afifvdin
Repo: quran/quran.com-frontend-next PR: 2540
File: src/components/QuranReader/TranslationView/TranslationText/TranslationAndReference.tsx:60-60
Timestamp: 2025-10-26T10:22:52.381Z
Learning: In src/components/QuranReader/TranslationView/TranslationText/TranslationAndReference.tsx, verse references displayed alongside chapter names should use English/Western numerals only, not localized numerals, as per design specifications.

Applied to files:

  • src/components/QuranicCalendar/WeeklyVerses/ActionButtons.tsx
🔇 Additional comments (2)
src/components/QuranicCalendar/WeeklyVerses/ActionButtons.tsx (2)

10-10: LGTM! Correct migration to useIsMobile hook.

The replacement of the isMobile() utility with the useIsMobile() hook is correct and aligns with the PR's goal of preventing hydration mismatches. This approach maintains a stable layout during SSR and client-side hydration.

Also applies to: 36-36


46-51: Excellent refactor addressing previous feedback!

The extraction of getMarkAsCompletedLabel() successfully resolves the nested ternary concerns raised in previous reviews. The helper function is clear, follows the early-return pattern, and maintains single responsibility. The resulting JSX is much cleaner.

Also applies to: 66-66


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.

@zonetecde
Copy link
Collaborator Author

@coderabbitai review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 1, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

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: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c48a956 and 90487ee.

📒 Files selected for processing (14)
  • src/components/HomePage/ReadingSection/ChapterCard/index.tsx (3 hunks)
  • src/components/HomePage/ReadingSection/index.tsx (4 hunks)
  • src/components/Onboarding/OnboardingProvider.tsx (2 hunks)
  • src/components/Onboarding/steps.ts (1 hunks)
  • src/components/QuranReader/ContextMenu/hooks/useContextMenuState.ts (3 hunks)
  • src/components/QuranReader/ContextMenu/index.tsx (3 hunks)
  • src/components/QuranReader/SidebarNavigation/SidebarNavigation.tsx (2 hunks)
  • src/components/QuranReader/SidebarNavigation/SidebarNavigationSelections.tsx (3 hunks)
  • src/components/QuranicCalendar/MyProgress/index.tsx (3 hunks)
  • src/components/QuranicCalendar/QuranicCalendarHero/ActionButtons.tsx (6 hunks)
  • src/components/QuranicCalendar/WeeklyVerses/ActionButtons.tsx (4 hunks)
  • src/components/Search/SearchInput/index.tsx (3 hunks)
  • src/hooks/useIsMobile.ts (1 hunks)
  • src/pages/index.tsx (3 hunks)
🧰 Additional context used
📓 Path-based instructions (14)
**/*.*

📄 CodeRabbit inference engine (.cursor/rules/bug-handling-with-todo-comments.mdc)

If you encounter a bug in existing code, or the instructions lead to suboptimal or buggy code, add comments starting with "TODO:" outlining the problems.

**/*.*: Utilize Early Returns: Use early returns to avoid nested conditions and improve readability.
Conditional Classes: Prefer conditional classes over ternary operators for class attributes.

**/*.*: Use comments sparingly, and when you do, make them meaningful.
Don't comment on obvious things. Excessive or unclear comments can clutter the codebase and become outdated.
Use comments to convey the 'why' behind specific actions or explain unusual behavior and potential pitfalls.
Provide meaningful information about the function's behavior and explain unusual behavior and potential pitfalls.

**/*.*: Write short functions that only do one thing.
Follow the single responsibility principle (SRP), which means that a function should have one purpose and perform it effectively.
If a function becomes too long or complex, consider breaking it into smaller, more manageable functions.

Order functions with those that are composing other functions appearing earlier in the file. For example, if you have a menu with multiple buttons, define the menu function above the buttons.

**/*.*: Always add helpful comments to the code explaining what you are doing.
Never delete old comments, unless they are no longer relevant because the code has been rewritten or deleted.

**/*.*: Choose names for variables, functions, and classes that reflect their purpose and behavior.
A name should tell you why it exists, what it does, and how it is used. If a name requires a comment, then the name does not reveal its intent.
Use specific names that provide a clearer understanding of what the variables represent and how they are used.

Files:

  • src/components/QuranicCalendar/QuranicCalendarHero/ActionButtons.tsx
  • src/components/QuranReader/SidebarNavigation/SidebarNavigationSelections.tsx
  • src/components/QuranReader/ContextMenu/index.tsx
  • src/components/Onboarding/steps.ts
  • src/components/QuranicCalendar/MyProgress/index.tsx
  • src/components/HomePage/ReadingSection/index.tsx
  • src/components/Onboarding/OnboardingProvider.tsx
  • src/components/Search/SearchInput/index.tsx
  • src/components/QuranicCalendar/WeeklyVerses/ActionButtons.tsx
  • src/hooks/useIsMobile.ts
  • src/components/QuranReader/SidebarNavigation/SidebarNavigation.tsx
  • src/components/HomePage/ReadingSection/ChapterCard/index.tsx
  • src/components/QuranReader/ContextMenu/hooks/useContextMenuState.ts
  • src/pages/index.tsx
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/next-js-conventions.mdc)

**/*.{js,jsx,ts,tsx}: Rely on Next.js Pages Router for state changes.
Minimize 'use client' usage: Prefer server components and Next.js SSR features.
Minimize 'use client' usage: Use 'use client' only for Web API access in small components.
Minimize 'use client' usage: Avoid using 'use client' for data fetching or state management.

**/*.{js,jsx,ts,tsx}: Optimize Web Vitals (LCP, CLS, FID)
Use dynamic loading for non-critical components using @src/components/dls/Spinner/Spinner.tsx

Files:

  • src/components/QuranicCalendar/QuranicCalendarHero/ActionButtons.tsx
  • src/components/QuranReader/SidebarNavigation/SidebarNavigationSelections.tsx
  • src/components/QuranReader/ContextMenu/index.tsx
  • src/components/Onboarding/steps.ts
  • src/components/QuranicCalendar/MyProgress/index.tsx
  • src/components/HomePage/ReadingSection/index.tsx
  • src/components/Onboarding/OnboardingProvider.tsx
  • src/components/Search/SearchInput/index.tsx
  • src/components/QuranicCalendar/WeeklyVerses/ActionButtons.tsx
  • src/hooks/useIsMobile.ts
  • src/components/QuranReader/SidebarNavigation/SidebarNavigation.tsx
  • src/components/HomePage/ReadingSection/ChapterCard/index.tsx
  • src/components/QuranReader/ContextMenu/hooks/useContextMenuState.ts
  • src/pages/index.tsx
src/components/**/*.tsx

📄 CodeRabbit inference engine (.cursor/rules/react-functional-components.mdc)

src/components/**/*.tsx: Always use React functional components with hooks.
Use React.FC for functional components with props.

Files:

  • src/components/QuranicCalendar/QuranicCalendarHero/ActionButtons.tsx
  • src/components/QuranReader/SidebarNavigation/SidebarNavigationSelections.tsx
  • src/components/QuranReader/ContextMenu/index.tsx
  • src/components/QuranicCalendar/MyProgress/index.tsx
  • src/components/HomePage/ReadingSection/index.tsx
  • src/components/Onboarding/OnboardingProvider.tsx
  • src/components/Search/SearchInput/index.tsx
  • src/components/QuranicCalendar/WeeklyVerses/ActionButtons.tsx
  • src/components/QuranReader/SidebarNavigation/SidebarNavigation.tsx
  • src/components/HomePage/ReadingSection/ChapterCard/index.tsx
**/*.{tsx,jsx}

📄 CodeRabbit inference engine (.cursor/rules/react.mdc)

**/*.{tsx,jsx}: Use functional components over class components
Keep components small and focused
Extract reusable logic into custom hooks
Use composition over inheritance
Split large components into smaller, focused ones
Follow the Rules of Hooks
Use custom hooks for reusable logic
Use appropriate dependency arrays in useEffect
Implement cleanup in useEffect when needed
Avoid nested hooks
Use useState for local component state
Avoid prop drilling through proper state management
Implement proper memoization (useMemo, useCallback)
Use React.memo for expensive components
Avoid unnecessary re-renders
Implement proper lazy loading
Use proper key props in lists
Profile and optimize render performance
Show appropriate loading and error states
Handle async errors properly
Show user-friendly error messages
Implement proper fallback UI
Log errors appropriately
Handle edge cases gracefully
Use semantic HTML elements
Implement proper ARIA attributes
Ensure keyboard navigation
Handle focus management
Provide proper alt text for images
Use proper imports/exports
Document complex component logic

Files:

  • src/components/QuranicCalendar/QuranicCalendarHero/ActionButtons.tsx
  • src/components/QuranReader/SidebarNavigation/SidebarNavigationSelections.tsx
  • src/components/QuranReader/ContextMenu/index.tsx
  • src/components/QuranicCalendar/MyProgress/index.tsx
  • src/components/HomePage/ReadingSection/index.tsx
  • src/components/Onboarding/OnboardingProvider.tsx
  • src/components/Search/SearchInput/index.tsx
  • src/components/QuranicCalendar/WeeklyVerses/ActionButtons.tsx
  • src/components/QuranReader/SidebarNavigation/SidebarNavigation.tsx
  • src/components/HomePage/ReadingSection/ChapterCard/index.tsx
  • src/pages/index.tsx
**/*.tsx

📄 CodeRabbit inference engine (.cursor/rules/react.mdc)

Implement proper prop types with TypeScript

**/*.tsx: Prefix interfaces for React props with 'Props' (e.g., ButtonProps)
Implement proper error boundaries

React: use functional components only; extract reusable logic into custom hooks; apply proper memoization (React.memo/useMemo/useCallback)

Files:

  • src/components/QuranicCalendar/QuranicCalendarHero/ActionButtons.tsx
  • src/components/QuranReader/SidebarNavigation/SidebarNavigationSelections.tsx
  • src/components/QuranReader/ContextMenu/index.tsx
  • src/components/QuranicCalendar/MyProgress/index.tsx
  • src/components/HomePage/ReadingSection/index.tsx
  • src/components/Onboarding/OnboardingProvider.tsx
  • src/components/Search/SearchInput/index.tsx
  • src/components/QuranicCalendar/WeeklyVerses/ActionButtons.tsx
  • src/components/QuranReader/SidebarNavigation/SidebarNavigation.tsx
  • src/components/HomePage/ReadingSection/ChapterCard/index.tsx
  • src/pages/index.tsx
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/react.mdc)

Use xstate for complex state logic

**/*.{ts,tsx}: TypeScript: prefer interfaces over type aliases for object shapes; avoid any; add explicit return types for public functions
Error handling: define and use custom error types; use async/await correctly; show user-friendly error messages
Use Redux Toolkit for state management and XState for complex state machines
Implement i18n with next-translate in components and utilities

Files:

  • src/components/QuranicCalendar/QuranicCalendarHero/ActionButtons.tsx
  • src/components/QuranReader/SidebarNavigation/SidebarNavigationSelections.tsx
  • src/components/QuranReader/ContextMenu/index.tsx
  • src/components/Onboarding/steps.ts
  • src/components/QuranicCalendar/MyProgress/index.tsx
  • src/components/HomePage/ReadingSection/index.tsx
  • src/components/Onboarding/OnboardingProvider.tsx
  • src/components/Search/SearchInput/index.tsx
  • src/components/QuranicCalendar/WeeklyVerses/ActionButtons.tsx
  • src/hooks/useIsMobile.ts
  • src/components/QuranReader/SidebarNavigation/SidebarNavigation.tsx
  • src/components/HomePage/ReadingSection/ChapterCard/index.tsx
  • src/components/QuranReader/ContextMenu/hooks/useContextMenuState.ts
  • src/pages/index.tsx
**/*.{ts,tsx,d.ts}

📄 CodeRabbit inference engine (.cursor/rules/typescript.mdc)

**/*.{ts,tsx,d.ts}: Prefer interfaces over types for object definitions
Use type for unions, intersections, and mapped types
Avoid using any, prefer unknown for unknown types
Leverage TypeScript's built-in utility types
Use generics for reusable type patterns
Use PascalCase for type names and interfaces
Use camelCase for variables and functions
Use UPPER_CASE for constants
Use descriptive names with auxiliary verbs (e.g., isLoading, hasError)
Use explicit return types for public functions
Use arrow functions for callbacks and methods
Implement proper error handling with custom error types
Use function overloads for complex type scenarios
Prefer async/await over Promises
Use readonly for immutable properties
Leverage discriminated unions for type safety
Use type guards for runtime type checking
Implement proper null checking
Avoid type assertions unless necessary
Create custom error types for domain-specific errors
Use Result types for operations that can fail
Use try-catch blocks with typed catch clauses
Handle Promise rejections properly

Files:

  • src/components/QuranicCalendar/QuranicCalendarHero/ActionButtons.tsx
  • src/components/QuranReader/SidebarNavigation/SidebarNavigationSelections.tsx
  • src/components/QuranReader/ContextMenu/index.tsx
  • src/components/Onboarding/steps.ts
  • src/components/QuranicCalendar/MyProgress/index.tsx
  • src/components/HomePage/ReadingSection/index.tsx
  • src/components/Onboarding/OnboardingProvider.tsx
  • src/components/Search/SearchInput/index.tsx
  • src/components/QuranicCalendar/WeeklyVerses/ActionButtons.tsx
  • src/hooks/useIsMobile.ts
  • src/components/QuranReader/SidebarNavigation/SidebarNavigation.tsx
  • src/components/HomePage/ReadingSection/ChapterCard/index.tsx
  • src/components/QuranReader/ContextMenu/hooks/useContextMenuState.ts
  • src/pages/index.tsx
{src,types}/**/*.ts?(x)

📄 CodeRabbit inference engine (CLAUDE.md)

Use TypeScript throughout the codebase with strict configuration

Files:

  • src/components/QuranicCalendar/QuranicCalendarHero/ActionButtons.tsx
  • src/components/QuranReader/SidebarNavigation/SidebarNavigationSelections.tsx
  • src/components/QuranReader/ContextMenu/index.tsx
  • src/components/Onboarding/steps.ts
  • src/components/QuranicCalendar/MyProgress/index.tsx
  • src/components/HomePage/ReadingSection/index.tsx
  • src/components/Onboarding/OnboardingProvider.tsx
  • src/components/Search/SearchInput/index.tsx
  • src/components/QuranicCalendar/WeeklyVerses/ActionButtons.tsx
  • src/hooks/useIsMobile.ts
  • src/components/QuranReader/SidebarNavigation/SidebarNavigation.tsx
  • src/components/HomePage/ReadingSection/ChapterCard/index.tsx
  • src/components/QuranReader/ContextMenu/hooks/useContextMenuState.ts
  • src/pages/index.tsx
src/**/*.tsx

📄 CodeRabbit inference engine (CLAUDE.md)

Prefer React functional components for UI implementation

Files:

  • src/components/QuranicCalendar/QuranicCalendarHero/ActionButtons.tsx
  • src/components/QuranReader/SidebarNavigation/SidebarNavigationSelections.tsx
  • src/components/QuranReader/ContextMenu/index.tsx
  • src/components/QuranicCalendar/MyProgress/index.tsx
  • src/components/HomePage/ReadingSection/index.tsx
  • src/components/Onboarding/OnboardingProvider.tsx
  • src/components/Search/SearchInput/index.tsx
  • src/components/QuranicCalendar/WeeklyVerses/ActionButtons.tsx
  • src/components/QuranReader/SidebarNavigation/SidebarNavigation.tsx
  • src/components/HomePage/ReadingSection/ChapterCard/index.tsx
  • src/pages/index.tsx
{src,types}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Use path aliases @/ for src and @/dls/* for design system imports

Files:

  • src/components/QuranicCalendar/QuranicCalendarHero/ActionButtons.tsx
  • src/components/QuranReader/SidebarNavigation/SidebarNavigationSelections.tsx
  • src/components/QuranReader/ContextMenu/index.tsx
  • src/components/Onboarding/steps.ts
  • src/components/QuranicCalendar/MyProgress/index.tsx
  • src/components/HomePage/ReadingSection/index.tsx
  • src/components/Onboarding/OnboardingProvider.tsx
  • src/components/Search/SearchInput/index.tsx
  • src/components/QuranicCalendar/WeeklyVerses/ActionButtons.tsx
  • src/hooks/useIsMobile.ts
  • src/components/QuranReader/SidebarNavigation/SidebarNavigation.tsx
  • src/components/HomePage/ReadingSection/ChapterCard/index.tsx
  • src/components/QuranReader/ContextMenu/hooks/useContextMenuState.ts
  • src/pages/index.tsx
src/components/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Organize React components by feature and place DLS components under src/components/dls

Files:

  • src/components/QuranicCalendar/QuranicCalendarHero/ActionButtons.tsx
  • src/components/QuranReader/SidebarNavigation/SidebarNavigationSelections.tsx
  • src/components/QuranReader/ContextMenu/index.tsx
  • src/components/Onboarding/steps.ts
  • src/components/QuranicCalendar/MyProgress/index.tsx
  • src/components/HomePage/ReadingSection/index.tsx
  • src/components/Onboarding/OnboardingProvider.tsx
  • src/components/Search/SearchInput/index.tsx
  • src/components/QuranicCalendar/WeeklyVerses/ActionButtons.tsx
  • src/components/QuranReader/SidebarNavigation/SidebarNavigation.tsx
  • src/components/HomePage/ReadingSection/ChapterCard/index.tsx
  • src/components/QuranReader/ContextMenu/hooks/useContextMenuState.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx,js,jsx}: Order imports: React first, then external, then internal; alphabetize within groups with blank lines between groups
Naming: camelCase for variables/functions; PascalCase for types, interfaces, and React components; UPPER_CASE for constants
Functions should be <= 30 lines, prefer early returns, single responsibility, and descriptive names

Files:

  • src/components/QuranicCalendar/QuranicCalendarHero/ActionButtons.tsx
  • src/components/QuranReader/SidebarNavigation/SidebarNavigationSelections.tsx
  • src/components/QuranReader/ContextMenu/index.tsx
  • src/components/Onboarding/steps.ts
  • src/components/QuranicCalendar/MyProgress/index.tsx
  • src/components/HomePage/ReadingSection/index.tsx
  • src/components/Onboarding/OnboardingProvider.tsx
  • src/components/Search/SearchInput/index.tsx
  • src/components/QuranicCalendar/WeeklyVerses/ActionButtons.tsx
  • src/hooks/useIsMobile.ts
  • src/components/QuranReader/SidebarNavigation/SidebarNavigation.tsx
  • src/components/HomePage/ReadingSection/ChapterCard/index.tsx
  • src/components/QuranReader/ContextMenu/hooks/useContextMenuState.ts
  • src/pages/index.tsx
**/*.{ts,tsx,js,jsx,scss}

📄 CodeRabbit inference engine (AGENTS.md)

Use Prettier formatting: single quotes, 2-space indentation, 100-character line width, and trailing commas

Files:

  • src/components/QuranicCalendar/QuranicCalendarHero/ActionButtons.tsx
  • src/components/QuranReader/SidebarNavigation/SidebarNavigationSelections.tsx
  • src/components/QuranReader/ContextMenu/index.tsx
  • src/components/Onboarding/steps.ts
  • src/components/QuranicCalendar/MyProgress/index.tsx
  • src/components/HomePage/ReadingSection/index.tsx
  • src/components/Onboarding/OnboardingProvider.tsx
  • src/components/Search/SearchInput/index.tsx
  • src/components/QuranicCalendar/WeeklyVerses/ActionButtons.tsx
  • src/hooks/useIsMobile.ts
  • src/components/QuranReader/SidebarNavigation/SidebarNavigation.tsx
  • src/components/HomePage/ReadingSection/ChapterCard/index.tsx
  • src/components/QuranReader/ContextMenu/hooks/useContextMenuState.ts
  • src/pages/index.tsx
src/pages/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Use Next.js Pages Router; place all route files under src/pages

Files:

  • src/pages/index.tsx
🧠 Learnings (18)
📓 Common learnings
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-10-07T08:38:28.343Z
Learning: Applies to **/*.tsx : React: use functional components only; extract reusable logic into custom hooks; apply proper memoization (React.memo/useMemo/useCallback)
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .cursor/rules/react-functional-components.mdc:0-0
Timestamp: 2025-08-01T08:50:22.602Z
Learning: Applies to src/components/**/*.tsx : Always use React functional components with hooks.
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .cursor/rules/react.mdc:0-0
Timestamp: 2025-08-01T08:50:54.518Z
Learning: Applies to **/*.{tsx,jsx} : Extract reusable logic into custom hooks
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .cursor/rules/react.mdc:0-0
Timestamp: 2025-08-01T08:50:54.518Z
Learning: Applies to **/*.{tsx,jsx} : Use custom hooks for reusable logic
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .cursor/rules/react.mdc:0-0
Timestamp: 2025-08-01T08:50:54.518Z
Learning: Applies to **/use*.{tsx,jsx} : Keep hooks focused and simple
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-07T08:37:58.213Z
Learning: Applies to src/**/*.tsx : Prefer React functional components for UI implementation
Learnt from: jonybekov
Repo: quran/quran.com-frontend-next PR: 2537
File: src/redux/slices/session.ts:36-42
Timestamp: 2025-10-18T11:22:53.139Z
Learning: In Redux selectors, avoid calling functions that read from external state (cookies, localStorage, etc.) like `isLoggedIn()` from utils/auth/login. Instead, use reactive hooks like `useIsLoggedIn` directly in components and keep selectors focused only on Redux state to ensure proper memoization.
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .cursor/rules/react.mdc:0-0
Timestamp: 2025-08-01T08:50:54.518Z
Learning: Applies to **/*.{tsx,jsx} : Implement proper memoization (useMemo, useCallback)
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .cursor/rules/react.mdc:0-0
Timestamp: 2025-08-01T08:50:54.518Z
Learning: Applies to **/*.{tsx,jsx} : Avoid nested hooks
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .cursor/rules/react.mdc:0-0
Timestamp: 2025-08-01T08:50:54.518Z
Learning: Applies to **/*.{tsx,jsx} : Use functional components over class components
📚 Learning: 2025-10-28T09:59:48.894Z
Learnt from: afifvdin
Repo: quran/quran.com-frontend-next PR: 2557
File: src/components/QuranReader/ReflectionView/ReflectionBodyContainer/ReflectionBody/index.tsx:88-0
Timestamp: 2025-10-28T09:59:48.894Z
Learning: In src/components/QuranReader/ReflectionView/ReflectionBodyContainer/ReflectionBody/index.tsx, the empty `<div className={styles.separatorContainer} />` rendered when `isModal` is true is required for maintaining consistent spacing in modal view and should not be removed.

Applied to files:

  • src/components/QuranicCalendar/QuranicCalendarHero/ActionButtons.tsx
  • src/components/QuranReader/SidebarNavigation/SidebarNavigationSelections.tsx
  • src/components/QuranReader/ContextMenu/index.tsx
  • src/components/QuranicCalendar/MyProgress/index.tsx
  • src/components/QuranReader/SidebarNavigation/SidebarNavigation.tsx
  • src/pages/index.tsx
📚 Learning: 2025-10-18T11:22:53.139Z
Learnt from: jonybekov
Repo: quran/quran.com-frontend-next PR: 2537
File: src/redux/slices/session.ts:36-42
Timestamp: 2025-10-18T11:22:53.139Z
Learning: In Redux selectors, avoid calling functions that read from external state (cookies, localStorage, etc.) like `isLoggedIn()` from utils/auth/login. Instead, use reactive hooks like `useIsLoggedIn` directly in components and keep selectors focused only on Redux state to ensure proper memoization.

Applied to files:

  • src/components/QuranReader/SidebarNavigation/SidebarNavigationSelections.tsx
  • src/components/HomePage/ReadingSection/index.tsx
  • src/components/QuranReader/SidebarNavigation/SidebarNavigation.tsx
  • src/components/QuranReader/ContextMenu/hooks/useContextMenuState.ts
📚 Learning: 2025-08-01T08:50:54.518Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .cursor/rules/react.mdc:0-0
Timestamp: 2025-08-01T08:50:54.518Z
Learning: Applies to **/use*.{tsx,jsx} : Keep hooks focused and simple

Applied to files:

  • src/components/QuranReader/ContextMenu/index.tsx
  • src/components/QuranicCalendar/MyProgress/index.tsx
  • src/components/HomePage/ReadingSection/index.tsx
  • src/components/Onboarding/OnboardingProvider.tsx
  • src/components/Search/SearchInput/index.tsx
  • src/hooks/useIsMobile.ts
  • src/components/HomePage/ReadingSection/ChapterCard/index.tsx
  • src/components/QuranReader/ContextMenu/hooks/useContextMenuState.ts
  • src/pages/index.tsx
📚 Learning: 2025-10-07T08:38:28.343Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-10-07T08:38:28.343Z
Learning: Applies to **/*.tsx : React: use functional components only; extract reusable logic into custom hooks; apply proper memoization (React.memo/useMemo/useCallback)

Applied to files:

  • src/components/QuranReader/ContextMenu/index.tsx
  • src/components/QuranicCalendar/MyProgress/index.tsx
  • src/components/HomePage/ReadingSection/index.tsx
  • src/components/Onboarding/OnboardingProvider.tsx
  • src/components/Search/SearchInput/index.tsx
  • src/components/HomePage/ReadingSection/ChapterCard/index.tsx
  • src/components/QuranReader/ContextMenu/hooks/useContextMenuState.ts
  • src/pages/index.tsx
📚 Learning: 2025-08-01T08:50:54.518Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .cursor/rules/react.mdc:0-0
Timestamp: 2025-08-01T08:50:54.518Z
Learning: Applies to **/*.{tsx,jsx} : Use custom hooks for reusable logic

Applied to files:

  • src/components/QuranReader/ContextMenu/index.tsx
  • src/components/HomePage/ReadingSection/index.tsx
  • src/components/Onboarding/OnboardingProvider.tsx
  • src/components/Search/SearchInput/index.tsx
  • src/components/QuranReader/SidebarNavigation/SidebarNavigation.tsx
  • src/components/HomePage/ReadingSection/ChapterCard/index.tsx
  • src/components/QuranReader/ContextMenu/hooks/useContextMenuState.ts
  • src/pages/index.tsx
📚 Learning: 2025-08-01T08:50:54.518Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .cursor/rules/react.mdc:0-0
Timestamp: 2025-08-01T08:50:54.518Z
Learning: Applies to **/*.{tsx,jsx} : Extract reusable logic into custom hooks

Applied to files:

  • src/components/QuranReader/ContextMenu/index.tsx
  • src/components/HomePage/ReadingSection/index.tsx
  • src/components/Onboarding/OnboardingProvider.tsx
  • src/components/Search/SearchInput/index.tsx
  • src/components/HomePage/ReadingSection/ChapterCard/index.tsx
  • src/components/QuranReader/ContextMenu/hooks/useContextMenuState.ts
  • src/pages/index.tsx
📚 Learning: 2025-10-22T20:42:09.214Z
Learnt from: yousefdergham
Repo: quran/quran.com-frontend-next PR: 2547
File: src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx:35-59
Timestamp: 2025-10-22T20:42:09.214Z
Learning: Preference for quran.com-frontend-next: keep single-use, page-specific components inline. Example: NotEnrolledMessage in src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx should remain inline; extract only if reused elsewhere.

Applied to files:

  • src/components/QuranReader/ContextMenu/index.tsx
  • src/components/QuranReader/ContextMenu/hooks/useContextMenuState.ts
  • src/pages/index.tsx
📚 Learning: 2025-08-01T08:50:03.171Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .cursor/rules/next-js-conventions.mdc:0-0
Timestamp: 2025-08-01T08:50:03.171Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Minimize 'use client' usage: Use 'use client' only for Web API access in small components.

Applied to files:

  • src/components/QuranReader/ContextMenu/index.tsx
📚 Learning: 2025-10-09T11:21:33.919Z
Learnt from: zonetecde
Repo: quran/quran.com-frontend-next PR: 2523
File: src/components/QuranicCalendar/MyProgress/MonthCard.tsx:48-49
Timestamp: 2025-10-09T11:21:33.919Z
Learning: In the Quran in a Year calendar feature (src/components/QuranicCalendar/MyProgress/MonthCard.tsx), instant scrolling (window.scrollTo({ top: 0 }) without smooth behavior) is preferred over smooth scrolling when selecting a week. This is because instant scrolling provides immediate visual feedback of the verses and date changing, whereas smooth scrolling makes it look like nothing is changing during the animation.

Applied to files:

  • src/components/QuranicCalendar/MyProgress/index.tsx
  • src/components/HomePage/ReadingSection/index.tsx
  • src/components/QuranicCalendar/WeeklyVerses/ActionButtons.tsx
📚 Learning: 2025-10-19T10:49:21.536Z
Learnt from: afifvdin
Repo: quran/quran.com-frontend-next PR: 2539
File: src/components/HomePage/ReadingSection/StreakOrGoalCard/index.tsx:50-54
Timestamp: 2025-10-19T10:49:21.536Z
Learning: In src/components/HomePage/ReadingSection/StreakOrGoalCard/index.tsx, the component intentionally uses different analytics event names based on goal state: `homepage_reading_streak_card` when no goal exists and `homepage_reading_goal_card_arrow` when a goal exists. This is by design to track different user interaction contexts.

Applied to files:

  • src/components/HomePage/ReadingSection/index.tsx
  • src/components/HomePage/ReadingSection/ChapterCard/index.tsx
📚 Learning: 2025-08-01T08:50:22.602Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .cursor/rules/react-functional-components.mdc:0-0
Timestamp: 2025-08-01T08:50:22.602Z
Learning: Applies to src/components/**/*.tsx : Always use React functional components with hooks.

Applied to files:

  • src/components/HomePage/ReadingSection/index.tsx
  • src/components/HomePage/ReadingSection/ChapterCard/index.tsx
📚 Learning: 2025-08-01T08:51:05.924Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .cursor/rules/redux-toolkit-best-practices.mdc:0-0
Timestamp: 2025-08-01T08:51:05.924Z
Learning: Applies to src/redux/**/*.ts : Use Redux hooks (useSelector, useDispatch) in components.

Applied to files:

  • src/components/QuranReader/SidebarNavigation/SidebarNavigation.tsx
  • src/components/QuranReader/ContextMenu/hooks/useContextMenuState.ts
📚 Learning: 2025-10-25T12:14:44.062Z
Learnt from: yousefdergham
Repo: quran/quran.com-frontend-next PR: 2547
File: src/pages/learning-plans/[slug]/lessons/[lessonSlugOrId]/index.tsx:58-64
Timestamp: 2025-10-25T12:14:44.062Z
Learning: In quran.com-frontend-next, router.query values (like slug) are not considered reactive dependencies by the project's react-hooks/exhaustive-deps rule and don't need to be included in useEffect dependency arrays. Toast functions from useToast() are also stable and don't need to be in deps.

Applied to files:

  • src/components/QuranReader/SidebarNavigation/SidebarNavigation.tsx
  • src/components/QuranReader/ContextMenu/hooks/useContextMenuState.ts
📚 Learning: 2025-10-07T08:37:58.213Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-07T08:37:58.213Z
Learning: Applies to src/**/*.tsx : Prefer React functional components for UI implementation

Applied to files:

  • src/components/HomePage/ReadingSection/ChapterCard/index.tsx
📚 Learning: 2025-08-01T08:50:54.518Z
Learnt from: CR
Repo: quran/quran.com-frontend-next PR: 0
File: .cursor/rules/react.mdc:0-0
Timestamp: 2025-08-01T08:50:54.518Z
Learning: Applies to **/*.{tsx,jsx} : Use functional components over class components

Applied to files:

  • src/components/HomePage/ReadingSection/ChapterCard/index.tsx
📚 Learning: 2025-10-19T11:34:07.609Z
Learnt from: afifvdin
Repo: quran/quran.com-frontend-next PR: 2540
File: src/components/Verse/PlainVerseText/index.tsx:4-4
Timestamp: 2025-10-19T11:34:07.609Z
Learning: In src/components/Verse/PlainVerseText/index.tsx, the translation for verse titles should be wired directly to the component using next-translate rather than passed as props from parent components, as this ensures the wording from locales is centralized and only needs to be changed in one place.

Applied to files:

  • src/components/HomePage/ReadingSection/ChapterCard/index.tsx
📚 Learning: 2025-10-26T10:22:52.381Z
Learnt from: afifvdin
Repo: quran/quran.com-frontend-next PR: 2540
File: src/components/QuranReader/TranslationView/TranslationText/TranslationAndReference.tsx:60-60
Timestamp: 2025-10-26T10:22:52.381Z
Learning: In src/components/QuranReader/TranslationView/TranslationText/TranslationAndReference.tsx, verse references displayed alongside chapter names should use English/Western numerals only, not localized numerals, as per design specifications.

Applied to files:

  • src/components/HomePage/ReadingSection/ChapterCard/index.tsx
🔇 Additional comments (13)
src/components/QuranReader/SidebarNavigation/SidebarNavigationSelections.tsx (1)

8-8: LGTM! Proper migration to useIsMobile hook.

The migration from isMobile() function to the useIsMobile hook is implemented correctly. The hook is called unconditionally at the top level, and isMobileView is used consistently to determine mobile-specific behavior (closing sidebar after navigation). This prevents SSR/client hydration mismatches.

Also applies to: 43-43, 81-81

src/components/HomePage/ReadingSection/ChapterCard/index.tsx (1)

12-12: LGTM! Clean migration to useIsMobile hook.

The hook is properly integrated at the component level and used to control the display format of the translated chapter name. The desktop-first approach ensures consistent SSR rendering, avoiding hydration mismatches.

Also applies to: 34-34, 59-59

src/components/QuranicCalendar/MyProgress/index.tsx (1)

15-15: LGTM! Critical hydration fix for calendar layout.

The migration to useIsMobile is especially important here as it controls a major layout difference (CarouselView vs grid). Using the hook ensures consistent initial rendering between server and client, preventing layout shifts.

Also applies to: 37-37, 86-86

src/components/Onboarding/OnboardingProvider.tsx (1)

13-13: LGTM! Proper hook integration with correct memoization.

The migration includes the important detail of adding isMobileView to the useMemo dependency array (line 47), ensuring onboarding steps are recalculated when the mobile view state changes. This follows React best practices for memoization.

Also applies to: 43-43, 46-47

src/components/QuranReader/ContextMenu/hooks/useContextMenuState.ts (1)

9-9: LGTM! Hook-based mobile detection in custom hook.

The useIsMobile hook is correctly integrated within this custom hook to control sidebar visibility logic. Using the hook instead of a direct function call ensures reactive updates and prevents hydration mismatches in sidebar behavior.

Also applies to: 46-46, 84-84

src/components/Search/SearchInput/index.tsx (1)

15-15: LGTM! Consistent mobile detection for search behavior.

The hook integration ensures the search input's mobile drawer behavior is determined reactively and consistently with SSR, preventing hydration issues when the search component initially renders.

Also applies to: 54-54, 98-98

src/components/QuranReader/SidebarNavigation/SidebarNavigation.tsx (1)

18-18: LGTM! Reactive mobile detection for outside-click handler.

The hook is properly used to enable/disable the outside-click detector based on mobile view state. This ensures the sidebar's outside-click behavior is consistent with the initial server render, preventing hydration errors.

Also applies to: 43-43, 51-51

src/components/QuranReader/ContextMenu/index.tsx (1)

18-18: LGTM! Hook integration for responsive context menu layout.

The useIsMobile hook is correctly used to derive two computed values (isMobileScrolledView and isNotMobileOrScrolledView) that control multiple rendering paths in the context menu. The desktop-first approach ensures consistent initial rendering across SSR and client hydration.

Also applies to: 28-28, 57-58

src/components/QuranicCalendar/QuranicCalendarHero/ActionButtons.tsx (1)

10-10: LGTM! Clean migration to useIsMobile hook.

The migration from isMobile() function calls to the useIsMobile() hook is consistent throughout the component. All mobile-specific conditionals now use isMobileView, which will help prevent hydration mismatches by maintaining stable markup between SSR and client-side hydration.

Also applies to: 41-41, 66-66, 81-81, 93-93, 104-108

src/pages/index.tsx (1)

22-22: LGTM! Consistent mobile detection migration.

The migration to useIsMobile() hook is correct and aligns with the PR's goal of fixing hydration mismatches. The isMobileView is properly used to determine whether to render MobileHomepageSections.

Also applies to: 40-40, 59-61

src/components/HomePage/ReadingSection/index.tsx (1)

16-16: LGTM! Proper migration to hook-based mobile detection.

The component correctly migrates to the useIsMobile() hook, replacing all isMobile() function calls with isMobileView. The mobile-specific layout decisions now use a stable value that won't cause hydration mismatches.

Also applies to: 35-35, 78-78, 116-127

src/components/Onboarding/steps.ts (1)

30-33: LGTM! Good design with parameterized mobile detection.

The function now accepts isDeviceMobile as a parameter with a desktop-first default (false), allowing the caller to pass in the mobile state from the useIsMobile() hook. This approach correctly externalizes the mobile detection logic and maintains consistency with the broader migration pattern.

Also applies to: 59-59, 113-116, 178-181, 228-231

src/hooks/useIsMobile.ts (1)

12-18: Let me check if there's conditional rendering/layout changes based on the mobile detection:

Based on my verification, the review comment raises a valid and well-reasoned concern, though it remains empirically unverified.

Key findings:

  1. Hook Implementation: The useIsMobile hook correctly uses a desktop-first default (false) and updates via useEffect post-mount, preventing hydration mismatches.

  2. Widespread Usage: The hook is used in 24+ locations across layout-critical components (SidebarNavigation, ContextMenu, HomePage, ReadingSection, ChapterCard), where state changes could trigger visible reflows.

  3. CLS Risk is Real: Industry patterns document this trade-off—adopting mobile-first or deferring rendering risks FOUC or CLS when guesses are wrong; rendering both variations causes shifts when one is removed.

  4. Unverified Empirically: The provided script was instructional only, not actual test results. CLS impacts SEO as Google uses it to evaluate user experience and page rankings.

The review comment is sound but requires manual verification on actual mobile devices and throttled connections (Slow 3G) to measure whether the current CLS trade-off aligns with your performance goals. Test using Lighthouse and Chrome DevTools' Performance tab.

@osamasayed osamasayed requested a review from Copilot November 2, 2025 01:39
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This pull request refactors the mobile detection logic by replacing direct calls to the isMobile() utility function with a React hook useIsMobile(). This ensures proper SSR/CSR hydration alignment and reactive updates when the viewport is resized.

  • Introduces useIsMobile hook that manages mobile detection state reactively with window resize listeners
  • Replaces all instances of isMobile() function calls with the useIsMobile() hook across components
  • Updates the onboarding system to accept mobile state as a parameter instead of checking it internally

Reviewed Changes

Copilot reviewed 14 out of 14 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
src/hooks/useIsMobile.ts Simplified hook to use false as initial state for consistent SSR/CSR rendering
src/pages/index.tsx Replaced isMobile() call with useIsMobile() hook
src/components/Search/SearchInput/index.tsx Replaced isMobile() call with useIsMobile() hook
src/components/QuranicCalendar/WeeklyVerses/ActionButtons.tsx Replaced isMobile() call with useIsMobile() hook and extracted label logic
src/components/QuranicCalendar/QuranicCalendarHero/ActionButtons.tsx Replaced isMobile() call with useIsMobile() hook
src/components/QuranicCalendar/MyProgress/index.tsx Replaced isMobile() call with useIsMobile() hook
src/components/QuranReader/SidebarNavigation/SidebarNavigationSelections.tsx Replaced isMobile() call with useIsMobile() hook
src/components/QuranReader/SidebarNavigation/SidebarNavigation.tsx Replaced isMobile() call with useIsMobile() hook
src/components/QuranReader/ContextMenu/index.tsx Replaced isMobile() call with useIsMobile() hook
src/components/QuranReader/ContextMenu/hooks/useContextMenuState.ts Replaced isMobile() call with useIsMobile() hook
src/components/Onboarding/steps.ts Removed internal isMobile() call and accepts mobile state as parameter
src/components/Onboarding/OnboardingProvider.tsx Calls useIsMobile() and passes result to checklistIndexToOnboardingSteps
src/components/HomePage/ReadingSection/index.tsx Replaced isMobile() call with useIsMobile() hook
src/components/HomePage/ReadingSection/ChapterCard/index.tsx Replaced isMobile() call with useIsMobile() hook

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 46 to 50
const markAsCompletedLabel = isMobileView
? '\u2713'
: !isCompleted
? t('mark-as-completed')
: t('week-completed');
Copy link

Copilot AI Nov 2, 2025

Choose a reason for hiding this comment

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

[nitpick] The ternary operator chain for markAsCompletedLabel is nested and harder to read. Consider refactoring to use a simpler if-else structure or extract to a separate function for better clarity.

Copilot uses AI. Check for mistakes.
@zonetecde
Copy link
Collaborator Author

replaced with #2568

@zonetecde zonetecde closed this Nov 5, 2025
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.

2 participants