0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-04-15 03:01:37 -05:00

Added fixed height to avoid jumps in the Recommendations settings (#18184)

closes https://github.com/TryGhost/Product/issues/3881

We observe the height of the recommendation table, and keep it fixed between pages — so that the UX is smoother when navigating between pages.
This commit is contained in:
Sag 2023-09-18 17:43:57 +02:00 committed by GitHub
parent b545dfa0cc
commit 3b1fcb6c16
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 41 additions and 18 deletions

View file

@ -39,31 +39,55 @@ const Table: React.FC<TableProps> = ({header, children, borderTop, hint, hintSep
className
);
// We want to avoid layout jumps when we load a new page of the table, or when data is invalidated
const table = React.useRef<HTMLTableSectionElement>(null);
const maxTableHeight = React.useRef(0);
const [tableHeight, setTableHeight] = React.useState<number | undefined>(undefined);
const multiplePages = pagination && pagination.pages && pagination.pages > 1;
// Observe the height of the table content. This is used to:
// 1) avoid layout jumps when loading a new page of the table
// 2) keep the same table height between pages, cf. https://github.com/TryGhost/Product/issues/3881
React.useEffect(() => {
// Add resize observer to table
if (table.current) {
const resizeObserver = new ResizeObserver((entries) => {
const height = entries[0].target.clientHeight;
setTableHeight(height);
if (height > maxTableHeight.current) {
maxTableHeight.current = height;
}
});
resizeObserver.observe(table.current);
return () => {
resizeObserver.disconnect();
};
}
}, [isLoading]);
}, [isLoading, pagination]);
const loadingStyle = React.useMemo(() => {
if (tableHeight === undefined) {
return undefined;
return {
height: 'auto'
};
}
return {
height: tableHeight
height: maxTableHeight.current
};
}, [tableHeight]);
const spaceHeightStyle = React.useMemo(() => {
if (tableHeight === undefined) {
return {
height: 0
};
}
return {
height: maxTableHeight.current - tableHeight
};
}, [tableHeight]);
@ -71,18 +95,17 @@ const Table: React.FC<TableProps> = ({header, children, borderTop, hint, hintSep
<>
<div className='w-full overflow-x-auto'>
{pageTitle && <Heading>{pageTitle}</Heading>}
{/* TODO: make this div have the same height across all pages */}
<div>
<table className={tableClasses}>
{header && <thead className='border-b border-grey-200 dark:border-grey-600'>
<TableRow bgOnHover={false} separator={false}>{header}</TableRow>
</thead>}
{!isLoading && <tbody ref={table}>
{children}
</tbody>}
</table>
</div>
<table className={tableClasses}>
{header && <thead className='border-b border-grey-200 dark:border-grey-600'>
<TableRow bgOnHover={false} separator={false}>{header}</TableRow>
</thead>}
{!isLoading && <tbody ref={table}>
{children}
</tbody>}
{multiplePages && <div style={spaceHeightStyle} />}
</table>
{isLoading && <LoadingIndicator delay={200} size='lg' style={loadingStyle} />}

View file

@ -53,7 +53,7 @@ module.exports = {
apiType: 'content',
response: {}
};
const transacting = userOptions.transacting;
const response = await postsService.browsePosts({
context: {public: true}, // mimic Content API request