Skip to content

fix: disable navbar back and forward buttons at history boundaries#38947

Open
schourasia750 wants to merge 5 commits intoRocketChat:developfrom
schourasia750:fix-forward-blur
Open

fix: disable navbar back and forward buttons at history boundaries#38947
schourasia750 wants to merge 5 commits intoRocketChat:developfrom
schourasia750:fix-forward-blur

Conversation

@schourasia750
Copy link

@schourasia750 schourasia750 commented Feb 23, 2026

Summary

This PR fixes an issue where the Back and Forward navigation buttons in the navbar were not getting disabled when the user reached the beginning or end of the navigation history.

The buttons remained clickable even when no navigation was possible.


Changes Made

  • Added proper validation for navigation history state.
  • Disabled the Back button when there is no previous entry in history.
  • Disabled the Forward button when there is no next entry in history.
  • Ensured buttons dynamically update based on history changes.

How to Test

  1. Navigate between multiple rooms/pages.
  2. Click the Back button until reaching the first visited page.
  3. Verify that the Back button becomes disabled.
  4. Click the Forward button until reaching the last page.
  5. Verify that the Forward button becomes disabled.

Expected Result

Navigation buttons should reflect the correct enabled/disabled state based on available browser history.


image

Related Issue

Fixes #38945

Summary by CodeRabbit

  • New Features
    • Improved browser history tracking and navigation. Back and forward buttons now intelligently disable when unavailable based on your current position in browsing history, providing a more intuitive navigation experience. This prevents confusion about valid navigation actions and enhances overall usability of the navigation controls.

@schourasia750 schourasia750 requested a review from a team as a code owner February 23, 2026 19:04
@dionisio-bot
Copy link
Contributor

dionisio-bot bot commented Feb 23, 2026

Looks like this PR is ready to merge! 🎉
If you have any trouble, please check the PR guidelines

@changeset-bot
Copy link

changeset-bot bot commented Feb 23, 2026

⚠️ No Changeset found

Latest commit: 99f83fd

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 23, 2026

Walkthrough

The changes implement navigation history state tracking within the Router class and extend the RouterContext API to expose methods for querying back/forward navigation availability. The navbar component now subscribes to route changes, monitors history state, and conditionally disables back and forward buttons based on navigation capability.

Changes

Cohort / File(s) Summary
Router History State Management
apps/meteor/client/router/index.tsx
Introduces private state variables for in-flight history management (historyIndex, historyMaxIndex, pendingHistoryDelta, pendingPush). Defers navigation delta application via history.go() and updates state in refresh cycle. Adds public methods getCanGoBack() and getCanGoForward() to query navigation capability based on current history position.
Router Context API Extensions
packages/ui-contexts/src/RouterContext.ts, packages/mock-providers/src/MockedRouterContext.tsx
Extends RouterContextValue interface with two new public methods: getCanGoBack() and getCanGoForward(), both returning boolean. Provides default implementations in context default value and mock router context, returning false.
NavBar Navigation UI Updates
apps/meteor/client/navbar/NavBarNavigation.tsx
Adds useEffect hook to subscribe to route changes via subscribeToRouteChange. Introduces local state for routeTick, canGoBack, and canGoForward derived from router. Updates Back and Forward NavBarItem components with disabled props based on navigation capability. Replaces direct navigate() calls with router.navigate().

Sequence Diagram

sequenceDiagram
    participant User
    participant NavBar as NavBar Component
    participant Router
    participant History as Browser History

    User->>NavBar: Click Back Button
    NavBar->>Router: router.navigate(-1)
    Router->>History: history.go(-1)
    History-->>Router: Route change event
    Router->>Router: Update historyIndex state
    Router-->>NavBar: subscribeToRouteChange callback
    NavBar->>Router: getCanGoBack()
    Router-->>NavBar: Return boolean (can navigate back)
    NavBar->>NavBar: Update canGoBack state
    NavBar->>NavBar: Disable/Enable Back button
    NavBar-->>User: Render updated UI
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 Hoppy history hops along,
Back and forward, strong and song,
Buttons disabled at the end,
Perfect navigation, hopping friend! 🎀

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Out of Scope Changes check ❓ Inconclusive A potential issue identified: the router/index.tsx diff shows duplicated insertion of getCanGoBack and getCanGoForward methods in two locations, suggesting either merge conflict artifacts or unintended duplication in the final code. Review the final state of apps/meteor/client/router/index.tsx to confirm these getter methods appear only once in the compiled class, and remove any duplicate declarations.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main objective: disabling navbar back and forward buttons at history boundaries, which is the core fix implemented across all modified files.
Linked Issues check ✅ Passed The pull request fully addresses all coding requirements from issue #38945: implements history state tracking via router methods (getCanGoBack/getCanGoForward), disables buttons based on history position, and dynamically updates button states on navigation.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

Tip

Issue Planner is now in beta. Read the docs and try it out! Share your feedback on Discord.


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.

Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

No issues found across 4 files

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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/meteor/client/navbar/NavBarNavigation.tsx`:
- Around line 32-45: The back/forward icons are inverted: in the
NavBarNavigation component swap the icon props on the two NavBarItem instances
so the Back button (onClick={() => router.navigate(-1)}, disabled={!canGoBack})
uses 'chevron-left' and the Forward button (onClick={() => router.navigate(1)},
disabled={!canGoForward}) uses 'chevron-right'; update the icon string values
passed to the NavBarItem components to match this mapping.

In `@apps/meteor/client/router/index.tsx`:
- Around line 177-185: The historyIndex can go negative when applying
pendingHistoryDelta; after applying pendingHistoryDelta in the router (symbols:
pendingHistoryDelta, historyIndex, historyMaxIndex) clamp historyIndex into the
valid range [0, historyMaxIndex] (e.g. set historyIndex = Math.max(0,
Math.min(historyIndex, historyMaxIndex))) before handling pendingPush so
getCanGoBack/getCanGoForward reflect the correct enabled state; leave the
pendingPush logic (increment and update historyMaxIndex) unchanged.
- Around line 293-296: The pendingHistoryDelta leak happens because
pendingHistoryDelta is set before calling history.go(delta) and never cleared if
history.go is a no-op; update the code in the branch that handles numeric
toOrDelta (the block that sets this.pendingHistoryDelta and calls history.go) to
only keep pendingHistoryDelta until navigation actually occurs: set a one-time
popstate listener (or reuse the existing refresh() trigger) to clear
this.pendingHistoryDelta when popstate fires and apply the delta to
historyIndex, and also register a short fallback timer to clear
pendingHistoryDelta if no popstate occurs within a small window (indicating
history.go was a no-op). This ensures pendingHistoryDelta, history.go,
refresh(), and historyIndex interactions are robust and prevents stale deltas
from being applied later.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 98a6c58 and fe6d953.

📒 Files selected for processing (4)
  • apps/meteor/client/navbar/NavBarNavigation.tsx
  • apps/meteor/client/router/index.tsx
  • packages/mock-providers/src/MockedRouterContext.tsx
  • packages/ui-contexts/src/RouterContext.ts
📜 Review details
⏰ 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). (1)
  • GitHub Check: cubic · AI code reviewer
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx,js}

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

**/*.{ts,tsx,js}: Write concise, technical TypeScript/JavaScript with accurate typing in Playwright tests
Avoid code comments in the implementation

Files:

  • apps/meteor/client/navbar/NavBarNavigation.tsx
  • packages/mock-providers/src/MockedRouterContext.tsx
  • apps/meteor/client/router/index.tsx
  • packages/ui-contexts/src/RouterContext.ts
🧠 Learnings (1)
📚 Learning: 2025-09-15T13:10:30.049Z
Learnt from: Dnouv
Repo: RocketChat/Rocket.Chat PR: 36868
File: packages/http-router/src/Router.ts:416-425
Timestamp: 2025-09-15T13:10:30.049Z
Learning: In packages/http-router/src/Router.ts, the dispatch() method's use of replaceAll('//', '/') on the full path is acceptable because URL normalization and query string handling is performed by the caller function before dispatch() is invoked.

Applied to files:

  • apps/meteor/client/router/index.tsx
🔇 Additional comments (3)
packages/ui-contexts/src/RouterContext.ts (1)

77-78: LGTM — clean API additions with safe defaults.

Returning false (instead of throwing as other unimplemented methods do) is the right choice here; it is a valid sentinel that prevents runtime crashes when the context is consumed outside a provider.

Also applies to: 109-111

packages/mock-providers/src/MockedRouterContext.tsx (1)

19-21: LGTM — correctly placed before the spread.

Declaring getCanGoBack/getCanGoForward before ...router means consumers can still override them via the router prop, matching the established pattern of all other mocked methods.

apps/meteor/client/router/index.tsx (1)

339-341: LGTM — boundary conditions are correct.

historyIndex > 0 and historyIndex < historyMaxIndex correctly model "has in-app back history" and "has in-app forward history" respectively.

Comment on lines +177 to +185
if (this.pendingHistoryDelta !== 0) {
this.historyIndex += this.pendingHistoryDelta;
this.pendingHistoryDelta = 0;
}
if (this.pendingPush) {
this.historyIndex += 1;
this.historyMaxIndex = this.historyIndex;
this.pendingPush = false;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

historyIndex is not clamped after applying pendingHistoryDelta.

If pendingHistoryDelta pushes historyIndex below 0 (e.g., delta = -2, index = 1), historyIndex becomes -1. getCanGoBack() still correctly returns false (since -1 > 0 is false), but getCanGoForward() will return true as long as historyMaxIndex >= 0, producing an incorrect enabled state on the Forward button.

🛡️ Proposed fix: clamp after applying delta
 if (this.pendingHistoryDelta !== 0) {
     this.historyIndex += this.pendingHistoryDelta;
+    this.historyIndex = Math.max(0, Math.min(this.historyIndex, this.historyMaxIndex));
     this.pendingHistoryDelta = 0;
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (this.pendingHistoryDelta !== 0) {
this.historyIndex += this.pendingHistoryDelta;
this.pendingHistoryDelta = 0;
}
if (this.pendingPush) {
this.historyIndex += 1;
this.historyMaxIndex = this.historyIndex;
this.pendingPush = false;
}
if (this.pendingHistoryDelta !== 0) {
this.historyIndex += this.pendingHistoryDelta;
this.historyIndex = Math.max(0, Math.min(this.historyIndex, this.historyMaxIndex));
this.pendingHistoryDelta = 0;
}
if (this.pendingPush) {
this.historyIndex += 1;
this.historyMaxIndex = this.historyIndex;
this.pendingPush = false;
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/meteor/client/router/index.tsx` around lines 177 - 185, The historyIndex
can go negative when applying pendingHistoryDelta; after applying
pendingHistoryDelta in the router (symbols: pendingHistoryDelta, historyIndex,
historyMaxIndex) clamp historyIndex into the valid range [0, historyMaxIndex]
(e.g. set historyIndex = Math.max(0, Math.min(historyIndex, historyMaxIndex)))
before handling pendingPush so getCanGoBack/getCanGoForward reflect the correct
enabled state; leave the pendingPush logic (increment and update
historyMaxIndex) unchanged.

@ggazzo ggazzo added this to the 8.3.0 milestone Feb 23, 2026
ggazzo
ggazzo previously approved these changes Feb 23, 2026
@ggazzo ggazzo added the stat: QA assured Means it has been tested and approved by a company insider label Feb 23, 2026
@ggazzo ggazzo dismissed their stale review February 23, 2026 22:23

need to check

@dionisio-bot dionisio-bot bot enabled auto-merge February 24, 2026 05:03
@schourasia750 schourasia750 requested a review from ggazzo February 27, 2026 12:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

stat: QA assured Means it has been tested and approved by a company insider

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix: The back and forward buttons in the navbar are not getting disabled even if being in the last or first page

2 participants