diff --git a/apps/client/src/features/base/components/base-table.tsx b/apps/client/src/features/base/components/base-table.tsx index 2bcdb529a..ab7f2508b 100644 --- a/apps/client/src/features/base/components/base-table.tsx +++ b/apps/client/src/features/base/components/base-table.tsx @@ -314,27 +314,16 @@ export function BaseTable({ pageId, embedded }: BaseTableProps) { if (!base) return null; - // When the table is embedded inline in a doc page, the parent - // measures the available area and exposes - // --embed-width / --embed-shift / --embed-pad. We extend the - // toolbar and grid sections out to the full available width via - // those vars, then re-pad the inner content so it visually aligns - // with page text. Sticky inset-inline-start keeps the toolbar - // pinned to the page-content edge during horizontal scroll. - const extendStyle = embedded + // When embedded inline in a doc page, the parent + // exposes --embed-extend-l / --embed-extend-r (positive px values). + // We pull the grid's left/right edges outward via negative margin — + // box-model: width: auto becomes parent_width + extend, so the box + // physically grows past its parent's bounds. The toolbar keeps the + // parent-constrained width so it stays in line with the page text. + const gridExtendStyle = embedded ? ({ - position: "relative", - width: "var(--embed-width, 100%)", - insetInlineStart: "var(--embed-shift, 0px)", - paddingInline: "var(--embed-pad, 0px)", - } as const) - : undefined; - - const stickyToolbarStyle = embedded - ? ({ - position: "sticky", - insetInlineStart: 0, - zIndex: 4, + marginLeft: "calc(-1 * var(--embed-extend-l, 0px))", + marginRight: "calc(-1 * var(--embed-extend-r, 0px))", } as const) : undefined; @@ -346,29 +335,25 @@ export function BaseTable({ pageId, embedded }: BaseTableProps) { height: embedded ? "auto" : "100%", }} > -
- -
- -
-
-
+ + +
baseWidth + 32) return cur; + const r = cur.getBoundingClientRect(); + if (r.width > rect.width + 32) { + targetLeft = r.left + LEFT_GUTTER; + break; + } cur = cur.parentElement; } - return null; -} + const extendLeft = Math.max(0, rect.left - targetLeft); -function applyExtension(wrapper: HTMLDivElement) { - const wrapperRect = wrapper.getBoundingClientRect(); - if (wrapperRect.width === 0) return; - const wider = findWiderAncestor(wrapper); - if (!wider) { - wrapper.style.setProperty("--embed-shift", "0px"); - wrapper.style.setProperty("--embed-width", "100%"); - wrapper.style.setProperty("--embed-pad", "0px"); - return; - } - const widerRect = wider.getBoundingClientRect(); - const targetLeft = widerRect.left + SIDE_GUTTER; - const targetWidth = widerRect.width - SIDE_GUTTER * 2; - const shift = targetLeft - wrapperRect.left; - wrapper.style.setProperty("--embed-shift", `${shift}px`); - wrapper.style.setProperty("--embed-width", `${targetWidth}px`); - // Re-pad inner content back to the original wrapper bounds so - // toolbar buttons / first column visually align with page text. - wrapper.style.setProperty("--embed-pad", `${-shift}px`); + wrapper.style.setProperty("--embed-extend-r", `${extendRight}px`); + wrapper.style.setProperty("--embed-extend-l", `${extendLeft}px`); } export function BaseEmbedView({ node }: NodeViewProps) { @@ -57,8 +54,17 @@ export function BaseEmbedView({ node }: NodeViewProps) { const ro = new ResizeObserver(update); ro.observe(wrapper); - const wider = findWiderAncestor(wrapper); - if (wider) ro.observe(wider); + // Also observe an ancestor so sidebar collapse / window changes + // propagate even when the wrapper itself doesn't resize. + let cur: HTMLElement | null = wrapper.parentElement; + while (cur && cur !== document.body) { + const r = cur.getBoundingClientRect(); + if (r.width > wrapper.getBoundingClientRect().width + 32) { + ro.observe(cur); + break; + } + cur = cur.parentElement; + } window.addEventListener("resize", update); return () => {