diff --git a/.node-version b/.node-version index 4a1f488b..02c8b485 100644 --- a/.node-version +++ b/.node-version @@ -1 +1 @@ -18.17.1 +18.18.0 diff --git a/README.md b/README.md index cd371921..8f15055f 100644 --- a/README.md +++ b/README.md @@ -11,9 +11,9 @@ I keep an ongoing list of [post ideas](https://github.com/jakejarvis/jarv.is/iss ## đŸ•šī¸ Getting Started -Run `pnpm install` to install the necessary dependencies and `pnpm run dev` to start the local server, and then open [http://localhost:3000/](http://localhost:3000/). Pages will live-refresh when source files are changed. ([pnpm is required!](https://pnpm.io/installation)) +Run `pnpm install` to install the necessary dependencies and `pnpm dev` to start the local server, and then open [http://localhost:3000/](http://localhost:3000/). Pages will live-refresh when source files are changed. -Most production steps are handled [automatically by Vercel](https://vercel.com/docs/concepts/next.js/overview#supported-next.js-features), but running `pnpm build` locally will still generate an unoptimized, less-than-ideal static version. +Most production steps are handled [automatically by Vercel](https://vercel.com/docs/frameworks/nextjs), but running `pnpm build` locally will still generate an unoptimized, less-than-ideal static version which can be served via `pnpm start`. **⚡ Bonus tip:** [Volta](https://volta.sh/), a magical, blazing-fast alternative to [nvm](https://github.com/nvm-sh/nvm), is used to pin the exact Node.js version used for development. It's completely optional but I highly recommend it in general! diff --git a/components/ContactForm/ContactForm.tsx b/components/ContactForm/ContactForm.tsx index 196a38f2..2c0e23bb 100644 --- a/components/ContactForm/ContactForm.tsx +++ b/components/ContactForm/ContactForm.tsx @@ -3,7 +3,8 @@ import { Formik, Form, Field } from "formik"; import TextareaAutosize from "react-textarea-autosize"; import Link from "../Link"; import Captcha from "../Captcha"; -import { CheckOcticon, XOcticon, MarkdownIcon } from "../Icons"; +import { GoCheck, GoX } from "react-icons/go"; +import { SiMarkdown } from "react-icons/si"; import { styled, theme, css } from "../../lib/styles/stitches.config"; import type { FormikHelpers, FormikProps, FieldInputProps, FieldMetaProps } from "formik"; @@ -47,8 +48,7 @@ const MarkdownTip = styled("div", { lineHeight: 1.75, }); -const MarkdownTipIcon = styled(MarkdownIcon, { - fill: "currentColor", +const MarkdownTipIcon = styled(SiMarkdown, { width: "1.25em", height: "1.25em", verticalAlign: "-0.25em", @@ -288,7 +288,7 @@ const ContactForm = ({ className }: ContactFormProps) => { diff --git a/components/CopyButton/CopyButton.tsx b/components/CopyButton/CopyButton.tsx index 685a5668..0158bc5f 100644 --- a/components/CopyButton/CopyButton.tsx +++ b/components/CopyButton/CopyButton.tsx @@ -1,7 +1,7 @@ import { forwardRef, useState, useEffect } from "react"; import innerText from "react-innertext"; import copy from "copy-to-clipboard"; -import { ClipboardOcticon, CheckOcticon } from "../Icons"; +import { FiClipboard, FiCheck } from "react-icons/fi"; import { styled, theme } from "../../lib/styles/stitches.config"; import type { ReactNode, Ref, ComponentPropsWithoutRef, ElementRef, MouseEventHandler } from "react"; @@ -29,7 +29,6 @@ const Icon = styled("svg", { width: "1.25em", height: "1.25em", verticalAlign: "-0.3em", - fill: "currentColor", }); export type CopyButtonProps = ComponentPropsWithoutRef & { @@ -77,7 +76,7 @@ const CopyButton = ({ source, timeout = 2000, ...rest }: CopyButtonProps, ref: R copied={copied} {...rest} > - + ); }; diff --git a/components/Figure/Figure.tsx b/components/Figure/Figure.tsx index d50d930f..59bf4f37 100644 --- a/components/Figure/Figure.tsx +++ b/components/Figure/Figure.tsx @@ -1,7 +1,7 @@ import innerText from "react-innertext"; -import Image, { ImageProps } from "../Image"; +import Image from "../Image"; import { styled, theme } from "../../lib/styles/stitches.config"; -import type { PropsWithChildren } from "react"; +import type { PropsWithChildren, ComponentPropsWithoutRef } from "react"; const Wrapper = styled("figure", { margin: "1em auto", @@ -15,7 +15,7 @@ const Caption = styled("figcaption", { marginTop: "-0.4em", }); -export type FigureProps = Omit & +export type FigureProps = Omit, "alt"> & PropsWithChildren<{ alt?: string; // becomes optional -- pulled from plaintext-ified caption if missing }>; diff --git a/components/Footer/Footer.tsx b/components/Footer/Footer.tsx index 36a900a7..6b61e759 100644 --- a/components/Footer/Footer.tsx +++ b/components/Footer/Footer.tsx @@ -1,5 +1,6 @@ import Link from "../Link"; -import { HeartIcon, NextjsLogo } from "../Icons"; +import { GoHeartFill } from "react-icons/go"; +import { SiNextdotjs } from "react-icons/si"; import { styled, theme, keyframes } from "../../lib/styles/stitches.config"; import * as config from "../../lib/config"; import type { ComponentPropsWithoutRef } from "react"; @@ -37,27 +38,11 @@ const PlainLink = styled(Link, { color: theme.colors.mediumDark, }); -const NextjsLink = styled(PlainLink, { - "&:hover, &:focus-visible": { - color: theme.colors.medium, - }, -}); - -const ViewSourceLink = styled(PlainLink, { - paddingBottom: "2px", - borderBottom: `1px solid ${theme.colors.light}`, - - "&:hover, &:focus-visible": { - borderColor: theme.colors.kindaLight, - }, -}); - const Icon = styled("svg", { width: "1.25em", height: "1.25em", verticalAlign: "-0.25em", margin: "0 0.075em", - fill: "currentColor", }); const Heart = styled("span", { @@ -99,20 +84,38 @@ const Footer = ({ ...rest }: FooterProps) => {
Made with{" "} - + {" "} and{" "} - - - + + + .{" "} - View source. - +
diff --git a/components/HeadingAnchor/HeadingAnchor.tsx b/components/HeadingAnchor/HeadingAnchor.tsx index e32c892b..c9a0d2c1 100644 --- a/components/HeadingAnchor/HeadingAnchor.tsx +++ b/components/HeadingAnchor/HeadingAnchor.tsx @@ -1,27 +1,17 @@ import Link from "../Link"; -import { LinkIcon } from "../Icons"; -import { styled } from "../../lib/styles/stitches.config"; +import { FiLink } from "react-icons/fi"; import type { ComponentPropsWithoutRef } from "react"; -const AnchorLink = styled(Link, { - lineHeight: 1, -}); - -const Icon = styled(LinkIcon, { - width: "0.8em", - height: "0.8em", -}); - -export type HeadingAnchorProps = Omit, "href"> & { +export type HeadingAnchorProps = Omit, "href"> & { id: string; title: string; }; const HeadingAnchor = ({ id, title, ...rest }: HeadingAnchorProps) => { return ( - - - + + + ); }; diff --git a/components/Icons/index.ts b/components/Icons/index.ts deleted file mode 100644 index ed698b56..00000000 --- a/components/Icons/index.ts +++ /dev/null @@ -1,28 +0,0 @@ -// Icons from various packs, imported directly from the package's SVG files instead of their exports so they're all -// processed consistently via svgr/webpack into React components. -// NOTE: each package's path inside ./node_modules *must* be listed in svgr's webpack config in next.config.js. - -// feather icons: https://feathericons.com/ -export { default as ContactIcon } from "feather-icons/dist/icons/mail.svg"; -export { default as DateIcon } from "feather-icons/dist/icons/calendar.svg"; -export { default as EditIcon } from "feather-icons/dist/icons/edit.svg"; -export { default as HomeIcon } from "feather-icons/dist/icons/home.svg"; -export { default as LinkIcon } from "feather-icons/dist/icons/link.svg"; -export { default as NotesIcon } from "feather-icons/dist/icons/edit-3.svg"; -export { default as ProjectsIcon } from "feather-icons/dist/icons/code.svg"; -export { default as TagIcon } from "feather-icons/dist/icons/tag.svg"; -export { default as ViewsIcon } from "feather-icons/dist/icons/eye.svg"; - -// octicons: https://primer.style/octicons/ -export { default as CheckOcticon } from "@primer/octicons/build/svg/check-16.svg"; -export { default as ClipboardOcticon } from "@primer/octicons/build/svg/paste-16.svg"; -export { default as ForkOcticon } from "@primer/octicons/build/svg/repo-forked-16.svg"; -export { default as HeartIcon } from "@primer/octicons/build/svg/heart-fill-16.svg"; -export { default as MarkdownIcon } from "@primer/octicons/build/svg/markdown-16.svg"; -export { default as OctocatOcticon } from "@primer/octicons/build/svg/mark-github-16.svg"; -export { default as StarOcticon } from "@primer/octicons/build/svg/star-16.svg"; -export { default as XOcticon } from "@primer/octicons/build/svg/x-16.svg"; - -// simple icons: https://simpleicons.org/ -export { default as NextjsLogo } from "simple-icons/icons/nextdotjs.svg"; -export { default as Windows95Logo } from "simple-icons/icons/windows95.svg"; diff --git a/components/MenuItem/MenuItem.tsx b/components/MenuItem/MenuItem.tsx index 950d5892..fea67298 100644 --- a/components/MenuItem/MenuItem.tsx +++ b/components/MenuItem/MenuItem.tsx @@ -1,5 +1,6 @@ import Link from "../Link"; import { styled, theme } from "../../lib/styles/stitches.config"; +import type { IconType } from "react-icons"; const MenuLink = styled(Link, { display: "inline-block", @@ -45,20 +46,17 @@ const Label = styled("span", { }); export type MenuItemProps = { - href?: string; + icon?: IconType; text?: string; + href?: string; current?: boolean; className?: string; - - // `any` avoids conflicts with @svgr/webpack, see: node_modules/next/image-types/global.d.ts - // eslint-disable-next-line @typescript-eslint/no-explicit-any - icon: any; }; -const MenuItem = ({ icon: ItemIcon, href, text, current, className }: MenuItemProps) => { - const linkContent = ( +const MenuItem = ({ icon, text, href, current, className }: MenuItemProps) => { + const item = ( <> - + {icon && } {text && } ); @@ -67,12 +65,12 @@ const MenuItem = ({ icon: ItemIcon, href, text, current, className }: MenuItemPr if (href) { return ( - {linkContent} + {item} ); } - return linkContent; + return item; }; export default MenuItem; diff --git a/components/NoteMeta/NoteMeta.tsx b/components/NoteMeta/NoteMeta.tsx index 9001acf0..8fc879c4 100644 --- a/components/NoteMeta/NoteMeta.tsx +++ b/components/NoteMeta/NoteMeta.tsx @@ -2,7 +2,7 @@ import Link from "../Link"; import Time from "../Time"; import HitCounter from "../HitCounter"; import NoteTitle from "../NoteTitle"; -import { DateIcon, TagIcon, EditIcon, ViewsIcon } from "../Icons"; +import { FiCalendar, FiTag, FiEdit, FiEye } from "react-icons/fi"; import { styled, theme } from "../../lib/styles/stitches.config"; import * as config from "../../lib/config"; import type { NoteFrontMatter } from "../../types"; @@ -68,14 +68,14 @@ const NoteMeta = ({ slug, date, title, htmlTitle, tags }: NoteMetaProps) => { }} underline={false} > - +