merge with softNavigate pagination changes from #601

This commit is contained in:
James Fenn
2023-07-11 11:29:07 -04:00
parent 0f99740cba
commit 6b9df317a1
4 changed files with 67 additions and 11 deletions

View File

@@ -0,0 +1,26 @@
export const onSoftNavClick =
(softNavigate: (href: string) => void) => (e: MouseEvent) => {
let link = e.target as HTMLElement;
// Could click on a child element of an anchor
while (link && !(link instanceof HTMLAnchorElement)) {
link = link.parentElement;
}
if (!link) return;
if (
link instanceof HTMLAnchorElement &&
link.href &&
(!link.target || link.target === "_self") &&
link.origin === location.origin &&
e.button === 0 && // left click only
!e.metaKey && // open in new tab (mac)
!e.ctrlKey && // open in new tab (windows)
!e.altKey && // download
!e.shiftKey && // open in new window
!e.defaultPrevented
) {
e.preventDefault();
softNavigate(link.href);
}
};

View File

@@ -11,7 +11,7 @@ import {
} from "@floating-ui/react"; } from "@floating-ui/react";
import { useRef, useState } from "preact/hooks"; import { useRef, useState } from "preact/hooks";
import { Fragment } from "preact"; import { Fragment } from "preact";
import { createPortal } from "preact/compat"; import { createPortal, StateUpdater } from "preact/compat";
import mainStyles from "./pagination.module.scss"; import mainStyles from "./pagination.module.scss";
import more from "src/icons/more_horiz.svg?raw"; import more from "src/icons/more_horiz.svg?raw";
import { PaginationProps } from "components/pagination/types"; import { PaginationProps } from "components/pagination/types";
@@ -21,14 +21,23 @@ import subtract from "../../icons/subtract.svg?raw";
import add from "../../icons/add.svg?raw"; import add from "../../icons/add.svg?raw";
import { Input } from "components/input/input"; import { Input } from "components/input/input";
function PopupContents(props: Pick<PaginationProps, "page" | "getPageHref">) { function PopupContents(
props: Pick<PaginationProps, "page" | "getPageHref" | "softNavigate"> & {
setIsOpen: StateUpdater<boolean>;
}
) {
const [count, setCount] = useState(props.page.currentPage); const [count, setCount] = useState(props.page.currentPage);
return ( return (
<form <form
class={style.popupInner} class={style.popupInner}
onSubmit={(e) => { onSubmit={(e) => {
e.preventDefault(); e.preventDefault();
location.href = `/page/${count}`; if (props.softNavigate) {
props.softNavigate(props.getPageHref(count));
props.setIsOpen(false);
return;
}
location.href = props.getPageHref(count);
}} }}
> >
<div class={style.popupTopArea}> <div class={style.popupTopArea}>
@@ -80,7 +89,7 @@ function PopupContents(props: Pick<PaginationProps, "page" | "getPageHref">) {
} }
export function PaginationMenuAndPopover( export function PaginationMenuAndPopover(
props: Pick<PaginationProps, "page" | "getPageHref"> props: Pick<PaginationProps, "page" | "getPageHref" | "softNavigate">
) { ) {
const [isOpen, setIsOpen] = useState(false); const [isOpen, setIsOpen] = useState(false);
const arrowRef = useRef(null); const arrowRef = useRef(null);
@@ -90,7 +99,7 @@ export function PaginationMenuAndPopover(
placement: "top", placement: "top",
onOpenChange: setIsOpen, onOpenChange: setIsOpen,
middleware: [ middleware: [
offset(32 - (14 / 2)), offset(32 - 14 / 2),
arrow({ arrow({
element: arrowRef, element: arrowRef,
}), }),
@@ -120,7 +129,7 @@ export function PaginationMenuAndPopover(
{...getFloatingProps()} {...getFloatingProps()}
class={style.popup} class={style.popup}
> >
<PopupContents {...props} /> <PopupContents {...props} setIsOpen={setIsOpen} />
<FloatingArrow <FloatingArrow
ref={arrowRef} ref={arrowRef}
context={context} context={context}

View File

@@ -5,12 +5,14 @@ import { PaginationMenuAndPopover } from "components/pagination/pagination-popov
import { useEffect, useState } from "preact/hooks"; import { useEffect, useState } from "preact/hooks";
import { PaginationButtonProps, PaginationProps } from "components/pagination/types"; import { PaginationButtonProps, PaginationProps } from "components/pagination/types";
import { usePagination } from "./use-pagination"; import { usePagination } from "./use-pagination";
import { onSoftNavClick } from "./on-click-base";
function PaginationButton({ function PaginationButton({
pageInfo, pageInfo,
pageNum, pageNum,
href, href,
selected selected,
softNavigate,
}: PaginationButtonProps) { }: PaginationButtonProps) {
const pageOptionalMin = Math.min(Math.max(1, pageInfo.currentPage - 1), pageInfo.lastPage - 3); const pageOptionalMin = Math.min(Math.max(1, pageInfo.currentPage - 1), pageInfo.lastPage - 3);
const isOptional = pageNum < pageOptionalMin || pageNum > pageOptionalMin + 3; const isOptional = pageNum < pageOptionalMin || pageNum > pageOptionalMin + 3;
@@ -22,6 +24,7 @@ function PaginationButton({
selected ? styles.selected : "" selected ? styles.selected : ""
}`} }`}
href={href} href={href}
onClick={softNavigate ? onSoftNavClick(softNavigate) : undefined}
aria-label={`Go to page ${pageNum}`} aria-label={`Go to page ${pageNum}`}
aria-current={selected || undefined} aria-current={selected || undefined}
> >
@@ -35,7 +38,7 @@ function PaginationButton({
* This prevents the pagination menu from rendering on SSR, which throws errors * This prevents the pagination menu from rendering on SSR, which throws errors
*/ */
function PaginationMenuWrapper( function PaginationMenuWrapper(
props: Pick<PaginationProps, "page" | "getPageHref"> props: Pick<PaginationProps, "page" | "getPageHref" | "softNavigate">
) { ) {
const [shouldRender, setShouldRender] = useState(false); const [shouldRender, setShouldRender] = useState(false);
@@ -54,6 +57,7 @@ export const Pagination = ({
class: className = "", class: className = "",
id = "post-list-pagination", id = "post-list-pagination",
getPageHref = (pageNum: number) => `${rootURL}${pageNum}`, getPageHref = (pageNum: number) => `${rootURL}${pageNum}`,
softNavigate,
}: PaginationProps) => { }: PaginationProps) => {
// if there's only one page, don't render anything // if there's only one page, don't render anything
if (page.currentPage === 1 && page.lastPage < 2) return <></>; if (page.currentPage === 1 && page.lastPage < 2) return <></>;
@@ -68,7 +72,12 @@ export const Pagination = ({
<a <a
className={`text-style-body-medium-bold ${styles.paginationButton} ${styles.paginationIconButton}`} className={`text-style-body-medium-bold ${styles.paginationButton} ${styles.paginationIconButton}`}
aria-label="Previous" aria-label="Previous"
href={!isPreviousEnabled ? "javascript:void(0)" : getPageHref(page.currentPage - 1)} href={
!isPreviousEnabled
? "javascript:void(0)"
: getPageHref(page.currentPage - 1)
}
onClick={softNavigate ? onSoftNavClick(softNavigate) : undefined}
aria-disabled={!isPreviousEnabled} aria-disabled={!isPreviousEnabled}
dangerouslySetInnerHTML={{ __html: back }} dangerouslySetInnerHTML={{ __html: back }}
/> />
@@ -81,16 +90,26 @@ export const Pagination = ({
pageNum={pageNum} pageNum={pageNum}
selected={pageNum === page.currentPage} selected={pageNum === page.currentPage}
href={getPageHref(pageNum)} href={getPageHref(pageNum)}
softNavigate={softNavigate}
/> />
) : ( ) : (
<PaginationMenuWrapper page={page} getPageHref={getPageHref} /> <PaginationMenuWrapper
page={page}
getPageHref={getPageHref}
softNavigate={softNavigate}
/>
); );
})} })}
<li className={`${styles.paginationItem}`}> <li className={`${styles.paginationItem}`}>
<a <a
className={`text-style-body-medium-bold ${styles.paginationButton} ${styles.paginationIconButton}`} className={`text-style-body-medium-bold ${styles.paginationButton} ${styles.paginationIconButton}`}
href={!isNextEnabled ? "javascript:void(0)" : getPageHref(page.currentPage + 1)} href={
!isNextEnabled
? "javascript:void(0)"
: getPageHref(page.currentPage + 1)
}
onClick={softNavigate ? onSoftNavClick(softNavigate) : undefined}
aria-label="Next" aria-label="Next"
aria-disabled={!isNextEnabled} aria-disabled={!isNextEnabled}
dangerouslySetInnerHTML={{ __html: forward }} dangerouslySetInnerHTML={{ __html: forward }}

View File

@@ -8,6 +8,7 @@ export interface PaginationButtonProps {
pageNum: number; pageNum: number;
selected: boolean; selected: boolean;
href: string; href: string;
softNavigate?: (href: string) => void;
} }
export interface PaginationProps { export interface PaginationProps {
@@ -16,4 +17,5 @@ export interface PaginationProps {
id?: string; id?: string;
rootURL?: string; rootURL?: string;
getPageHref?: (pageNum: number) => string; getPageHref?: (pageNum: number) => string;
softNavigate?: (href: string) => void;
} }