1
mirror of https://github.com/jakejarvis/jarv.is.git synced 2026-01-15 11:12:57 -05:00

add accessible skip-to-content link

This commit is contained in:
2022-05-30 22:52:46 -04:00
parent be54bc2644
commit 9410a6b2df
6 changed files with 111 additions and 70 deletions

View File

@@ -1,7 +1,7 @@
import useSWR from "swr"; import useSWR from "swr";
import commaNumber from "comma-number"; import commaNumber from "comma-number";
import Loading from "../Loading"; import Loading from "../Loading";
import { fetcher } from "../../lib/helpers/fetcher"; import fetcher from "../../lib/helpers/fetcher";
export type HitCounterProps = { export type HitCounterProps = {
slug: string; slug: string;

View File

@@ -34,6 +34,35 @@ const FlexedFooter = styled(Footer, {
flex: 1, flex: 1,
}); });
const SkipNavLink = styled("a", {
// accessible invisibility stuff pulled from @reach/skip-nav:
// https://github.com/reach/reach-ui/blob/main/packages/skip-nav/styles.css
border: 0,
clip: "rect(0 0 0 0)",
height: "1px",
width: "1px",
margin: "-1px",
padding: 0,
overflow: "hidden",
position: "absolute",
"&:focus": {
padding: "1rem",
position: "fixed",
top: "10px",
left: "10px",
zIndex: 99999,
width: "auto",
height: "auto",
clip: "auto",
background: "$superDuperLight",
color: "$link",
border: "2px solid $kindaLight",
borderRadius: "$rounded",
textDecoration: "underline",
},
});
export type LayoutProps = ComponentProps<typeof Flex> & { export type LayoutProps = ComponentProps<typeof Flex> & {
container?: boolean; // pass false to disable default `<main>` container styles with padding, etc. container?: boolean; // pass false to disable default `<main>` container styles with padding, etc.
}; };
@@ -48,16 +77,26 @@ const Layout = ({ container = true, children, ...rest }: LayoutProps) => {
<meta name="theme-color" content={themeColors[activeTheme === "dark" ? "dark" : "light"]} /> <meta name="theme-color" content={themeColors[activeTheme === "dark" ? "dark" : "light"]} />
</Head> </Head>
<SkipNavLink href="#skip-nav" role="link" tabIndex={0}>
Skip to content
</SkipNavLink>
<Flex {...rest}> <Flex {...rest}>
<StickyHeader /> <StickyHeader />
{/* passing `container={false}` to Layout allows 100% control of the content area on a per-page basis */} {/* passing `container={false}` to Layout allows 100% control of the content area on a per-page basis */}
{container ? ( {container ? (
<Default> <Default>
<Container>{children}</Container> <Container>
<div id="skip-nav" />
{children}
</Container>
</Default> </Default>
) : ( ) : (
<>{children}</> <>
<div id="skip-nav" />
{children}
</>
)} )}
<FlexedFooter /> <FlexedFooter />

View File

@@ -1,4 +1,3 @@
import { ErrorBoundary } from "react-error-boundary";
import NextLink from "next/link"; import NextLink from "next/link";
import Time from "../Time"; import Time from "../Time";
import HitCounter from "../HitCounter"; import HitCounter from "../HitCounter";
@@ -107,7 +106,6 @@ const NoteMeta = ({ slug, date, title, htmlTitle, tags = [] }: NoteMetaProps) =>
{/* only count hits on production site */} {/* only count hits on production site */}
{process.env.NEXT_PUBLIC_VERCEL_ENV === "production" && ( {process.env.NEXT_PUBLIC_VERCEL_ENV === "production" && (
<ErrorBoundary fallback={null}>
<MetaItem <MetaItem
// fix potential layout shift when number of hits loads // fix potential layout shift when number of hits loads
css={{ minWidth: "7em", marginRight: 0 }} css={{ minWidth: "7em", marginRight: 0 }}
@@ -117,7 +115,6 @@ const NoteMeta = ({ slug, date, title, htmlTitle, tags = [] }: NoteMetaProps) =>
</span> </span>
<HitCounter slug={`notes/${slug}`} /> <HitCounter slug={`notes/${slug}`} />
</MetaItem> </MetaItem>
</ErrorBoundary>
)} )}
</Wrapper> </Wrapper>

View File

@@ -3,5 +3,10 @@
// note: fetch does *not* need to be poly/ponyfilled in Next.js: // note: fetch does *not* need to be poly/ponyfilled in Next.js:
// https://nextjs.org/blog/next-9-1-7#new-built-in-polyfills-fetch-url-and-objectassign // https://nextjs.org/blog/next-9-1-7#new-built-in-polyfills-fetch-url-and-objectassign
// eslint-disable-next-line no-undef // eslint-disable-next-line @typescript-eslint/no-explicit-any
export const fetcher = (url: RequestInfo) => fetch(url).then((res) => res.json()); const fetcher = async (input: RequestInfo, init?: RequestInit): Promise<any> => {
const res = await fetch(input, init);
return res.json();
};
export default fetcher;

View File

@@ -90,8 +90,8 @@
"@types/remove-markdown": "^0.3.1", "@types/remove-markdown": "^0.3.1",
"@types/sanitize-html": "^2.6.2", "@types/sanitize-html": "^2.6.2",
"@types/uglify-js": "^3.13.2", "@types/uglify-js": "^3.13.2",
"@typescript-eslint/eslint-plugin": "^5.26.0", "@typescript-eslint/eslint-plugin": "^5.27.0",
"@typescript-eslint/parser": "^5.26.0", "@typescript-eslint/parser": "^5.27.0",
"cross-env": "^7.0.3", "cross-env": "^7.0.3",
"eslint": "~8.16.0", "eslint": "~8.16.0",
"eslint-config-next": "12.1.7-canary.24", "eslint-config-next": "12.1.7-canary.24",

102
yarn.lock
View File

@@ -1754,14 +1754,14 @@
resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.6.tgz#250a7b16c3b91f672a24552ec64678eeb1d3a08d" resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.6.tgz#250a7b16c3b91f672a24552ec64678eeb1d3a08d"
integrity sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ== integrity sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==
"@typescript-eslint/eslint-plugin@^5.26.0": "@typescript-eslint/eslint-plugin@^5.27.0":
version "5.26.0" version "5.27.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.26.0.tgz#c1f98ccba9d345e38992975d3ca56ed6260643c2" resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.27.0.tgz#23d82a4f21aaafd8f69dbab7e716323bb6695cc8"
integrity sha512-oGCmo0PqnRZZndr+KwvvAUvD3kNE4AfyoGCwOZpoCncSh4MVD06JTE8XQa2u9u+NX5CsyZMBTEc2C72zx38eYA== integrity sha512-DDrIA7GXtmHXr1VCcx9HivA39eprYBIFxbQEHI6NyraRDxCGpxAFiYQAT/1Y0vh1C+o2vfBiy4IuPoXxtTZCAQ==
dependencies: dependencies:
"@typescript-eslint/scope-manager" "5.26.0" "@typescript-eslint/scope-manager" "5.27.0"
"@typescript-eslint/type-utils" "5.26.0" "@typescript-eslint/type-utils" "5.27.0"
"@typescript-eslint/utils" "5.26.0" "@typescript-eslint/utils" "5.27.0"
debug "^4.3.4" debug "^4.3.4"
functional-red-black-tree "^1.0.1" functional-red-black-tree "^1.0.1"
ignore "^5.2.0" ignore "^5.2.0"
@@ -1769,69 +1769,69 @@
semver "^7.3.7" semver "^7.3.7"
tsutils "^3.21.0" tsutils "^3.21.0"
"@typescript-eslint/parser@^5.21.0", "@typescript-eslint/parser@^5.26.0": "@typescript-eslint/parser@^5.21.0", "@typescript-eslint/parser@^5.27.0":
version "5.26.0" version "5.27.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.26.0.tgz#a61b14205fe2ab7533deb4d35e604add9a4ceee2" resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.27.0.tgz#62bb091ed5cf9c7e126e80021bb563dcf36b6b12"
integrity sha512-n/IzU87ttzIdnAH5vQ4BBDnLPly7rC5VnjN3m0xBG82HK6rhRxnCb3w/GyWbNDghPd+NktJqB/wl6+YkzZ5T5Q== integrity sha512-8oGjQF46c52l7fMiPPvX4It3u3V3JipssqDfHQ2hcR0AeR8Zge+OYyKUCm5b70X72N1qXt0qgHenwN6Gc2SXZA==
dependencies: dependencies:
"@typescript-eslint/scope-manager" "5.26.0" "@typescript-eslint/scope-manager" "5.27.0"
"@typescript-eslint/types" "5.26.0" "@typescript-eslint/types" "5.27.0"
"@typescript-eslint/typescript-estree" "5.26.0" "@typescript-eslint/typescript-estree" "5.27.0"
debug "^4.3.4" debug "^4.3.4"
"@typescript-eslint/scope-manager@5.26.0": "@typescript-eslint/scope-manager@5.27.0":
version "5.26.0" version "5.27.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.26.0.tgz#44209c7f649d1a120f0717e0e82da856e9871339" resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.27.0.tgz#a272178f613050ed62f51f69aae1e19e870a8bbb"
integrity sha512-gVzTJUESuTwiju/7NiTb4c5oqod8xt5GhMbExKsCTp6adU3mya6AGJ4Pl9xC7x2DX9UYFsjImC0mA62BCY22Iw== integrity sha512-VnykheBQ/sHd1Vt0LJ1JLrMH1GzHO+SzX6VTXuStISIsvRiurue/eRkTqSrG0CexHQgKG8shyJfR4o5VYioB9g==
dependencies: dependencies:
"@typescript-eslint/types" "5.26.0" "@typescript-eslint/types" "5.27.0"
"@typescript-eslint/visitor-keys" "5.26.0" "@typescript-eslint/visitor-keys" "5.27.0"
"@typescript-eslint/type-utils@5.26.0": "@typescript-eslint/type-utils@5.27.0":
version "5.26.0" version "5.27.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.26.0.tgz#937dee97702361744a3815c58991acf078230013" resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.27.0.tgz#36fd95f6747412251d79c795b586ba766cf0974b"
integrity sha512-7ccbUVWGLmcRDSA1+ADkDBl5fP87EJt0fnijsMFTVHXKGduYMgienC/i3QwoVhDADUAPoytgjbZbCOMj4TY55A== integrity sha512-vpTvRRchaf628Hb/Xzfek+85o//zEUotr1SmexKvTfs7czXfYjXVT/a5yDbpzLBX1rhbqxjDdr1Gyo0x1Fc64g==
dependencies: dependencies:
"@typescript-eslint/utils" "5.26.0" "@typescript-eslint/utils" "5.27.0"
debug "^4.3.4" debug "^4.3.4"
tsutils "^3.21.0" tsutils "^3.21.0"
"@typescript-eslint/types@5.26.0": "@typescript-eslint/types@5.27.0":
version "5.26.0" version "5.27.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.26.0.tgz#cb204bb154d3c103d9cc4d225f311b08219469f3" resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.27.0.tgz#c3f44b9dda6177a9554f94a74745ca495ba9c001"
integrity sha512-8794JZFE1RN4XaExLWLI2oSXsVImNkl79PzTOOWt9h0UHROwJedNOD2IJyfL0NbddFllcktGIO2aOu10avQQyA== integrity sha512-lY6C7oGm9a/GWhmUDOs3xAVRz4ty/XKlQ2fOLr8GAIryGn0+UBOoJDWyHer3UgrHkenorwvBnphhP+zPmzmw0A==
"@typescript-eslint/typescript-estree@5.26.0": "@typescript-eslint/typescript-estree@5.27.0":
version "5.26.0" version "5.27.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.26.0.tgz#16cbceedb0011c2ed4f607255f3ee1e6e43b88c3" resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.27.0.tgz#7965f5b553c634c5354a47dcce0b40b94611e995"
integrity sha512-EyGpw6eQDsfD6jIqmXP3rU5oHScZ51tL/cZgFbFBvWuCwrIptl+oueUZzSmLtxFuSOQ9vDcJIs+279gnJkfd1w== integrity sha512-QywPMFvgZ+MHSLRofLI7BDL+UczFFHyj0vF5ibeChDAJgdTV8k4xgEwF0geFhVlPc1p8r70eYewzpo6ps+9LJQ==
dependencies: dependencies:
"@typescript-eslint/types" "5.26.0" "@typescript-eslint/types" "5.27.0"
"@typescript-eslint/visitor-keys" "5.26.0" "@typescript-eslint/visitor-keys" "5.27.0"
debug "^4.3.4" debug "^4.3.4"
globby "^11.1.0" globby "^11.1.0"
is-glob "^4.0.3" is-glob "^4.0.3"
semver "^7.3.7" semver "^7.3.7"
tsutils "^3.21.0" tsutils "^3.21.0"
"@typescript-eslint/utils@5.26.0": "@typescript-eslint/utils@5.27.0":
version "5.26.0" version "5.27.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.26.0.tgz#896b8480eb124096e99c8b240460bb4298afcfb4" resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.27.0.tgz#d0021cbf686467a6a9499bd0589e19665f9f7e71"
integrity sha512-PJFwcTq2Pt4AMOKfe3zQOdez6InIDOjUJJD3v3LyEtxHGVVRK3Vo7Dd923t/4M9hSH2q2CLvcTdxlLPjcIk3eg== integrity sha512-nZvCrkIJppym7cIbP3pOwIkAefXOmfGPnCM0LQfzNaKxJHI6VjI8NC662uoiPlaf5f6ymkTy9C3NQXev2mdXmA==
dependencies: dependencies:
"@types/json-schema" "^7.0.9" "@types/json-schema" "^7.0.9"
"@typescript-eslint/scope-manager" "5.26.0" "@typescript-eslint/scope-manager" "5.27.0"
"@typescript-eslint/types" "5.26.0" "@typescript-eslint/types" "5.27.0"
"@typescript-eslint/typescript-estree" "5.26.0" "@typescript-eslint/typescript-estree" "5.27.0"
eslint-scope "^5.1.1" eslint-scope "^5.1.1"
eslint-utils "^3.0.0" eslint-utils "^3.0.0"
"@typescript-eslint/visitor-keys@5.26.0": "@typescript-eslint/visitor-keys@5.27.0":
version "5.26.0" version "5.27.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.26.0.tgz#7195f756e367f789c0e83035297c45b417b57f57" resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.27.0.tgz#97aa9a5d2f3df8215e6d3b77f9d214a24db269bd"
integrity sha512-wei+ffqHanYDOQgg/fS6Hcar6wAWv0CUPQ3TZzOWd2BLfgP539rb49bwua8WRAs7R6kOSLn82rfEu2ro6Llt8Q== integrity sha512-46cYrteA2MrIAjv9ai44OQDUoCZyHeGIc4lsjCUX2WT6r4C+kidz1bNiR4017wHOPUythYeH+Sc7/cFP97KEAA==
dependencies: dependencies:
"@typescript-eslint/types" "5.26.0" "@typescript-eslint/types" "5.27.0"
eslint-visitor-keys "^3.3.0" eslint-visitor-keys "^3.3.0"
"@xobotyi/scrollbar-width@^1.9.5": "@xobotyi/scrollbar-width@^1.9.5":
@@ -2589,9 +2589,9 @@ eastasianwidth@^0.2.0:
integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==
electron-to-chromium@^1.4.118: electron-to-chromium@^1.4.118:
version "1.4.141" version "1.4.142"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.141.tgz#4dd9119e8a99f1c83c51dfcf1bed79ea541f08d6" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.142.tgz#70cc8871f7c0122b29256089989e67cee637b40d"
integrity sha512-mfBcbqc0qc6RlxrsIgLG2wCqkiPAjEezHxGTu7p3dHHFOurH4EjS9rFZndX5axC8264rI1Pcbw8uQP39oZckeA== integrity sha512-ea8Q1YX0JRp4GylOmX4gFHIizi0j9GfRW4EkaHnkZp0agRCBB4ZGeCv17IEzIvBkiYVwfoKVhKZJbTfqCRdQdg==
emoji-regex@^8.0.0: emoji-regex@^8.0.0:
version "8.0.0" version "8.0.0"
@@ -4246,7 +4246,7 @@ mdn-data@2.0.14:
mdurl@^1.0.0: mdurl@^1.0.0:
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e" resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e"
integrity sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4= integrity sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==
memoize-one@^5.1.1: memoize-one@^5.1.1:
version "5.2.1" version "5.2.1"