Conversation
There was a problem hiding this comment.
Pull request overview
Introduces a new react-grid-layout-based Dashboard component suite (grid, widget gallery, provider, wrapper) and upgrades react-grid-layout to support the implementation.
Changes:
- Added a
Dashboardcomponent with responsive, draggable/resizable widget layout and persistence hooks. - Added supporting components/utilities: widget gallery, provider/context for drag state, layout normalization/serialization.
- Updated dependency versions for
react-grid-layout(and lockfile) to the required release.
Reviewed changes
Copilot reviewed 13 out of 14 changed files in this pull request and generated 10 comments.
Show a summary per file
| File | Description |
|---|---|
| pnpm-lock.yaml | Updates lockfile for react-grid-layout version bump. |
| packages/frappe-ui-react/package.json | Bumps react-grid-layout dependency to ^2.2.2. |
| packages/frappe-ui-react/src/components/index.ts | Re-exports the new dashboard module from the main components barrel. |
| packages/frappe-ui-react/src/components/dashboard/index.ts | Dashboard module barrel exports (Dashboard, gallery, provider, types). |
| packages/frappe-ui-react/src/components/dashboard/types.ts | Adds types for widgets, breakpoints, layouts, and component props. |
| packages/frappe-ui-react/src/components/dashboard/dashboard.tsx | Implements main Dashboard behavior (state, add/remove, drop handling, persistence callback). |
| packages/frappe-ui-react/src/components/dashboard/layoutContainer.tsx | Integrates ResponsiveGridLayout, renders widgets, handles breakpoint/layout updates and drop events. |
| packages/frappe-ui-react/src/components/dashboard/widgetWrapper.tsx | Adds widget chrome (remove button, drag handle) and hover behavior. |
| packages/frappe-ui-react/src/components/dashboard/dashboardContext.tsx | Adds context/provider to share drag state and widget add handler between dashboard and gallery. |
| packages/frappe-ui-react/src/components/dashboard/dashboardWidgetGallery.tsx | Implements widget gallery list/grid and wiring to context. |
| packages/frappe-ui-react/src/components/dashboard/dashboardWidgetGalleryItem.tsx | Implements individual gallery items with preview + drag/click behaviors. |
| packages/frappe-ui-react/src/components/dashboard/dashboardUtil.ts | Adds helpers for layout normalization, serialization, and key management. |
| packages/frappe-ui-react/src/components/dashboard/dashboard.css | Adds CSS to suppress initial layout transitions. |
| packages/frappe-ui-react/src/components/dashboard/dashboard.stories.tsx | Adds Storybook examples showcasing dashboard usage and widget gallery interactions. |
Files not reviewed (1)
- pnpm-lock.yaml: Language not supported
packages/frappe-ui-react/src/components/dashboard/dashboardUtil.ts
Outdated
Show resolved
Hide resolved
packages/frappe-ui-react/src/components/dashboard/dashboard.tsx
Outdated
Show resolved
Hide resolved
| setLayouts((prevLayouts) => { | ||
| const newLayouts: DashboardLayouts = { ...prevLayouts }; | ||
|
|
||
| for (const bp in prevLayouts) { |
There was a problem hiding this comment.
addWidgetToLayout iterates only over existing keys in prevLayouts. If layouts is {} (no initialLayouts and no savedLayout), adding a widget becomes a no-op because there are no breakpoints to append to. Consider seeding prevLayouts with at least a default breakpoint set (e.g. lg/md/sm/xs/xxs) when it's empty.
| for (const bp in prevLayouts) { | |
| const layoutBreakpoints: Breakpoint[] = | |
| Object.keys(prevLayouts).length > 0 | |
| ? (Object.keys(prevLayouts) as Breakpoint[]) | |
| : (["lg", "md", "sm", "xs", "xxs"] as Breakpoint[]); | |
| for (const bp of layoutBreakpoints) { |
packages/frappe-ui-react/src/components/dashboard/widgetWrapper.tsx
Outdated
Show resolved
Hide resolved
packages/frappe-ui-react/src/components/dashboard/dashboardWidgetGallery.tsx
Outdated
Show resolved
Hide resolved
| <div className="absolute top-2 right-2 z-10 flex items-center gap-1"> | ||
| {showRemoveButton && ( | ||
| <Button | ||
| onClick={() => onRemove(widgetId)} | ||
| icon={() => <X className="w-4 h-4" />} | ||
| /> | ||
| )} |
There was a problem hiding this comment.
LayoutContainer sets draggableCancel to .dashboard-drag-cancel, but neither the remove button nor its wrapper has that class. When dragHandle is false (drag from anywhere), clicking the remove button may initiate a drag instead of removing. Add the cancel class to the control area/buttons (or update draggableCancel to match what’s rendered).
a5434d9 to
f59e050
Compare
Description
react-grid-layoutbased Dashboard component:Components
Features
Responsive Layout
Row-Based Layout Syntax
Widget Operations
Widget Gallery
Layout Controls
Relevant Technical Choices
Testing Instructions
Additional Information:
Screenshot/Screencast
Dashboard.Grid.Demo.mp4
Checklist
Fixes #94