Skip to content

ui: UX Imporovements for Chat Tabs and Scroll on Chat Conversation route load/refresh + transition/animation improvements - #31030

Merged
ggerganov merged 9 commits into
masterfrom
allozaur/ui/chat-landing-and-tabs
Oct 26, 2026
Merged

ggerganov merged 9 commits into
masterfrom
allozaur/ui/chat-landing-and-tabs

Conversation

@allozaur

@allozaur allozaur commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

Overview

Conversation tabs behave like browser tabs: a plain navigation reuses the current tab, and only an explicit action (Cmd/Ctrl-click, middle-click, "Open in new tab", the New chat button) adds one. Opening or refreshing a conversation now lands at its bottom before the first paint, and following a streaming response only stops when the reader really scrolls up. Also fades the chat form between its centered and bottom positions, and stops the page and dialogs from elastic-bouncing past their ends.

Details

  • Tabs: route sync replaces the current tab instead of growing the strip on every navigation; openInNewTab() is the only way to add one and opens in the background by default. Route/tab resolution moves to a chat-tabs util; closing a tab picks the neighbour from the visible tabs.
  • Landing: the bottom is re-pinned from a ResizeObserver, so every late resize (lazy rows, content-visibility, highlighting) is corrected in the frame that caused it. The last 8 rows mount eagerly; SvelteKit's own scroll reset is disabled for chat routes.
  • Auto-scroll: wheel-up, touch, scroll keys and scrollbar drag count as intent (250 ms window); scroll anchoring and re-renders no longer cancel following.
  • Layout: the tab bar offset accounts for its full height, the tab fade and tab surfaces become shared styles.
  • New unit tests for the tabs store.

Requirements

  • I have read and agree with the contributing guidelines
  • AI usage disclosure: YES, Claude (Opus 5.5 Medium) + llama-ui (ggml-org/Qwen3.8-Flash-Next:IQ4_NL + MTP:Q4_0)

@allozaur
allozaur force-pushed the allozaur/ui/chat-landing-and-tabs branch 2 times, most recently from cd54e5e to be794e4 Compare October 23, 2026 10:29
@allozaur
allozaur marked this pull request as ready for review October 23, 2026 11:14
@allozaur
allozaur requested a review from a team as a code owner October 23, 2026 11:14
Copilot AI balanced review requested due to automatic review settings October 23, 2026 11:14

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

An organization owner can choose the repository organization as the billing source for reviews requested by members with a paid Copilot license. Learn about Copilot code review billing.

@allozaur allozaur changed the title ui: UX Imporovements for Chat Tabs and Scroll on Chat Conversation route load/refresh ui: UX Imporovements for Chat Tabs and Scroll on Chat Conversation route load/refresh + transition/animation improvements Oct 23, 2026
Pin the page to its bottom with a ResizeObserver until it stops resizing or the reader interacts, and mount the last rows eagerly so the landing frame shows real content.

Assisted by: Claude (Opus 5.5 Medium)
A plain navigation shows the chat in the current tab instead of adding one, and the new-chat tab turns into the conversation it starts. New tabs come only from explicit actions: the + button, Cmd/Ctrl-click or middle-click on a sidebar chat, and its Open in new tab menu item, which open in the background. Closing a tab moves to its neighbour among the tabs the view shows.

Assisted by: Claude (Opus 5.5 Medium)
Move the tab item surface (shape, resting and active looks) to TAB_SURFACE_* class constants and the fade under the tab bar to a global chat-top-fade class, so other elements can match the tabs.

Assisted by: Claude (Opus 5.5 Medium)
The tab bar reported 1.25rem of its height while it takes 3.3125rem (pt-3.25 + h-10), so a short conversation still left a few pixels to scroll. Use the bar's full height and drop the extra 1rem from the column's minimum height, so it fills the viewport exactly; the centered new-chat form moves up by the same 1rem to keep its place.

Assisted by: Claude (Opus 5.5 Medium)
Elastic overscroll on the root scroller dragged the sticky and fixed bars (tab bar, chat form) along at the top and bottom of a chat, and they jumped back on release. Set overscroll-behavior: none on html and body.

Assisted by: Claude (Opus 5.5 Medium)
Dialogs scroll on their own (the settings panel, the search results), so the page rule did not reach them and their sticky navigation still jumped on overscroll. Turn off overscroll on dialog panels and on the scroll containers inside them. Only scroll containers: Firefox counts an overflow-hidden box such as truncated text as one, and `none` there kept the wheel from scrolling the list around it.

Assisted by: Claude (Opus 5.5 Medium)
The last answer's minimum height leaves room for the last question only, so the synthetic row that a new chat starts with (Set working directory to ...) made a short first exchange overflow by that row. When everything above the last question is synthetic, count those rows as part of it.

Assisted by: Claude (Opus 5.5 Medium)
Auto-scroll stopped whenever the page moved up, including moves the
reader did not make: scroll anchoring and blocks re-rendering shorter
while a response streams. Only the reader's wheel, touch, scroll keys
or scrollbar drag now count as scrolling up.

The send scroll also looked up the new user bubble by position, which
picked an older message when the answer row had not rendered yet.

Assisted by: Claude (Opus 5.5 Medium)
The form no longer slides across the column between the new-chat center
and the bottom. It fades out drifting toward where it goes and fades
back in where it lands, quicker when opening a chat than when going back
to a new one. Its wrapper keeps the same height in both positions, so
the messages never shift while it moves.

The new-chat greeting fades in as the form settles, also on a refresh or
a first visit. Reduced motion keeps only the fades.

Assisted by: Claude (Opus 5.5 Medium)
@allozaur allozaur added the merge ready A maintainer can use this label to indicate that they consider the changes final and ready to merge. label Oct 25, 2026
@allozaur
allozaur force-pushed the allozaur/ui/chat-landing-and-tabs branch from be794e4 to 13680ec Compare October 25, 2026 09:06

@ServeurpersoCom ServeurpersoCom left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

(rebase)

@ggerganov
ggerganov merged commit dc9e3be into master Oct 26, 2026
9 checks passed
@ggerganov
ggerganov deleted the allozaur/ui/chat-landing-and-tabs branch October 26, 2026 08:13
auRose94 pushed a commit to auRose94/llama.cpp that referenced this pull request Oct 28, 2026
* ui : land opened conversations at their bottom before the first paint

Pin the page to its bottom with a ResizeObserver until it stops resizing or the reader interacts, and mount the last rows eagerly so the landing frame shows real content.

Assisted by: Claude (Opus 5.5 Medium)

* ui : make conversation tabs browser-style

A plain navigation shows the chat in the current tab instead of adding one, and the new-chat tab turns into the conversation it starts. New tabs come only from explicit actions: the + button, Cmd/Ctrl-click or middle-click on a sidebar chat, and its Open in new tab menu item, which open in the background. Closing a tab moves to its neighbour among the tabs the view shows.

Assisted by: Claude (Opus 5.5 Medium)

* ui : share the tab surface and tab bar fade styles

Move the tab item surface (shape, resting and active looks) to TAB_SURFACE_* class constants and the fade under the tab bar to a global chat-top-fade class, so other elements can match the tabs.

Assisted by: Claude (Opus 5.5 Medium)

* ui : fit the chat column below the tab bar

The tab bar reported 1.25rem of its height while it takes 3.3125rem (pt-3.25 + h-10), so a short conversation still left a few pixels to scroll. Use the bar's full height and drop the extra 1rem from the column's minimum height, so it fills the viewport exactly; the centered new-chat form moves up by the same 1rem to keep its place.

Assisted by: Claude (Opus 5.5 Medium)

* ui : stop the page from bouncing past its ends

Elastic overscroll on the root scroller dragged the sticky and fixed bars (tab bar, chat form) along at the top and bottom of a chat, and they jumped back on release. Set overscroll-behavior: none on html and body.

Assisted by: Claude (Opus 5.5 Medium)

* ui : stop scrolled dialogs from bouncing past their ends

Dialogs scroll on their own (the settings panel, the search results), so the page rule did not reach them and their sticky navigation still jumped on overscroll. Turn off overscroll on dialog panels and on the scroll containers inside them. Only scroll containers: Firefox counts an overflow-hidden box such as truncated text as one, and `none` there kept the wheel from scrolling the list around it.

Assisted by: Claude (Opus 5.5 Medium)

* ui : fit a first exchange opened by the working directory row

The last answer's minimum height leaves room for the last question only, so the synthetic row that a new chat starts with (Set working directory to ...) made a short first exchange overflow by that row. When everything above the last question is synthetic, count those rows as part of it.

Assisted by: Claude (Opus 5.5 Medium)

* ui : keep following a streaming response until the reader scrolls up

Auto-scroll stopped whenever the page moved up, including moves the
reader did not make: scroll anchoring and blocks re-rendering shorter
while a response streams. Only the reader's wheel, touch, scroll keys
or scrollbar drag now count as scrolling up.

The send scroll also looked up the new user bubble by position, which
picked an older message when the answer row had not rendered yet.

Assisted by: Claude (Opus 5.5 Medium)

* ui : fade the chat form between its centered and bottom positions

The form no longer slides across the column between the new-chat center
and the bottom. It fades out drifting toward where it goes and fades
back in where it lands, quicker when opening a chat than when going back
to a new one. Its wrapper keeps the same height in both positions, so
the messages never shift while it moves.

The new-chat greeting fades in as the form settles, also on a refresh or
a first visit. Reduced motion keeps only the fades.

Assisted by: Claude (Opus 5.5 Medium)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

merge ready A maintainer can use this label to indicate that they consider the changes final and ready to merge. server/ui

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants