Skip to content

feat(sidebar): add SidebarRail collapsed icon navigation rail#40558

Open
ggazzo wants to merge 8 commits into
developfrom
feat/local-sidebar-collapsed
Open

feat(sidebar): add SidebarRail collapsed icon navigation rail#40558
ggazzo wants to merge 8 commits into
developfrom
feat/local-sidebar-collapsed

Conversation

@ggazzo
Copy link
Copy Markdown
Member

@ggazzo ggazzo commented May 15, 2026

Summary

  • Adds SidebarRail — a 44px icon-only navigation rail (Material Design "navigation rail" pattern) that mirrors the Figma "Local Sidebar / Collapsed" node and composes existing NavBar items (Home, Directory, Marketplace, Administration menu, UserMenu) plus rail-specific variants (Create-new pencil-box menu, Inbox with unread badge, Phone via useMediaCallAction, icon-only Login fallback, horizontal Divider with rail tokens).
  • Introduces a thin HorizontalDivider wrapper around Fuselage Divider so callers can express horizontal-only intent at the type level.
  • Unblocks Storybook on develop: switches ImageGallery to Swiper's public exports paths, expands the meteor mock to cover the SDK subscribe/callAsync surface, and adds a NormalModuleReplacementPlugin that swaps the live SDKClient for a no-op mock so stories that touch hooks like useStatusItems or useUnread render without a DDP connection.

Test plan

  • cd apps/meteor && CI=1 yarn storybook opens cleanly without webpack build failures
  • Story Sidebar/SidebarRail/Anonymous renders the rail with the icon-only login button
  • Story Sidebar/SidebarRail/LoggedIn renders the rail with the user avatar (no Meteor.connection.subscribe runtime error)
  • Story Sidebar/SidebarRail/WithUnreadBadge shows the danger badge on the inbox item
  • Story Sidebar/SidebarRail/WithCreatePermissions shows the create-new menu populated
  • yarn tsc --noEmit --skipLibCheck passes for the new files

Summary by CodeRabbit

  • New Features

    • Sidebar rail navigation with header, create/new, calls, login, user menus, visual dividers, and integrated secondary call panel; route-sync keeps call UI aligned with navigation.
    • Inline-capable media call widget with embeddable slot, improved inline behavior, and keypad/controls adjustments.
  • Documentation

    • Storybook stories demonstrating sidebar rail states.
  • Localization

    • Added English translation for "Inbox".
  • Chores

    • Runtime feature flag to toggle the sidebar rail.

@ggazzo ggazzo requested a review from a team as a code owner May 15, 2026 15:50
@dionisio-bot
Copy link
Copy Markdown
Contributor

dionisio-bot Bot commented May 15, 2026

Looks like this PR is not ready to merge, because of the following issues:

  • This PR is missing the 'stat: QA assured' label

Please fix the issues and try again

If you have any trouble, please check the PR guidelines

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented May 15, 2026

⚠️ No Changeset found

Latest commit: cfe679c

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
Copy Markdown
Contributor

coderabbitai Bot commented May 15, 2026

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 2b2a1123-4589-4461-bd1a-8a97fa369a6b

📥 Commits

Reviewing files that changed from the base of the PR and between 519c194 and cfe679c.

📒 Files selected for processing (1)
  • apps/meteor/client/views/root/MainLayout/LayoutWithSidebar.spec.tsx
📜 Recent 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). (4)
  • GitHub Check: 📦 Build Packages
  • GitHub Check: cubic · AI code reviewer
  • GitHub Check: CodeQL-Build
  • GitHub Check: CodeQL-Build
🧰 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/views/root/MainLayout/LayoutWithSidebar.spec.tsx
🧠 Learnings (15)
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Utilize Playwright fixtures (`test`, `page`, `expect`) for consistency in test files

Applied to files:

  • apps/meteor/client/views/root/MainLayout/LayoutWithSidebar.spec.tsx
📚 Learning: 2025-12-16T17:29:45.163Z
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 37834
File: apps/meteor/tests/e2e/page-objects/fragments/admin-flextab-emoji.ts:12-22
Timestamp: 2025-12-16T17:29:45.163Z
Learning: In page object files under `apps/meteor/tests/e2e/page-objects/`, always import `expect` from `../../utils/test` (Playwright's async expect), not from Jest. Jest's `expect` has a synchronous signature and will cause TypeScript errors when used with web-first assertions like `toBeVisible()`.

Applied to files:

  • apps/meteor/client/views/root/MainLayout/LayoutWithSidebar.spec.tsx
📚 Learning: 2026-04-17T18:33:27.211Z
Learnt from: d-gubert
Repo: RocketChat/Rocket.Chat PR: 39858
File: apps/meteor/tests/e2e/apps/uikit-interactions.spec.ts:123-151
Timestamp: 2026-04-17T18:33:27.211Z
Learning: In RocketChat/Rocket.Chat (`apps/meteor/tests/e2e/apps/uikit-interactions.spec.ts`), `executeBlockActionHandler` invocations originating from a **modal** surface intentionally do NOT include a `block_action_room` (room property) in the interaction payload. Modals are not scoped to a room, so no room id is available in that context. Do not flag the absence of a room assertion in the modal block-action test as a missing coverage bug; instead, document it explicitly with a `test.step` asserting the room entry is `undefined`.

Applied to files:

  • apps/meteor/client/views/root/MainLayout/LayoutWithSidebar.spec.tsx
📚 Learning: 2026-02-24T19:36:55.089Z
Learnt from: juliajforesti
Repo: RocketChat/Rocket.Chat PR: 38493
File: apps/meteor/tests/e2e/page-objects/fragments/home-content.ts:60-82
Timestamp: 2026-02-24T19:36:55.089Z
Learning: In RocketChat/Rocket.Chat e2e tests (apps/meteor/tests/e2e/page-objects/fragments/home-content.ts), thread message preview listitems do not have aria-roledescription="message", so lastThreadMessagePreview locator cannot be scoped to messageListItems (which filters for aria-roledescription="message"). It should remain scoped to page.getByRole('listitem') or mainMessageList.getByRole('listitem').

Applied to files:

  • apps/meteor/client/views/root/MainLayout/LayoutWithSidebar.spec.tsx
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Use `expect` matchers for assertions (`toEqual`, `toContain`, `toBeTruthy`, `toHaveLength`, etc.) instead of `assert` statements in Playwright tests

Applied to files:

  • apps/meteor/client/views/root/MainLayout/LayoutWithSidebar.spec.tsx
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Prefer web-first assertions (`toBeVisible`, `toHaveText`, etc.) in Playwright tests

Applied to files:

  • apps/meteor/client/views/root/MainLayout/LayoutWithSidebar.spec.tsx
📚 Learning: 2025-12-10T21:00:54.909Z
Learnt from: KevLehman
Repo: RocketChat/Rocket.Chat PR: 37091
File: ee/packages/abac/jest.config.ts:4-7
Timestamp: 2025-12-10T21:00:54.909Z
Learning: Rocket.Chat monorepo: Jest testMatch pattern '<rootDir>/src/**/*.spec.(ts|js|mjs)' is valid in this repo and used across multiple packages (e.g., packages/tools, ee/packages/omnichannel-services). Do not flag it as invalid in future reviews.

Applied to files:

  • apps/meteor/client/views/root/MainLayout/LayoutWithSidebar.spec.tsx
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.{ts,spec.ts} : Follow Page Object Model pattern consistently in Playwright tests

Applied to files:

  • apps/meteor/client/views/root/MainLayout/LayoutWithSidebar.spec.tsx
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Maintain test isolation between test cases in Playwright tests

Applied to files:

  • apps/meteor/client/views/root/MainLayout/LayoutWithSidebar.spec.tsx
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/page-objects/**/*.ts : Utilize existing page objects pattern from `apps/meteor/tests/e2e/page-objects/`

Applied to files:

  • apps/meteor/client/views/root/MainLayout/LayoutWithSidebar.spec.tsx
📚 Learning: 2026-04-13T16:40:55.864Z
Learnt from: ricardogarim
Repo: RocketChat/Rocket.Chat PR: 40100
File: apps/meteor/client/views/root/MainLayout/EmbeddedPreload.tsx:18-35
Timestamp: 2026-04-13T16:40:55.864Z
Learning: In Rocket.Chat's embedded mode (`?layout=embedded`), route changes are driven by the parent frame reloading the iframe URL, which causes a full remount of the React tree (including `EmbeddedPreload` at `apps/meteor/client/views/root/MainLayout/EmbeddedPreload.tsx`). The component never survives a navigation, so `roomParams` (computed via `useMemo`) is always fresh on mount. A `[router]` singleton as the sole `useMemo` dependency is therefore correct and intentional — do not flag it as a stale-dependency bug in this component.

Applied to files:

  • apps/meteor/client/views/root/MainLayout/LayoutWithSidebar.spec.tsx
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.{ts,spec.ts} : Store commonly used locators in variables/constants for reuse

Applied to files:

  • apps/meteor/client/views/root/MainLayout/LayoutWithSidebar.spec.tsx
📚 Learning: 2026-03-06T18:10:15.268Z
Learnt from: tassoevan
Repo: RocketChat/Rocket.Chat PR: 39397
File: packages/gazzodown/src/code/CodeBlock.spec.tsx:47-68
Timestamp: 2026-03-06T18:10:15.268Z
Learning: In tests (especially those using testing-library/dom/jsdom) for Rocket.Chat components, the HTML <code> element has an implicit ARIA role of 'code'. Therefore, screen.getByRole('code') or screen.findByRole('code') will locate <code> elements even without a role attribute. Do not flag findByRole('code') as invalid in reviews; prefer using the implicit role instead of adding role="code" unless necessary for accessibility.

Applied to files:

  • apps/meteor/client/views/root/MainLayout/LayoutWithSidebar.spec.tsx
📚 Learning: 2026-03-27T14:52:56.865Z
Learnt from: dougfabris
Repo: RocketChat/Rocket.Chat PR: 39892
File: apps/meteor/client/views/room/contextualBar/Threads/Thread.tsx:150-155
Timestamp: 2026-03-27T14:52:56.865Z
Learning: In Rocket.Chat, there are two different `ModalBackdrop` components with different prop APIs. During review, confirm the import source: (1) `rocket.chat/fuselage` `ModalBackdrop` uses `ModalBackdropProps` based on `BoxProps` (so it supports `onClick` and other Box/DOM props) and does not have an `onDismiss` prop; (2) `rocket.chat/ui-client` `ModalBackdrop` uses a narrower props interface like `{ children?: ReactNode; onDismiss?: () => void }` and handles Escape keypress and outside mouse-up, and it does not forward arbitrary DOM props such as `onClick`. Flag mismatched props (e.g., `onDismiss` passed to the fuselage component or `onClick` passed to the ui-client component) and ensure the usage matches the correct component being imported.

Applied to files:

  • apps/meteor/client/views/root/MainLayout/LayoutWithSidebar.spec.tsx
📚 Learning: 2026-05-06T12:21:44.083Z
Learnt from: juliajforesti
Repo: RocketChat/Rocket.Chat PR: 40256
File: apps/meteor/client/components/CreateDiscussion/CreateDiscussion.tsx:121-149
Timestamp: 2026-05-06T12:21:44.083Z
Learning: Field wrappers in rocket.chat/fuselage-forms (Field, FieldLabel, FieldRow, FieldError, FieldHint) auto-create htmlFor/id associations, aria-describedby, and role="alert" for errors. Do not manually set htmlFor, id, aria-describedby, or role attributes when using these wrappers. This automatic wiring does not apply to plain rocket.chat/fuselage components, which require explicit ID wiring per the accessibility docs. In code reviews, prefer using fuselage-forms wrappers for form fields and verify there is no unnecessary manual ID/aria wiring in files that use these wrappers. If a component uses plain fuselage components, ensure proper id wiring as per docs.

Applied to files:

  • apps/meteor/client/views/root/MainLayout/LayoutWithSidebar.spec.tsx
🔇 Additional comments (1)
apps/meteor/client/views/root/MainLayout/LayoutWithSidebar.spec.tsx (1)

14-17: LGTM!


Walkthrough

Adds a SidebarRail UI and integrates it into the main layout; implements a MediaCallWidget slot so the VoIP widget can render inline inside the sidebar with adjusted styling and UI behavior.

Changes

SidebarRail Navigation Feature

Layer / File(s) Summary
Storybook Mock Infrastructure
apps/meteor/.storybook/mocks/meteor.js
Adds DDPCommon stub with parseDDP and stringifyDDP functions to support Storybook component testing.
HorizontalDivider Component
apps/meteor/client/components/HorizontalDivider/HorizontalDivider.tsx, apps/meteor/client/components/HorizontalDivider/index.ts
New reusable HorizontalDivider wrapper that forces non-vertical divider rendering for use in sidebar layouts.
SidebarRail Core and Navigation Items
apps/meteor/client/sidebar/SidebarRail/SidebarRail.tsx, apps/meteor/client/sidebar/SidebarRail/SidebarRailHeader.tsx, apps/meteor/client/sidebar/SidebarRail/SidebarRailCreateNew.tsx, apps/meteor/client/sidebar/SidebarRail/SidebarRailDivider.tsx, apps/meteor/client/sidebar/SidebarRail/SidebarRailLoginPage.tsx, apps/meteor/client/sidebar/SidebarRail/SidebarRailPhone.tsx, apps/meteor/client/sidebar/SidebarRail/SidebarRailCallPanel.tsx, apps/meteor/client/sidebar/SidebarRail/SidebarRailCallRouteSync.tsx, apps/meteor/client/sidebar/SidebarRail/index.ts
Main SidebarRail organizes three NavBarGroups for pages, voice calls, and workspace preferences. Subcomponents render logo header, create menu, login button, call history navigation, media widget panel, and route synchronization logic. All re-exported via module index.
Storybook Stories and Localization
apps/meteor/client/sidebar/SidebarRail/SidebarRail.stories.tsx, packages/i18n/src/locales/en.i18n.json
Four Storybook stories demonstrate sidebar in anonymous, logged-in, unread badge, and permission scenarios. Mock helpers configure i18n and user context. English translation for "Inbox" added.
Layout Integration and Feature Flag
apps/meteor/client/views/root/MainLayout/sidebarRailFlag.ts, apps/meteor/client/views/root/MainLayout/LayoutWithSidebar.tsx, apps/meteor/client/views/root/MainLayout/SecondaryPanel.tsx, apps/meteor/client/views/root/MainLayout/MainLayoutStyleTags.tsx
LayoutWithSidebar switches from feature-flagged secondary sidebar to sidebar-rail layout controlled by USE_SIDEBAR_RAIL. New SecondaryPanel extracts conditional logic for call panel vs. rooms navigation vs. sidebar fallback. Dark palette extended to rail and panel selectors.

Media Call Widget Inline Mode

Layer / File(s) Summary
MediaCallWidgetSlot Context and Component
packages/ui-voip/src/context/MediaCallWidgetSlotContext.ts, packages/ui-voip/src/components/MediaCallWidgetSlot.tsx
New React context tracks slot DOM element and inline flag. MediaCallWidgetSlot component registers itself with context and renders a full-width flex container for widget mounting.
Widget Inline Mode Styling and Handle
packages/ui-voip/src/components/Widget/Widget.tsx, packages/ui-voip/src/components/Widget/WidgetHandle.tsx, packages/ui-voip/src/components/index.ts
WidgetBase accepts inline prop and applies fixed positioning only in floating mode. Widget reads inline from context and conditionally wires drag behavior. WidgetHandle hides when inline. Exports updated to expose MediaCallWidgetSlot.
Provider Integration and Portal Routing
packages/ui-voip/src/providers/MediaCallProvider.tsx, packages/ui-voip/src/providers/MediaCallViewProvider.tsx, packages/ui-voip/src/index.ts
MediaCallProvider manages slot state and wraps provider tree with MediaCallWidgetSlotContext.Provider. MediaCallViewProvider conditionally renders widget via createPortal into slot or fallback AnchorPortal. Public exports include useMediaCallView and MediaCallWidgetSlot.
NewCall View Inline UI
packages/ui-voip/src/views/MediaCallWidget/NewCall.tsx
NewCall reads inline flag and conditionally renders centered Keypad only in inline mode. Close button visibility toggled based on mode.
Session Reducer Peer Information Swap
packages/ui-voip/src/providers/useMediaSession.ts
toggleWidget reducer now preserves dialer when swapping peer info in new session state, enabling seamless peer switching within inline widget.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested reviewers

  • pierre-lehnen-rc
  • gabriellsh
🚥 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 accurately summarizes the primary change: adding a SidebarRail collapsed icon navigation rail component.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.

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


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.

@ggazzo ggazzo marked this pull request as draft May 15, 2026 15:53
@coderabbitai coderabbitai Bot added the type: feature Pull requests that introduces new feature label May 15, 2026
Copy link
Copy Markdown
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

🧹 Nitpick comments (1)
apps/meteor/client/sidebar/SidebarRail/SidebarRailInbox.tsx (1)

13-13: 💤 Low value

Consider narrowing the type assertion.

The type assertion as string | number | null | undefined is very broad. If the session value has a more specific expected shape, consider typing it more precisely or using a type guard for runtime validation.

🤖 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 `@apps/meteor/client/sidebar/SidebarRail/SidebarRailInbox.tsx` at line 13, The
broad type assertion on unread from useSession in SidebarRailInbox should be
narrowed: update the call to useSession or the unread variable to a more
specific type (e.g., useSession<number | null> or useSession<string | null>)
matching the actual session shape, or add a runtime type guard that validates
the value before using it; modify the unread declaration and any subsequent
logic that reads it (references to unread and the useSession call in
SidebarRailInbox) so the compiler knows the exact expected type and you handle
null/undefined safely.
🤖 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 `@apps/meteor/client/sidebar/SidebarRail/SidebarRailInbox.tsx`:
- Around line 18-20: The Inbox button's click handler (handleClick using
useEffectEvent) currently calls router.navigate('/home') which mismatches the
active-state check for '/inbox' and no '/inbox' route exists; update handleClick
to navigate to an actual inbox route that your app uses (e.g.,
'/admin/email-inboxes' or whichever inbox route you add), or else remove the
'/inbox' active-route check if this button is intended as a home shortcut;
specifically modify the function referenced as handleClick (and its
router.navigate(...) call) to point to the correct route that matches the
existing active-route logic.

---

Nitpick comments:
In `@apps/meteor/client/sidebar/SidebarRail/SidebarRailInbox.tsx`:
- Line 13: The broad type assertion on unread from useSession in
SidebarRailInbox should be narrowed: update the call to useSession or the unread
variable to a more specific type (e.g., useSession<number | null> or
useSession<string | null>) matching the actual session shape, or add a runtime
type guard that validates the value before using it; modify the unread
declaration and any subsequent logic that reads it (references to unread and the
useSession call in SidebarRailInbox) so the compiler knows the exact expected
type and you handle null/undefined safely.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 9d711b83-6927-4fd0-bec0-b5f3d241bc7a

📥 Commits

Reviewing files that changed from the base of the PR and between 7f61187 and 9ed59bb.

📒 Files selected for processing (15)
  • apps/meteor/.storybook/main.ts
  • apps/meteor/.storybook/mocks/meteor.js
  • apps/meteor/.storybook/mocks/sdk.ts
  • apps/meteor/client/components/HorizontalDivider/HorizontalDivider.tsx
  • apps/meteor/client/components/HorizontalDivider/index.ts
  • apps/meteor/client/components/ImageGallery/ImageGallery.tsx
  • apps/meteor/client/sidebar/SidebarRail/SidebarRail.stories.tsx
  • apps/meteor/client/sidebar/SidebarRail/SidebarRail.tsx
  • apps/meteor/client/sidebar/SidebarRail/SidebarRailCreateNew.tsx
  • apps/meteor/client/sidebar/SidebarRail/SidebarRailDivider.tsx
  • apps/meteor/client/sidebar/SidebarRail/SidebarRailInbox.tsx
  • apps/meteor/client/sidebar/SidebarRail/SidebarRailLoginPage.tsx
  • apps/meteor/client/sidebar/SidebarRail/SidebarRailPhone.tsx
  • apps/meteor/client/sidebar/SidebarRail/index.ts
  • packages/i18n/src/locales/en.i18n.json
📜 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). (4)
  • GitHub Check: 📦 Build Packages
  • GitHub Check: cubic · AI code reviewer
  • GitHub Check: CodeQL-Build
  • GitHub Check: CodeQL-Build
🧰 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/components/HorizontalDivider/index.ts
  • apps/meteor/client/sidebar/SidebarRail/index.ts
  • apps/meteor/client/components/HorizontalDivider/HorizontalDivider.tsx
  • apps/meteor/client/sidebar/SidebarRail/SidebarRailLoginPage.tsx
  • apps/meteor/client/sidebar/SidebarRail/SidebarRailDivider.tsx
  • apps/meteor/client/sidebar/SidebarRail/SidebarRail.stories.tsx
  • apps/meteor/client/sidebar/SidebarRail/SidebarRailPhone.tsx
  • apps/meteor/client/sidebar/SidebarRail/SidebarRailInbox.tsx
  • apps/meteor/client/components/ImageGallery/ImageGallery.tsx
  • apps/meteor/client/sidebar/SidebarRail/SidebarRail.tsx
  • apps/meteor/client/sidebar/SidebarRail/SidebarRailCreateNew.tsx
🧠 Learnings (6)
📚 Learning: 2026-02-10T16:32:42.586Z
Learnt from: tassoevan
Repo: RocketChat/Rocket.Chat PR: 38528
File: apps/meteor/client/startup/roles.ts:14-14
Timestamp: 2026-02-10T16:32:42.586Z
Learning: In Rocket.Chat's Meteor client code, DDP streams use EJSON and Date fields arrive as Date objects; do not manually construct new Date() in stream handlers (for example, in sdk.stream()). Only REST API responses return plain JSON where dates are strings, so implement explicit conversion there if needed. Apply this guidance to all TypeScript files under apps/meteor/client to ensure consistent date handling in DDP streams and REST responses.

Applied to files:

  • apps/meteor/client/components/HorizontalDivider/index.ts
  • apps/meteor/client/sidebar/SidebarRail/index.ts
📚 Learning: 2026-05-11T20:30:35.265Z
Learnt from: tassoevan
Repo: RocketChat/Rocket.Chat PR: 40480
File: apps/meteor/client/meteor/startup/accounts.ts:59-61
Timestamp: 2026-05-11T20:30:35.265Z
Learning: In Rocket.Chat’s Meteor client code, when calling `dispatchToastMessage` with `{ type: 'error' }`, pass the raw caught error object as `message` without manual normalization. `dispatchToastMessage` is designed to accept `message: unknown` for error toasts, so avoid converting errors to strings (e.g., `String(error)`) or extracting `error.message` before passing them.

Applied to files:

  • apps/meteor/client/components/HorizontalDivider/index.ts
  • apps/meteor/client/sidebar/SidebarRail/index.ts
📚 Learning: 2026-02-26T19:25:44.063Z
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 38778
File: packages/ui-voip/src/providers/useMediaSession.ts:192-192
Timestamp: 2026-02-26T19:25:44.063Z
Learning: In the Rocket.Chat repository, do not reference Biome lint rules in code review feedback. Biome is not used even if biome.json exists; only reference Biome rules if there is explicit, project-wide usage documented. For TypeScript files, review lint implications without Biome guidance unless the project enables Biome rules.

Applied to files:

  • apps/meteor/client/components/HorizontalDivider/index.ts
  • apps/meteor/client/sidebar/SidebarRail/index.ts
📚 Learning: 2026-02-26T19:25:44.063Z
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 38778
File: packages/ui-voip/src/providers/useMediaSession.ts:192-192
Timestamp: 2026-02-26T19:25:44.063Z
Learning: In this repository (RocketChat/Rocket.Chat), Biome lint rules are not used even if a biome.json exists. When reviewing TypeScript files (e.g., packages/ui-voip/src/providers/useMediaSession.ts), ensure lint suggestions do not reference Biome-specific rules. Rely on general ESLint/TypeScript lint rules and project conventions instead.

Applied to files:

  • apps/meteor/client/components/HorizontalDivider/index.ts
  • apps/meteor/client/sidebar/SidebarRail/index.ts
📚 Learning: 2026-05-06T12:21:44.083Z
Learnt from: juliajforesti
Repo: RocketChat/Rocket.Chat PR: 40256
File: apps/meteor/client/components/CreateDiscussion/CreateDiscussion.tsx:121-149
Timestamp: 2026-05-06T12:21:44.083Z
Learning: Field wrappers in rocket.chat/fuselage-forms (Field, FieldLabel, FieldRow, FieldError, FieldHint) auto-create htmlFor/id associations, aria-describedby, and role="alert" for errors. Do not manually set htmlFor, id, aria-describedby, or role attributes when using these wrappers. This automatic wiring does not apply to plain rocket.chat/fuselage components, which require explicit ID wiring per the accessibility docs. In code reviews, prefer using fuselage-forms wrappers for form fields and verify there is no unnecessary manual ID/aria wiring in files that use these wrappers. If a component uses plain fuselage components, ensure proper id wiring as per docs.

Applied to files:

  • apps/meteor/client/components/HorizontalDivider/index.ts
  • apps/meteor/client/sidebar/SidebarRail/index.ts
  • apps/meteor/client/components/HorizontalDivider/HorizontalDivider.tsx
  • apps/meteor/client/sidebar/SidebarRail/SidebarRailLoginPage.tsx
  • apps/meteor/client/sidebar/SidebarRail/SidebarRailDivider.tsx
  • apps/meteor/client/sidebar/SidebarRail/SidebarRail.stories.tsx
  • apps/meteor/client/sidebar/SidebarRail/SidebarRailPhone.tsx
  • apps/meteor/client/sidebar/SidebarRail/SidebarRailInbox.tsx
  • apps/meteor/client/components/ImageGallery/ImageGallery.tsx
  • apps/meteor/client/sidebar/SidebarRail/SidebarRail.tsx
  • apps/meteor/client/sidebar/SidebarRail/SidebarRailCreateNew.tsx
📚 Learning: 2026-03-27T14:52:56.865Z
Learnt from: dougfabris
Repo: RocketChat/Rocket.Chat PR: 39892
File: apps/meteor/client/views/room/contextualBar/Threads/Thread.tsx:150-155
Timestamp: 2026-03-27T14:52:56.865Z
Learning: In Rocket.Chat, there are two different `ModalBackdrop` components with different prop APIs. During review, confirm the import source: (1) `rocket.chat/fuselage` `ModalBackdrop` uses `ModalBackdropProps` based on `BoxProps` (so it supports `onClick` and other Box/DOM props) and does not have an `onDismiss` prop; (2) `rocket.chat/ui-client` `ModalBackdrop` uses a narrower props interface like `{ children?: ReactNode; onDismiss?: () => void }` and handles Escape keypress and outside mouse-up, and it does not forward arbitrary DOM props such as `onClick`. Flag mismatched props (e.g., `onDismiss` passed to the fuselage component or `onClick` passed to the ui-client component) and ensure the usage matches the correct component being imported.

Applied to files:

  • apps/meteor/client/components/HorizontalDivider/HorizontalDivider.tsx
  • apps/meteor/client/sidebar/SidebarRail/SidebarRailLoginPage.tsx
  • apps/meteor/client/sidebar/SidebarRail/SidebarRailDivider.tsx
  • apps/meteor/client/sidebar/SidebarRail/SidebarRail.stories.tsx
  • apps/meteor/client/sidebar/SidebarRail/SidebarRailPhone.tsx
  • apps/meteor/client/sidebar/SidebarRail/SidebarRailInbox.tsx
  • apps/meteor/client/components/ImageGallery/ImageGallery.tsx
  • apps/meteor/client/sidebar/SidebarRail/SidebarRail.tsx
  • apps/meteor/client/sidebar/SidebarRail/SidebarRailCreateNew.tsx
🪛 Biome (2.4.15)
apps/meteor/.storybook/mocks/meteor.js

[error] 44-47: Illegal use of an export declaration outside of a module

(parse)

🔇 Additional comments (14)
apps/meteor/.storybook/main.ts (1)

53-53: LGTM!

apps/meteor/.storybook/mocks/sdk.ts (1)

1-21: LGTM!

apps/meteor/client/components/ImageGallery/ImageGallery.tsx (1)

8-13: LGTM!

apps/meteor/client/components/HorizontalDivider/HorizontalDivider.tsx (1)

1-8: LGTM!

apps/meteor/client/components/HorizontalDivider/index.ts (1)

1-1: LGTM!

apps/meteor/.storybook/mocks/meteor.js (1)

44-47: The mock's export shape is already compatible with the codebase. All code imports DDPCommon as a named export and accesses parseDDP and stringifyDDP as object properties (DDPCommon.parseDDP, DDPCommon.stringifyDDP), which matches the mock's structure exactly.

apps/meteor/client/sidebar/SidebarRail/SidebarRail.tsx (1)

1-57: LGTM!

apps/meteor/client/sidebar/SidebarRail/SidebarRailCreateNew.tsx (1)

1-22: LGTM!

apps/meteor/client/sidebar/SidebarRail/SidebarRailDivider.tsx (1)

1-11: LGTM!

apps/meteor/client/sidebar/SidebarRail/SidebarRailLoginPage.tsx (1)

1-15: LGTM!

apps/meteor/client/sidebar/SidebarRail/SidebarRailPhone.tsx (1)

1-17: LGTM!

apps/meteor/client/sidebar/SidebarRail/index.ts (1)

1-1: LGTM!

apps/meteor/client/sidebar/SidebarRail/SidebarRail.stories.tsx (1)

1-65: LGTM!

packages/i18n/src/locales/en.i18n.json (1)

2664-2664: LGTM!

Comment on lines +18 to +20
const handleClick = useEffectEvent(() => {
router.navigate('/home');
});
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Search for inbox route definitions and other inbox navigation patterns

# Search for inbox route definitions
echo "=== Inbox route definitions ==="
rg -n --type=ts --type=tsx 'path.*inbox|route.*inbox' -i -C2

# Search for other inbox navigation patterns
echo -e "\n=== Other inbox navigation calls ==="
rg -n --type=ts --type=tsx "navigate\(['\"].*inbox" -i -C2

Repository: RocketChat/Rocket.Chat

Length of output: 210


🏁 Script executed:

#!/bin/bash
# Search without unrecognized file types
echo "=== Searching for inbox route definitions ==="
rg -n 'path.*inbox|route.*inbox' -i -g '*.ts' -g '*.js' -g '*.tsx' -g '*.jsx' -C2

echo -e "\n=== Searching for inbox navigation calls ==="
rg -n "navigate\(['\"].*inbox" -i -g '*.ts' -g '*.js' -g '*.tsx' -g '*.jsx' -C2

echo -e "\n=== Checking SidebarRailInbox.tsx content ==="
cat apps/meteor/client/sidebar/SidebarRail/SidebarRailInbox.tsx

echo -e "\n=== Searching for /home navigation calls to understand pattern ==="
rg -n "navigate\(['\"]\/home" -g '*.ts' -g '*.js' -g '*.tsx' -g '*.jsx' -C1 | head -30

Repository: RocketChat/Rocket.Chat

Length of output: 5628


🏁 Script executed:

#!/bin/bash
# Search for /inbox route specifically
echo "=== Searching for /inbox route ==="
rg -n "path.*\/inbox|pattern.*\/inbox|route.*\/inbox|\'/inbox\'|\"/inbox\"" -g '*.ts' -g '*.js' -g '*.tsx' -g '*.jsx' -C2

echo -e "\n=== Searching for route registrations ==="
rg -n "registerRoute|createRoute" -g '*.ts' -g '*.tsx' -g '*.js' -g '*.jsx' | head -30

echo -e "\n=== Searching for all route patterns containing inbox ==="
rg -n "pattern|pathname" -g 'routes*.ts' -g 'routes*.tsx' -C1

Repository: RocketChat/Rocket.Chat

Length of output: 26869


🏁 Script executed:

#!/bin/bash
# Search for /inbox without regex escaping
echo "=== Searching for /inbox string directly ==="
rg "/inbox" -g '*.ts' -g '*.tsx' -g '*.js' -g '*.jsx' -C2

echo -e "\n=== Searching for inbox string in route files ==="
rg "inbox" apps/meteor/client/startup/routes.tsx apps/meteor/client/views/admin/routes.tsx

echo -e "\n=== Check SidebarRailInbox again with context ==="
cat -n apps/meteor/client/sidebar/SidebarRail/SidebarRailInbox.tsx | sed -n '10,25p'

Repository: RocketChat/Rocket.Chat

Length of output: 2214


Navigation target should be /inbox (or equivalent inbox route).

The Inbox button checks for a route containing /inbox (line 16) but navigates to /home instead. Additionally, no /inbox route exists in the codebase—only /admin/email-inboxes for admin settings. The route detection logic on line 16 will never match, breaking the active state indicator. Update the navigation to match an actual inbox route or remove the route detection if this is intentionally a home shortcut.

🤖 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 `@apps/meteor/client/sidebar/SidebarRail/SidebarRailInbox.tsx` around lines 18
- 20, The Inbox button's click handler (handleClick using useEffectEvent)
currently calls router.navigate('/home') which mismatches the active-state check
for '/inbox' and no '/inbox' route exists; update handleClick to navigate to an
actual inbox route that your app uses (e.g., '/admin/email-inboxes' or whichever
inbox route you add), or else remove the '/inbox' active-route check if this
button is intended as a home shortcut; specifically modify the function
referenced as handleClick (and its router.navigate(...) call) to point to the
correct route that matches the existing active-route logic.

Copy link
Copy Markdown
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.

1 issue found across 15 files

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
Re-trigger cubic

Comment thread apps/meteor/client/sidebar/SidebarRail/SidebarRailInbox.tsx Outdated
@ggazzo ggazzo force-pushed the feat/local-sidebar-collapsed branch from bc28b3f to f1a6775 Compare May 15, 2026 20:35
@ggazzo ggazzo changed the base branch from develop to refactor/userstatuses-streamer-injection May 15, 2026 20:47
Base automatically changed from refactor/userstatuses-streamer-injection to develop May 16, 2026 03:02
@ggazzo ggazzo force-pushed the feat/local-sidebar-collapsed branch from be3f89b to 19c3b53 Compare May 18, 2026 13:20
@codecov
Copy link
Copy Markdown

codecov Bot commented May 18, 2026

Codecov Report

❌ Patch coverage is 58.06452% with 52 lines in your changes missing coverage. Please review.
✅ Project coverage is 69.74%. Comparing base (78814a8) to head (cfe679c).
⚠️ Report is 56 commits behind head on develop.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff            @@
##           develop   #40558    +/-   ##
=========================================
  Coverage    69.73%   69.74%            
=========================================
  Files         3322     3343    +21     
  Lines       122773   123273   +500     
  Branches     21887    22112   +225     
=========================================
+ Hits         85621    85982   +361     
- Misses       33800    33938   +138     
- Partials      3352     3353     +1     
Flag Coverage Δ
e2e 59.32% <25.45%> (+0.02%) ⬆️
e2e-api 46.22% <ø> (-0.93%) ⬇️
unit 70.47% <80.26%> (+0.06%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@ggazzo ggazzo force-pushed the feat/local-sidebar-collapsed branch 13 times, most recently from dd4df14 to de36ac0 Compare May 19, 2026 17:24
ggazzo added 2 commits May 19, 2026 15:00
`client/lib/sdk/ddpProtocol.ts` destructures `parseDDP` and
`stringifyDDP` from `DDPCommon` at module load. Without a matching
entry in the meteor mock any story whose bundle reaches the SDK
chain crashes with:

  Cannot destructure property 'parseDDP' of 'DDPCommon' as it is undefined

Add a narrow `DDPCommon` no-op (parseDDP/stringifyDDP) so the
destructuring resolves. Scoped change — does not re-introduce the
broader SDKClient stub.
Thin wrapper that forces `vertical={false}` on `@rocket.chat/fuselage`
Divider, providing a single horizontal-only entrypoint for callers
that want to express intent at the type level without re-implementing
the visual style.
@ggazzo ggazzo force-pushed the feat/local-sidebar-collapsed branch 2 times, most recently from 8f6b452 to 2c2f020 Compare May 19, 2026 18:51
@ggazzo ggazzo force-pushed the feat/local-sidebar-collapsed branch 3 times, most recently from 8fb05f6 to b0cc412 Compare May 20, 2026 16:16
ggazzo added 3 commits May 20, 2026 17:08
The widget is currently a floating, draggable portal. The sidebar
rail needs to host the same widget anchored inside a slot, so add a
slot-based mount mechanism and let the widget render in place without
dragging or border styles.

Slot mechanism
- `MediaCallWidgetSlotContext`: shared context exposing the active
  slot element + an `inline` boolean.
- `MediaCallWidgetSlot`: drop-in component that registers its own
  `<div>` as the target. Removing it from the tree restores the
  floating portal automatically. The slot aligns its child to the
  top so the anchored widget keeps its intrinsic height instead of
  stretching to the container.
- `MediaCallProvider`: hosts the slot state above the view provider
  so consumers in `children` and the widget itself share the same
  context value. `MediaCallProvider` now wraps `children` with
  `MediaCallViewProvider` so `useMediaCallView` resolves in the app
  tree.
- `MediaCallViewProvider`: when a slot is registered the widget is
  rendered via `createPortal(widget, slot)`; otherwise it falls back
  to the previous `AnchorPortal` mount.

Widget composition
- `WidgetBase`: inline branch drops the fixed positioning, border,
  and z-index. Background, border-radius, shadow and width are kept
  so the anchored render looks the same as the floating one.
- `Widget`: read inline from context, skip drag wiring when inline.
- `WidgetHandle`: hide itself when inline (drag is disabled).
- `NewCall`: render the numeric Keypad below the autocomplete when
  inline so the dialer matches the sidebar layout in the design.

Visibility rules
- Only "undock" the widget for active call states (calling, ringing,
  ongoing). When the slot is gone and the session is idle the widget
  renders nothing instead of popping out as a floating NewCall.

Snapshot tests regenerated to reflect the inline-aware render tree.
44px-wide vertical navigation rail (Material Design "navigation rail"
pattern) matching the Figma "Local Sidebar / Collapsed" design.

Composes existing NavBar items (Home, Directory, Marketplace,
Administration menu, UserMenu) and adds rail-specific variants:
- `SidebarRailCreateNew`: pencil-box menu reusing `useCreateNewMenu`.
- `SidebarRailPhone`: phone icon that navigates to `/call-history`
  and reflects the route in its `pressed` state.
- `SidebarRailCallPanel`: Sidepanel-based second-level container
  hosting a `MediaCallWidgetSlot` for the dialer body.
- `SidebarRailCallRouteSync`: keeps the dialer open while on
  `/call-history` (bouncing back from `closed` to `new`) and closes
  it on leave when the dialer is idle.
- `SidebarRailHeader`: slim top bar reusing the Fuselage NavBar with
  the workspace 28px icon and the existing `NavBarNavigation`
  (search + back/forward), suppressing the legacy NavBar groups.
- `SidebarRailLoginPage`: icon-only login NavBarItem for the avatar
  slot when no user is signed in.
- `SidebarRailDivider`: horizontal divider with rail-specific tokens.

Includes an `Inbox` i18n key reused later and a Storybook file with
Anonymous, LoggedIn, WithUnreadBadge and WithCreatePermissions
variants.
When `USE_SIDEBAR_RAIL` is true (and the layout is not embedded /
mobile), replace the top horizontal `NavBar` with the slim
`SidebarRailHeader` and render `SidebarRail` as the first column of
`#rocket-chat`. The legacy NavBar path remains for the other cases
so the change is reversible by flipping a single constant.

- `sidebarRailFlag.ts`: dev-only constant, intended to be replaced
  by `useFeaturePreview('sidebarRail')` in a follow-up before any
  rollout.
- `LayoutWithSidebar.tsx`: pick the header, render the rail, and
  drive the secondary slot through a new `SecondaryPanel`. While on
  `/call-history` the slot renders the rail call panel; otherwise
  it falls back to the existing Sidebar / NavigationRegion feature
  preview split.
- `SecondaryPanel.tsx`: extracted into its own file to comply with
  `react/no-multi-comp`.
- `MainLayoutStyleTags.tsx`: extend the dark palette selector to
  cover `.rcx-sidebar-rail` so the rail keeps the dark surface in
  both themes.
@ggazzo ggazzo force-pushed the feat/local-sidebar-collapsed branch from b0cc412 to daae7a0 Compare May 20, 2026 20:08
@ggazzo ggazzo marked this pull request as ready for review June 2, 2026 15:26
@ggazzo ggazzo added this to the POC-VOICE milestone Jun 2, 2026
Copy link
Copy Markdown
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.

🧹 Nitpick comments (3)
apps/meteor/client/sidebar/SidebarRail/SidebarRailPhone.tsx (1)

16-20: ⚡ Quick win

Extract the call-history route contract into a shared helper.

'/call-history' and its matching logic are duplicated here, in SidebarRailCallRouteSync, and in SecondaryPanel. A shared constant/helper keeps navigation, active state, and panel selection from drifting.

🤖 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 `@apps/meteor/client/sidebar/SidebarRail/SidebarRailPhone.tsx` around lines 16
- 20, The '/call-history' literal and its matching logic are duplicated; extract
a shared route constant/helper (e.g., CALL_HISTORY_ROUTE or
getCallHistoryRoute()/isCallHistoryRoute()) and replace the literal and includes
checks in SidebarRailPhone (isActive and handleClick using useEffectEvent),
SidebarRailCallRouteSync, and SecondaryPanel so navigation, active-state
detection, and panel selection all reference the same symbol; update imports
where needed and ensure router.navigate and currentRoute?.includes use the
shared helper for consistency.
apps/meteor/client/sidebar/SidebarRail/SidebarRailCallRouteSync.tsx (1)

15-23: ⚡ Quick win

Remove the inline implementation comments.

The intent here is already expressible through naming or a small helper; the added comments violate the repo rule for implementation files. As per coding guidelines, "Avoid code comments in the implementation".

🤖 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 `@apps/meteor/client/sidebar/SidebarRail/SidebarRailCallRouteSync.tsx` around
lines 15 - 23, Remove the inline implementation comments in
SidebarRailCallRouteSync.tsx by replacing them with clearer naming or a tiny
helper; specifically, eliminate the two comment blocks above the conditional
checks using onRoute and sessionState.state and instead ensure the logic is
self-documenting (for example, extract intent into a small helper like
isOnCallHistoryRoute/onIdleDialer or rename toggleWidget usage contextually) so
the behavior around toggleWidget(), sessionState.state === 'closed', and
sessionState.state === 'new' is clear without implementation comments.
packages/ui-voip/src/providers/useMediaSession.ts (1)

76-78: ⚡ Quick win

Remove the reducer comment block.

This branch is clear from the code, and the new inline note violates the repo rule against implementation comments.

As per coding guidelines, "Avoid code comments in the implementation".

🤖 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 `@packages/ui-voip/src/providers/useMediaSession.ts` around lines 76 - 78,
Remove the implementation comment block inside useMediaSession's reducer (the
multi-line note beginning "// If a peer is supplied while the dialer is already
open, replace the peer instead of toggling closed — keeps "Call rodrigo"
working..."). Edit the reducer in useMediaSession to delete that inline
explanatory comment so the implementation contains no implementation comments,
leaving only code and any allowed high-level documentation.
🤖 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.

Nitpick comments:
In `@apps/meteor/client/sidebar/SidebarRail/SidebarRailCallRouteSync.tsx`:
- Around line 15-23: Remove the inline implementation comments in
SidebarRailCallRouteSync.tsx by replacing them with clearer naming or a tiny
helper; specifically, eliminate the two comment blocks above the conditional
checks using onRoute and sessionState.state and instead ensure the logic is
self-documenting (for example, extract intent into a small helper like
isOnCallHistoryRoute/onIdleDialer or rename toggleWidget usage contextually) so
the behavior around toggleWidget(), sessionState.state === 'closed', and
sessionState.state === 'new' is clear without implementation comments.

In `@apps/meteor/client/sidebar/SidebarRail/SidebarRailPhone.tsx`:
- Around line 16-20: The '/call-history' literal and its matching logic are
duplicated; extract a shared route constant/helper (e.g., CALL_HISTORY_ROUTE or
getCallHistoryRoute()/isCallHistoryRoute()) and replace the literal and includes
checks in SidebarRailPhone (isActive and handleClick using useEffectEvent),
SidebarRailCallRouteSync, and SecondaryPanel so navigation, active-state
detection, and panel selection all reference the same symbol; update imports
where needed and ensure router.navigate and currentRoute?.includes use the
shared helper for consistency.

In `@packages/ui-voip/src/providers/useMediaSession.ts`:
- Around line 76-78: Remove the implementation comment block inside
useMediaSession's reducer (the multi-line note beginning "// If a peer is
supplied while the dialer is already open, replace the peer instead of toggling
closed — keeps "Call rodrigo" working..."). Edit the reducer in useMediaSession
to delete that inline explanatory comment so the implementation contains no
implementation comments, leaving only code and any allowed high-level
documentation.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 06bae544-85d5-4d86-89ae-47009650653a

📥 Commits

Reviewing files that changed from the base of the PR and between 9ed59bb and daae7a0.

⛔ Files ignored due to path filters (2)
  • packages/ui-voip/src/components/Widget/__snapshots__/Widget.spec.tsx.snap is excluded by !**/*.snap
  • packages/ui-voip/src/views/MediaCallWidget/__snapshots__/MediaCallWidget.spec.tsx.snap is excluded by !**/*.snap
📒 Files selected for processing (28)
  • apps/meteor/.storybook/mocks/meteor.js
  • apps/meteor/client/components/HorizontalDivider/HorizontalDivider.tsx
  • apps/meteor/client/components/HorizontalDivider/index.ts
  • apps/meteor/client/sidebar/SidebarRail/SidebarRail.stories.tsx
  • apps/meteor/client/sidebar/SidebarRail/SidebarRail.tsx
  • apps/meteor/client/sidebar/SidebarRail/SidebarRailCallPanel.tsx
  • apps/meteor/client/sidebar/SidebarRail/SidebarRailCallRouteSync.tsx
  • apps/meteor/client/sidebar/SidebarRail/SidebarRailCreateNew.tsx
  • apps/meteor/client/sidebar/SidebarRail/SidebarRailDivider.tsx
  • apps/meteor/client/sidebar/SidebarRail/SidebarRailHeader.tsx
  • apps/meteor/client/sidebar/SidebarRail/SidebarRailLoginPage.tsx
  • apps/meteor/client/sidebar/SidebarRail/SidebarRailPhone.tsx
  • apps/meteor/client/sidebar/SidebarRail/index.ts
  • apps/meteor/client/views/root/MainLayout/LayoutWithSidebar.tsx
  • apps/meteor/client/views/root/MainLayout/MainLayoutStyleTags.tsx
  • apps/meteor/client/views/root/MainLayout/SecondaryPanel.tsx
  • apps/meteor/client/views/root/MainLayout/sidebarRailFlag.ts
  • packages/i18n/src/locales/en.i18n.json
  • packages/ui-voip/src/components/MediaCallWidgetSlot.tsx
  • packages/ui-voip/src/components/Widget/Widget.tsx
  • packages/ui-voip/src/components/Widget/WidgetHandle.tsx
  • packages/ui-voip/src/components/index.ts
  • packages/ui-voip/src/context/MediaCallWidgetSlotContext.ts
  • packages/ui-voip/src/index.ts
  • packages/ui-voip/src/providers/MediaCallProvider.tsx
  • packages/ui-voip/src/providers/MediaCallViewProvider.tsx
  • packages/ui-voip/src/providers/useMediaSession.ts
  • packages/ui-voip/src/views/MediaCallWidget/NewCall.tsx
✅ Files skipped from review due to trivial changes (8)
  • apps/meteor/client/views/root/MainLayout/sidebarRailFlag.ts
  • apps/meteor/client/views/root/MainLayout/MainLayoutStyleTags.tsx
  • packages/ui-voip/src/index.ts
  • packages/ui-voip/src/components/index.ts
  • apps/meteor/client/components/HorizontalDivider/index.ts
  • packages/ui-voip/src/context/MediaCallWidgetSlotContext.ts
  • apps/meteor/client/sidebar/SidebarRail/SidebarRailHeader.tsx
  • apps/meteor/client/sidebar/SidebarRail/index.ts
🚧 Files skipped from review as they are similar to previous changes (7)
  • apps/meteor/client/sidebar/SidebarRail/SidebarRailCreateNew.tsx
  • apps/meteor/client/sidebar/SidebarRail/SidebarRailLoginPage.tsx
  • packages/i18n/src/locales/en.i18n.json
  • apps/meteor/client/sidebar/SidebarRail/SidebarRail.stories.tsx
  • apps/meteor/client/sidebar/SidebarRail/SidebarRailDivider.tsx
  • apps/meteor/client/components/HorizontalDivider/HorizontalDivider.tsx
  • apps/meteor/client/sidebar/SidebarRail/SidebarRail.tsx
📜 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). (2)
  • GitHub Check: cubic · AI code reviewer
  • GitHub Check: Hacktron Security Check
🧰 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/sidebar/SidebarRail/SidebarRailCallPanel.tsx
  • apps/meteor/client/views/root/MainLayout/SecondaryPanel.tsx
  • packages/ui-voip/src/components/MediaCallWidgetSlot.tsx
  • apps/meteor/client/sidebar/SidebarRail/SidebarRailCallRouteSync.tsx
  • packages/ui-voip/src/views/MediaCallWidget/NewCall.tsx
  • packages/ui-voip/src/components/Widget/Widget.tsx
  • packages/ui-voip/src/providers/MediaCallViewProvider.tsx
  • packages/ui-voip/src/providers/useMediaSession.ts
  • packages/ui-voip/src/components/Widget/WidgetHandle.tsx
  • apps/meteor/client/sidebar/SidebarRail/SidebarRailPhone.tsx
  • apps/meteor/client/views/root/MainLayout/LayoutWithSidebar.tsx
  • packages/ui-voip/src/providers/MediaCallProvider.tsx
🧠 Learnings (6)
📚 Learning: 2026-03-27T14:52:56.865Z
Learnt from: dougfabris
Repo: RocketChat/Rocket.Chat PR: 39892
File: apps/meteor/client/views/room/contextualBar/Threads/Thread.tsx:150-155
Timestamp: 2026-03-27T14:52:56.865Z
Learning: In Rocket.Chat, there are two different `ModalBackdrop` components with different prop APIs. During review, confirm the import source: (1) `rocket.chat/fuselage` `ModalBackdrop` uses `ModalBackdropProps` based on `BoxProps` (so it supports `onClick` and other Box/DOM props) and does not have an `onDismiss` prop; (2) `rocket.chat/ui-client` `ModalBackdrop` uses a narrower props interface like `{ children?: ReactNode; onDismiss?: () => void }` and handles Escape keypress and outside mouse-up, and it does not forward arbitrary DOM props such as `onClick`. Flag mismatched props (e.g., `onDismiss` passed to the fuselage component or `onClick` passed to the ui-client component) and ensure the usage matches the correct component being imported.

Applied to files:

  • apps/meteor/client/sidebar/SidebarRail/SidebarRailCallPanel.tsx
  • apps/meteor/client/views/root/MainLayout/SecondaryPanel.tsx
  • packages/ui-voip/src/components/MediaCallWidgetSlot.tsx
  • apps/meteor/client/sidebar/SidebarRail/SidebarRailCallRouteSync.tsx
  • packages/ui-voip/src/views/MediaCallWidget/NewCall.tsx
  • packages/ui-voip/src/components/Widget/Widget.tsx
  • packages/ui-voip/src/providers/MediaCallViewProvider.tsx
  • packages/ui-voip/src/components/Widget/WidgetHandle.tsx
  • apps/meteor/client/sidebar/SidebarRail/SidebarRailPhone.tsx
  • apps/meteor/client/views/root/MainLayout/LayoutWithSidebar.tsx
  • packages/ui-voip/src/providers/MediaCallProvider.tsx
📚 Learning: 2026-05-06T12:21:44.083Z
Learnt from: juliajforesti
Repo: RocketChat/Rocket.Chat PR: 40256
File: apps/meteor/client/components/CreateDiscussion/CreateDiscussion.tsx:121-149
Timestamp: 2026-05-06T12:21:44.083Z
Learning: Field wrappers in rocket.chat/fuselage-forms (Field, FieldLabel, FieldRow, FieldError, FieldHint) auto-create htmlFor/id associations, aria-describedby, and role="alert" for errors. Do not manually set htmlFor, id, aria-describedby, or role attributes when using these wrappers. This automatic wiring does not apply to plain rocket.chat/fuselage components, which require explicit ID wiring per the accessibility docs. In code reviews, prefer using fuselage-forms wrappers for form fields and verify there is no unnecessary manual ID/aria wiring in files that use these wrappers. If a component uses plain fuselage components, ensure proper id wiring as per docs.

Applied to files:

  • apps/meteor/client/sidebar/SidebarRail/SidebarRailCallPanel.tsx
  • apps/meteor/client/views/root/MainLayout/SecondaryPanel.tsx
  • packages/ui-voip/src/components/MediaCallWidgetSlot.tsx
  • apps/meteor/client/sidebar/SidebarRail/SidebarRailCallRouteSync.tsx
  • packages/ui-voip/src/views/MediaCallWidget/NewCall.tsx
  • packages/ui-voip/src/components/Widget/Widget.tsx
  • packages/ui-voip/src/providers/MediaCallViewProvider.tsx
  • packages/ui-voip/src/providers/useMediaSession.ts
  • packages/ui-voip/src/components/Widget/WidgetHandle.tsx
  • apps/meteor/client/sidebar/SidebarRail/SidebarRailPhone.tsx
  • apps/meteor/client/views/root/MainLayout/LayoutWithSidebar.tsx
  • packages/ui-voip/src/providers/MediaCallProvider.tsx
📚 Learning: 2026-02-26T19:22:29.385Z
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 38778
File: packages/ui-voip/src/views/CallHistoryContextualbar/CallHistoryActions.tsx:40-40
Timestamp: 2026-02-26T19:22:29.385Z
Learning: For TSX files in the UI VOIP package, ensure that when a media session state is 'unavailable', the voiceCall action is excluded from the actions object passed to CallHistoryActions so it does not render in the menu. This filtering should occur upstream (before getItems is called) to avoid tooltips or UI hints for unavailable actions. If there are multiple actions with availability states, implement a centralized helper to filter actions based on session state.

Applied to files:

  • packages/ui-voip/src/components/MediaCallWidgetSlot.tsx
  • packages/ui-voip/src/views/MediaCallWidget/NewCall.tsx
  • packages/ui-voip/src/components/Widget/Widget.tsx
  • packages/ui-voip/src/providers/MediaCallViewProvider.tsx
  • packages/ui-voip/src/components/Widget/WidgetHandle.tsx
  • packages/ui-voip/src/providers/MediaCallProvider.tsx
📚 Learning: 2026-05-05T12:34:29.042Z
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 40331
File: packages/ui-voip/src/views/MediaCallWidget/OngoingCallWithScreen.tsx:69-69
Timestamp: 2026-05-05T12:34:29.042Z
Learning: In Rocket.Chat’s `packages/ui-voip` UI (e.g., media/call widgets), voice/media calls are only supported in Direct Message (DM) rooms. Rocket.Chat models a DM as a “room” with exactly two participants, so handlers like `onClickDirectMessage` are the correct destination—even when the UI text/element says “Open in room” (e.g., on the shared screen card/`StreamCard`). During review, don’t flag a “DM vs room” mismatch for these cases; they intentionally map to the same destination.

Applied to files:

  • packages/ui-voip/src/components/MediaCallWidgetSlot.tsx
  • packages/ui-voip/src/views/MediaCallWidget/NewCall.tsx
  • packages/ui-voip/src/components/Widget/Widget.tsx
  • packages/ui-voip/src/providers/MediaCallViewProvider.tsx
  • packages/ui-voip/src/components/Widget/WidgetHandle.tsx
  • packages/ui-voip/src/providers/MediaCallProvider.tsx
📚 Learning: 2026-02-26T19:25:44.063Z
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 38778
File: packages/ui-voip/src/providers/useMediaSession.ts:192-192
Timestamp: 2026-02-26T19:25:44.063Z
Learning: In the Rocket.Chat repository, do not reference Biome lint rules in code review feedback. Biome is not used even if biome.json exists; only reference Biome rules if there is explicit, project-wide usage documented. For TypeScript files, review lint implications without Biome guidance unless the project enables Biome rules.

Applied to files:

  • packages/ui-voip/src/providers/useMediaSession.ts
📚 Learning: 2026-02-26T19:25:44.063Z
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 38778
File: packages/ui-voip/src/providers/useMediaSession.ts:192-192
Timestamp: 2026-02-26T19:25:44.063Z
Learning: In this repository (RocketChat/Rocket.Chat), Biome lint rules are not used even if a biome.json exists. When reviewing TypeScript files (e.g., packages/ui-voip/src/providers/useMediaSession.ts), ensure lint suggestions do not reference Biome-specific rules. Rely on general ESLint/TypeScript lint rules and project conventions instead.

Applied to files:

  • packages/ui-voip/src/providers/useMediaSession.ts
🪛 Biome (2.4.16)
apps/meteor/.storybook/mocks/meteor.js

[error] 31-34: Illegal use of an export declaration outside of a module

(parse)

Copy link
Copy Markdown
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.

4 issues found across 30 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="apps/meteor/client/sidebar/SidebarRail/SidebarRailCallRouteSync.tsx">

<violation number="1" location="apps/meteor/client/sidebar/SidebarRail/SidebarRailCallRouteSync.tsx:13">
P2: Route detection uses substring matching, which can misclassify non-call-history paths and trigger incorrect widget toggles.</violation>
</file>

<file name="packages/ui-voip/src/components/Widget/Widget.tsx">

<violation number="1" location="packages/ui-voip/src/components/Widget/Widget.tsx:50">
P2: Inline mode can leave a stale body bounding observer active because the effect returns early without clearing `boundingRef`.</violation>
</file>

<file name="packages/ui-voip/src/views/MediaCallWidget/NewCall.tsx">

<violation number="1" location="packages/ui-voip/src/views/MediaCallWidget/NewCall.tsx:46">
P1: Keypad presses update the autocomplete filter but do not select the dialed number as the call peer. When a user dials a number via the Keypad in inline mode and clicks Call, `onCall` will find no `peerInfo` (or a stale one), and the call will silently fail because `onKeypadPress` only calls `setFilter` without calling `onSelectPeer({ number: ... })`. This makes the inline Keypad functionally broken for initiating calls.</violation>
</file>

<file name="apps/meteor/.storybook/mocks/meteor.js">

<violation number="1" location="apps/meteor/.storybook/mocks/meteor.js:32">
P2: `DDPCommon.parseDDP/stringifyDDP` should preserve DDP payload shape; the current no-op stub can break any Storybook path that decodes or re-encodes messages.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

)}
{inline && (
<Box display='flex' justifyContent='center' mbs={12}>
<Keypad onKeyPress={autocomplete.onKeypadPress} />
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P1: Keypad presses update the autocomplete filter but do not select the dialed number as the call peer. When a user dials a number via the Keypad in inline mode and clicks Call, onCall will find no peerInfo (or a stale one), and the call will silently fail because onKeypadPress only calls setFilter without calling onSelectPeer({ number: ... }). This makes the inline Keypad functionally broken for initiating calls.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/ui-voip/src/views/MediaCallWidget/NewCall.tsx, line 46:

<comment>Keypad presses update the autocomplete filter but do not select the dialed number as the call peer. When a user dials a number via the Keypad in inline mode and clicks Call, `onCall` will find no `peerInfo` (or a stale one), and the call will silently fail because `onKeypadPress` only calls `setFilter` without calling `onSelectPeer({ number: ... })`. This makes the inline Keypad functionally broken for initiating calls.</comment>

<file context>
@@ -38,6 +41,11 @@ const NewCall = () => {
 				)}
+				{inline && (
+					<Box display='flex' justifyContent='center' mbs={12}>
+						<Keypad onKeyPress={autocomplete.onKeypadPress} />
+					</Box>
+				)}
</file context>

const { toggleWidget } = useWidgetExternalControls();

useEffect(() => {
const onRoute = currentRoutePath?.includes('/call-history') ?? false;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2: Route detection uses substring matching, which can misclassify non-call-history paths and trigger incorrect widget toggles.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/meteor/client/sidebar/SidebarRail/SidebarRailCallRouteSync.tsx, line 13:

<comment>Route detection uses substring matching, which can misclassify non-call-history paths and trigger incorrect widget toggles.</comment>

<file context>
@@ -0,0 +1,31 @@
+	const { toggleWidget } = useWidgetExternalControls();
+
+	useEffect(() => {
+		const onRoute = currentRoutePath?.includes('/call-history') ?? false;
+
+		// On /call-history: keep the dialer open. If the session is idle (closed)
</file context>

const [draggableRef, boundingRef, handleRef] = useDraggable({ onChangePosition, restorePosition });

useLayoutEffect(() => {
if (inline) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2: Inline mode can leave a stale body bounding observer active because the effect returns early without clearing boundingRef.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/ui-voip/src/components/Widget/Widget.tsx, line 50:

<comment>Inline mode can leave a stale body bounding observer active because the effect returns early without clearing `boundingRef`.</comment>

<file context>
@@ -36,16 +43,25 @@ type WidgetProps = {
 	const [draggableRef, boundingRef, handleRef] = useDraggable({ onChangePosition, restorePosition });
 
 	useLayoutEffect(() => {
+		if (inline) {
+			return;
+		}
</file context>

};

export const DDPCommon = {
parseDDP: () => undefined,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2: DDPCommon.parseDDP/stringifyDDP should preserve DDP payload shape; the current no-op stub can break any Storybook path that decodes or re-encodes messages.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/meteor/.storybook/mocks/meteor.js, line 32:

<comment>`DDPCommon.parseDDP/stringifyDDP` should preserve DDP payload shape; the current no-op stub can break any Storybook path that decodes or re-encodes messages.</comment>

<file context>
@@ -28,6 +28,11 @@ export const Meteor = {
 };
 
+export const DDPCommon = {
+	parseDDP: () => undefined,
+	stringifyDDP: () => '',
+};
</file context>

Expose the SidebarRail flag on window.USE_SIDEBAR_RAIL (default false) so it can be toggled at runtime via a custom script, instead of a hardcoded build-time constant. Read on every render through isSidebarRailEnabled().
Copy link
Copy Markdown
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.

🧹 Nitpick comments (1)
apps/meteor/client/views/root/MainLayout/sidebarRailFlag.ts (1)

7-17: 💤 Low value

Consider removing the JSDoc comment per coding guidelines.

The extensive JSDoc comment provides useful API documentation, but the coding guidelines specify "Avoid code comments in the implementation" for TypeScript files. If runtime toggle documentation is needed, consider moving it to external docs or README.

As per coding guidelines: "Avoid code comments in the implementation" for **/*.{ts,tsx,js} files.

🤖 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 `@apps/meteor/client/views/root/MainLayout/sidebarRailFlag.ts` around lines 7 -
17, Remove the JSDoc block at the top of sidebarRailFlag.ts and any other
implementation-level comments that document runtime behavior; leave no
multi-line comments in the TypeScript implementation and, if needed, move the
usage note about toggling window.USE_SIDEBAR_RAIL to external documentation
(README or developer docs) instead—search for the symbol USE_SIDEBAR_RAIL or
references to SidebarRail in this file to confirm you removed only the comment
and not any code.
🤖 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.

Nitpick comments:
In `@apps/meteor/client/views/root/MainLayout/sidebarRailFlag.ts`:
- Around line 7-17: Remove the JSDoc block at the top of sidebarRailFlag.ts and
any other implementation-level comments that document runtime behavior; leave no
multi-line comments in the TypeScript implementation and, if needed, move the
usage note about toggling window.USE_SIDEBAR_RAIL to external documentation
(README or developer docs) instead—search for the symbol USE_SIDEBAR_RAIL or
references to SidebarRail in this file to confirm you removed only the comment
and not any code.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 32da67c3-c9d1-4948-95b0-085c5b30616d

📥 Commits

Reviewing files that changed from the base of the PR and between daae7a0 and 9b595b1.

📒 Files selected for processing (2)
  • apps/meteor/client/views/root/MainLayout/LayoutWithSidebar.tsx
  • apps/meteor/client/views/root/MainLayout/sidebarRailFlag.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/meteor/client/views/root/MainLayout/LayoutWithSidebar.tsx
📜 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). (5)
  • GitHub Check: cubic · AI code reviewer
  • GitHub Check: ⚙️ Variables Setup
  • GitHub Check: CodeQL-Build
  • GitHub Check: Hacktron Security Check
  • GitHub Check: CodeQL-Build
🧰 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/views/root/MainLayout/sidebarRailFlag.ts
🧠 Learnings (6)
📚 Learning: 2026-01-17T01:51:47.764Z
Learnt from: tassoevan
Repo: RocketChat/Rocket.Chat PR: 38219
File: packages/core-typings/src/cloud/Announcement.ts:5-6
Timestamp: 2026-01-17T01:51:47.764Z
Learning: In packages/core-typings/src/cloud/Announcement.ts, the AnnouncementSchema.createdBy field intentionally overrides IBannerSchema.createdBy (object with _id and optional username) with a string enum ['cloud', 'system'] to match existing runtime behavior. This is documented as technical debt with a FIXME comment at apps/meteor/app/cloud/server/functions/syncWorkspace/handleCommsSync.ts:53 and should not be flagged as an error until the runtime behavior is corrected.

Applied to files:

  • apps/meteor/client/views/root/MainLayout/sidebarRailFlag.ts
📚 Learning: 2026-02-10T16:32:42.586Z
Learnt from: tassoevan
Repo: RocketChat/Rocket.Chat PR: 38528
File: apps/meteor/client/startup/roles.ts:14-14
Timestamp: 2026-02-10T16:32:42.586Z
Learning: In Rocket.Chat's Meteor client code, DDP streams use EJSON and Date fields arrive as Date objects; do not manually construct new Date() in stream handlers (for example, in sdk.stream()). Only REST API responses return plain JSON where dates are strings, so implement explicit conversion there if needed. Apply this guidance to all TypeScript files under apps/meteor/client to ensure consistent date handling in DDP streams and REST responses.

Applied to files:

  • apps/meteor/client/views/root/MainLayout/sidebarRailFlag.ts
📚 Learning: 2026-05-11T20:30:35.265Z
Learnt from: tassoevan
Repo: RocketChat/Rocket.Chat PR: 40480
File: apps/meteor/client/meteor/startup/accounts.ts:59-61
Timestamp: 2026-05-11T20:30:35.265Z
Learning: In Rocket.Chat’s Meteor client code, when calling `dispatchToastMessage` with `{ type: 'error' }`, pass the raw caught error object as `message` without manual normalization. `dispatchToastMessage` is designed to accept `message: unknown` for error toasts, so avoid converting errors to strings (e.g., `String(error)`) or extracting `error.message` before passing them.

Applied to files:

  • apps/meteor/client/views/root/MainLayout/sidebarRailFlag.ts
📚 Learning: 2026-02-26T19:25:44.063Z
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 38778
File: packages/ui-voip/src/providers/useMediaSession.ts:192-192
Timestamp: 2026-02-26T19:25:44.063Z
Learning: In the Rocket.Chat repository, do not reference Biome lint rules in code review feedback. Biome is not used even if biome.json exists; only reference Biome rules if there is explicit, project-wide usage documented. For TypeScript files, review lint implications without Biome guidance unless the project enables Biome rules.

Applied to files:

  • apps/meteor/client/views/root/MainLayout/sidebarRailFlag.ts
📚 Learning: 2026-02-26T19:25:44.063Z
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 38778
File: packages/ui-voip/src/providers/useMediaSession.ts:192-192
Timestamp: 2026-02-26T19:25:44.063Z
Learning: In this repository (RocketChat/Rocket.Chat), Biome lint rules are not used even if a biome.json exists. When reviewing TypeScript files (e.g., packages/ui-voip/src/providers/useMediaSession.ts), ensure lint suggestions do not reference Biome-specific rules. Rely on general ESLint/TypeScript lint rules and project conventions instead.

Applied to files:

  • apps/meteor/client/views/root/MainLayout/sidebarRailFlag.ts
📚 Learning: 2026-05-06T12:21:44.083Z
Learnt from: juliajforesti
Repo: RocketChat/Rocket.Chat PR: 40256
File: apps/meteor/client/components/CreateDiscussion/CreateDiscussion.tsx:121-149
Timestamp: 2026-05-06T12:21:44.083Z
Learning: Field wrappers in rocket.chat/fuselage-forms (Field, FieldLabel, FieldRow, FieldError, FieldHint) auto-create htmlFor/id associations, aria-describedby, and role="alert" for errors. Do not manually set htmlFor, id, aria-describedby, or role attributes when using these wrappers. This automatic wiring does not apply to plain rocket.chat/fuselage components, which require explicit ID wiring per the accessibility docs. In code reviews, prefer using fuselage-forms wrappers for form fields and verify there is no unnecessary manual ID/aria wiring in files that use these wrappers. If a component uses plain fuselage components, ensure proper id wiring as per docs.

Applied to files:

  • apps/meteor/client/views/root/MainLayout/sidebarRailFlag.ts
🔇 Additional comments (2)
apps/meteor/client/views/root/MainLayout/sidebarRailFlag.ts (2)

1-5: LGTM!


18-18: LGTM!

ggazzo added 2 commits June 3, 2026 14:27
The global Window interface augmentation must keep the lib name 'Window', which violates the I-prefix naming-convention rule. Disable the rule on that line.
The spec still mocked the removed layout modules (Sidebar, NavigationRegion, FeaturePreview) while LayoutWithSidebar now imports SidebarRail, SidebarRailHeader, SidebarRailCallRouteSync and SecondaryPanel. The unmocked real SidebarRail pulled app/utils/client -> rocketchat.info into the jest graph, which jest cannot parse (SyntaxError). Mock the new imports instead.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

add-to-poc type: feature Pull requests that introduces new feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant