Allow middle click to open new tab

This commit is contained in:
DrMint 2022-08-08 22:12:18 +02:00
parent c2c434eb80
commit 82c605086b
14 changed files with 341 additions and 308 deletions

View File

@ -24,5 +24,14 @@ module.exports = {
hreflang: "ja",
},
],
exclude: ["/en/*", "/fr/*", "/ja/*", "/es/*", "/pt-br/*", "/404", "/500", "/dev/*"],
exclude: [
"/en/*",
"/fr/*",
"/ja/*",
"/es/*",
"/pt-br/*",
"/404",
"/500",
"/dev/*",
],
};

View File

@ -1,10 +0,0 @@
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png" />
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png" />
<link rel="manifest" href="/site.webmanifest" />
<link rel="mask-icon" href="/safari-pinned-tab.svg" color="#9c6644" />
<meta name="apple-mobile-web-app-title" content="Accord's Library" />
<meta name="application-name" content="Accord's Library" />
<meta name="msapplication-TileColor" content="#feecd6" />
<meta name="msapplication-TileImage" content="/mstile-144x144.png" />
<meta name="theme-color" content="#feecd6" />

View File

@ -1,4 +1,4 @@
import Link from "next/link";
import { Link } from "components/Inputs/Link";
import { DatePickerFragment } from "graphql/generated";
import { cIf, cJoin } from "helpers/className";
@ -20,17 +20,14 @@ export const ChroniclePreview = ({
title,
isActive,
}: Props): JSX.Element => (
<Link href={url}>
<div
<Link
href={url}
className={cJoin(
`flex w-full cursor-pointer gap-4 rounded-2xl py-4 px-5
text-left align-top outline outline-2 outline-offset-[-2px] outline-mid transition-all
hover:bg-mid hover:shadow-inner-sm hover:shadow-shade
hover:outline-[transparent] hover:active:shadow-inner hover:active:shadow-shade`,
cIf(
isActive,
"bg-mid shadow-inner-sm shadow-shade outline-[transparent]"
)
cIf(isActive, "bg-mid shadow-inner-sm shadow-shade outline-[transparent]")
)}
>
<div className="text-right">
@ -40,7 +37,6 @@ export const ChroniclePreview = ({
</p>
</div>
<p className="text-lg leading-tight">{title}</p>
</div>
</Link>
);

View File

@ -1,5 +1,5 @@
import { useRouter } from "next/router";
import React, { MouseEventHandler } from "react";
import { Link } from "./Link";
import { Ico, Icon } from "components/Ico";
import { cIf, cJoin } from "helpers/className";
import { ConditionalWrapper, Wrapper } from "helpers/component";
@ -17,8 +17,7 @@ interface Props {
active?: boolean;
icon?: Icon;
text?: string | null | undefined;
locale?: string;
target?: "_blank";
alwaysNewTab?: boolean;
onClick?: MouseEventHandler<HTMLDivElement>;
draggable?: boolean;
badgeNumber?: number;
@ -35,30 +34,17 @@ export const Button = ({
className,
icon,
text,
target,
href,
locale,
alwaysNewTab = false,
badgeNumber,
size = "normal",
}: Props): JSX.Element => {
const router = useRouter();
return (
}: Props): JSX.Element => (
<ConditionalWrapper
isWrapping={isDefined(target)}
wrapperProps={{ href: href }}
isWrapping={isDefinedAndNotEmpty(href)}
wrapperProps={{ href: href ?? "", alwaysNewTab }}
wrapper={LinkWrapper}
>
<div
className="relative"
onClick={() => {
if (!isDefined(target) && (isDefined(href) || isDefined(locale))) {
router.push(href ?? router.asPath, href, {
locale: locale,
});
}
}}
>
<div className="relative">
<div
draggable={draggable}
id={id}
@ -98,7 +84,6 @@ export const Button = ({
</div>
</ConditionalWrapper>
);
};
/*
*
@ -106,11 +91,16 @@ export const Button = ({
*/
interface LinkWrapperProps {
href?: string;
href: string;
alwaysNewTab: boolean;
}
const LinkWrapper = ({ children, href }: LinkWrapperProps & Wrapper) => (
<a href={href} target="_blank" rel="noreferrer">
const LinkWrapper = ({
children,
alwaysNewTab,
href,
}: LinkWrapperProps & Wrapper) => (
<Link href={href} alwaysNewTab={alwaysNewTab}>
{children}
</a>
</Link>
);

View File

@ -0,0 +1,62 @@
import router from "next/router";
import { MouseEventHandler, useState } from "react";
import { isDefined } from "helpers/others";
interface Props {
href: string;
className?: string;
allowNewTab?: boolean;
alwaysNewTab?: boolean;
children: React.ReactNode;
onClick?: MouseEventHandler<HTMLDivElement>;
}
export const Link = ({
href,
allowNewTab = true,
alwaysNewTab = false,
children,
className,
onClick,
}: Props): JSX.Element => {
const [isValidClick, setIsValidClick] = useState(false);
return (
<div
className={className}
onMouseLeave={() => setIsValidClick(false)}
onContextMenu={(event) => event.preventDefault()}
onMouseDown={(event) => {
event.preventDefault();
setIsValidClick(true);
}}
onMouseUp={(event) => {
if (isDefined(onClick)) {
onClick(event);
} else if (isValidClick && href) {
if (event.button !== MouseButton.Right) {
if (alwaysNewTab) {
window.open(href, "_blank");
} else if (event.button === MouseButton.Left) {
if (href.startsWith("#")) {
router.replace(href);
} else {
router.push(href);
}
} else if (allowNewTab) {
window.open(href, "_blank");
}
}
}
}}
>
{children}
</div>
);
};
enum MouseButton {
Left = 0,
Middle = 1,
Right = 2,
}

View File

@ -4,6 +4,7 @@ import { Ico, Icon } from "components/Ico";
import { ToolTip } from "components/ToolTip";
import { cJoin, cIf } from "helpers/className";
import { isDefinedAndNotEmpty } from "helpers/others";
import { Link } from "components/Inputs/Link";
/*
*
@ -51,17 +52,9 @@ export const NavOption = ({
className="text-left"
disabled={!reduced}
>
<div
onClick={(event) => {
if (onClick) onClick(event);
if (url) {
if (url.startsWith("#")) {
router.replace(url);
} else {
router.push(url);
}
}
}}
<Link
href={url}
onClick={onClick}
className={cJoin(
`relative grid w-full cursor-pointer auto-cols-fr grid-flow-col grid-cols-[auto]
justify-center gap-x-5 rounded-2xl p-4 transition-all hover:bg-mid hover:shadow-inner-sm
@ -84,7 +77,7 @@ export const NavOption = ({
)}
</div>
)}
</div>
</Link>
</ToolTip>
);
};

View File

@ -1,5 +1,4 @@
import Markdown from "markdown-to-jsx";
import Link from "next/link";
import { HorizontalLine } from "components/HorizontalLine";
import { Button } from "components/Inputs/Button";
import { NavOption } from "components/PanelComponents/NavOption";
@ -11,6 +10,7 @@ import { useMediaDesktop } from "hooks/useMediaQuery";
import { Icon } from "components/Ico";
import { cIf, cJoin } from "helpers/className";
import { isDefinedAndNotEmpty } from "helpers/others";
import { Link } from "components/Inputs/Link";
/*
*
@ -54,7 +54,7 @@ export const MainPanel = ({ langui }: Props): JSX.Element => {
<div>
<div className="grid place-items-center">
<Link href="/" passHref>
<Link href="/" className="flex w-full justify-center">
<div
className={cJoin(
`mb-4 aspect-square cursor-pointer bg-black transition-colors

View File

@ -1,4 +1,4 @@
import { Dispatch, SetStateAction, useEffect } from "react";
import { useEffect } from "react";
import Hotkeys from "react-hot-keys";
import { useAppLayout } from "contexts/AppLayoutContext";
import { cIf, cJoin } from "helpers/className";

View File

@ -1,9 +1,9 @@
import Link from "next/link";
import { useMemo } from "react";
import { useRouter } from "next/router";
import { Chip } from "./Chip";
import { Ico, Icon } from "./Ico";
import { Img } from "./Img";
import { Link } from "./Inputs/Link";
import { useAppLayout } from "contexts/AppLayoutContext";
import {
DatePickerFragment,
@ -131,8 +131,8 @@ export const PreviewCard = ({
);
return (
<Link href={href} passHref>
<div
<Link
href={href}
className="group grid cursor-pointer items-end text-left transition-transform
drop-shadow-shade-xl hover:scale-[1.02]"
>
@ -293,7 +293,6 @@ export const PreviewCard = ({
{infoAppend}
</div>
</div>
</Link>
);
};

View File

@ -1,6 +1,6 @@
import Link from "next/link";
import { Chip } from "./Chip";
import { Img } from "./Img";
import { Link } from "./Inputs/Link";
import { UploadImageFragment } from "graphql/generated";
import { ImageQuality } from "helpers/img";
@ -32,8 +32,8 @@ export const PreviewLine = ({
bottomChips,
thumbnailAspectRatio,
}: Props): JSX.Element => (
<Link href={href} passHref>
<div
<Link
href={href}
className="flex h-36 w-full cursor-pointer flex-row place-items-center gap-4 overflow-hidden
rounded-md bg-light pr-4 transition-transform drop-shadow-shade-xl hover:scale-[1.02]"
>
@ -59,9 +59,7 @@ export const PreviewLine = ({
<div className="my-1 flex flex-col">
{pre_title && <p className="mb-1 leading-none">{pre_title}</p>}
{title && (
<p className="font-headers text-lg font-bold leading-none">
{title}
</p>
<p className="font-headers text-lg font-bold leading-none">{title}</p>
)}
{subtitle && <p className="leading-none">{subtitle}</p>}
</div>
@ -73,6 +71,5 @@ export const PreviewLine = ({
</div>
)}
</div>
</div>
</Link>
);

View File

@ -1,5 +1,4 @@
import { useCallback } from "react";
import Link from "next/link";
import { Chip } from "components/Chip";
import { ToolTip } from "components/ToolTip";
import { AppStaticProps } from "graphql/getAppStaticProps";
@ -87,12 +86,10 @@ const DefinitionCard = ({
<p>{selectedTranslation?.definition}</p>
{source?.url && source.name && (
<Link href={source.url}>
<div className="mt-3 flex place-items-center gap-2 mobile:flex-col mobile:text-center">
<p>{langui.source}: </p>
<Button size="small" text={source.name} />
<Button href={source.url} size="small" text={source.name} />
</div>
</Link>
)}
</>
);

View File

@ -53,15 +53,15 @@ const CheckupContents = ({ contents, ...otherProps }: Props): JSX.Element => {
>
<Button
href={line.frontendUrl}
target="_blank"
className="w-4 text-xs"
text="F"
alwaysNewTab
/>
<Button
href={line.backendUrl}
target="_blank"
className="w-4 text-xs"
text="B"
alwaysNewTab
/>
<p>{line.subitems.join(" -> ")}</p>
<p>{line.name}</p>

View File

@ -58,15 +58,15 @@ const CheckupLibraryItems = ({
>
<Button
href={line.frontendUrl}
target="_blank"
className="w-4 text-xs"
text="F"
alwaysNewTab
/>
<Button
href={line.backendUrl}
target="_blank"
className="w-4 text-xs"
text="B"
alwaysNewTab
/>
<p>{line.subitems.join(" -> ")}</p>
<p>{line.name}</p>

View File

@ -230,8 +230,8 @@ const LibrarySlug = ({
<Fragment key={index}>
<Button
href={url.url}
target={"_blank"}
text={prettyURL(url.url)}
alwaysNewTab
/>
</Fragment>
)