From e2fb545d0b031b396ace5105322563a1976f441e Mon Sep 17 00:00:00 2001 From: Joshua Seigler Date: Tue, 10 Jun 2025 23:43:20 -0400 Subject: [PATCH] better circuits --- assets/scripts/animations.js | 62 ++++++++++++++++++++++++++++++++++++ site/_includes/base.njk | 62 ++---------------------------------- site/_includes/css/site.css | 44 ++++++++++++++++++------- 3 files changed, 97 insertions(+), 71 deletions(-) create mode 100644 assets/scripts/animations.js diff --git a/assets/scripts/animations.js b/assets/scripts/animations.js new file mode 100644 index 0000000..678b454 --- /dev/null +++ b/assets/scripts/animations.js @@ -0,0 +1,62 @@ +'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); + }); + } +} +Array.from( + document.querySelectorAll('a[href],.nav-toggle-button,button,input') +).forEach(el => { + el.addEventListener('mouseenter', rippleListener(el)); + el.addEventListener('focus', rippleListener(el)); +}); diff --git a/site/_includes/base.njk b/site/_includes/base.njk index 3a5d003..0902283 100644 --- a/site/_includes/base.njk +++ b/site/_includes/base.njk @@ -24,6 +24,7 @@ title: Joshua's Homepage + {% include "-header.njk" %} @@ -32,63 +33,4 @@ title: Joshua's Homepage {% include "-footer.njk" %} - - \ No newline at end of file + diff --git a/site/_includes/css/site.css b/site/_includes/css/site.css index 9c81196..710eb10 100644 --- a/site/_includes/css/site.css +++ b/site/_includes/css/site.css @@ -133,6 +133,11 @@ nav label:has(input:checked) { 0 0 1rem var(--c-accent); text-decoration: none; border-radius: 0.5rem; + & img { + box-shadow: + 0 0 0.5rem var(--c-accent), + 0 0 1rem var(--c-accent); + } } a[href]:focus-visible, nav label:focus-visible, @@ -562,11 +567,13 @@ body .isso-input-wrapper label { height: auto; } -body .isso-input-wrapper input, body .isso-textarea, body .isso-preview { +body .isso-input-wrapper input, +body .isso-textarea, +body .isso-preview { color: inherit; font-size: 1rem; background-color: transparent; - padding: .5rem; + padding: 0.5rem; width: 100%; border-radius: 0.2rem; line-height: 1.4rem; @@ -575,7 +582,9 @@ body .isso-input-wrapper input, body .isso-textarea, body .isso-preview { box-shadow: inset 0 0 2rem -1rem var(--c-accent); outline: none; &:focus { - box-shadow: inset 0 0 2rem -1rem var(--c-accent), inset 0 -1.5rem 2.5rem -1.5rem var(--c-accent); + box-shadow: + inset 0 0 2rem -1rem var(--c-accent), + inset 0 -1.5rem 2.5rem -1.5rem var(--c-accent); border-color: var(--c-accent); } } @@ -583,7 +592,13 @@ body .isso-textarea { line-height: 1.2; } body .isso-preview { - background: repeating-linear-gradient( -45deg, transparent, transparent 10px, var(--c-text-background-light) 10px, var(--c-text-background-light) 20px ); + background: repeating-linear-gradient( + -45deg, + transparent, + transparent 10px, + var(--c-text-background-light) 10px, + var(--c-text-background-light) 20px + ); } body .isso-post-action > input { color: inherit; @@ -595,18 +610,19 @@ body .isso-post-action > input { cursor: pointer; outline: 0; line-height: 1.4rem; - &:hover, &:focus-visible { + &:hover, + &:focus-visible { background-color: var(--c-accent); box-shadow: 0 0 0.5rem var(--c-accent), 0 0 1rem var(--c-accent); - } } body .isso-post-action { margin: 0; } -.isso-postbox:not(.isso-preview-mode) .isso-post-action:has(input[name="edit"]) { +.isso-postbox:not(.isso-preview-mode) + .isso-post-action:has(input[name="edit"]) { display: none; } @media (max-width: 60rem) { @@ -629,19 +645,25 @@ body .isso-post-action { @keyframes ripple { 0% { opacity: 0; - transform: scale(0.2) + transform: scale(0.2); } 10% { opacity: 0.75; } 100% { opacity: 1; - transform: scale(1); + transform: scale(1.5); } } .effect-instance { position: absolute; border-radius: 0.5rem; - background: radial-gradient(ellipse farthest-side at 50% 50%, var(--c-accent) 20%, color-mix(in lch, var(--c-accent), transparent) 40%, transparent); - animation: 2s ease-in normal forwards ripple; + background: radial-gradient( + ellipse farthest-side at 50% 50%, + var(--c-accent) 10%, + color-mix(in lch, var(--c-accent), transparent) 25%, + color-mix(in lch, var(--c-accent), transparent 80%) 35%, + transparent + ); + animation: 1s ease normal forwards ripple; }