Skip to content

fix: sidebar title disappears when switching between two sidebars#2905

Open
nzjrs wants to merge 1 commit into
Chainlit:mainfrom
nzjrs:fix/atomic-sidebar-set
Open

fix: sidebar title disappears when switching between two sidebars#2905
nzjrs wants to merge 1 commit into
Chainlit:mainfrom
nzjrs:fix/atomic-sidebar-set

Conversation

@nzjrs
Copy link
Copy Markdown
Contributor

@nzjrs nzjrs commented Apr 22, 2026

I have buttons in the header which are used to switch between two sidebars (or rather, switch out the contents of the one cl.ElementSidebar to make it look like two sidebars). I observer visual artefacts and inconsistency when doing this, specifically I replace the contents of it and its title regularly, yet sometimes only half of the replacement sticks, often the title replacement is ignored.

To reproduce:

Open sidebar A with ElementSidebar.set_title("A") followed by set_elements([a]), then open sidebar B with set_title("B") followed by set_elements([b], key="b"). Click back and forth between the two. Steady state: #side-view-title contains only the back-arrow button, no title text node after it. During each switch the title flashes for a render frame then vanishes. Body content renders fine; only the header title is lost.

The set_title handler writes the sideView atom, then the set_elements handler reads prev in its updater and falls back to title: prev?.title || '' when prev is undefined. Instrumenting the updater with a console.log shows prev observed as undefined on every set_elements call even though the preceding set_title handler just wrote to the atom synchronously in the same tick. Something in React 18 + Recoil 0.7.7's nextTree/Batcher interaction drops the staged write across socket.io event callbacks; I did not isolate the Recoil-internals bug.

It's hard to finesse the Recoil to coordinate state across two events so I Add ElementSidebar.set(title, elements, key=None) that emits a single set_sidebar frame carrying all three fields, and a frontend handler that writes the atom from the payload alone and never reading prev for state it did not produce. The existing set_title and set_elements APIs and handlers are untouched for back-compat; callers that migrate to .set() stop seeing the title loss.


Summary by cubic

Fixes the disappearing sidebar title when switching between sidebars by sending a single atomic update. Adds a new backend API and client handler to set title, elements, and key together without relying on prior state.

  • Bug Fixes
    • Added ElementSidebar.set(title, elements, key=None) to emit one set_sidebar payload; empty elements closes the sidebar.
    • Client listens to set_sidebar and sets sideView directly, avoiding the React 18 + Recoil batching race that dropped the title.
    • Keeps set_title and set_elements for back-compat; callers can migrate to .set() to prevent the flicker.
    • Skips redundant updates when key and title match; element URL hydration is preserved.

Written for commit a58f84d. Summary will update on new commits.

Open sidebar A with `ElementSidebar.set_title("A")` followed by
`set_elements([a])`, then open sidebar B with `set_title("B")` followed
by `set_elements([b], key="b")`. Click back and forth between the two.
Steady state: `#side-view-title` contains only the back-arrow button,
no title text node after it. During each switch the title flashes for
a render frame then vanishes. Body content renders fine; only the
header title is lost.

The `set_title` handler writes the sideView atom, then the
`set_elements` handler reads `prev` in its updater and falls back to
`title: prev?.title || ''` when prev is undefined. Instrumenting the
updater with a `console.log` shows `prev` observed as undefined on
every `set_elements` call even though the preceding `set_title`
handler just wrote to the atom synchronously in the same tick.
Something in React 18 + Recoil 0.7.7's nextTree/Batcher interaction
drops the staged write across socket.io event callbacks; I did not
isolate the Recoil-internals bug.

Rather than chase the Recoil bug, stop coordinating state across two
events. Add `ElementSidebar.set(title, elements, key=None)` that emits
a single `set_sidebar` frame carrying all three fields, and a frontend
handler that writes the atom from the payload alone -- never reading
`prev` for state it did not produce. The existing `set_title` and
`set_elements` APIs and handlers are untouched for back-compat;
callers that migrate to `.set()` stop seeing the title loss.
@dosubot dosubot Bot added size:M This PR changes 30-99 lines, ignoring generated files. bug Something isn't working frontend Pertains to the frontend. labels Apr 22, 2026
Copy link
Copy Markdown
Contributor

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

Choose a reason for hiding this comment

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

No issues found across 2 files

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 7, 2026

This PR is stale because it has been open for 14 days with no activity.

@github-actions github-actions Bot added the stale Issue has not had recent activity or appears to be solved. Stale issues will be automatically closed label May 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working frontend Pertains to the frontend. size:M This PR changes 30-99 lines, ignoring generated files. stale Issue has not had recent activity or appears to be solved. Stale issues will be automatically closed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant