1
mirror of https://github.com/jakejarvis/jarv.is.git synced 2025-04-26 15:28:28 -04:00
2022-07-06 03:02:09 -04:00

64 lines
2.1 KiB
TypeScript

import NextLink from "next/link";
import { styled } from "../../lib/styles/stitches.config";
import { baseUrl } from "../../lib/config";
import type { ComponentProps } from "react";
const StyledLink = styled(NextLink, {
color: "$link",
textDecoration: "none",
variants: {
underline: {
// fancy animated link underline effect (on by default)
true: {
// sets psuedo linear-gradient() for the underline's color; see stitches config for the weird calculation behind
// the local `$$underlineColor` variable.
setUnderlineVars: {},
backgroundImage: `linear-gradient($$underlineColor, $$underlineColor)`,
backgroundPosition: "0% 100%",
backgroundRepeat: "no-repeat",
backgroundSize: "0% $borderWidths$underline",
paddingBottom: "0.2rem",
"@media (prefers-reduced-motion: no-preference)": {
transition: "background-size $linkHover",
},
"&:hover": {
backgroundSize: "100% $borderWidths$underline",
},
},
false: {},
},
},
});
export type LinkProps = ComponentProps<typeof StyledLink> & {
openInNewTab?: boolean;
};
const Link = ({ href, rel, target, prefetch = false, underline = true, openInNewTab, ...rest }: LinkProps) => {
// This component auto-detects whether or not this link should open in the same window (the default for internal
// links) or a new tab (the default for external links). Defaults can be overridden with `openInNewTab={true}`.
const isExternal =
typeof href === "string" && !(href.startsWith("/") || href.startsWith("#") || href.startsWith(baseUrl));
if (openInNewTab || isExternal) {
return (
<StyledLink
href={href}
target={target || "_blank"}
rel={`${rel || ""} noopener ${isExternal ? "noreferrer" : ""}`.trim()}
underline={underline}
{...rest}
/>
);
}
// If link is to an internal page, simply pass *everything* along as-is to next/link.
return <StyledLink {...{ href, rel, target, prefetch, underline, ...rest }} />;
};
export default Link;