fix: Exclude nested tables from sticky scrollbar

Share the nested-table check between the sticky header and sticky
scrollbar via a memoized isNestedTable() helper, so a nested table that
overflows horizontally no longer shows a viewport-pinned floating
scrollbar from the constructor tick or update().

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Tom Moor
2026-06-02 08:49:03 -04:00
parent dc3484120c
commit e331be0572
+25 -5
View File
@@ -148,6 +148,8 @@ export class TableView extends ProsemirrorTableView {
private syncingScroll = false;
private nestedTable: boolean | null = null;
private scrollHandler: ((event: Event) => void) | null = null;
private resizeHandler: (() => void) | null = null;
@@ -168,7 +170,7 @@ export class TableView extends ProsemirrorTableView {
// Defer setup to ensure DOM is fully rendered
setTimeout(() => {
// Skip sticky behavior for nested tables
if (this.dom.closest(`table .${EditorStyleHelper.table}`)) {
if (this.isNestedTable()) {
return;
}
@@ -298,11 +300,13 @@ export class TableView extends ProsemirrorTableView {
const viewportHeight =
window.innerHeight || document.documentElement.clientHeight;
// Only show the floating scrollbar when the browser renders persistent
// scrollbars (otherwise the table can be scrolled by gesture and a floating
// bar would look out of place), the table overflows horizontally, is within
// view, and its real scrollbar sits below the bottom of the viewport.
// Only show the floating scrollbar when this is not a nested table, the
// browser renders persistent scrollbars (otherwise the table can be
// scrolled by gesture and a floating bar would look out of place), the
// table overflows horizontally, is within view, and its real scrollbar sits
// below the bottom of the viewport.
const shouldShow =
!this.isNestedTable() &&
hasVisibleScrollbars() &&
overflows &&
rect.top < viewportHeight &&
@@ -340,6 +344,22 @@ export class TableView extends ProsemirrorTableView {
}
}
/**
* Returns whether this table is nested within another table. Nested tables
* are excluded from sticky header and sticky scrollbar behavior. The result
* is memoized once the DOM is connected, as nesting is structural and stable.
*
* @returns whether the table is nested within another table.
*/
private isNestedTable(): boolean {
if (this.nestedTable === null && isBrowser && this.dom.isConnected) {
this.nestedTable = !!this.dom.closest(
`table .${EditorStyleHelper.table}`
);
}
return this.nestedTable ?? false;
}
/**
* Gets the current header offset from the CSS variable.
*