Skip to content

[WEB-4328] feat: sidebar revamp#7217

Merged
sriramveeraghanta merged 56 commits intopreviewfrom
feat-sidebar-revamp
Jul 8, 2025
Merged

[WEB-4328] feat: sidebar revamp#7217
sriramveeraghanta merged 56 commits intopreviewfrom
feat-sidebar-revamp

Conversation

@anmolsinghbhatia
Copy link
Collaborator

@anmolsinghbhatia anmolsinghbhatia commented Jun 16, 2025

Summary

  • Revamped the layout with a canvas-like design for improved usability and aesthetics.
  • Redesigned the App Sidebar with better structure and enhanced UX.
  • App Sidebar changes include:
    • Resizable Sidebar: Users can now adjust the sidebar width for better flexibility.
    • Enhanced Collapsed State: Improved behavior and visual consistency when the sidebar is collapsed.
    • Peek View on Hover: Peek view is triggered by hovering near the left edge when the sidebar is collapsed, offering quick access without full expansion.
    • UX & Micro-Interaction Enhancements: Refined animations, transitions, and interactions for a more polished user experience.
  • Added micro-interactions and animations across components.
  • Corrected spacing and padding inconsistencies.
  • Performed code refactoring for improved maintainability and readability.

Type of Change

  • Feature
  • Improvement
  • Code refactoring

Reference

[WEB-4328]

Summary by CodeRabbit

  • New Features

    • Introduced a resizable and collapsible sidebar with peek-on-hover functionality.
    • Added new icons (AI, Plane, Wiki) for enhanced visual elements.
    • Sidebar now supports extended panels with improved outside click handling via new wrapper components.
    • Workspace and settings layouts updated with rounded borders and modernized containers.
    • Added new wrapper components to improve sidebar state and outside click handling.
  • Improvements

    • Sidebar UI simplified: always shows labels and actions, removing collapsed mode variations.
    • Enhanced accessibility and consistency across sidebar navigation, favorites, and project lists.
    • Notification and user menus now offer unified, streamlined interactions.
    • Sidebar state (open, dropdowns, peek) is now managed more robustly for better user experience.
    • Sidebar toggle buttons and menus updated for clearer interaction and styling consistency.
  • Bug Fixes

    • Corrected navigation links for project menu items.
  • Chores

    • Added and exported new constants and components for sidebar and icon management.
    • Refactored theme store to use clearer sidebar state naming and added new sidebar-related observables.
    • Extended public API exports for sidebar and workspace components.

@anmolsinghbhatia anmolsinghbhatia self-assigned this Jun 16, 2025
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jun 16, 2025

Walkthrough

This update introduces a new resizable, collapsible, and peekable sidebar architecture, refactoring the sidebar's state management and UI. It removes all conditional rendering based on sidebar collapse, centralizes sidebar state in the theme store, and adds new components for sidebar resizing and extended sidebar handling. Tooltips and mobile-specific sidebar behaviors are removed.

Changes

Files/Groups Change Summary
web/app/(all)/[workspaceSlug]/(projects)/_sidebar.tsx, web/core/components/sidebar/resizable-sidebar.tsx, web/app/(all)/[workspaceSlug]/(projects)/extended-sidebar-wrapper.tsx Added new sidebar components: ProjectAppSidebar, ResizableSidebar, and ExtendedSidebarWrapper for resizable, collapsible, and peekable sidebar functionality.
web/core/store/theme.store.ts Theme store extended with new observables and actions for sidebar dropdown, peek, and extended sidebar open states. Naming updated from "collapsed" to "opened".
web/app/(all)/[workspaceSlug]/(projects)/extended-project-sidebar.tsx, web/app/(all)/[workspaceSlug]/(projects)/extended-sidebar.tsx Refactored extended sidebar logic to use new wrapper component and updated state management.
web/app/(all)/[workspaceSlug]/(projects)/sidebar.tsx Simplified sidebar JSX structure, removed collapse-dependent logic, and eliminated extended sidebar components from render.
web/app/(all)/[workspaceSlug]/(projects)/layout.tsx Switched sidebar import to new ProjectAppSidebar component.
web/app/(all)/[workspaceSlug]/(projects)/header.tsx, web/core/components/core/app-header.tsx Wrapped headers with MobX observer for reactive updates.
web/core/components/sidebar/index.ts Exported new ResizableSidebar component.
web/core/components/sidebar/sidebar-menu-hamburger-toggle.tsx Refactored hamburger toggle event handling and CSS classes.
web/core/components/workspace-notifications/notification-app-sidebar-option.tsx Removed isSidebarCollapsed prop and related conditional rendering.
web/core/components/workspace-notifications/sidebar/header/root.tsx Sidebar hamburger toggle now only shows when sidebar is collapsed.
web/core/components/workspace/sidebar/dropdown.tsx Refactored dropdown state management, synchronizing open state with theme store.
web/core/components/workspace/sidebar/favorites/favorite-folder.tsx, web/core/components/workspace/sidebar/favorites/favorite-items/common/favorite-item-title.tsx, web/core/components/workspace/sidebar/favorites/favorite-items/common/favorite-item-wrapper.tsx, web/core/components/workspace/sidebar/favorites/favorite-items/root.tsx, web/core/components/workspace/sidebar/favorites/favorites-menu.tsx Removed all sidebar collapse state and related conditional rendering in favorites UI.
web/core/components/workspace/sidebar/help-section.tsx Simplified styling, added sidebar peek state handling, and unified menu placement.
web/core/components/workspace/sidebar/project-navigation.tsx, web/ce/components/sidebar/project-navigation-root.tsx Removed sidebar collapse state and tooltips from project navigation; simplified props.
web/core/components/workspace/sidebar/projects-list-item.tsx, web/core/components/workspace/sidebar/projects-list.tsx Removed collapse-dependent logic, unified project list UI, and improved menu interaction.
web/core/components/workspace/sidebar/quick-actions.tsx Removed collapse-dependent styling and always renders label.
web/core/components/workspace/sidebar/sidebar-menu-items.tsx Removed collapse state, simplified toggle logic and styling.
web/core/components/workspace/sidebar/user-menu-item.tsx, web/core/components/workspace/sidebar/user-menu.tsx Removed tooltips, collapse state, and mobile detection; always renders full label.
web/core/components/workspace/sidebar/workspace-menu-header.tsx, web/core/components/workspace/sidebar/workspace-menu.tsx Removed collapse state, always renders content, and simplified styling.
web/core/components/workspace/sidebar/workspace-menu-item.tsx Removed tooltips, collapse state, and mobile detection; always renders full label and badge.
web/ce/components/workspace/sidebar/app-search.tsx, web/ce/components/workspace/sidebar/extended-sidebar-item.tsx Removed collapse state and related conditional logic; minor cleanup.
packages/constants/src/sidebar.ts, packages/constants/src/index.ts Added new sidebar width constant and exported sidebar module.
packages/ui/src/icons/ai-icon.tsx, packages/ui/src/icons/plane-icon.tsx, packages/ui/src/icons/wiki-icon.tsx, packages/ui/src/icons/index.ts Added new icon components and exported them.
web/app/(all)/[workspaceSlug]/layout.tsx, web/ce/components/workspace/content-wrapper.tsx, web/ce/components/workspace/app-switcher.tsx, web/ce/components/workspace/index.ts Added new workspace layout and content wrapper components and exports.
web/app/(all)/profile/layout.tsx, web/app/(all)/[workspaceSlug]/(settings)/layout.tsx Added rounded borders and container styling to layout wrappers.
web/ce/components/app-rail/index.ts, web/ce/components/app-rail/root.tsx Added new app rail components with empty root component.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant ProjectAppSidebar
    participant ResizableSidebar
    participant ThemeStore

    User->>ProjectAppSidebar: Interact (resize/collapse/peek)
    ProjectAppSidebar->>ThemeStore: Read/write sidebar state
    ProjectAppSidebar->>ResizableSidebar: Pass state & handlers
    ResizableSidebar->>ThemeStore: Notify on collapse/peek/resize
    ResizableSidebar-->>User: Update UI (resize/peek/collapse)
Loading
sequenceDiagram
    participant User
    participant ExtendedSidebarWrapper
    participant ThemeStore

    User->>ExtendedSidebarWrapper: Click outside sidebar
    ExtendedSidebarWrapper->>ThemeStore: Update isExtendedSidebarOpened = false
    ExtendedSidebarWrapper-->>User: Hide extended sidebar
Loading

Suggested labels

✨feature, 🧹chore, ready_to_merge

Suggested reviewers

  • vamsikrishnamathala
  • sriramveeraghanta
  • prateekshourya29

Poem

🐇
The sidebar now resizes, collapses, and peeks,
With state all in one place—no more old mystiques!
Tooltips have hopped away,
Extended panels here to stay,
A tidy new warren for sidebars—oh, what tweaks!
🥕


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ee16f1a and dc51f84.

📒 Files selected for processing (1)
  • web/core/hooks/use-workspace-paths.ts (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • web/core/hooks/use-workspace-paths.ts
✨ Finishing Touches
  • 📝 Generate Docstrings

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@makeplane
Copy link

makeplane bot commented Jun 16, 2025

Pull Request Linked with Plane Work Items

Comment Automatically Generated by Plane

@anmolsinghbhatia anmolsinghbhatia changed the title [ WEB-4328] feat: sidebar revamp [WEB-4328] feat: sidebar revamp Jun 18, 2025
@anmolsinghbhatia anmolsinghbhatia marked this pull request as ready for review June 18, 2025 13:03
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 7

🔭 Outside diff range comments (2)
web/core/components/workspace/sidebar/favorites/favorite-items/root.tsx (1)

60-128: Effect dependency set can cause unnecessary re-subscriptions

elementRef?.current is always the same reference for the component lifetime; including it re-runs the DnD registration on every render even when nothing relevant changed.

-}, [elementRef?.current, isDragging, isLastChild, favorite.id]);
+// elementRef.current is stable; handleDrop/parentId should be tracked instead
+}, [isLastChild, favorite.id, handleDrop, parentId]);

This avoids needless combine() churn while ensuring closures stay fresh.

web/app/(all)/[workspaceSlug]/(projects)/sidebar.tsx (1)

27-42: Outside-click detector no longer works – ref is never attached

useOutsideClickDetector(ref, …) relies on the DOM node stored in ref,
but after the refactor the root element with ref={ref} was removed.
Result: sidebar can’t auto-close on outside clicks → broken UX on mobile.

Add ref={ref} to the top-level wrapper (or another encompassing element).

-<div className="px-4">
+<div ref={ref} className="px-4">

Don’t forget to export the correct typing if you wrap the sidebar in another component.

🧹 Nitpick comments (25)
web/core/components/sidebar/index.ts (1)

1-2: Wildcard re-exports may hide name collisions

Using export * from multiple modules can silently mask duplicate symbol names (e.g., two modules exposing SidebarContext). TypeScript will surface an error only if the symbols collide and are imported downstream with import { … }.

If both sidebar-navigation and resizable-sidebar export identically named helpers, the later one wins at runtime. Consider re-exporting explicitly to make any overlaps obvious:

-export * from "./sidebar-navigation";
-export * from "./resizable-sidebar";
+export { SidebarNavigation } from "./sidebar-navigation";
+export { ResizableSidebar }  from "./resizable-sidebar";
web/ce/components/workspace/sidebar/app-search.tsx (1)

17-17: Minor accessibility enhancement

While the unconditional border fixes the visual jump when the sidebar collapses, the button still lacks a focus-visible:ring for keyboard users.

-className="flex-shrink-0 size-8 aspect-square grid place-items-center rounded hover:bg-custom-sidebar-background-90 outline-none border-[0.5px] border-custom-sidebar-border-300"
+className="flex-shrink-0 size-8 aspect-square grid place-items-center rounded hover:bg-custom-sidebar-background-90 focus-visible:ring-2 focus-visible:ring-primary outline-none border-[0.5px] border-custom-sidebar-border-300"
web/core/components/workspace-notifications/notification-app-sidebar-option.tsx (1)

37-38: String concatenation produces a leading space

The template literal \@ ${count}`yields"@ 12"` (double space). Use trimming or drop the trailing space:

-<CountChip count={`${isMentionsEnabled ? `@ ` : ``}${getNumberCount(totalNotifications)}`} />
+<CountChip count={`${isMentionsEnabled ? "@" : ""}${getNumberCount(totalNotifications)}`} />
web/core/components/workspace/sidebar/workspace-menu-header.tsx (1)

34-37: Replace the any cast with a proper union to avoid losing type-safety

The as any cast here bypasses the compiler and can hide real permission-checking bugs.
Create an explicit union or overload for allowPermissions instead of falling back to any.

-const isAdmin = allowPermissions([EUserWorkspaceRoles.ADMIN] as any, EUserPermissionsLevel.WORKSPACE);
+const isAdmin = allowPermissions(
+  [EUserWorkspaceRoles.ADMIN] as readonly EUserWorkspaceRoles[],
+  EUserPermissionsLevel.WORKSPACE
+);

This retains strict typing while satisfying the function signature.

web/core/components/workspace/sidebar/workspace-menu.tsx (1)

3-3: Unnecessary React import with the new JSX runtime

Since the project uses the automatic JSX runtime, importing React solely for JSX transform is redundant.

-import React from "react";

Removing unused imports cleans up the bundle and avoids ESLint “no-unused-vars” warnings.

web/core/components/workspace/sidebar/favorites/favorite-items/common/favorite-item-wrapper.tsx (1)

13-27: Remove redundant React fragment & duplicate group class

  1. The <>...</> wrapper around the single <div> adds an unnecessary node in the React tree.
  2. "group/project-item" already applies the group variant – the extra "group" is therefore superfluous.
   return (
-    <>
-      <div
+    <div
         ref={elementRef}
         className={cn(
           "group/project-item cursor-pointer relative group flex items-center justify-between w-full gap-1.5 rounded px-2 py-1 outline-none text-custom-sidebar-text-200 hover:bg-custom-sidebar-background-90 active:bg-custom-sidebar-background-90",
           {
             "bg-custom-sidebar-background-90": isMenuActive,
           }
         )}
       >
         {children}
       </div>
-    </>
   );
web/core/components/core/sidebar/sidebar-menu-hamburger-toggle.tsx (1)

20-22: Consider typing the event generic

const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {  }

Typing the target element helps editors offer better intellisense and prevents accidental misuse.

web/app/(all)/[workspaceSlug]/(projects)/header.tsx (1)

3-4: Prefer mobx-react-lite over mobx-react

mobx-react re-exports the lite API but also bundles legacy class-component helpers, increasing bundle size ~3-4 kB gzipped. Switching imports keeps tree-shaking tight:

-import { observer } from "mobx-react";
+import { observer } from "mobx-react-lite";
web/core/components/workspace/sidebar/favorites/favorite-items/root.tsx (1)

133-144: Pass stable callbacks to child to avoid re-render loops

handleQuickAction is recreated each render, triggering unnecessary updates in FavoriteItemQuickAction.
Wrap with useCallback:

-const handleQuickAction = (value: boolean) => setIsMenuActive(value);
+const handleQuickAction = useCallback(
+  (value: boolean) => setIsMenuActive(value),
+  []
+);
web/core/components/core/app-header.tsx (1)

4-5: Same note: switch to the lean mobx-react-lite package

-import { observer } from "mobx-react";
+import { observer } from "mobx-react-lite";
web/core/components/workspace/sidebar/quick-actions.tsx (2)

24-58: isDraftButtonOpen state & hover handlers are now dead code

After the collapse-aware UI was removed, nothing references isDraftButtonOpen.
Keeping the state, ref and mouse-over logic adds needless complexity and cognitive load.

-  const [isDraftButtonOpen, setIsDraftButtonOpen] = useState(false);
-  // ...
-  const handleMouseEnter = () => { … setIsDraftButtonOpen(true); };
-  const handleMouseLeave = () => { … setIsDraftButtonOpen(false); };

You can drop the state, the handlers, the timeoutRef, and the onMouseEnter/onMouseLeave props on the <button> without changing behaviour.
Less code → easier maintenance.


76-84: Superfluous empty object passed to cn

cn("flex …", {}) yields the same class string as cn("flex …").
Remove the empty object to avoid noise.

-<div className={cn("flex items-center justify-between gap-1 cursor-pointer", {})}>
+<div className={cn("flex items-center justify-between gap-1 cursor-pointer")}>
web/app/(all)/[workspaceSlug]/(projects)/extended-sidebar.tsx (1)

98-104: Double-negation of a boolean

isExtendedSidebarOpened is already a boolean.
{!!isExtendedSidebarOpened} is redundant and obscures intent.

-      isExtendedSidebarOpened={!!isExtendedSidebarOpened}
+      isExtendedSidebarOpened={isExtendedSidebarOpened}
web/app/(all)/[workspaceSlug]/(projects)/sidebar.tsx (1)

61-69: Consider making scroll container focusable for keyboard users

The new scroll container has overflow-y-auto but no focus ring.
Adding tabIndex={0} lets keyboard users scroll it with arrow keys/PageUp/Down.

-<div className="flex flex-col gap-1 … vertical-scrollbar px-4">
+<div tabIndex={0} className="flex flex-col gap-1 … vertical-scrollbar px-4">
web/core/components/workspace/sidebar/projects-list.tsx (1)

67-71: Use forEach (or reduce) instead of map for side-effects

Array.prototype.map is meant to transform arrays and return a new one.
Here it’s used only for its side-effect of pushing elements into joinedProjectsList, which is slightly misleading for future readers.

-joinedProjects.map((projectId) => {
+joinedProjects.forEach((projectId) => {
web/app/(all)/[workspaceSlug]/(projects)/_sidebar.tsx (1)

46-50: Drop the redundant React fragment

The fragment adds an extra node (and Biome flags it). Pass the component directly:

-        extendedSidebar={
-          <>
-            <ExtendedAppSidebar />
-          </>
-        }
+        extendedSidebar={<ExtendedAppSidebar />}
web/ce/components/workspace/sidebar/sidebar-item.tsx (1)

32-39: Minor readability: early-return guard can exit sooner

You already close the extended sidebar when it’s open.
Consider flipping the condition for early exit to avoid the nested if:

-    if (window.innerWidth < 768) {
-      toggleSidebar();
-    }
-    if (isExtendedSidebarOpened) toggleExtendedSidebar(false);
+    if (window.innerWidth < 768) {
+      toggleSidebar();
+    }
+    if (isExtendedSidebarOpened) {
+      toggleExtendedSidebar(false);
+    }
web/core/components/workspace/sidebar/sidebar-menu-items.tsx (1)

63-64: Hard-coded “More” string bypasses i18n

Replace with a translation key to keep the UI localisable.

-          <span>More</span>
+          <span>{t("sidebar.more")}</span>
web/app/(all)/[workspaceSlug]/(projects)/extended-sidebar-wrapper.tsx (1)

24-24: Consider extracting the localStorage key as a constant.

The hardcoded string "sidebarWidth" should be defined as a constant to improve maintainability and prevent typos.

Add a constant at the top of the file:

+const SIDEBAR_WIDTH_STORAGE_KEY = "sidebarWidth";
+
 export const ExtendedSidebarWrapper: FC<Props> = observer((props) => {

Then update line 24:

-  const { storedValue } = useLocalStorage("sidebarWidth", 250);
+  const { storedValue } = useLocalStorage(SIDEBAR_WIDTH_STORAGE_KEY, 250);
web/core/components/sidebar/resizable-sidebar.tsx (1)

214-219: Consider adding keyboard accessibility for sidebar toggle.

The resize handle supports double-click to toggle the sidebar, but lacks keyboard accessibility.

Consider making the resize handle keyboard accessible:

           <div
             className={cn(
               "transition-all duration-200 cursor-ew-resize absolute h-full w-1 z-[20]",
               !isResizing && "hover:bg-custom-background-90",
               isResizing && "w-1.5 bg-custom-background-80",
               "top-0 right-0"
             )}
             onDoubleClick={() => toggleCollapsed()}
             onMouseDown={startResizing}
+            onKeyDown={(e) => {
+              if (e.key === 'Enter' || e.key === ' ') {
+                e.preventDefault();
+                toggleCollapsed();
+              }
+            }}
+            tabIndex={0}
             role="separator"
             aria-label="Resize sidebar"
           />

Also applies to: 275-280

web/core/components/workspace/sidebar/help-section.tsx (1)

154-160: Hard-coded tooltip breaks i18n consistency

"Expand" / "Hide" are user-visible strings but bypass useTranslation().
Please pass them through t() like the rest of the file to avoid untranslated UI.

web/core/components/workspace/sidebar/dropdown.tsx (1)

72-77: Missing dependency in useEffect

useEffect references toggleAnySidebarDropdown but omits it from the dependency array.
Add it (or wrap the store action in useCallback) to satisfy exhaustive-deps and avoid stale closure issues.

web/core/components/workspace/sidebar/projects-list-item.tsx (2)

193-196: Same dependency omission as above

toggleAnySidebarDropdown is used inside useEffect but not listed in the dependency array.
Add it or disable the lint rule explicitly.


282-283: Possible stale toggle

setIsMenuActive(!isMenuActive) relies on the stale value of isMenuActive.
Prefer the functional form to avoid race conditions:

- onClick={() => setIsMenuActive(!isMenuActive)}
+ onClick={() => setIsMenuActive((prev) => !prev)}
web/core/store/theme.store.ts (1)

32-37: Consider defaulting observable booleans to false

Initialising all sidebar flags to undefined forces downstream code to coerce three states (undefined | true | false).
Setting them to false simplifies logic and avoids accidental truthy/falsy bugs.

Also applies to: 73-80

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d65f0e2 and c2457a4.

📒 Files selected for processing (35)
  • web/app/(all)/[workspaceSlug]/(projects)/_sidebar.tsx (1 hunks)
  • web/app/(all)/[workspaceSlug]/(projects)/extended-project-sidebar.tsx (5 hunks)
  • web/app/(all)/[workspaceSlug]/(projects)/extended-sidebar-wrapper.tsx (1 hunks)
  • web/app/(all)/[workspaceSlug]/(projects)/extended-sidebar.tsx (3 hunks)
  • web/app/(all)/[workspaceSlug]/(projects)/header.tsx (3 hunks)
  • web/app/(all)/[workspaceSlug]/(projects)/layout.tsx (1 hunks)
  • web/app/(all)/[workspaceSlug]/(projects)/sidebar.tsx (1 hunks)
  • web/ce/components/sidebar/project-navigation-root.tsx (1 hunks)
  • web/ce/components/workspace/sidebar/app-search.tsx (1 hunks)
  • web/ce/components/workspace/sidebar/extended-sidebar-item.tsx (0 hunks)
  • web/ce/components/workspace/sidebar/sidebar-item.tsx (2 hunks)
  • web/core/components/core/app-header.tsx (1 hunks)
  • web/core/components/core/sidebar/sidebar-menu-hamburger-toggle.tsx (1 hunks)
  • web/core/components/sidebar/index.ts (1 hunks)
  • web/core/components/sidebar/resizable-sidebar.tsx (1 hunks)
  • web/core/components/workspace-notifications/notification-app-sidebar-option.tsx (1 hunks)
  • web/core/components/workspace-notifications/sidebar/header/root.tsx (2 hunks)
  • web/core/components/workspace/sidebar/dropdown.tsx (4 hunks)
  • web/core/components/workspace/sidebar/favorites/favorite-folder.tsx (2 hunks)
  • web/core/components/workspace/sidebar/favorites/favorite-items/common/favorite-item-title.tsx (1 hunks)
  • web/core/components/workspace/sidebar/favorites/favorite-items/common/favorite-item-wrapper.tsx (1 hunks)
  • web/core/components/workspace/sidebar/favorites/favorite-items/root.tsx (2 hunks)
  • web/core/components/workspace/sidebar/favorites/favorites-menu.tsx (3 hunks)
  • web/core/components/workspace/sidebar/help-section.tsx (4 hunks)
  • web/core/components/workspace/sidebar/project-navigation.tsx (3 hunks)
  • web/core/components/workspace/sidebar/projects-list-item.tsx (6 hunks)
  • web/core/components/workspace/sidebar/projects-list.tsx (5 hunks)
  • web/core/components/workspace/sidebar/quick-actions.tsx (3 hunks)
  • web/core/components/workspace/sidebar/sidebar-menu-items.tsx (2 hunks)
  • web/core/components/workspace/sidebar/user-menu-item.tsx (2 hunks)
  • web/core/components/workspace/sidebar/user-menu.tsx (2 hunks)
  • web/core/components/workspace/sidebar/workspace-menu-header.tsx (2 hunks)
  • web/core/components/workspace/sidebar/workspace-menu-item.tsx (2 hunks)
  • web/core/components/workspace/sidebar/workspace-menu.tsx (2 hunks)
  • web/core/store/theme.store.ts (6 hunks)
💤 Files with no reviewable changes (1)
  • web/ce/components/workspace/sidebar/extended-sidebar-item.tsx
🧰 Additional context used
🪛 Biome (1.9.4)
web/core/components/workspace/sidebar/project-navigation.tsx

[error] 175-175: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)

web/core/components/workspace/sidebar/favorites/favorites-menu.tsx

[error] 256-262: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)


[error] 264-271: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)

web/app/(all)/[workspaceSlug]/(projects)/_sidebar.tsx

[error] 47-49: Avoid using unnecessary Fragment.

A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment

(lint/complexity/noUselessFragments)

🔇 Additional comments (16)
web/app/(all)/[workspaceSlug]/(projects)/layout.tsx (1)

8-8: Double-check relative import & eager loading of the new sidebar

  1. The underscore-prefixed ./_sidebar file will be bundled eagerly because it’s imported at the top level of a client component.
    • Make sure you actually want the entire resizable-sidebar code in the first paint; if not, consider a dynamic import with React’s lazy() to defer ~35-40 KB of JS from the critical path.
  2. Confirm that all other modules have been migrated away from the old ./sidebar path to avoid duplicate side-bar instances in the bundle.

No code change required if eager loading is intentional.

Also applies to: 16-16

web/core/components/workspace/sidebar/user-menu.tsx (1)

55-55: Static container class looks good

Switching to a constant class string simplifies the component and avoids unnecessary re-renders. 👍

web/core/components/workspace-notifications/sidebar/header/root.tsx (1)

22-29: Hamburger toggle now hidden on mobile when sidebar is expanded – verify UX parity

SidebarHamburgerToggle is rendered only when sidebarCollapsed is true.
On small screens the sidebar often starts expanded; users will lose the toggle and be unable to collapse it.

Confirm that:

  1. sidebarCollapsed defaults to true on mobile, or
  2. SidebarHamburgerToggle has its own responsive visibility rules.

If neither is true, re-introduce a mobile-only wrapper:

-{sidebarCollapsed && <SidebarHamburgerToggle />}
+{(sidebarCollapsed || isMobile) && <SidebarHamburgerToggle />}
web/core/components/workspace/sidebar/workspace-menu.tsx (1)

69-70: Static padding may mis-align when nested inside the resizable sidebar

Previously the panel’s padding varied with sidebarCollapsed. After the refactor it’s hard-coded (mt-0.5).
Double-check spacing in both collapsed and peek states; you might need responsive utility classes or a parent flex gap instead.

web/core/components/workspace/sidebar/favorites/favorite-items/common/favorite-item-title.tsx (1)

26-30: Fixed 8-px left margin is no longer conditional – confirm visual alignment

className="ml-8" was previously applied only when the sidebar was collapsed to compensate for the hidden title.
Now the margin is always present, which may shift icons/text rightward in the full-width sidebar.

If the intent is to keep previous spacing, move the margin back behind a layout context check or drop it:

-<Tooltip ... className="ml-8">
+<Tooltip ...>
web/ce/components/sidebar/project-navigation-root.tsx (1)

13-15: ```shell
#!/bin/bash

Retry searching for any references to the obsolete prop across TS/TSX files

rg -n "isSidebarCollapsed" -g ".ts" -g ".tsx" --color never


</details>
<details>
<summary>web/core/components/core/sidebar/sidebar-menu-hamburger-toggle.tsx (1)</summary>

`11-15`: **👍 Explicit click handler with propagation cancelation looks solid**

The new `handleClick` prevents both bubbling & default behaviour, eliminating accidental container-click side-effects while still delegating the toggle logic to the store.  
No further action needed.

</details>
<details>
<summary>web/app/(all)/[workspaceSlug]/(projects)/header.tsx (1)</summary>

`31-32`: **Great: flex util cleans up spacing**

The extra `flex items-center gap-2` wrapper fixes breadcrumb mis-alignment on narrow widths. Nice touch.

</details>
<details>
<summary>web/core/components/core/app-header.tsx (1)</summary>

`25-26`: **Conditional render improves a11y & layout – good job**

Showing the hamburger only when the sidebar is collapsed keeps the DOM clean and prevents duplicate tab-stops on wide screens.

</details>
<details>
<summary>web/core/components/workspace/sidebar/user-menu-item.tsx (1)</summary>

`55-63`: **Refactor looks good**

Tooltip and collapse logic were cleanly removed; the component is now simpler and easier to reason about.

</details>
<details>
<summary>web/core/components/workspace/sidebar/workspace-menu-item.tsx (1)</summary>

`50-64`: **Simplification acknowledged**

Removal of tooltip/collapse branches makes the markup leaner while preserving behaviour.

</details>
<details>
<summary>web/app/(all)/[workspaceSlug]/(projects)/extended-sidebar-wrapper.tsx (1)</summary>

`33-43`: ```shell
#!/bin/bash
grep -R "storedValue" -n web/app
web/app/(all)/[workspaceSlug]/(projects)/extended-project-sidebar.tsx (1)

18-18: Clean refactor to use the ExtendedSidebarWrapper component.

The migration to use ExtendedSidebarWrapper simplifies the component by delegating container rendering and outside click detection logic. The state management integration with the theme store is well implemented.

Also applies to: 30-31, 77-77, 98-103

web/core/components/workspace/sidebar/favorites/favorite-folder.tsx (1)

169-257: Excellent simplification by removing sidebar collapse logic.

The removal of conditional rendering based on sidebar state improves code maintainability and provides a consistent user experience. The UI elements now render uniformly, making the component behavior more predictable.

web/core/components/workspace/sidebar/favorites/favorites-menu.tsx (1)

177-233: Well-implemented UI improvements.

The addition of the create folder button with proper tooltip and the simplified menu structure improves usability. The removal of sidebar collapse dependencies makes the component behavior more consistent.

web/core/components/sidebar/resizable-sidebar.tsx (1)

28-288: Well-architected resizable sidebar component.

The component demonstrates excellent separation of concerns, proper state management, and thoughtful UX considerations with the peek functionality. The accessibility attributes and cleanup logic are particularly well implemented.

@anmolsinghbhatia anmolsinghbhatia marked this pull request as ready for review July 1, 2025 14:46
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (1)
web/app/(all)/[workspaceSlug]/(projects)/_sidebar.tsx (1)

40-40: Use SIDEBAR_WIDTH constant instead of magic number

The hardcoded 250 should be replaced with the imported SIDEBAR_WIDTH constant for consistency.

-        defaultWidth={storedValue ?? 250}
+        defaultWidth={storedValue ?? SIDEBAR_WIDTH}
🧹 Nitpick comments (3)
web/app/(all)/[workspaceSlug]/(projects)/_sidebar.tsx (3)

31-31: Remove redundant variable assignment

The isAnyExtendedSidebarOpen variable is just aliasing isExtendedSidebarOpened without any transformation. Consider using the original variable directly or adding a meaningful comment if this alias serves a specific purpose.

-  // derived values
-  const isAnyExtendedSidebarOpen = isExtendedSidebarOpened;

Then update line 55:

-        isAnyExtendedSidebarExpanded={isAnyExtendedSidebarOpen}
+        isAnyExtendedSidebarExpanded={isExtendedSidebarOpened}

50-54: Remove unnecessary Fragment wrapper

The Fragment around ExtendedAppSidebar is redundant since it only contains a single child element.

-        extendedSidebar={
-          <>
-            <ExtendedAppSidebar />
-          </>
-        }
+        extendedSidebar={<ExtendedAppSidebar />}

15-62: Consider component complexity and prop drilling

The ProjectAppSidebar component is passing many props to ResizableSidebar (14 props). While functional, this indicates high coupling. Consider if some of these props could be:

  • Grouped into configuration objects
  • Handled internally by ResizableSidebar with sensible defaults
  • Moved to a context provider for shared sidebar state

The current implementation works well but may benefit from simplification in future iterations.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5b09c4b and 1d56fb7.

📒 Files selected for processing (19)
  • packages/constants/src/workspace.ts (1 hunks)
  • packages/ui/src/icons/ai-icon.tsx (1 hunks)
  • packages/ui/src/icons/index.ts (1 hunks)
  • packages/ui/src/icons/plane-icon.tsx (1 hunks)
  • packages/ui/src/icons/wiki-icon.tsx (1 hunks)
  • web/app/(all)/[workspaceSlug]/(projects)/_sidebar.tsx (1 hunks)
  • web/app/(all)/[workspaceSlug]/(projects)/extended-sidebar-wrapper.tsx (1 hunks)
  • web/app/(all)/[workspaceSlug]/(projects)/extended-sidebar.tsx (3 hunks)
  • web/app/(all)/[workspaceSlug]/(projects)/header.tsx (3 hunks)
  • web/app/(all)/[workspaceSlug]/(projects)/layout.tsx (1 hunks)
  • web/app/(all)/[workspaceSlug]/(projects)/sidebar.tsx (2 hunks)
  • web/app/(all)/[workspaceSlug]/(settings)/layout.tsx (1 hunks)
  • web/app/(all)/[workspaceSlug]/layout.tsx (1 hunks)
  • web/app/(all)/profile/layout.tsx (1 hunks)
  • web/ce/components/app-rail/index.ts (1 hunks)
  • web/ce/components/app-rail/root.tsx (1 hunks)
  • web/ce/components/workspace/app-switcher.tsx (1 hunks)
  • web/ce/components/workspace/content-wrapper.tsx (1 hunks)
  • web/ce/components/workspace/index.ts (1 hunks)
✅ Files skipped from review due to trivial changes (13)
  • web/app/(all)/profile/layout.tsx
  • web/ce/components/app-rail/root.tsx
  • web/ce/components/workspace/app-switcher.tsx
  • web/app/(all)/[workspaceSlug]/layout.tsx
  • web/ce/components/workspace/content-wrapper.tsx
  • packages/ui/src/icons/plane-icon.tsx
  • packages/ui/src/icons/index.ts
  • packages/ui/src/icons/wiki-icon.tsx
  • packages/constants/src/workspace.ts
  • web/ce/components/workspace/index.ts
  • web/app/(all)/[workspaceSlug]/(settings)/layout.tsx
  • packages/ui/src/icons/ai-icon.tsx
  • web/ce/components/app-rail/index.ts
🚧 Files skipped from review as they are similar to previous changes (4)
  • web/app/(all)/[workspaceSlug]/(projects)/layout.tsx
  • web/app/(all)/[workspaceSlug]/(projects)/extended-sidebar.tsx
  • web/app/(all)/[workspaceSlug]/(projects)/header.tsx
  • web/app/(all)/[workspaceSlug]/(projects)/sidebar.tsx
🧰 Additional context used
🧠 Learnings (1)
web/app/(all)/[workspaceSlug]/(projects)/_sidebar.tsx (1)
Learnt from: vamsikrishnamathala
PR: makeplane/plane#7061
File: web/core/components/workspace-notifications/root.tsx:18-18
Timestamp: 2025-05-14T13:16:23.323Z
Learning: In the Plane project codebase, the path alias `@/plane-web` resolves to the `ce` directory, making imports like `@/plane-web/hooks/use-notification-preview` correctly resolve to files in `web/ce/hooks/`.
🪛 Biome (1.9.4)
web/app/(all)/[workspaceSlug]/(projects)/_sidebar.tsx

[error] 51-53: Avoid using unnecessary Fragment.

A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment

(lint/complexity/noUselessFragments)

🔇 Additional comments (3)
web/app/(all)/[workspaceSlug]/(projects)/extended-sidebar-wrapper.tsx (3)

1-11: LGTM: Clean imports and dependency management

The imports are well-organized and the custom hook integration for outside click detection is appropriate for this wrapper component.


20-25: LGTM: Proper MobX integration and hook usage

The component correctly uses the observer wrapper for reactivity and integrates the custom outside click detection hook appropriately.


28-44: LGTM: Well-implemented sidebar container with smooth animations

The sidebar container implementation is solid with:

  • Proper conditional styling based on open state
  • Smooth transform animations for show/hide
  • Dynamic positioning based on stored sidebar width
  • Appropriate z-index and styling classes

The animation approach using transform and opacity provides good performance compared to changing layout properties.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
packages/constants/src/sidebar.ts (1)

1-2: Good practice using centralized constants, but consider responsive design.

The centralized constants approach is excellent for maintainability and consistency across components. The 50px difference between default and extended sidebar widths provides a reasonable visual distinction.

However, consider whether fixed pixel values are optimal for responsive design. For smaller screens or mobile devices, these widths might be too large and could negatively impact usability.

Consider making these responsive or configurable:

-export const SIDEBAR_WIDTH = 250;
-export const EXTENDED_SIDEBAR_WIDTH = 300;
+export const SIDEBAR_WIDTH = {
+  DESKTOP: 250,
+  TABLET: 200,
+  MOBILE: 280 // Could be full width on mobile
+};
+export const EXTENDED_SIDEBAR_WIDTH = {
+  DESKTOP: 300,
+  TABLET: 250,
+  MOBILE: 320
+};

Alternatively, consider using CSS custom properties or a configuration system for user preferences.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1d56fb7 and ee16f1a.

📒 Files selected for processing (2)
  • packages/constants/src/sidebar.ts (1 hunks)
  • web/app/(all)/[workspaceSlug]/(projects)/extended-sidebar-wrapper.tsx (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • web/app/(all)/[workspaceSlug]/(projects)/extended-sidebar-wrapper.tsx

@aaryan610 aaryan610 self-requested a review July 3, 2025 11:02
const { workspaceSlug, projectId } = useParams();
// store hooks
const { t } = useTranslation();
const {} = useAppTheme();
Copy link
Member

Choose a reason for hiding this comment

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

remove this

@sriramveeraghanta sriramveeraghanta merged commit 0225d80 into preview Jul 8, 2025
5 of 6 checks passed
@sriramveeraghanta sriramveeraghanta deleted the feat-sidebar-revamp branch July 8, 2025 14:48
lifeiscontent pushed a commit that referenced this pull request Aug 18, 2025
* chore: sidebar peek state added to theme store

* chore: extended sidebar wrapper added

* chore: resizeable sidebar component added

* chore: appsidebar root component

* chore: updated sidebar and applied necessary changes across codebase

* chore: code refactor

* chore: code refactor

* chore: code refactor

* chore: breadcrumb changes

* chore: sidebar improvements and fixes

* chore: enhancements and fixes

* fix: peek sidebar leave

* chore: code refactor

* chore: code refactor

* chore: code refactor

* chore: icons added

* chore: add dock variable and toggle function to theme store

* chore: code refactor

* chore: code refactor

* chore: code refactor

* chore: theme and workspace store updated

* chore: workspace content wrapper and apprail context

* chore: workspace and project wrapper updated

* chore: app rail component

* chore: content wrapper

* chore: sidebar component updated

* chore: layout changes and code refactoring

* chore: code refactor

* chore: code refactor

* chore: code refactor

* chore: code refactor

* chore: code refactor

* chore: code refactor

* chore: appsidebar toggle button

* chore: code refactor

* chore: workspace menu improvements

* chore: sidebar spacing and padding improvements

* chore: settings layout improvement

* chore: enhancements

* chore: extended sidebar code refactor

* chore: code refactor

* fix: merge conflict

* fix: merge conflict

* chore: code refactor

* chore: code refactor

* chore: code refactor

* chore: code refactor
@coderabbitai coderabbitai bot mentioned this pull request Oct 1, 2025
Closed
6 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants