diff --git a/app/components/ArrowKeyNavigation.tsx b/app/components/ArrowKeyNavigation.tsx index 7033e58ad..02bb0d697 100644 --- a/app/components/ArrowKeyNavigation.tsx +++ b/app/components/ArrowKeyNavigation.tsx @@ -6,7 +6,7 @@ import { CompositeStateReturn, } from "reakit/Composite"; -type Props = { +type Props = React.HTMLAttributes & { children: (composite: CompositeStateReturn) => React.ReactNode; onEscape?: (ev: React.KeyboardEvent) => void; }; diff --git a/app/components/EventListItem.tsx b/app/components/EventListItem.tsx index 58034b869..ff22994a7 100644 --- a/app/components/EventListItem.tsx +++ b/app/components/EventListItem.tsx @@ -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(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 = ; 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 = ; - 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; diff --git a/app/components/List/Item.tsx b/app/components/List/Item.tsx index 708e7d016..25c86e34f 100644 --- a/app/components/List/Item.tsx +++ b/app/components/List/Item.tsx @@ -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, "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")}; diff --git a/app/components/NavLink.tsx b/app/components/NavLink.tsx index a81ff4f72..889ac3cd4 100644 --- a/app/components/NavLink.tsx +++ b/app/components/NavLink.tsx @@ -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 & { ) => React.ReactNode; exact?: boolean; activeStyle?: React.CSSProperties; - to: string; + to: LocationDescriptor; }; function NavLinkWithChildrenFunc( @@ -20,7 +21,7 @@ function NavLinkWithChildrenFunc( ref?: React.Ref ) { return ( - + {({ match, location }) => ( {children diff --git a/app/components/ScrollToTop.ts b/app/components/ScrollToTop.ts index d7638e9a2..d9ffbe464 100644 --- a/app/components/ScrollToTop.ts +++ b/app/components/ScrollToTop.ts @@ -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; } diff --git a/shared/i18n/locales/en_US/translation.json b/shared/i18n/locales/en_US/translation.json index 1e95be70b..ffd0f0e96 100644 --- a/shared/i18n/locales/en_US/translation.json +++ b/shared/i18n/locales/en_US/translation.json @@ -144,7 +144,7 @@ "Report a Bug": "Report a Bug", "Show Detail": "Show Detail", "{{userName}} edited": "{{userName}} edited", - "Live editing": "Live editing", + "Latest": "Latest", "{{userName}} archived": "{{userName}} archived", "{{userName}} restored": "{{userName}} restored", "{{userName}} deleted": "{{userName}} deleted",