mirror of
https://github.com/jakejarvis/jarv.is.git
synced 2026-01-10 16:22:55 -05:00
refactor component/page function returns
This commit is contained in:
@@ -92,13 +92,15 @@ export type CodeBlockProps = ComponentProps<typeof Code> & {
|
||||
highlight?: boolean;
|
||||
};
|
||||
|
||||
const CodeBlock = ({ highlight, className, children, ...rest }: CodeBlockProps) => (
|
||||
<Block highlight={highlight}>
|
||||
<CornerCopyButton source={children} />
|
||||
<Code className={className?.replace("code-highlight", "").trim()} {...rest}>
|
||||
{children}
|
||||
</Code>
|
||||
</Block>
|
||||
);
|
||||
const CodeBlock = ({ highlight, className, children, ...rest }: CodeBlockProps) => {
|
||||
return (
|
||||
<Block highlight={highlight}>
|
||||
<CornerCopyButton source={children} />
|
||||
<Code className={className?.replace("code-highlight", "").trim()} {...rest}>
|
||||
{children}
|
||||
</Code>
|
||||
</Block>
|
||||
);
|
||||
};
|
||||
|
||||
export default CodeBlock;
|
||||
|
||||
@@ -26,14 +26,14 @@ const CodeHybrid = ({ forceBlock, className, children, ...rest }: CodeHybridProp
|
||||
{children}
|
||||
</CodeBlock>
|
||||
);
|
||||
} else {
|
||||
// inline code in paragraphs, headings, etc. (never highlighted)
|
||||
return (
|
||||
<CodeInline className={className} {...rest}>
|
||||
{children}
|
||||
</CodeInline>
|
||||
);
|
||||
}
|
||||
|
||||
// simple inline code in paragraphs, headings, etc. (never highlighted)
|
||||
return (
|
||||
<CodeInline className={className} {...rest}>
|
||||
{children}
|
||||
</CodeInline>
|
||||
);
|
||||
};
|
||||
|
||||
export default CodeHybrid;
|
||||
|
||||
@@ -3,7 +3,7 @@ import innerText from "react-innertext";
|
||||
import copy from "copy-to-clipboard";
|
||||
import { ClipboardOcticon, CheckOcticon } from "../Icons";
|
||||
import { styled } from "../../lib/styles/stitches.config";
|
||||
import type { ReactNode, Ref } from "react";
|
||||
import type { ReactNode, Ref, MouseEventHandler } from "react";
|
||||
|
||||
const Button = styled("button", {
|
||||
lineHeight: 1,
|
||||
@@ -44,9 +44,9 @@ const CopyButton = forwardRef(function CopyButton(
|
||||
) {
|
||||
const [copied, setCopied] = useState(false);
|
||||
|
||||
const handleCopy = (e) => {
|
||||
const handleCopy: MouseEventHandler<HTMLButtonElement> = (e) => {
|
||||
// prevent unintentional double-clicks by unfocusing button
|
||||
e.target.blur();
|
||||
e.currentTarget.blur();
|
||||
|
||||
// send plaintext to the clipboard
|
||||
const didCopy = copy(innerText(source));
|
||||
|
||||
@@ -83,48 +83,50 @@ const Heart = styled("span", {
|
||||
|
||||
export type FooterProps = ComponentProps<typeof Wrapper>;
|
||||
|
||||
const Footer = ({ ...rest }: FooterProps) => (
|
||||
<Wrapper {...rest}>
|
||||
<Row>
|
||||
<div>
|
||||
Content{" "}
|
||||
<Link href="/license/" prefetch={false} title="Creative Commons Attribution 4.0 International">
|
||||
licensed under CC-BY-4.0
|
||||
</Link>
|
||||
,{" "}
|
||||
<Link href="/previously/" prefetch={false} title="Previously on...">
|
||||
2001
|
||||
</Link>{" "}
|
||||
– {new Date(process.env.NEXT_PUBLIC_RELEASE_DATE).getUTCFullYear()}.
|
||||
</div>
|
||||
const Footer = ({ ...rest }: FooterProps) => {
|
||||
return (
|
||||
<Wrapper {...rest}>
|
||||
<Row>
|
||||
<div>
|
||||
Content{" "}
|
||||
<Link href="/license/" prefetch={false} title="Creative Commons Attribution 4.0 International">
|
||||
licensed under CC-BY-4.0
|
||||
</Link>
|
||||
,{" "}
|
||||
<Link href="/previously/" prefetch={false} title="Previously on...">
|
||||
2001
|
||||
</Link>{" "}
|
||||
– {new Date(process.env.NEXT_PUBLIC_RELEASE_DATE).getUTCFullYear()}.
|
||||
</div>
|
||||
|
||||
<div>
|
||||
Made with{" "}
|
||||
<Heart title="Love">
|
||||
<Icon as={HeartIcon} />
|
||||
</Heart>{" "}
|
||||
and{" "}
|
||||
<NextjsLink
|
||||
href="https://nextjs.org/"
|
||||
title="Powered by Next.js"
|
||||
aria-label="Next.js"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<Icon as={NextjsLogo} />
|
||||
</NextjsLink>
|
||||
.{" "}
|
||||
<ViewSourceLink
|
||||
href={`https://github.com/${config.githubRepo}`}
|
||||
title="View Source on GitHub"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
View source.
|
||||
</ViewSourceLink>
|
||||
</div>
|
||||
</Row>
|
||||
</Wrapper>
|
||||
);
|
||||
<div>
|
||||
Made with{" "}
|
||||
<Heart title="Love">
|
||||
<Icon as={HeartIcon} />
|
||||
</Heart>{" "}
|
||||
and{" "}
|
||||
<NextjsLink
|
||||
href="https://nextjs.org/"
|
||||
title="Powered by Next.js"
|
||||
aria-label="Next.js"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<Icon as={NextjsLogo} />
|
||||
</NextjsLink>
|
||||
.{" "}
|
||||
<ViewSourceLink
|
||||
href={`https://github.com/${config.githubRepo}`}
|
||||
title="View Source on GitHub"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
View source.
|
||||
</ViewSourceLink>
|
||||
</div>
|
||||
</Row>
|
||||
</Wrapper>
|
||||
);
|
||||
};
|
||||
|
||||
export default Footer;
|
||||
|
||||
@@ -44,13 +44,15 @@ const ResponsiveMenu = styled(Menu, {
|
||||
|
||||
export type HeaderProps = ComponentProps<typeof Wrapper>;
|
||||
|
||||
const Header = ({ ...rest }: HeaderProps) => (
|
||||
<Wrapper {...rest}>
|
||||
<Nav>
|
||||
<Selfie />
|
||||
<ResponsiveMenu />
|
||||
</Nav>
|
||||
</Wrapper>
|
||||
);
|
||||
const Header = ({ ...rest }: HeaderProps) => {
|
||||
return (
|
||||
<Wrapper {...rest}>
|
||||
<Nav>
|
||||
<Selfie />
|
||||
<ResponsiveMenu />
|
||||
</Nav>
|
||||
</Wrapper>
|
||||
);
|
||||
};
|
||||
|
||||
export default Header;
|
||||
|
||||
@@ -17,10 +17,12 @@ export type HeadingAnchorProps = ComponentProps<typeof AnchorLink> & {
|
||||
title: string;
|
||||
};
|
||||
|
||||
const HeadingAnchor = ({ id, title, ...rest }: HeadingAnchorProps) => (
|
||||
<AnchorLink href={`#${id}`} title={`Jump to "${title}"`} tabIndex={-1} aria-hidden={true} {...rest}>
|
||||
<Icon />
|
||||
</AnchorLink>
|
||||
);
|
||||
const HeadingAnchor = ({ id, title, ...rest }: HeadingAnchorProps) => {
|
||||
return (
|
||||
<AnchorLink href={`#${id}`} title={`Jump to "${title}"`} tabIndex={-1} aria-hidden={true} {...rest}>
|
||||
<Icon />
|
||||
</AnchorLink>
|
||||
);
|
||||
};
|
||||
|
||||
export default HeadingAnchor;
|
||||
|
||||
@@ -17,20 +17,22 @@ export type IFrameProps = ComponentProps<typeof RoundedIFrame> & {
|
||||
noScroll?: boolean;
|
||||
};
|
||||
|
||||
const IFrame = ({ src, title, height, width, allowScripts, noScroll, css, ...rest }: IFrameProps) => (
|
||||
<RoundedIFrame
|
||||
src={src}
|
||||
title={title}
|
||||
sandbox={allowScripts ? "allow-same-origin allow-scripts allow-popups" : undefined}
|
||||
scrolling={noScroll ? "no" : undefined}
|
||||
loading="lazy"
|
||||
css={{
|
||||
height: `${height}px`,
|
||||
maxWidth: width ? `${width}px` : "100%",
|
||||
...css,
|
||||
}}
|
||||
{...rest}
|
||||
/>
|
||||
);
|
||||
const IFrame = ({ src, title, height, width, allowScripts, noScroll, css, ...rest }: IFrameProps) => {
|
||||
return (
|
||||
<RoundedIFrame
|
||||
src={src}
|
||||
title={title}
|
||||
sandbox={allowScripts ? "allow-same-origin allow-scripts allow-popups" : undefined}
|
||||
scrolling={noScroll ? "no" : undefined}
|
||||
loading="lazy"
|
||||
css={{
|
||||
height: `${height}px`,
|
||||
maxWidth: width ? `${width}px` : "100%",
|
||||
...css,
|
||||
}}
|
||||
{...rest}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default IFrame;
|
||||
|
||||
@@ -67,7 +67,7 @@ const Image = ({
|
||||
{img}
|
||||
</Link>
|
||||
) : (
|
||||
img
|
||||
<>{img}</>
|
||||
)}
|
||||
</Wrapper>
|
||||
);
|
||||
|
||||
@@ -57,7 +57,7 @@ const Layout = ({ container = true, children, ...rest }: LayoutProps) => {
|
||||
<Container>{children}</Container>
|
||||
</Default>
|
||||
) : (
|
||||
children
|
||||
<>{children}</>
|
||||
)}
|
||||
|
||||
<FlexedFooter />
|
||||
|
||||
@@ -36,10 +36,12 @@ const Track = styled("div", {
|
||||
|
||||
export type MarqueeProps = ComponentProps<typeof Wrapper>;
|
||||
|
||||
const Marquee = ({ children, ...rest }: MarqueeProps) => (
|
||||
<Wrapper {...rest}>
|
||||
<Track>{children}</Track>
|
||||
</Wrapper>
|
||||
);
|
||||
const Marquee = ({ children, ...rest }: MarqueeProps) => {
|
||||
return (
|
||||
<Wrapper {...rest}>
|
||||
<Track>{children}</Track>
|
||||
</Wrapper>
|
||||
);
|
||||
};
|
||||
|
||||
export default Marquee;
|
||||
|
||||
@@ -71,9 +71,9 @@ const MenuItem = ({ icon: ItemIcon, href, text, current, className }: MenuItemPr
|
||||
{linkContent}
|
||||
</Link>
|
||||
);
|
||||
} else {
|
||||
return linkContent;
|
||||
}
|
||||
|
||||
return <>{linkContent}</>;
|
||||
};
|
||||
|
||||
export default MenuItem;
|
||||
|
||||
@@ -58,70 +58,72 @@ const Tag = styled("span", {
|
||||
|
||||
export type NoteMetaProps = Pick<NoteFrontMatter, "slug" | "date" | "title" | "htmlTitle" | "tags">;
|
||||
|
||||
const NoteMeta = ({ slug, date, title, htmlTitle, tags = [] }: NoteMetaProps) => (
|
||||
<>
|
||||
<Wrapper>
|
||||
<MetaItem>
|
||||
<MetaLink
|
||||
href={{
|
||||
pathname: "/notes/[slug]/",
|
||||
query: { slug },
|
||||
}}
|
||||
>
|
||||
<span>
|
||||
<Icon as={DateIcon} />
|
||||
</span>
|
||||
<Time date={date} format="MMMM D, YYYY" />
|
||||
</MetaLink>
|
||||
</MetaItem>
|
||||
|
||||
{tags.length > 0 && (
|
||||
const NoteMeta = ({ slug, date, title, htmlTitle, tags = [] }: NoteMetaProps) => {
|
||||
return (
|
||||
<>
|
||||
<Wrapper>
|
||||
<MetaItem>
|
||||
<span title="Tags">
|
||||
<Icon as={TagIcon} />
|
||||
</span>
|
||||
<TagsList>
|
||||
{tags.map((tag) => (
|
||||
<Tag key={tag} title={tag}>
|
||||
{tag}
|
||||
</Tag>
|
||||
))}
|
||||
</TagsList>
|
||||
</MetaItem>
|
||||
)}
|
||||
|
||||
<MetaItem>
|
||||
<MetaLink
|
||||
href={`https://github.com/${config.githubRepo}/blob/main/notes/${slug}.mdx`}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
title={`Edit "${title}" on GitHub`}
|
||||
>
|
||||
<span>
|
||||
<Icon as={EditIcon} />
|
||||
</span>
|
||||
<span>Improve This Post</span>
|
||||
</MetaLink>
|
||||
</MetaItem>
|
||||
|
||||
{/* only count hits on production site */}
|
||||
{process.env.NEXT_PUBLIC_VERCEL_ENV === "production" && (
|
||||
<ErrorBoundary fallback={null}>
|
||||
<MetaItem
|
||||
// fix potential layout shift when number of hits loads
|
||||
css={{ minWidth: "7em", marginRight: 0 }}
|
||||
<MetaLink
|
||||
href={{
|
||||
pathname: "/notes/[slug]/",
|
||||
query: { slug },
|
||||
}}
|
||||
>
|
||||
<span>
|
||||
<Icon as={ViewsIcon} />
|
||||
<Icon as={DateIcon} />
|
||||
</span>
|
||||
<HitCounter slug={`notes/${slug}`} />
|
||||
</MetaItem>
|
||||
</ErrorBoundary>
|
||||
)}
|
||||
</Wrapper>
|
||||
<Time date={date} format="MMMM D, YYYY" />
|
||||
</MetaLink>
|
||||
</MetaItem>
|
||||
|
||||
<NoteTitle slug={slug} htmlTitle={htmlTitle || title} />
|
||||
</>
|
||||
);
|
||||
{tags.length > 0 && (
|
||||
<MetaItem>
|
||||
<span title="Tags">
|
||||
<Icon as={TagIcon} />
|
||||
</span>
|
||||
<TagsList>
|
||||
{tags.map((tag) => (
|
||||
<Tag key={tag} title={tag}>
|
||||
{tag}
|
||||
</Tag>
|
||||
))}
|
||||
</TagsList>
|
||||
</MetaItem>
|
||||
)}
|
||||
|
||||
<MetaItem>
|
||||
<MetaLink
|
||||
href={`https://github.com/${config.githubRepo}/blob/main/notes/${slug}.mdx`}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
title={`Edit "${title}" on GitHub`}
|
||||
>
|
||||
<span>
|
||||
<Icon as={EditIcon} />
|
||||
</span>
|
||||
<span>Improve This Post</span>
|
||||
</MetaLink>
|
||||
</MetaItem>
|
||||
|
||||
{/* only count hits on production site */}
|
||||
{process.env.NEXT_PUBLIC_VERCEL_ENV === "production" && (
|
||||
<ErrorBoundary fallback={null}>
|
||||
<MetaItem
|
||||
// fix potential layout shift when number of hits loads
|
||||
css={{ minWidth: "7em", marginRight: 0 }}
|
||||
>
|
||||
<span>
|
||||
<Icon as={ViewsIcon} />
|
||||
</span>
|
||||
<HitCounter slug={`notes/${slug}`} />
|
||||
</MetaItem>
|
||||
</ErrorBoundary>
|
||||
)}
|
||||
</Wrapper>
|
||||
|
||||
<NoteTitle slug={slug} htmlTitle={htmlTitle || title} />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default NoteMeta;
|
||||
|
||||
@@ -25,16 +25,18 @@ const Link = styled(NextLink, {
|
||||
|
||||
export type NoteTitleProps = Pick<NoteFrontMatter, "slug" | "htmlTitle"> & ComponentProps<typeof Title>;
|
||||
|
||||
const NoteTitle = ({ slug, htmlTitle, ...rest }: NoteTitleProps) => (
|
||||
<Title {...rest}>
|
||||
<Link
|
||||
href={{
|
||||
pathname: "/notes/[slug]/",
|
||||
query: { slug },
|
||||
}}
|
||||
dangerouslySetInnerHTML={{ __html: htmlTitle }}
|
||||
/>
|
||||
</Title>
|
||||
);
|
||||
const NoteTitle = ({ slug, htmlTitle, ...rest }: NoteTitleProps) => {
|
||||
return (
|
||||
<Title {...rest}>
|
||||
<Link
|
||||
href={{
|
||||
pathname: "/notes/[slug]/",
|
||||
query: { slug },
|
||||
}}
|
||||
dangerouslySetInnerHTML={{ __html: htmlTitle }}
|
||||
/>
|
||||
</Title>
|
||||
);
|
||||
};
|
||||
|
||||
export default NoteTitle;
|
||||
|
||||
@@ -23,10 +23,12 @@ export type OctocatLinkProps = ComponentProps<typeof Link> & {
|
||||
repo: string;
|
||||
};
|
||||
|
||||
const OctocatLink = ({ repo, className, ...rest }: OctocatLinkProps) => (
|
||||
<Link href={`https://github.com/${repo}`} target="_blank" rel="noopener noreferrer" {...rest}>
|
||||
<Octocat className={className} />
|
||||
</Link>
|
||||
);
|
||||
const OctocatLink = ({ repo, className, ...rest }: OctocatLinkProps) => {
|
||||
return (
|
||||
<Link href={`https://github.com/${repo}`} target="_blank" rel="noopener noreferrer" {...rest}>
|
||||
<Octocat className={className} />
|
||||
</Link>
|
||||
);
|
||||
};
|
||||
|
||||
export default OctocatLink;
|
||||
|
||||
@@ -50,11 +50,13 @@ const Name = styled("span", {
|
||||
|
||||
export type SelfieProps = Omit<ComponentProps<typeof Link>, "href">;
|
||||
|
||||
const Selfie = ({ ...rest }: SelfieProps) => (
|
||||
<Link href="/" rel="author" title={authorName} {...rest}>
|
||||
<Image src={selfieJpg} alt={`Photo of ${authorName}`} width={50} height={50} quality={60} layout="raw" priority />
|
||||
<Name>{authorName}</Name>
|
||||
</Link>
|
||||
);
|
||||
const Selfie = ({ ...rest }: SelfieProps) => {
|
||||
return (
|
||||
<Link href="/" rel="author" title={authorName} {...rest}>
|
||||
<Image src={selfieJpg} alt={`Photo of ${authorName}`} width={50} height={50} quality={60} layout="raw" priority />
|
||||
<Name>{authorName}</Name>
|
||||
</Link>
|
||||
);
|
||||
};
|
||||
|
||||
export default Selfie;
|
||||
|
||||
@@ -6,10 +6,12 @@ export type TimeProps = {
|
||||
className?: string;
|
||||
};
|
||||
|
||||
const Time = ({ date, format = "MMM D", className }: TimeProps) => (
|
||||
<time dateTime={formatDateISO(date)} title={formatDate(date)} className={className}>
|
||||
{formatDate(date, format)}
|
||||
</time>
|
||||
);
|
||||
const Time = ({ date, format = "MMM D", className }: TimeProps) => {
|
||||
return (
|
||||
<time dateTime={formatDateISO(date)} title={formatDate(date)} className={className}>
|
||||
{formatDate(date, format)}
|
||||
</time>
|
||||
);
|
||||
};
|
||||
|
||||
export default Time;
|
||||
|
||||
Reference in New Issue
Block a user