mirror of
https://github.com/docmost/docmost.git
synced 2026-08-29 18:14:58 +08:00
feat(base): extend inline embed scroll viewport leftward, anchor first cell with grid padding
Bring back the leftward extension via negative margin-left so the scroll viewport reaches AppShell.Main's left edge, then offset the .grid with padding-left = extendLeft so the first cell still lines up with page-content on load. The extended area becomes scrollable empty space the user can pan into — same shape as Notion's inline databases. Done with one new CSS var (--embed-grid-pad-left) consumed by the .grid in grid.module.css. Standalone full-page bases never set the var, so it's a no-op there.
This commit is contained in:
@@ -315,14 +315,16 @@ export function BaseTable({ pageId, embedded }: BaseTableProps) {
|
|||||||
if (!base) return null;
|
if (!base) return null;
|
||||||
|
|
||||||
// When embedded inline in a doc page, the parent <NodeViewWrapper>
|
// When embedded inline in a doc page, the parent <NodeViewWrapper>
|
||||||
// exposes --embed-extend-r (positive px). We pull the grid's right
|
// exposes --embed-extend-l / --embed-extend-r (positive px). We
|
||||||
// edge outward via negative margin-right — box-model: width: auto
|
// pull both edges outward via negative margin so the scroll viewport
|
||||||
// becomes parent_width + |margin|, so the box physically grows past
|
// grows toward AppShell.Main's edges. Initial visual alignment with
|
||||||
// its parent's bounds. Left edge stays at the wrapper's natural
|
// page text is preserved by --embed-grid-pad-left, applied to the
|
||||||
// (page-content) position so the table aligns with page text on
|
// .grid in grid.module.css — that padding makes the first cell sit
|
||||||
// load. Toolbar is unchanged.
|
// at page-content-left on load while still letting the user pan
|
||||||
|
// left into the extended viewport. Toolbar is unchanged.
|
||||||
const gridExtendStyle = embedded
|
const gridExtendStyle = embedded
|
||||||
? ({
|
? ({
|
||||||
|
marginLeft: "calc(-1 * var(--embed-extend-l, 0px))",
|
||||||
marginRight: "calc(-1 * var(--embed-extend-r, 0px))",
|
marginRight: "calc(-1 * var(--embed-extend-r, 0px))",
|
||||||
} as const)
|
} as const)
|
||||||
: undefined;
|
: undefined;
|
||||||
|
|||||||
@@ -13,6 +13,12 @@
|
|||||||
border: 1px solid
|
border: 1px solid
|
||||||
light-dark(var(--mantine-color-gray-2), var(--mantine-color-dark-4));
|
light-dark(var(--mantine-color-gray-2), var(--mantine-color-dark-4));
|
||||||
border-radius: var(--mantine-radius-sm);
|
border-radius: var(--mantine-radius-sm);
|
||||||
|
/* When the embed wrapper extends the scroll viewport leftward, this
|
||||||
|
* padding pushes the first cell back to page-content alignment so
|
||||||
|
* the table looks aligned on load. The padded area is part of the
|
||||||
|
* scrollable region — the user can pan left into it. Standalone
|
||||||
|
* full-page bases never set the var, so it's a no-op there. */
|
||||||
|
padding-left: var(--embed-grid-pad-left, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
.headerRow {
|
.headerRow {
|
||||||
|
|||||||
@@ -6,23 +6,28 @@ import { useBaseQuery } from "@/features/base/queries/base-query";
|
|||||||
|
|
||||||
const SIDE_GUTTER = 8;
|
const SIDE_GUTTER = 8;
|
||||||
|
|
||||||
// Extend the grid only to the right — toward AppShell.Main's right
|
// Extend the scroll viewport on both sides (toward AppShell.Main's
|
||||||
// edge. The left edge stays at the wrapper's natural (page-content)
|
// edges), but offset the grid content with padding-left = extendLeft
|
||||||
// position so the table is visually aligned with the page text on
|
// so the first cell still lines up with page-content on load. The
|
||||||
// load, matching Notion. Leftward scroll-viewport extension is only
|
// extra leftward area becomes scrollable empty space the user can
|
||||||
// meaningful once we add frozen columns that need to lock at the
|
// pan into — same behavior as Notion's inline databases.
|
||||||
// sidebar edge; deferred until then.
|
|
||||||
function applyExtension(wrapper: HTMLDivElement) {
|
function applyExtension(wrapper: HTMLDivElement) {
|
||||||
const rect = wrapper.getBoundingClientRect();
|
const rect = wrapper.getBoundingClientRect();
|
||||||
if (rect.width === 0) return;
|
if (rect.width === 0) return;
|
||||||
|
|
||||||
const main = wrapper.closest("main") as HTMLElement | null;
|
const main = wrapper.closest("main") as HTMLElement | null;
|
||||||
const targetRight = main
|
const mainRect = main?.getBoundingClientRect();
|
||||||
? main.getBoundingClientRect().right - SIDE_GUTTER
|
const targetLeft = (mainRect?.left ?? 0) + SIDE_GUTTER;
|
||||||
|
const targetRight = mainRect
|
||||||
|
? mainRect.right - SIDE_GUTTER
|
||||||
: window.innerWidth - SIDE_GUTTER;
|
: window.innerWidth - SIDE_GUTTER;
|
||||||
|
|
||||||
|
const extendLeft = Math.max(0, rect.left - targetLeft);
|
||||||
const extendRight = Math.max(0, targetRight - rect.right);
|
const extendRight = Math.max(0, targetRight - rect.right);
|
||||||
|
|
||||||
|
wrapper.style.setProperty("--embed-extend-l", `${extendLeft}px`);
|
||||||
wrapper.style.setProperty("--embed-extend-r", `${extendRight}px`);
|
wrapper.style.setProperty("--embed-extend-r", `${extendRight}px`);
|
||||||
|
wrapper.style.setProperty("--embed-grid-pad-left", `${extendLeft}px`);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function BaseEmbedView({ node }: NodeViewProps) {
|
export function BaseEmbedView({ node }: NodeViewProps) {
|
||||||
|
|||||||
Reference in New Issue
Block a user