fix(nav): stop the native chat list overscrolling when its content fits the window

This commit is contained in:
heaven 2026-06-07 01:46:40 +03:00
parent 2581ff8137
commit 674616f398
2 changed files with 36 additions and 2 deletions

View file

@ -395,8 +395,33 @@ export function PageNavContent({
size="300"
hideTrack
visibility="Hover"
// folds `direction="Vertical"` sets `overflow-y: scroll`, which makes
// this a *user-scrollable* container even when the list fits (scroll
// range 0, permanently pinned at its boundary). On Android any
// touch-drag on such a boundary-pinned scroller fires the elastic
// overscroll stretch — the list "bounces" though it has nothing to
// scroll. `overflow-y: auto` is user-scrollable only when content
// actually overflows: short lists become inert (no overscroll), long
// lists still scroll normally. Inline style wins over the recipe class.
style={{ overflowY: 'auto' }}
>
<div className={css.PageNavContent}>{children}</div>
{/* `css.PageNavContent` carries a 32px (`S700`) bottom padding for
breathing room below the last row. That padding is part of the
scroll content, so once the list grows to within 32px of the
viewport it overflows by however much of the padding doesn't fit
the list visually "fits" (a gap shows below it) yet you can still
scroll a few px into the leftover padding. On native the curtain
list already has its own bottom boundary (the pinned DirectSelfRow /
WorkspaceFooter, or the screen edge), so the in-scroll breather is
redundant; dropping it there means a list that fits has zero scroll
range. Desktop keeps the breather (mouse-scrolling into it is
harmless and the last row wants the air at the panel bottom). */}
<div
className={css.PageNavContent}
style={isNativePlatform() ? { paddingBottom: 0 } : undefined}
>
{children}
</div>
</Scroll>
</Box>
);

View file

@ -143,7 +143,16 @@ export const PageNavHeader = recipe({
export type PageNavHeaderVariants = RecipeVariants<typeof PageNavHeader>;
export const PageNavContent = style({
minHeight: '100%',
// No `min-height: 100%`. It used to force this padded wrapper to at least
// the scroll viewport's height, but the div is transparent (the curtain on
// native / the PageNav inner column on web paints the background) so the
// fill was invisible — its only real effect was a ~1px scroll overflow:
// `100%` resolves against the fractional flex-parent height and rounds UP
// while the viewport's clientHeight rounds DOWN, leaving the list
// permanently scrollable by a hair even when it fits. That hair is the
// "useless" overscroll on native. Letting the wrapper size to its content
// means a short list has no scroll range at all (paired with the
// `overflow-y: auto` override on the Scroll in Page.tsx).
padding: config.space.S200,
paddingRight: 0,
paddingBottom: config.space.S700,