diff --git a/assets/scripts/animations.js b/assets/scripts/animations.js index 678b454..b26944a 100644 --- a/assets/scripts/animations.js +++ b/assets/scripts/animations.js @@ -1,62 +1,67 @@ -'use strict' +"use strict"; -const body = document.documentElement || document.body; -function setScrollAmount() { - body.style.setProperty("--scrollLengthPx", body.scrollTop); -} -setScrollAmount(); -document.addEventListener("scroll", setScrollAmount); -document.addEventListener("resize", setScrollAmount); -function rippleListener(el) { - return(evt) => { - const rects = Array.from(evt.target.getClientRects()); - Array.from(evt.target.children).forEach(child => { - rects.push(...Array.from(child.getClientRects())); - }); - rects.forEach(rect => { - const {top, left, width, height} = rect; - const effects = body.querySelector("#effects"); - const newEffect = document.createElement("div"); - newEffect.classList.add("effect-instance"); - const padding = '10rem'; - newEffect.style.top = `calc(${ - top + window.scrollY - }px - ${padding})`; - newEffect.style.left = `calc(${ - left + window.scrollX - }px - ${padding})`; - newEffect.style.width = `calc(${ - width - }px + 2 * ${padding})`; - newEffect.style.height = `calc(${ - height - }px + 2 * ${padding})`; - effects.appendChild(newEffect); - const reverser = () => { - newEffect.getAnimations().forEach(anim => { - if (anim.currentTime < 100) { - anim.pause(); - effects.removeChild(newEffect); - return; - } - anim.pause(); - anim.updatePlaybackRate(0.25); - anim.reverse(); - anim.addEventListener('finish', () => { - if (effects.contains(newEffect)) { - effects.removeChild(newEffect); - } - }); - }); - }; - el.addEventListener('mouseleave', reverser); - el.addEventListener('blur', reverser); - }); +// function setScrollAmount() { +// (document.documentElement || document.body).style.setProperty("--scrollLengthPx", body.scrollTop); +// } +// setScrollAmount(); +// document.addEventListener("scroll", setScrollAmount); +// document.addEventListener("resize", setScrollAmount); + +/** @param {Event} evt */ +function addEffect({ target }) { + const effectsLayer = document.querySelector("#effects"); + if ( + target == null || + !target["matches"] || + !target.matches( + "a[href],.nav-toggle-button,button,input,label:not(:has(input))", + ) + ) { + return; } + const rects = Array.from(target.getClientRects()); + Array.from(target.children).forEach((child) => { + rects.push(...Array.from(child.getClientRects())); + }); + rects.forEach((rect) => { + const { top, left, width, height } = rect; + const newEffect = document.createElement("div"); + newEffect.__effectParent = target; + newEffect.classList.add("effect-instance"); + const padding = "10rem"; + newEffect.style.top = `calc(${top + window.scrollY}px - ${padding})`; + newEffect.style.left = `calc(${left + window.scrollX}px - ${padding})`; + newEffect.style.width = `calc(${width}px + 2 * ${padding})`; + newEffect.style.height = `calc(${height}px + 2 * ${padding})`; + effectsLayer.appendChild(newEffect); + }); } -Array.from( - document.querySelectorAll('a[href],.nav-toggle-button,button,input') -).forEach(el => { - el.addEventListener('mouseenter', rippleListener(el)); - el.addEventListener('focus', rippleListener(el)); -}); +document.addEventListener("mouseenter", addEffect, true); +document.addEventListener("focus", addEffect, true); + +/** @param {Event} evt */ +function removeEffect({target}) { + const effectsLayer = document.querySelector("#effects"); + const effects = Array.from(effectsLayer.children).filter( + (e) => e.__effectParent === target, + ); + effects.forEach(e => { + e.getAnimations().forEach(anim => { + if (anim.currentTime < 100) { + anim.pause(); + effectsLayer.removeChild(e); + return; + } + anim.pause(); + anim.updatePlaybackRate(-0.25); + anim.play(); + anim.addEventListener('finish', () => { + if (effectsLayer.contains(e)) { + effectsLayer.removeChild(e); + } + }); + }); + }) +}; +document.addEventListener('mouseleave', removeEffect, true); +document.addEventListener('blur', removeEffect, true); diff --git a/eleventy.config.js b/eleventy.config.js index 2e93222..8552a94 100644 --- a/eleventy.config.js +++ b/eleventy.config.js @@ -11,6 +11,7 @@ import utc from "dayjs/plugin/utc.js"; import clean from "eleventy-plugin-clean"; import site from "./site/_data/site.js"; import { feedPlugin } from "@11ty/eleventy-plugin-rss"; +import { execSync } from 'child_process'; dayjs.extend(utc); @@ -133,6 +134,10 @@ export default (config) => { stylesheet: "/simple-atom.xslt", }); + config.on('eleventy.after', () => { + execSync(`npx pagefind --site dist --glob \"**/*.html\"`, { encoding: 'utf-8' }); + }); + return { dir: { input: "site", diff --git a/package-lock.json b/package-lock.json index e7bec67..eff28c0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,6 +18,9 @@ "markdown-it-anchor": "^9.0.1", "markdown-it-link-attributes": "^4.0.1", "prettier": "^3.3.1" + }, + "devDependencies": { + "pagefind": "^1.3.0" } }, "node_modules/@11ty/dependency-tree": { @@ -520,6 +523,76 @@ "win32" ] }, + "node_modules/@pagefind/darwin-arm64": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@pagefind/darwin-arm64/-/darwin-arm64-1.3.0.tgz", + "integrity": "sha512-365BEGl6ChOsauRjyVpBjXybflXAOvoMROw3TucAROHIcdBvXk9/2AmEvGFU0r75+vdQI4LJdJdpH4Y6Yqaj4A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@pagefind/darwin-x64": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@pagefind/darwin-x64/-/darwin-x64-1.3.0.tgz", + "integrity": "sha512-zlGHA23uuXmS8z3XxEGmbHpWDxXfPZ47QS06tGUq0HDcZjXjXHeLG+cboOy828QIV5FXsm9MjfkP5e4ZNbOkow==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@pagefind/linux-arm64": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@pagefind/linux-arm64/-/linux-arm64-1.3.0.tgz", + "integrity": "sha512-8lsxNAiBRUk72JvetSBXs4WRpYrQrVJXjlRRnOL6UCdBN9Nlsz0t7hWstRk36+JqHpGWOKYiuHLzGYqYAqoOnQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@pagefind/linux-x64": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@pagefind/linux-x64/-/linux-x64-1.3.0.tgz", + "integrity": "sha512-hAvqdPJv7A20Ucb6FQGE6jhjqy+vZ6pf+s2tFMNtMBG+fzcdc91uTw7aP/1Vo5plD0dAOHwdxfkyw0ugal4kcQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@pagefind/windows-x64": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@pagefind/windows-x64/-/windows-x64-1.3.0.tgz", + "integrity": "sha512-BR1bIRWOMqkf8IoU576YDhij1Wd/Zf2kX/kCI0b2qzCKC8wcc2GQJaaRMCpzvCCrmliO4vtJ6RITp/AnoYUUmQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, "node_modules/@pkgjs/parseargs": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", @@ -1896,6 +1969,23 @@ "license": "BlueOak-1.0.0", "peer": true }, + "node_modules/pagefind": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/pagefind/-/pagefind-1.3.0.tgz", + "integrity": "sha512-8KPLGT5g9s+olKMRTU9LFekLizkVIu9tes90O1/aigJ0T5LmyPqTzGJrETnSw3meSYg58YH7JTzhTTW/3z6VAw==", + "dev": true, + "license": "MIT", + "bin": { + "pagefind": "lib/runner/bin.cjs" + }, + "optionalDependencies": { + "@pagefind/darwin-arm64": "1.3.0", + "@pagefind/darwin-x64": "1.3.0", + "@pagefind/linux-arm64": "1.3.0", + "@pagefind/linux-x64": "1.3.0", + "@pagefind/windows-x64": "1.3.0" + } + }, "node_modules/parse-srcset": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/parse-srcset/-/parse-srcset-1.0.2.tgz", diff --git a/package.json b/package.json index 6e417a9..e80c0b9 100644 --- a/package.json +++ b/package.json @@ -22,5 +22,8 @@ "markdown-it-anchor": "^9.0.1", "markdown-it-link-attributes": "^4.0.1", "prettier": "^3.3.1" + }, + "devDependencies": { + "pagefind": "^1.3.0" } } diff --git a/site/_includes/-header.njk b/site/_includes/-header.njk index af59891..c561816 100644 --- a/site/_includes/-header.njk +++ b/site/_includes/-header.njk @@ -49,8 +49,10 @@ /recipes /music /books + + {% include "-search.njk" %}

{{ tag | capitalize if tag else title }}

{%- if author -%} diff --git a/site/_includes/-search.njk b/site/_includes/-search.njk new file mode 100644 index 0000000..299a595 --- /dev/null +++ b/site/_includes/-search.njk @@ -0,0 +1,4 @@ +
+ + +
diff --git a/site/_includes/base.njk b/site/_includes/base.njk index 0902283..da3541c 100644 --- a/site/_includes/base.njk +++ b/site/_includes/base.njk @@ -28,7 +28,7 @@ title: Joshua's Homepage {% include "-header.njk" %} -
+
{{ content | safe }}
{% include "-footer.njk" %} diff --git a/site/_includes/css/site.css b/site/_includes/css/site.css index 710eb10..abc6c5d 100644 --- a/site/_includes/css/site.css +++ b/site/_includes/css/site.css @@ -113,17 +113,24 @@ body { a { color: inherit; } -a[href] { +a[href], button#search { + appearance: none; text-decoration-line: underline; box-decoration-break: clone; padding: 0.1em; margin: -0.1em; position: relative; } -a[href]:hover, -a[href]:focus-visible, -nav label:hover, -nav label:focus-visible, +button#search { + background: transparent; + border: none; + color: inherit; + font-family: inherit; + font-size: inherit; + margin-left: auto; +} +:is(a, nav label, button#search):hover, +:is(a, nav label, button#search):focus-visible, nav label:has(input:focus-visible), nav label:has(input:checked) { outline: none; @@ -139,8 +146,7 @@ nav label:has(input:checked) { 0 0 1rem var(--c-accent); } } -a[href]:focus-visible, -nav label:focus-visible, +:is(a[href], button, button#search, nav label):focus-visible, nav label:has(input:focus-visible) { z-index: 1; outline: 2px solid var(--c-text-dark); @@ -396,7 +402,8 @@ footer section { position: relative; cursor: pointer; text-decoration-line: underline; - display: inline-block; + display: inline-flex; + align-items: center; border-radius: 0; padding: 0.1rem 0.25rem; margin: 0;