scroll up on active NavLink click, mobile messages & footer

This commit is contained in:
Martti Malmi 2023-12-01 17:33:36 +02:00
parent dda38ab824
commit 689839e043
7 changed files with 33 additions and 26 deletions

View File

@ -0,0 +1,20 @@
import { NavLink as RouterNavLink, NavLinkProps, useLocation } from "react-router-dom";
export default function NavLink(props: NavLinkProps) {
const { to, onClick, ...rest } = props;
const location = useLocation();
const isActive = location.pathname === to.toString();
const handleClick = (event) => {
if (onClick) {
onClick(event);
}
if (isActive) {
window.scrollTo({ top: 0, behavior: "instant" });
}
};
return <RouterNavLink to={to} onClick={handleClick} {...rest} />;
}

View File

@ -1,5 +1,5 @@
import React from "react"; import React from "react";
import { NavLink } from "react-router-dom"; import NavLink from "@/Element/Button/NavLink";
import useLogin from "@/Hooks/useLogin"; import useLogin from "@/Hooks/useLogin";
import Icon from "@/Icons/Icon"; import Icon from "@/Icons/Icon";
import { ProfileLink } from "@/Element/User/ProfileLink"; import { ProfileLink } from "@/Element/User/ProfileLink";

View File

@ -1,5 +1,5 @@
import { LogoHeader } from "./LogoHeader"; import { LogoHeader } from "./LogoHeader";
import { NavLink, useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
import Icon from "@/Icons/Icon"; import Icon from "@/Icons/Icon";
import { ProfileLink } from "../../Element/User/ProfileLink"; import { ProfileLink } from "../../Element/User/ProfileLink";
import Avatar from "../../Element/User/Avatar"; import Avatar from "../../Element/User/Avatar";
@ -10,6 +10,7 @@ import { FormattedMessage, useIntl } from "react-intl";
import classNames from "classnames"; import classNames from "classnames";
import { getCurrentSubscription } from "@/Subscription"; import { getCurrentSubscription } from "@/Subscription";
import { HasNotificationsMarker } from "@/Pages/Layout/HasNotificationsMarker"; import { HasNotificationsMarker } from "@/Pages/Layout/HasNotificationsMarker";
import NavLink from "@/Element/Button/NavLink";
const MENU_ITEMS = [ const MENU_ITEMS = [
{ {

View File

@ -1,4 +1,4 @@
import { Link, useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
import { base64 } from "@scure/base"; import { base64 } from "@scure/base";
import { unwrap } from "@snort/shared"; import { unwrap } from "@snort/shared";
import { FormattedMessage } from "react-intl"; import { FormattedMessage } from "react-intl";
@ -9,6 +9,7 @@ import useLogin from "@/Hooks/useLogin";
import useEventPublisher from "@/Hooks/useEventPublisher"; import useEventPublisher from "@/Hooks/useEventPublisher";
import SnortApi from "@/External/SnortApi"; import SnortApi from "@/External/SnortApi";
import { HasNotificationsMarker } from "@/Pages/Layout/HasNotificationsMarker"; import { HasNotificationsMarker } from "@/Pages/Layout/HasNotificationsMarker";
import NavLink from "@/Element/Button/NavLink";
const NotificationsHeader = () => { const NotificationsHeader = () => {
const navigate = useNavigate(); const navigate = useNavigate();
@ -70,10 +71,10 @@ const NotificationsHeader = () => {
return ( return (
<div className="flex justify-between"> <div className="flex justify-between">
<Link className="btn" to="/notifications" onClick={goToNotifications}> <NavLink className="btn" to="/notifications" onClick={goToNotifications}>
<Icon name="bell-02" size={24} /> <Icon name="bell-02" size={24} />
<HasNotificationsMarker /> <HasNotificationsMarker />
</Link> </NavLink>
</div> </div>
); );
}; };

View File

@ -21,7 +21,6 @@ import Footer from "@/Pages/Layout/Footer";
export default function Index() { export default function Index() {
const location = useLocation(); const location = useLocation();
const [pageClass, setPageClass] = useState("page");
const { id, stalker } = useLogin(s => ({ id: s.id, stalker: s.stalker ?? false })); const { id, stalker } = useLogin(s => ({ id: s.id, stalker: s.stalker ?? false }));
useTheme(); useTheme();
@ -29,22 +28,9 @@ export default function Index() {
useLoginFeed(); useLoginFeed();
const hideHeaderPaths = ["/login", "/new"]; const hideHeaderPaths = ["/login", "/new"];
const shouldHideFooter = location.pathname.startsWith("/messages/");
const shouldHideHeader = hideHeaderPaths.some(path => location.pathname.startsWith(path)); const shouldHideHeader = hideHeaderPaths.some(path => location.pathname.startsWith(path));
const pageClassPaths = useMemo(
() => ({
widePage: ["/login", "/messages"],
noScroll: ["/messages"],
}),
[],
);
useEffect(() => {
const isWidePage = pageClassPaths.widePage.some(path => location.pathname.startsWith(path));
const isNoScroll = pageClassPaths.noScroll.some(path => location.pathname.startsWith(path));
setPageClass(isWidePage ? (isNoScroll ? "scroll-lock" : "") : "page");
}, [location, pageClassPaths]);
const handleKeyboardShortcut = useCallback(event => { const handleKeyboardShortcut = useCallback(event => {
if (event.target && !isFormElement(event.target as HTMLElement)) { if (event.target && !isFormElement(event.target as HTMLElement)) {
event.preventDefault(); event.preventDefault();
@ -58,7 +44,7 @@ export default function Index() {
return ( return (
<div className="flex justify-center"> <div className="flex justify-center">
<div className={`${pageClass} w-full max-w-screen-xl`}> <div className="w-full max-w-screen-xl">
{!shouldHideHeader && <Header />} {!shouldHideHeader && <Header />}
<div className="flex flex-row w-full"> <div className="flex flex-row w-full">
<NavSidebar /> <NavSidebar />
@ -73,7 +59,7 @@ export default function Index() {
</div> </div>
<LoginUnlock /> <LoginUnlock />
{isStalker && <StalkerModal id={id} />} {isStalker && <StalkerModal id={id} />}
<Footer /> {!shouldHideFooter && <Footer/>}
</div> </div>
); );
} }

View File

@ -88,9 +88,9 @@ export default function MessagesPage() {
} }
return ( return (
<div className="flex flex-1 h-screen overflow-hidden"> <div className="flex flex-1 md:h-screen md:overflow-hidden">
{(pageWidth >= TwoCol || !chat) && ( {(pageWidth >= TwoCol || !chat) && (
<div className="overflow-y-auto h-screen p-1 w-full md:w-1/3 flex-shrink-0"> <div className="overflow-y-auto md:h-screen p-1 w-full md:w-1/3 flex-shrink-0">
<div className="flex items-center justify-between p-2"> <div className="flex items-center justify-between p-2">
<button disabled={unreadCount <= 0} type="button" className="text-sm font-semibold"> <button disabled={unreadCount <= 0} type="button" className="text-sm font-semibold">
<FormattedMessage defaultMessage="Mark all read" id="ShdEie" /> <FormattedMessage defaultMessage="Mark all read" id="ShdEie" />

View File

@ -357,7 +357,6 @@ export default function ProfilePage({ id: propId, state }: ProfilePageProps) {
return <TabElement key={v.value} t={v} tab={tab} setTab={setTab} />; return <TabElement key={v.value} t={v} tab={tab} setTab={setTab} />;
} }
const w = window.document.querySelector(".page")?.clientWidth;
return ( return (
<> <>
<div className="profile"> <div className="profile">
@ -366,7 +365,7 @@ export default function ProfilePage({ id: propId, state }: ProfilePageProps) {
alt="banner" alt="banner"
className="banner pointer" className="banner pointer"
src={user.banner} src={user.banner}
size={w} size={940}
onClick={() => setModalImage(user.banner || "")} onClick={() => setModalImage(user.banner || "")}
/> />
)} )}