layer5io / layer5io/sistent

DashboardLayout offers no way to reopen the desktop sticky picker: isSidebarOpen is both 'should it exist' and 'is it showing'

Open
#1,845 2 comments 0 reactions 1 assignee View on GitHub

@NSTKrishna is already working on this.

Since Sep 16, 2026.

Dominant language
TypeScript
Stars
137
Forks
239
Avg merge
4d 14h
Merged PRs (30d)
5

Description

Summary

Below the md breakpoint, DashboardLayout renders sidebarContent inside a BottomSheet and pairs it with a floating action button to reopen that sheet. But WidgetPicker draws its own close control (aria-label="Close widget picker") inside that content, and that control is wired to the consumer's onClose - the same callback that clears isSidebarOpen.

So on mobile there are two close affordances in the same sheet with different and irreconcilable outcomes:

  • The sheet's own close clears DashboardLayout's internal open state. isSidebarOpen stays true, so the FAB renders and the user can reopen the sheet. Correct.
  • WidgetPicker's X runs the consumer's onClose, which clears isSidebarOpen. That unmounts the sheet and the FAB together, so the picker cannot be reopened at all until the consumer's own state cycles.

The second one is a dead end the user cannot get out of from the UI.

Where

DashboardLayout, mobile branch (from the built 0.22.6 bundle, names shortened):

isSidebarOpen && isMobile && (
  <>
    <BottomSheet open={internalOpen} onClose={() => setInternalOpen(false)} ...>
      {sidebarContent}
    </BottomSheet>
    {!internalOpen && <Fab onClick={() => setInternalOpen(true)} ... />}
  </>
)

Both the sheet and the FAB are gated on isSidebarOpen, so anything that clears it takes the FAB with it. WidgetPicker's X is rendered inside sidebarContent, which is exactly what the sheet is displaying.

Why the consumer cannot fix this cleanly

A consumer could make its onClose breakpoint-aware - clear isSidebarOpen on desktop, do nothing on mobile - but that requires restating Sistent's md breakpoint in the consumer, so the panel's behaviour and the component's layout decision become two values that must agree and nothing checks. That is the class of bug we were already fixing in layer5io/meshery-cloud#5992, so we declined to introduce another instance of it and left the X consistent with desktop.

Suggested fix

WidgetPicker should not render its own close control when it is being displayed inside the bottom sheet - the sheet already provides one, and the two mean different things. Options, in rough order of preference:

  1. DashboardLayout tells WidgetPicker it is embedded (a context value or an internal prop), and WidgetPicker omits its X in that case.
  2. WidgetPicker takes an explicit prop to suppress the close control, and DashboardLayout sets it on the mobile branch.
  3. DashboardLayout gates the FAB on something other than isSidebarOpen, so a consumer clearing that prop still leaves a way back.

Either of the first two keeps the breakpoint knowledge inside the component that already owns it.

Consumer status

Not blocking. layer5io/meshery-cloud#5992 separated panel visibility from its edit-session lifetime, so the X is no longer destructive there - it closes the panel and the edit session continues with its guards armed. On mobile the picker simply cannot be reopened until edit mode cycles, which is a degraded but non-destructive state, and better than the behaviour it replaced.

Related: layer5io/sistent#1843, layer5io/sistent#1844.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.