Skip to content

Replace react-grid-layout with plain CSS grid and remove drag#377

Closed
urjitc wants to merge 1 commit into
mainfrom
capy/replace-rgl-with-css
Closed

Replace react-grid-layout with plain CSS grid and remove drag#377
urjitc wants to merge 1 commit into
mainfrom
capy/replace-rgl-with-css

Conversation

@urjitc

@urjitc urjitc commented Apr 16, 2026

Copy link
Copy Markdown
Member

This PR removes the react-grid-layout dependency entirely and replaces the workspace grid with a plain CSS grid layout using grid-auto-flow: dense and uniform 200x200 cards. All RGL-specific CSS overrides (390 lines), grid layout helpers, and the auto-scroll hook have been deleted. WorkspaceGrid now renders without drag/resize wiring, cards use layout-independent preview logic (disabled), and workspace operations no longer emit layout diffs. Legacy layout types remain for backwards compatibility.

  • package.json: Removed react-grid-layout dependency
  • next.config.ts: Removed transpilePackages: ["react-grid-layout"]
  • src/app/globals.css: Deleted 390-line RGL override block; kept .flip-card-content isolation rule
  • src/components/workspace-canvas/WorkspaceGrid.tsx: Replaced entire component with CSS grid using gridTemplateColumns: repeat(auto-fill, minmax(200px, 1fr)) and neutral data-workspace-card wrappers
  • src/components/workspace-canvas/WorkspaceContent.tsx: Removed auto-scroll hook usage and onDragStart/onDragStop props
  • src/components/workspace-canvas/WorkspaceCard.tsx: Removed getLayoutForBreakpoint; preview now always false; removed layout comparison in memoization
  • src/components/workspace-canvas/MarqueeSelector.tsx: Changed selector from .react-grid-item to [data-workspace-card]
  • src/hooks/workspace/use-workspace-operations.ts: Removed findNextAvailablePosition usage; items no longer receive layout; layout diff extraction deleted from updateAllItems
  • src/app/api/workspaces/autogen/route.ts: Removed findNextAvailablePosition import and position assignment for PDF/image items
  • src/lib/workspace-state/types.ts: Added @deprecated comment to layout field
  • src/lib/workspace/templates.ts: Removed layout properties from template items
  • src/lib/workspace/import-validation.ts: Removed layout validation checks
  • src/components/workspace-canvas/WorkspaceHeader.tsx: Removed DEFAULT_CARD_DIMENSIONS usage
  • src/components/workspace-canvas/WorkspaceSection.tsx: Removed DEFAULT_CARD_DIMENSIONS usage
  • src/components/workspace-canvas/WorkspaceCanvasDropzone.tsx: Removed DEFAULT_CARD_DIMENSIONS usage

Deleted:

  • src/lib/workspace-state/grid-layout-helpers.ts
  • src/hooks/ui/use-auto-scroll.ts

Open in Capy ENG-54 · 5.4

Summary by CodeRabbit

Release Notes

  • Refactor
    • Workspace canvas layout system refactored to use CSS grid auto-layout
    • Items are no longer draggable or resizable within the workspace
    • Auto-scroll functionality during drag operations has been removed
    • Layout positioning and constraints have been simplified

@vercel

vercel Bot commented Apr 16, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
thinkex Ready Ready Preview, Comment Apr 16, 2026 0:09am

Request Review

@urjitc urjitc added the capy Generated by capy.ai label Apr 16, 2026 — with Capy AI
@github-project-automation github-project-automation Bot moved this to Backlog in Dev Board Apr 16, 2026
@coderabbitai

coderabbitai Bot commented Apr 16, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

This PR removes the react-grid-layout dependency and associated drag-drop grid system, replacing it with static CSS grid layout. Changes include deleting grid-layout helpers, auto-scroll functionality, layout positioning logic, and grid-related CSS, while updating components and types to reflect the new architecture.

Changes

Cohort / File(s) Summary
Dependency Removal
package.json, next.config.ts
Removed react-grid-layout dependency and transpilation configuration.
Grid System Architecture
src/components/workspace-canvas/WorkspaceGrid.tsx, src/lib/workspace-state/grid-layout-helpers.ts
Replaced drag-resize layout system with static CSS grid rendering; deleted 390 lines of layout utility functions (DEFAULT_CARD_DIMENSIONS, findNextAvailablePosition, itemsToLayout, recompactLayout, etc.).
Auto-Scroll Hook Removal
src/hooks/ui/use-auto-scroll.ts, src/components/workspace-canvas/WorkspaceContent.tsx, src/components/workspace-canvas/MarqueeSelector.tsx
Deleted entire useAutoScroll hook (276 lines) and removed all auto-scroll event wiring from drag handlers; updated marquee selector element exclusion from grid-specific selectors to data-workspace-card attribute.
Layout Calculation Removal
src/hooks/workspace/use-workspace-operations.ts, src/app/api/workspaces/autogen/route.ts
Removed layout position computation, layout field assignment in batch item creation, and layout-specific update events; eliminated findNextAvailablePosition seeding for uploaded PDFs/images.
Component Layout Decoupling
src/components/workspace-canvas/WorkspaceCard.tsx, src/components/workspace-canvas/WorkspaceHeader.tsx, src/components/workspace-canvas/WorkspaceSection.tsx, src/components/workspace-canvas/WorkspaceCanvasDropzone.tsx
Removed grid layout-based preview logic, memoization layout comparisons, and explicit layout dimension passing; hard-coded shouldShowPreview to false.
Styling Consolidation
src/app/globals.css
Removed 389 lines of react-grid-layout/react-grid-item CSS overrides; consolidated flashcard flip-card styling to grid-independent rules using isolation and contain properties.
Type & Validation Updates
src/lib/workspace-state/types.ts, src/lib/workspace/import-validation.ts
Marked Item.layout property as deprecated; removed numeric layout field validation logic from import validation.
Template Updates
src/lib/workspace/templates.ts
Removed layout properties from "Getting Started" template initial items.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐰 A rabbit hops through grids no more,
CSS flows like streams before,
No dragging, no snapping, just static grace,
Simpler layouts now hold their place!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately and concisely summarizes the primary changes: replacing react-grid-layout with plain CSS grid and removing drag functionality.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch capy/replace-rgl-with-css

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@greptile-apps

greptile-apps Bot commented Apr 16, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR removes the custom react-grid-layout fork entirely and replaces the workspace grid with a plain CSS auto-fill grid, deleting ~390 lines of RGL CSS overrides, the auto-scroll hook, and all layout-diff event emission. The migration is largely clean, but two spots need attention:

  • WorkspaceGridProps retains five props (isFiltered, isTemporaryFilter, onUpdateAllItems, onGridDragStateChange, onMoveItems) that are no longer consumed by the component.
  • The onOpenFolder! non-null assertion on line 69 of WorkspaceGrid.tsx hides a type-safety hole for an optional prop passed to FolderCard.

Confidence Score: 4/5

Safe to merge after addressing the non-null assertion on onOpenFolder in WorkspaceGrid.

One P1 finding: onOpenFolder! hides a runtime error for an optional prop passed into FolderCard. In the current call site it is always provided, but the type contract is broken and the interface cleanup has not removed the optional modifier. The remaining findings are P2 cleanup (dead props, leftover AUTOGEN_LAYOUTS).

src/components/workspace-canvas/WorkspaceGrid.tsx (non-null assertion + dead interface props), src/app/api/workspaces/autogen/route.ts (leftover AUTOGEN_LAYOUTS usage)

Important Files Changed

Filename Overview
src/components/workspace-canvas/WorkspaceGrid.tsx Replaced RGL with a plain CSS auto-fill grid; five props remain in the interface but are never used, and onOpenFolder! non-null assertion hides a potential runtime error.
src/app/api/workspaces/autogen/route.ts Removed PDF/image position assignment, but AUTOGEN_LAYOUTS and its usage for document/quiz/YouTube items are leftover dead code — layout values are still written to items but never read.
src/components/workspace-canvas/WorkspaceContent.tsx Removed useAutoScroll hook usage and drag callbacks; still passes now-unused props (isFiltered, onUpdateAllItems, onGridDragStateChange, onMoveItems) to WorkspaceGrid.
src/hooks/workspace/use-workspace-operations.ts Removed layout position computation and BULK_ITEMS_UPDATED layout-diff events; minor scope change in duplicate-name check from folder-scoped items to all items.
src/components/workspace-canvas/MarqueeSelector.tsx Removed useAutoScroll integration and updated selector target from .react-grid-item to [data-workspace-card]; straightforward cleanup.

Comments Outside Diff (1)

  1. src/app/api/workspaces/autogen/route.ts, line 46-53 (link)

    P2 AUTOGEN_LAYOUTS is now dead code

    layout is marked @deprecated in types.ts and the CSS grid ignores it entirely — yet AUTOGEN_LAYOUTS is still used to attach layout positions to document (line 870), quiz (line 875), and YouTube (lines 894, 907) items at creation time. These values are written into items but never read. The PDF/image position code was cleaned up but this block was left behind; it should also be removed for consistency.

    Fix in Cursor

Fix All in Cursor

Reviews (1): Last reviewed commit: "Remove react-grid-layout and replace wit..." | Re-trigger Greptile

Comment on lines 7 to +23
@@ -42,713 +17,89 @@ interface WorkspaceGridProps {
workspaceName: string;
workspaceIcon?: string | null;
workspaceColor?: string | null;
onMoveItem?: (itemId: string, folderId: string | null) => void; // Callback to move item to folder
onMoveItems?: (itemIds: string[], folderId: string | null) => void; // Callback to move multiple items to folder (bulk move)
onOpenFolder?: (folderId: string) => void; // Callback when folder is clicked
onDeleteFolderWithContents?: (folderId: string) => void; // Callback to delete folder and all items inside
onMoveItem?: (itemId: string, folderId: string | null) => void;
onMoveItems?: (itemIds: string[], folderId: string | null) => void;
onOpenFolder?: (folderId: string) => void;
onDeleteFolderWithContents?: (folderId: string) => void;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 Dead props in WorkspaceGridProps

Five props are declared in the interface and passed from WorkspaceContent but never destructured or used by WorkspaceGridComponent: isFiltered, isTemporaryFilter, onUpdateAllItems, onGridDragStateChange, and onMoveItems. Since drag/resize is gone, these can be removed from both the interface and every call site to keep the surface clean.

Suggested change
interface WorkspaceGridProps {
items: Item[];
allItems: Item[];
onUpdateItem: (itemId: string, updates: Partial<Item>) => void;
onDeleteItem: (itemId: string) => void;
onOpenModal: (itemId: string) => void;
workspaceName: string;
workspaceIcon?: string | null;
workspaceColor?: string | null;
onMoveItem?: (itemId: string, folderId: string | null) => void;
onOpenFolder?: (folderId: string) => void;
onDeleteFolderWithContents?: (folderId: string) => void;
}

Fix in Cursor

workspaceName={workspaceName}
workspaceIcon={workspaceIcon}
workspaceColor={workspaceColor}
onOpenFolder={onOpenFolder!}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P1 Non-null assertion on optional prop

onOpenFolder is typed as optional in WorkspaceGridProps, so it can be undefined. The ! operator only suppresses the TypeScript error — at runtime, if onOpenFolder is undefined and a user clicks a folder card, FolderCard will throw when it tries to invoke the handler. Since WorkspaceContent always provides it today, this silently works, but the type contract is broken.

Suggested change
onOpenFolder={onOpenFolder!}
onOpenFolder={onOpenFolder ?? (() => {})}

Or make onOpenFolder required in the interface since folder-type items require it.

Fix in Cursor

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/components/workspace-canvas/WorkspaceGrid.tsx (1)

7-24: 🛠️ Refactor suggestion | 🟠 Major

Remove unused props from interface.

Several props are declared in WorkspaceGridProps but never used:

  • onUpdateAllItems (line 14)
  • onGridDragStateChange (line 16)
  • onMoveItems (line 21)
  • isFiltered (line 10)
  • isTemporaryFilter (line 11)

These are relics of the removed drag/resize functionality. Keeping them creates confusion and requires parent components to pass unnecessary props.

♻️ Clean up interface
 interface WorkspaceGridProps {
   items: Item[];
   allItems: Item[];
-  isFiltered: boolean;
-  isTemporaryFilter?: boolean;
   onUpdateItem: (itemId: string, updates: Partial<Item>) => void;
   onDeleteItem: (itemId: string) => void;
-  onUpdateAllItems: (items: Item[]) => void;
   onOpenModal: (itemId: string) => void;
-  onGridDragStateChange?: (isDragging: boolean) => void;
   workspaceName: string;
   workspaceIcon?: string | null;
   workspaceColor?: string | null;
   onMoveItem?: (itemId: string, folderId: string | null) => void;
-  onMoveItems?: (itemIds: string[], folderId: string | null) => void;
   onOpenFolder?: (folderId: string) => void;
   onDeleteFolderWithContents?: (folderId: string) => void;
 }

Also update WorkspaceContent.tsx and WorkspaceSection.tsx to stop passing these unused props.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/workspace-canvas/WorkspaceGrid.tsx` around lines 7 - 24,
Remove the stale drag/resize props from the WorkspaceGridProps interface: delete
isFiltered, isTemporaryFilter, onUpdateAllItems, onGridDragStateChange, and
onMoveItems from the WorkspaceGridProps declaration in WorkspaceGrid.tsx; then
update callers (components WorkspaceContent and WorkspaceSection) to stop
passing those props when rendering <WorkspaceGrid /> and remove any related prop
destructuring or forwarding there so parents no longer require or pass these
unused properties. Ensure you only remove those identifiers and keep all
remaining props and handler names intact (onUpdateItem, onDeleteItem,
onOpenModal, onMoveItem, onOpenFolder, onDeleteFolderWithContents,
workspaceName, workspaceIcon, workspaceColor, items, allItems).
🧹 Nitpick comments (1)
src/hooks/workspace/use-workspace-operations.ts (1)

343-343: Unused parameter: initialLayout is no longer used.

The initialLayout parameter is accepted but never used in the function body. Consider removing it from the signature to avoid confusion, or mark it as deprecated if external callers depend on it.

♻️ Optional cleanup
   const createItem = useCallback(
     (
       type: CardType,
       name?: string,
       initialData?: Partial<Item["data"]>,
-      initialLayout?: { w: number; h: number },
     ) => {

Note: Also update the WorkspaceOperations interface and createItems signature.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/hooks/workspace/use-workspace-operations.ts` at line 343, The parameter
initialLayout in the useWorkspaceOperations function signature is unused; remove
it from the function signature and any internal references, and update the
related types: remove initialLayout from the WorkspaceOperations interface and
from the createItems(...) signature so types stay consistent; if external
callers still rely on that param, instead mark it deprecated in the interface
(or keep an optional overload) and forward-compatibility-comment its removal,
but prefer deleting the unused parameter across useWorkspaceOperations,
WorkspaceOperations, and createItems to eliminate the dead parameter.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/components/workspace-canvas/WorkspaceGrid.tsx`:
- Line 69: The code uses a non-null assertion on the optional prop onOpenFolder
in WorkspaceGrid (onOpenFolder!) which can throw at runtime if the caller omits
it; either make onOpenFolder required in the component props interface, or
remove the "!" and guard where it's used (e.g., call it conditionally or provide
a default no-op handler) so that usages like onOpenFolder are safe when the prop
is undefined; update the Props/interface declaration or the call sites in
WorkspaceGrid.tsx accordingly to ensure no runtime assertion is required.

---

Outside diff comments:
In `@src/components/workspace-canvas/WorkspaceGrid.tsx`:
- Around line 7-24: Remove the stale drag/resize props from the
WorkspaceGridProps interface: delete isFiltered, isTemporaryFilter,
onUpdateAllItems, onGridDragStateChange, and onMoveItems from the
WorkspaceGridProps declaration in WorkspaceGrid.tsx; then update callers
(components WorkspaceContent and WorkspaceSection) to stop passing those props
when rendering <WorkspaceGrid /> and remove any related prop destructuring or
forwarding there so parents no longer require or pass these unused properties.
Ensure you only remove those identifiers and keep all remaining props and
handler names intact (onUpdateItem, onDeleteItem, onOpenModal, onMoveItem,
onOpenFolder, onDeleteFolderWithContents, workspaceName, workspaceIcon,
workspaceColor, items, allItems).

---

Nitpick comments:
In `@src/hooks/workspace/use-workspace-operations.ts`:
- Line 343: The parameter initialLayout in the useWorkspaceOperations function
signature is unused; remove it from the function signature and any internal
references, and update the related types: remove initialLayout from the
WorkspaceOperations interface and from the createItems(...) signature so types
stay consistent; if external callers still rely on that param, instead mark it
deprecated in the interface (or keep an optional overload) and
forward-compatibility-comment its removal, but prefer deleting the unused
parameter across useWorkspaceOperations, WorkspaceOperations, and createItems to
eliminate the dead parameter.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: f0624dfa-1dc8-4fb3-be1d-d12222123269

📥 Commits

Reviewing files that changed from the base of the PR and between 7de7b4a and 1456e8c.

📒 Files selected for processing (17)
  • next.config.ts
  • package.json
  • src/app/api/workspaces/autogen/route.ts
  • src/app/globals.css
  • src/components/workspace-canvas/MarqueeSelector.tsx
  • src/components/workspace-canvas/WorkspaceCanvasDropzone.tsx
  • src/components/workspace-canvas/WorkspaceCard.tsx
  • src/components/workspace-canvas/WorkspaceContent.tsx
  • src/components/workspace-canvas/WorkspaceGrid.tsx
  • src/components/workspace-canvas/WorkspaceHeader.tsx
  • src/components/workspace-canvas/WorkspaceSection.tsx
  • src/hooks/ui/use-auto-scroll.ts
  • src/hooks/workspace/use-workspace-operations.ts
  • src/lib/workspace-state/grid-layout-helpers.ts
  • src/lib/workspace-state/types.ts
  • src/lib/workspace/import-validation.ts
  • src/lib/workspace/templates.ts
💤 Files with no reviewable changes (9)
  • package.json
  • next.config.ts
  • src/components/workspace-canvas/WorkspaceContent.tsx
  • src/components/workspace-canvas/WorkspaceSection.tsx
  • src/lib/workspace/templates.ts
  • src/app/api/workspaces/autogen/route.ts
  • src/lib/workspace/import-validation.ts
  • src/hooks/ui/use-auto-scroll.ts
  • src/lib/workspace-state/grid-layout-helpers.ts

workspaceName={workspaceName}
workspaceIcon={workspaceIcon}
workspaceColor={workspaceColor}
onOpenFolder={onOpenFolder!}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Avoid non-null assertion on optional prop.

onOpenFolder! uses a non-null assertion but onOpenFolder is declared as optional in the interface (line 22). If a caller doesn't provide this prop, this will throw at runtime.

🐛 Safer handling
               <FolderCard
                 item={item}
                 itemCount={folderItemCounts.get(item.id) || 0}
                 allItems={allItems}
                 workspaceName={workspaceName}
                 workspaceIcon={workspaceIcon}
                 workspaceColor={workspaceColor}
-                onOpenFolder={onOpenFolder!}
+                onOpenFolder={onOpenFolder ?? (() => {})}
                 onUpdateItem={onUpdateItem}

Alternatively, make onOpenFolder required in the interface if it's always expected.

📝 Committable suggestion

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

Suggested change
onOpenFolder={onOpenFolder!}
<FolderCard
item={item}
itemCount={folderItemCounts.get(item.id) || 0}
allItems={allItems}
workspaceName={workspaceName}
workspaceIcon={workspaceIcon}
workspaceColor={workspaceColor}
onOpenFolder={onOpenFolder ?? (() => {})}
onUpdateItem={onUpdateItem}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/workspace-canvas/WorkspaceGrid.tsx` at line 69, The code uses
a non-null assertion on the optional prop onOpenFolder in WorkspaceGrid
(onOpenFolder!) which can throw at runtime if the caller omits it; either make
onOpenFolder required in the component props interface, or remove the "!" and
guard where it's used (e.g., call it conditionally or provide a default no-op
handler) so that usages like onOpenFolder are safe when the prop is undefined;
update the Props/interface declaration or the call sites in WorkspaceGrid.tsx
accordingly to ensure no runtime assertion is required.

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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

No issues found across 17 files

Requires human review: This is a high-impact refactor that replaces a core layout library and removes major UI features (drag/resize). It requires human review to verify the new interaction model.

@urjitc urjitc closed this Apr 16, 2026
@github-project-automation github-project-automation Bot moved this from Backlog to Done in Dev Board Apr 16, 2026
@urjitc
urjitc deleted the capy/replace-rgl-with-css branch June 29, 2026 17:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

capy Generated by capy.ai

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

1 participant