feat(sidebar): add SidebarRail collapsed icon navigation rail#40558
feat(sidebar): add SidebarRail collapsed icon navigation rail#40558ggazzo wants to merge 8 commits into
Conversation
|
Looks like this PR is not ready to merge, because of the following issues:
Please fix the issues and try again If you have any trouble, please check the PR guidelines |
|
|
Note Reviews pausedIt 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 Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
📜 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)
🧰 Additional context used📓 Path-based instructions (1)**/*.{ts,tsx,js}📄 CodeRabbit inference engine (.cursor/rules/playwright.mdc)
Files:
🧠 Learnings (15)📚 Learning: 2025-11-24T17:08:17.065ZApplied to files:
📚 Learning: 2025-12-16T17:29:45.163ZApplied to files:
📚 Learning: 2026-04-17T18:33:27.211ZApplied to files:
📚 Learning: 2026-02-24T19:36:55.089ZApplied to files:
📚 Learning: 2025-11-24T17:08:17.065ZApplied to files:
📚 Learning: 2025-11-24T17:08:17.065ZApplied to files:
📚 Learning: 2025-12-10T21:00:54.909ZApplied to files:
📚 Learning: 2025-11-24T17:08:17.065ZApplied to files:
📚 Learning: 2025-11-24T17:08:17.065ZApplied to files:
📚 Learning: 2025-11-24T17:08:17.065ZApplied to files:
📚 Learning: 2026-04-13T16:40:55.864ZApplied to files:
📚 Learning: 2025-11-24T17:08:17.065ZApplied to files:
📚 Learning: 2026-03-06T18:10:15.268ZApplied to files:
📚 Learning: 2026-03-27T14:52:56.865ZApplied to files:
📚 Learning: 2026-05-06T12:21:44.083ZApplied to files:
🔇 Additional comments (1)
WalkthroughAdds 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. ChangesSidebarRail Navigation Feature
Media Call Widget Inline Mode
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Suggested reviewers
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ 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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
apps/meteor/client/sidebar/SidebarRail/SidebarRailInbox.tsx (1)
13-13: 💤 Low valueConsider narrowing the type assertion.
The type assertion
as string | number | null | undefinedis 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
📒 Files selected for processing (15)
apps/meteor/.storybook/main.tsapps/meteor/.storybook/mocks/meteor.jsapps/meteor/.storybook/mocks/sdk.tsapps/meteor/client/components/HorizontalDivider/HorizontalDivider.tsxapps/meteor/client/components/HorizontalDivider/index.tsapps/meteor/client/components/ImageGallery/ImageGallery.tsxapps/meteor/client/sidebar/SidebarRail/SidebarRail.stories.tsxapps/meteor/client/sidebar/SidebarRail/SidebarRail.tsxapps/meteor/client/sidebar/SidebarRail/SidebarRailCreateNew.tsxapps/meteor/client/sidebar/SidebarRail/SidebarRailDivider.tsxapps/meteor/client/sidebar/SidebarRail/SidebarRailInbox.tsxapps/meteor/client/sidebar/SidebarRail/SidebarRailLoginPage.tsxapps/meteor/client/sidebar/SidebarRail/SidebarRailPhone.tsxapps/meteor/client/sidebar/SidebarRail/index.tspackages/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.tsapps/meteor/client/sidebar/SidebarRail/index.tsapps/meteor/client/components/HorizontalDivider/HorizontalDivider.tsxapps/meteor/client/sidebar/SidebarRail/SidebarRailLoginPage.tsxapps/meteor/client/sidebar/SidebarRail/SidebarRailDivider.tsxapps/meteor/client/sidebar/SidebarRail/SidebarRail.stories.tsxapps/meteor/client/sidebar/SidebarRail/SidebarRailPhone.tsxapps/meteor/client/sidebar/SidebarRail/SidebarRailInbox.tsxapps/meteor/client/components/ImageGallery/ImageGallery.tsxapps/meteor/client/sidebar/SidebarRail/SidebarRail.tsxapps/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.tsapps/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.tsapps/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.tsapps/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.tsapps/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.tsapps/meteor/client/sidebar/SidebarRail/index.tsapps/meteor/client/components/HorizontalDivider/HorizontalDivider.tsxapps/meteor/client/sidebar/SidebarRail/SidebarRailLoginPage.tsxapps/meteor/client/sidebar/SidebarRail/SidebarRailDivider.tsxapps/meteor/client/sidebar/SidebarRail/SidebarRail.stories.tsxapps/meteor/client/sidebar/SidebarRail/SidebarRailPhone.tsxapps/meteor/client/sidebar/SidebarRail/SidebarRailInbox.tsxapps/meteor/client/components/ImageGallery/ImageGallery.tsxapps/meteor/client/sidebar/SidebarRail/SidebarRail.tsxapps/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.tsxapps/meteor/client/sidebar/SidebarRail/SidebarRailLoginPage.tsxapps/meteor/client/sidebar/SidebarRail/SidebarRailDivider.tsxapps/meteor/client/sidebar/SidebarRail/SidebarRail.stories.tsxapps/meteor/client/sidebar/SidebarRail/SidebarRailPhone.tsxapps/meteor/client/sidebar/SidebarRail/SidebarRailInbox.tsxapps/meteor/client/components/ImageGallery/ImageGallery.tsxapps/meteor/client/sidebar/SidebarRail/SidebarRail.tsxapps/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 importsDDPCommonas a named export and accessesparseDDPandstringifyDDPas 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!
| const handleClick = useEffectEvent(() => { | ||
| router.navigate('/home'); | ||
| }); |
There was a problem hiding this comment.
🧩 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 -C2Repository: 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 -30Repository: 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' -C1Repository: 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.
There was a problem hiding this comment.
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
bc28b3f to
f1a6775
Compare
be3f89b to
19c3b53
Compare
Codecov Report❌ Patch coverage is Additional details and impacted files@@ 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
Flags with carried forward coverage won't be shown. Click here to find out more. 🚀 New features to boost your workflow:
|
dd4df14 to
de36ac0
Compare
`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.
8f6b452 to
2c2f020
Compare
8fb05f6 to
b0cc412
Compare
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.
b0cc412 to
daae7a0
Compare
There was a problem hiding this comment.
🧹 Nitpick comments (3)
apps/meteor/client/sidebar/SidebarRail/SidebarRailPhone.tsx (1)
16-20: ⚡ Quick winExtract the call-history route contract into a shared helper.
'/call-history'and its matching logic are duplicated here, inSidebarRailCallRouteSync, and inSecondaryPanel. 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 winRemove 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 winRemove 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
⛔ Files ignored due to path filters (2)
packages/ui-voip/src/components/Widget/__snapshots__/Widget.spec.tsx.snapis excluded by!**/*.snappackages/ui-voip/src/views/MediaCallWidget/__snapshots__/MediaCallWidget.spec.tsx.snapis excluded by!**/*.snap
📒 Files selected for processing (28)
apps/meteor/.storybook/mocks/meteor.jsapps/meteor/client/components/HorizontalDivider/HorizontalDivider.tsxapps/meteor/client/components/HorizontalDivider/index.tsapps/meteor/client/sidebar/SidebarRail/SidebarRail.stories.tsxapps/meteor/client/sidebar/SidebarRail/SidebarRail.tsxapps/meteor/client/sidebar/SidebarRail/SidebarRailCallPanel.tsxapps/meteor/client/sidebar/SidebarRail/SidebarRailCallRouteSync.tsxapps/meteor/client/sidebar/SidebarRail/SidebarRailCreateNew.tsxapps/meteor/client/sidebar/SidebarRail/SidebarRailDivider.tsxapps/meteor/client/sidebar/SidebarRail/SidebarRailHeader.tsxapps/meteor/client/sidebar/SidebarRail/SidebarRailLoginPage.tsxapps/meteor/client/sidebar/SidebarRail/SidebarRailPhone.tsxapps/meteor/client/sidebar/SidebarRail/index.tsapps/meteor/client/views/root/MainLayout/LayoutWithSidebar.tsxapps/meteor/client/views/root/MainLayout/MainLayoutStyleTags.tsxapps/meteor/client/views/root/MainLayout/SecondaryPanel.tsxapps/meteor/client/views/root/MainLayout/sidebarRailFlag.tspackages/i18n/src/locales/en.i18n.jsonpackages/ui-voip/src/components/MediaCallWidgetSlot.tsxpackages/ui-voip/src/components/Widget/Widget.tsxpackages/ui-voip/src/components/Widget/WidgetHandle.tsxpackages/ui-voip/src/components/index.tspackages/ui-voip/src/context/MediaCallWidgetSlotContext.tspackages/ui-voip/src/index.tspackages/ui-voip/src/providers/MediaCallProvider.tsxpackages/ui-voip/src/providers/MediaCallViewProvider.tsxpackages/ui-voip/src/providers/useMediaSession.tspackages/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.tsxapps/meteor/client/views/root/MainLayout/SecondaryPanel.tsxpackages/ui-voip/src/components/MediaCallWidgetSlot.tsxapps/meteor/client/sidebar/SidebarRail/SidebarRailCallRouteSync.tsxpackages/ui-voip/src/views/MediaCallWidget/NewCall.tsxpackages/ui-voip/src/components/Widget/Widget.tsxpackages/ui-voip/src/providers/MediaCallViewProvider.tsxpackages/ui-voip/src/providers/useMediaSession.tspackages/ui-voip/src/components/Widget/WidgetHandle.tsxapps/meteor/client/sidebar/SidebarRail/SidebarRailPhone.tsxapps/meteor/client/views/root/MainLayout/LayoutWithSidebar.tsxpackages/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.tsxapps/meteor/client/views/root/MainLayout/SecondaryPanel.tsxpackages/ui-voip/src/components/MediaCallWidgetSlot.tsxapps/meteor/client/sidebar/SidebarRail/SidebarRailCallRouteSync.tsxpackages/ui-voip/src/views/MediaCallWidget/NewCall.tsxpackages/ui-voip/src/components/Widget/Widget.tsxpackages/ui-voip/src/providers/MediaCallViewProvider.tsxpackages/ui-voip/src/components/Widget/WidgetHandle.tsxapps/meteor/client/sidebar/SidebarRail/SidebarRailPhone.tsxapps/meteor/client/views/root/MainLayout/LayoutWithSidebar.tsxpackages/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.tsxapps/meteor/client/views/root/MainLayout/SecondaryPanel.tsxpackages/ui-voip/src/components/MediaCallWidgetSlot.tsxapps/meteor/client/sidebar/SidebarRail/SidebarRailCallRouteSync.tsxpackages/ui-voip/src/views/MediaCallWidget/NewCall.tsxpackages/ui-voip/src/components/Widget/Widget.tsxpackages/ui-voip/src/providers/MediaCallViewProvider.tsxpackages/ui-voip/src/providers/useMediaSession.tspackages/ui-voip/src/components/Widget/WidgetHandle.tsxapps/meteor/client/sidebar/SidebarRail/SidebarRailPhone.tsxapps/meteor/client/views/root/MainLayout/LayoutWithSidebar.tsxpackages/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.tsxpackages/ui-voip/src/views/MediaCallWidget/NewCall.tsxpackages/ui-voip/src/components/Widget/Widget.tsxpackages/ui-voip/src/providers/MediaCallViewProvider.tsxpackages/ui-voip/src/components/Widget/WidgetHandle.tsxpackages/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.tsxpackages/ui-voip/src/views/MediaCallWidget/NewCall.tsxpackages/ui-voip/src/components/Widget/Widget.tsxpackages/ui-voip/src/providers/MediaCallViewProvider.tsxpackages/ui-voip/src/components/Widget/WidgetHandle.tsxpackages/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)
There was a problem hiding this comment.
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} /> |
There was a problem hiding this comment.
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; |
There was a problem hiding this comment.
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) { |
There was a problem hiding this comment.
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, |
There was a problem hiding this comment.
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().
There was a problem hiding this comment.
🧹 Nitpick comments (1)
apps/meteor/client/views/root/MainLayout/sidebarRailFlag.ts (1)
7-17: 💤 Low valueConsider 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
📒 Files selected for processing (2)
apps/meteor/client/views/root/MainLayout/LayoutWithSidebar.tsxapps/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!
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.
Summary
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 viauseMediaCallAction, icon-only Login fallback, horizontal Divider with rail tokens).HorizontalDividerwrapper around FuselageDividerso callers can express horizontal-only intent at the type level.develop: switchesImageGalleryto Swiper's publicexportspaths, expands the meteor mock to cover the SDKsubscribe/callAsyncsurface, and adds aNormalModuleReplacementPluginthat swaps the liveSDKClientfor a no-op mock so stories that touch hooks likeuseStatusItemsoruseUnreadrender without a DDP connection.Test plan
cd apps/meteor && CI=1 yarn storybookopens cleanly without webpack build failuresSidebar/SidebarRail/Anonymousrenders the rail with the icon-only login buttonSidebar/SidebarRail/LoggedInrenders the rail with the user avatar (noMeteor.connection.subscriberuntime error)Sidebar/SidebarRail/WithUnreadBadgeshows the danger badge on the inbox itemSidebar/SidebarRail/WithCreatePermissionsshows the create-new menu populatedyarn tsc --noEmit --skipLibCheckpasses for the new filesSummary by CodeRabbit
New Features
Documentation
Localization
Chores