fix: Retain scroll position when navigating through document history

closes #4087
This commit is contained in:
Tom Moor
2022-09-08 13:01:01 +01:00
parent 810ef2134a
commit c2876ca396
6 changed files with 33 additions and 14 deletions

View File

@@ -6,7 +6,7 @@ import {
CompositeStateReturn,
} from "reakit/Composite";
type Props = {
type Props = React.HTMLAttributes<HTMLDivElement> & {
children: (composite: CompositeStateReturn) => React.ReactNode;
onEscape?: (ev: React.KeyboardEvent<HTMLDivElement>) => void;
};

View File

@@ -1,3 +1,4 @@
import { LocationDescriptor } from "history";
import { observer } from "mobx-react";
import {
TrashIcon,
@@ -39,7 +40,7 @@ const EventListItem = ({ event, latest, document, ...rest }: Props) => {
userName: event.actor.name,
};
const isRevision = event.name === "revisions.create";
let meta, icon, to;
let meta, icon, to: LocationDescriptor | undefined;
const ref = React.useRef<HTMLAnchorElement>(null);
// the time component tends to steal focus when clicked
@@ -58,13 +59,19 @@ const EventListItem = ({ event, latest, document, ...rest }: Props) => {
case "revisions.create":
icon = <EditIcon color="currentColor" size={16} />;
meta = t("{{userName}} edited", opts);
to = documentHistoryUrl(document, event.modelId || "");
to = {
pathname: documentHistoryUrl(document, event.modelId || ""),
state: { retainScrollPosition: true },
};
break;
case "documents.live_editing":
icon = <LightningIcon color="currentColor" size={16} />;
meta = t("Live editing");
to = documentHistoryUrl(document);
meta = t("Latest");
to = {
pathname: documentHistoryUrl(document),
state: { retainScrollPosition: true },
};
break;
case "documents.archive":
@@ -108,7 +115,10 @@ const EventListItem = ({ event, latest, document, ...rest }: Props) => {
return null;
}
const isActive = location.pathname === to;
const isActive =
typeof to === "string"
? location.pathname === to
: location.pathname === to?.pathname;
if (document.isDeleted) {
to = undefined;

View File

@@ -1,3 +1,4 @@
import { LocationDescriptor } from "history";
import * as React from "react";
import styled, { useTheme } from "styled-components";
import Flex from "~/components/Flex";
@@ -5,7 +6,7 @@ import NavLink from "~/components/NavLink";
export type Props = Omit<React.HTMLAttributes<HTMLAnchorElement>, "title"> & {
image?: React.ReactNode;
to?: string;
to?: LocationDescriptor;
exact?: boolean;
title: React.ReactNode;
subtitle?: React.ReactNode;
@@ -72,7 +73,7 @@ const ListItem = (
const Wrapper = styled.a<{
$small?: boolean;
$border?: boolean;
to?: string;
to?: LocationDescriptor;
}>`
display: flex;
padding: ${(props) => (props.$border === false ? 0 : "8px 0")};

View File

@@ -1,3 +1,4 @@
import { LocationDescriptor } from "history";
import * as React from "react";
import { match, NavLink, Route } from "react-router-dom";
@@ -12,7 +13,7 @@ type Props = React.ComponentProps<typeof NavLink> & {
) => React.ReactNode;
exact?: boolean;
activeStyle?: React.CSSProperties;
to: string;
to: LocationDescriptor;
};
function NavLinkWithChildrenFunc(
@@ -20,7 +21,7 @@ function NavLinkWithChildrenFunc(
ref?: React.Ref<HTMLAnchorElement>
) {
return (
<Route path={to} exact={exact}>
<Route path={typeof to === "string" ? to : to?.pathname} exact={exact}>
{({ match, location }) => (
<NavLink {...rest} to={to} exact={exact} ref={ref}>
{children

View File

@@ -8,11 +8,14 @@ type Props = {
};
export default function ScrollToTop({ children }: Props) {
const location = useLocation();
const location = useLocation<{ retainScrollPosition?: boolean }>();
const previousLocationPathname = usePrevious(location.pathname);
React.useEffect(() => {
if (location.pathname === previousLocationPathname) {
if (
location.pathname === previousLocationPathname ||
location.state?.retainScrollPosition
) {
return;
}
// exception for when entering or exiting document edit, scroll position should not reset
@@ -23,7 +26,11 @@ export default function ScrollToTop({ children }: Props) {
return;
}
window.scrollTo(0, 0);
}, [location.pathname, previousLocationPathname]);
}, [
location.pathname,
previousLocationPathname,
location.state?.retainScrollPosition,
]);
return children;
}