[UI] Add DashboardLayout and WidgetPicker components#1706
Conversation
Introduce a responsive DashboardLayout (sticky sidebar on desktop, bottom SwipeableDrawer on mobile) and a WidgetPicker UI with types for WidgetItem. Added files: src/custom/DashboardLayout/index.tsx, src/custom/WidgetPicker/WidgetPicker.tsx, src/custom/WidgetPicker/index.tsx. Updated exports in src/custom/index.ts, src/custom/index.tsx and root src/index.tsx to re-export the new components and their props/types so they are available from the package API. Signed-off-by: NSTKrishna <krishnagehlot936@gmail.com>
There was a problem hiding this comment.
Code Review
This pull request introduces two new custom components: DashboardLayout, which provides a responsive layout with a sticky sidebar on desktop and a swipeable bottom drawer on mobile, and WidgetPicker, which displays a list of available widgets to add. The feedback highlights a critical state desync issue in DashboardLayout where the onClose callback is not triggered when the mobile drawer is closed. Additionally, improvements are suggested for WidgetPicker to enhance type safety by replacing an any type with a more specific type, and to correct a discrepancy in the JSDoc documentation regarding the default header background color.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
Invoke the optional onClose callback when the mobile drawer is closed (in SwipeableDrawer.onClose and the header toggle). Remove an unused Drawer import. Improve WidgetPicker typings: use unknown for the extra properties index signature and change onAddWidget to accept the widget payload without its 'key'. Also update the headerBackgroundColor JSDoc default. These changes ensure proper close propagation and stronger type safety. Signed-off-by: NSTKrishna <krishnagehlot936@gmail.com>
Remove the isSidebarOpen condition from the mobile SwipeableDrawer to ensure the drawer is always displayed on mobile devices, regardless of sidebar state. Signed-off-by: NSTKrishna <krishnagehlot936@gmail.com>
Only expose the swipe area when the sidebar is open, and stop firing the layout `onClose` callback from mobile drawer toggles. This keeps mobile drawer state changes local while preserving the wider sidebar interaction area when appropriate. Signed-off-by: NSTKrishna <krishnagehlot936@gmail.com>
Drops the unused `onClose` prop from `DashboardLayout`'s public props and implementation, simplifying the component API. Signed-off-by: NSTKrishna <krishnagehlot936@gmail.com>
Katotodan
left a comment
There was a problem hiding this comment.
@NSTKrishna, thanks for the work.
Can you consider adding some accessibility features to clickable elements of this PR?
| const [isMobileDrawerOpen, setIsMobileDrawerOpen] = useState(false); | ||
| const drawerBleeding = 56; | ||
|
|
||
| useEffect(() => { | ||
| if (isSidebarOpen) { | ||
| setIsMobileDrawerOpen(true); | ||
| } else { | ||
| setIsMobileDrawerOpen(false); | ||
| } | ||
| }, [isSidebarOpen]); |
There was a problem hiding this comment.
From my understanding, the DashboardLayout can be opened or closed in two different ways:
- The parent component controls it through the
isSidebarOpenprop. - The
DashboardLayoutalso updates its own state when the user interacts with theSwipeableDrawer.
Could this lead to state inconsistencies or bugs in the future? For example, the drawer could be closed from within DashboardLayout while the parent component still considers it open. Would it make sense to have a single source of truth for the open state (for example, by notifying the parent of open/close events) so both remain synchronized?
Description
This PR introduces two new reusable components to
@sistent/sistentto support responsive, widget-based dashboard layouts across Meshery and Meshery Cloud.1.
DashboardLayoutA layout wrapper that manages the main content area and a sidebar for configuration/widgets.
SwipeableDrawer.sidebarWidth,sidebarTopOffset, andsidebarHeightfor easy integration with different navigation structures.sxprop to avoid polluting otherMuiDrawerinstances on the page.2.
WidgetPickerA component for displaying and adding widgets to a layout.
widgetsToAddand anonAddWidgetcallback, keeping it completely decoupled from domain logic.Changes Made
src/custom/DashboardLayout/index.tsxsrc/custom/WidgetPicker/WidgetPicker.tsxsrc/custom/index.ts,src/custom/index.tsx, andsrc/index.tsxDashboardLayoutSwipeableDrawerRelated Issues
mesheryandmeshery-clouddashboards and properly support mobile views.Testing Performed
npm run build,npm test- all 324 tests passing).npm packtarball integration in bothmesheryandmeshery-clouddevelopment environments.mdbreakpoint.SwipeableDrawerhandles opening/closing correctly without duplicate labeling.Demo
Screen.Recording.2026-07-13.at.6.43.33.AM.mov
Screen.Recording.2026-07-13.at.10.29.58.AM.mov
Notes for Reviewers
This PR fixes #
Signed commits