Skip to content

fix(conversation): show the map only while the conversation scrolls - #167

Open
pratikbuilds wants to merge 1 commit into
corbitsdev:mainfrom
pratikbuilds:fix/conversation-map-only-when-scrolling
Open

pratikbuilds wants to merge 1 commit into
corbitsdev:mainfrom
pratikbuilds:fix/conversation-map-only-when-scrolling

Conversation

@pratikbuilds

Copy link
Copy Markdown
Collaborator

Summary

ConversationMap now renders only while the conversation is taller than its view, so a short chat that fits on screen gets no rail with nowhere to jump to.

  • Overflow in the engine: on mount and on every resize of the log or its column, the conversation checks whether the content is taller than the view (contentOverflows in lib/conversation-scroll.ts). The space settle reserves after a sent item does not count, so a fitting chat padded out by its reserve still fits. There is 1px of slack for subpixel rounding.
  • Exposed to hosts: useConversation() gains overflowing, and Conversation carries data-overflowing while the content overflows. A host can give the column room for the rail only then, e.g. [&[data-overflowing]_[data-slot=conversation-column]]:pl-12 on Conversation. Both are additive; nothing existing changes shape. Both are false on the server and while no ConversationContent is mounted.
  • No flicker: toggling the rail's padding cannot make the map oscillate. Adding the padding makes the content taller when the map appears, and removing it makes the content shorter when the map goes, so each state holds.
  • Focus and preview: when the rail goes while a tick has focus, focus moves to the log. A preview that was open does not come back with the rail.
  • Story: the FewTurns pane is resizable and pads its column on data-overflowing, so it shows the map coming and going.

Overlap with #145

#145 also moves focus and clears the preview when the map hides (for fewer than two turns). Both touch the same effects in conversation-map.tsx. Whichever lands second needs a rebase; the behaviour is the same.

Verification

  • bun run check (891 tests), bun run build and bun run dep-guard pass.
  • New tests cover the map hiding and showing as the content grows and shrinks and as the window grows, the reserve not counting as overflow, overflow measured at mount, overflowing resetting when the log unmounts, and focus moving to the log when the rail goes.
  • Each new test fails when the behaviour it covers is reverted. With the preview clear removed, the test loops instead of failing.
  • Checked in Storybook in Chrome: FewTurns at 480px fits, with no map and 16px of padding. Shrunk to 160px it scrolls, and shows two ticks with 48px of padding. Grown back, both go again. ManyTurns keeps its 150 ticks.

Follow-up in Builder after a release: bump @corbits/react-ui, and move the column padding from data-mapped onto data-overflowing (corbitsdev/corbits-builder#154).

Closes #166

ConversationMap hid only below two turns, so two short turns that fit
the view still got a rail with nowhere to jump to. The engine now tracks
whether the content is taller than the view on every resize, not counting
the room `settle` reserves after a sent item, and the map renders only
then. useConversation() exposes it as `overflowing`, and Conversation
carries `data-overflowing`, so a host can give the column room for the
rail only while it shows.

Toggling that room cannot flicker: the padding makes the content taller
when the map appears and shorter when it goes, which keeps each state.

When the rail goes while a tick has focus, focus moves to the log, and a
preview open then does not come back with the rail.
@corbits-triage

corbits-triage Bot commented Nov 4, 2026 •

Copy link
Copy Markdown
Contributor

Triage: Pass

No changes needed from you. A maintainer will review this pull request.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ConversationMap shows on a conversation that does not scroll

1 participant