[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?
banana-three-join
left a comment
There was a problem hiding this comment.
Other than the requested changes, it looks good to me!
…ut-mobile-responsive
📝 WalkthroughWalkthroughAdds responsive ChangesDashboard and widget components
Estimated code review effort: 3 (Moderate) | ~25 minutes Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
Introduces a new `WidgetEmptyState` component with optional icon and action button support, and exports it through both `custom` and root barrels. Refactors `DashboardLayout` into its own file with explicit type/value re-exports and updates mobile sidebar rendering so the drawer is only mounted when the sidebar is open. Also switches `WidgetPicker` to explicit named/type exports for a clearer public API surface. Signed-off-by: NSTKrishna <krishnagehlot936@gmail.com>
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 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 `@src/custom/DashboardLayout/index.tsx`:
- Around line 104-110: Update the puller Box styling in DashboardLayout to
replace the hard-coded light/dark background colors with the semantic theme
token theme.palette.divider, preserving the existing dimensions and border
radius.
- Around line 82-102: The minimized drawer trigger in DashboardLayout must be
keyboard-operable and accessible. Replace the interactive Box behavior with a
focusable labelled button (or Sistent button) rendered outside the drawer when
minimized, reuse the existing toggle logic, and expose isMobileDrawerOpen
through the button’s expanded state.
In `@src/custom/index.tsx`:
- Line 193: Update the custom barrel in src/custom/index.tsx to re-export
DashboardLayout alongside WidgetPicker, using the existing DashboardLayout
export from the custom domain index; preserve the current exports and ensure the
symbol is available through the feature-local, domain, and root barrel chain.
In `@src/custom/WidgetPicker/WidgetPicker.tsx`:
- Around line 40-52: Update the `WidgetPicker` component’s `Box` `sx` prop to
compose the base styles and `containerSx` as an array, preserving callback and
array-based `SxProps` values instead of spreading `containerSx` into the base
object.
🪄 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 Plus
Run ID: f6f90140-acf6-4123-bd39-b29179641844
📒 Files selected for processing (6)
src/custom/DashboardLayout/index.tsxsrc/custom/WidgetPicker/WidgetPicker.tsxsrc/custom/WidgetPicker/index.tsxsrc/custom/index.tssrc/custom/index.tsxsrc/index.tsx
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 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 `@src/custom/DashboardLayout/DashboardLayout.tsx`:
- Around line 25-36: Remove the unused onClose prop from DashboardLayoutProps,
delete its callback documentation, and stop destructuring it in DashboardLayout.
Keep the component’s internal close behavior unchanged.
🪄 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 Plus
Run ID: 361b392d-3dc7-4524-bcbb-7fac97080c43
📒 Files selected for processing (6)
src/custom/DashboardLayout/DashboardLayout.tsxsrc/custom/DashboardLayout/index.tsxsrc/custom/WidgetEmptyState/index.tsxsrc/custom/WidgetPicker/index.tsxsrc/custom/index.tssrc/index.tsx
🚧 Files skipped from review as they are similar to previous changes (2)
- src/custom/index.ts
- src/index.tsx
This updates several dashboard-related components for better UX and consistency: DashboardLayout drops an unused `onClose` prop, adds keyboard-accessible sidebar toggle behavior, and uses theme divider color for the drawer handle. PlainCard and ResponsiveDataTable now show `WidgetEmptyState` when content is empty (including table `noMatch` text), and WidgetPicker now merges `containerSx` safely by supporting array/object forms. It also exports `DashboardLayout` from the custom barrel. Signed-off-by: NSTKrishna <krishnagehlot936@gmail.com>
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 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 `@src/custom/ResponsiveDataTable.tsx`:
- Around line 167-178: Update the options transformation around bodyTextLabels
and updatedOptions to always assign WidgetEmptyState for noMatch, using the
existing string value when provided and a fallback message otherwise. Build a
fresh body object with the resolved noMatch value instead of mutating
bodyTextLabels or any caller-owned options object.
- Around line 163-164: Update the textLabels declaration in ResponsiveDataTable
to use MUIDataTableOptions or a narrow local type whose body.noMatch accepts
string | React.ReactNode. Remove both any casts and the eslint suppression while
preserving the existing fallback to an empty labels object.
🪄 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 Plus
Run ID: 0a9896c3-7d47-4e3c-a46f-b9137e960ed3
📒 Files selected for processing (5)
src/custom/DashboardLayout/DashboardLayout.tsxsrc/custom/DashboardWidgets/PlainCard.tsxsrc/custom/ResponsiveDataTable.tsxsrc/custom/WidgetPicker/WidgetPicker.tsxsrc/custom/index.tsx
🚧 Files skipped from review as they are similar to previous changes (2)
- src/custom/index.tsx
- src/custom/WidgetPicker/WidgetPicker.tsx
Use `MUIDataTableOptions` for `ResponsiveDataTableProps.options` instead of `object`, removing `any` casts around `textLabels`. The no-match handling now consistently renders `WidgetEmptyState`, using the provided `body.noMatch` string when available and falling back to `"No data available"`. Signed-off-by: NSTKrishna <krishnagehlot936@gmail.com>
|
Once this is merged #1653 , we should replace the existing SwipeableDrawer in DashboardLayout with the new BottomSheet |
Description
This PR introduces two new reusable components to
@sistent/sistentto support responsive, widget-based dashboard layouts across Meshery and Meshery Cloud, and structurally integrates a standardized empty state universally across both ecosystems.1. DashboardLayout
A layout wrapper that manages the main content area and a sidebar for configuration/widgets.
SwipeableDrawer.theme.palette.dividertoken) that is fully keyboard-operable (role="button",tabIndex={0}).sidebarWidth,sidebarTopOffset, andsidebarHeightfor easy integration with different navigation structures.sxprop to avoid polluting other MuiDrawer instances on the page.2. WidgetPicker
A component for displaying and adding widgets to a layout.
widgetsToAddand anonAddWidgetcallback, keeping it completely decoupled from domain logic.3. Universal WidgetEmptyState Integration
Structurally embedded the newly designed
<WidgetEmptyState />natively into Sistent's core data-display components to automatically standardize empty states across all consumers.MUIDataTableOptionstyping to avoid object mutation bugs.resourcesarray is empty.Changes Made
src/custom/DashboardLayout/DashboardLayout.tsx(abstracted away from the index).src/custom/WidgetPicker/WidgetPicker.tsx.src/custom/index.ts,src/custom/index.tsx, andsrc/index.tsx(named exports).WidgetEmptyStatedirectly intoResponsiveDataTable.tsxandPlainCard.tsx.LatestBlogswidget empty state dummy data inside the Meshery consumer.Related Issues
mesheryandmeshery-clouddashboards and properly support mobile views.Testing Performed
npm run build,npm run lint- all linters passing cleanly).node_moduleslocal link in bothmesheryandmeshery-clouddevelopment environments.SwipeableDrawerhandles opening/closing correctly via both swipe and keyboard events.LatestBlogs) safely trigger the newWidgetEmptyStatewithout causing infinite loops or call stack errors.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
Summary by CodeRabbit
New Features
DashboardLayoutwith a sticky sidebar on larger screens and a bottom drawer sidebar on mobile.WidgetPickerto browse and add widgets, including optional thumbnails and customizable header colors (with optional close control).WidgetEmptyStatefor centered empty states with optional icon and action button.DashboardLayout,WidgetPicker, andWidgetEmptyState.UX Improvements
PlainCardempty rendering andResponsiveDataTable“no data” messaging to useWidgetEmptyState.