mirror of
https://github.com/docmost/docmost.git
synced 2026-08-31 10:55:29 +08:00
fix(base): keep editor scroll stable when inline-embed creation completes
The placeholder rendered the full 10-row BaseTableSkeleton (~440px)
while waiting for the create response, then BaseTable mounted, ran its
own queries, and rendered the same 10-row skeleton again until rows
loaded. The actual content for a freshly-created empty base is ~112px
— so the swap shrank the doc by ~330px and on a short page the
browser clamped scrollY past the new doc bottom, manifesting as a
"jump to top of editor."
Two changes to keep the height constant end-to-end:
1. BaseTableSkeleton now accepts a `rows` prop (default 10). The
placeholder in BaseEmbedView passes `rows={0}` so the skeleton
matches the height of the eventual empty base shell — header row +
AddRow button, no fake body rows.
2. The Database slash command now seeds `["bases", id]` and the
`["base-rows", id, undefined, undefined, undefined]` infinite-query
cache from the create response (the endpoint already returns the
full base with properties + views; the typed return was just too
narrow). BaseTable mounts with baseLoading/rowsLoading already
false and skips its own skeleton — no transient grow-then-shrink
between placeholder and final content.
End state: placeholder height ≈ rendered-empty-base height, and no
intermediate skeleton appears while BaseTable is "loading." The
scrollY clamp can't fire because the doc never shrinks.
This commit is contained in:
@@ -5,14 +5,24 @@ import classes from "@/features/base/styles/base-table-skeleton.module.css";
|
||||
const ROW_NUMBER_WIDTH = 64;
|
||||
const COLUMN_WIDTH = 180;
|
||||
const COLUMN_COUNT = 6;
|
||||
const ROW_COUNT = 10;
|
||||
const DEFAULT_ROW_COUNT = 10;
|
||||
|
||||
// Deterministic per-cell widths so the skeleton doesn't flicker between
|
||||
// renders. Values are rough normal distribution around 55-85 % of cell.
|
||||
const CELL_WIDTH_RATIOS = [0.78, 0.62, 0.84, 0.55, 0.71, 0.66];
|
||||
const HEADER_WIDTH_RATIOS = [0.42, 0.58, 0.5, 0.64, 0.46, 0.54];
|
||||
|
||||
export function BaseTableSkeleton() {
|
||||
type BaseTableSkeletonProps = {
|
||||
// Override the body row count. Pass 0 when rendering as the
|
||||
// "creating database" placeholder for a freshly-inserted inline embed
|
||||
// — the eventual empty base has no rows, so a 10-row skeleton would
|
||||
// shrink ~330px on swap and trip the browser's scrollY clamp.
|
||||
rows?: number;
|
||||
};
|
||||
|
||||
export function BaseTableSkeleton({
|
||||
rows = DEFAULT_ROW_COUNT,
|
||||
}: BaseTableSkeletonProps = {}) {
|
||||
const gridTemplateColumns = [
|
||||
`${ROW_NUMBER_WIDTH}px`,
|
||||
...Array.from({ length: COLUMN_COUNT }, () => `${COLUMN_WIDTH}px`),
|
||||
@@ -54,7 +64,7 @@ export function BaseTableSkeleton() {
|
||||
</div>
|
||||
))}
|
||||
|
||||
{Array.from({ length: ROW_COUNT }).map((_, rowIndex) => (
|
||||
{Array.from({ length: rows }).map((_, rowIndex) => (
|
||||
<div key={`row-${rowIndex}`} style={{ display: "contents" }}>
|
||||
<div className={gridClasses.cell}>
|
||||
<div className={classes.cellInner}>
|
||||
|
||||
Reference in New Issue
Block a user