nav hover: glow instead of the underline bar, and give keyboard focus the same glow
build-and-deploy / build (push) Failing after 11m32s

This commit is contained in:
2026-08-18 11:04:27 +10:00
parent 21616762e6
commit 8d394fe2c7
2 changed files with 8 additions and 38 deletions
+7 -16
View File
@@ -27,7 +27,7 @@ const links = [
target={l.external ? "_blank" : undefined} target={l.external ? "_blank" : undefined}
rel={l.external ? "noopener noreferrer" : undefined} rel={l.external ? "noopener noreferrer" : undefined}
> >
{l.label}<span class="nav__ul" aria-hidden="true"></span> {l.label}
</a> </a>
))} ))}
</nav> </nav>
@@ -98,21 +98,12 @@ const links = [
color: var(--text); color: var(--text);
text-decoration: none; text-decoration: none;
} }
/* Hover underline - scaleX sprung by the Motion layer, growing from the /* Hover = glow, not an underline (owner call 2026-08-18: the bar read as clunky).
start of the label. No scroll-spy: it tracked the active section as you Keyboard focus gets the same treatment so the affordance is not mouse-only. */
scrolled, which read as clunky on a page this short. */ .nav__links a:hover,
.nav__ul { .nav__links a:focus-visible {
position: absolute; color: var(--accent);
left: 0; text-shadow: 0 0 10px var(--accent-glow), 0 0 22px var(--accent-glow);
right: 0;
bottom: -0.45rem;
height: 2px;
border-radius: 2px;
background: linear-gradient(90deg, var(--accent), var(--accent-2));
box-shadow: 0 0 8px var(--accent-glow);
transform: scaleX(0);
transform-origin: 0 50%;
pointer-events: none;
} }
.nav__actions { .nav__actions {
display: flex; display: flex;
+1 -22
View File
@@ -84,32 +84,11 @@ function run(): void {
} }
/* 5. Nav - animated active-section underline + tactile hover. */ /* 5. Nav - animated active-section underline + tactile hover. */
initNav();
/* 6. Buttons - spring lift on hover, press on tap. */ /* Buttons - spring lift on hover, press on tap. (Nav hover is pure CSS glow now.) */
initButtons(); initButtons();
} }
function initNav(): void {
const links = Array.from(
document.querySelectorAll<HTMLAnchorElement>(".nav__links a"),
);
if (!links.length) return;
const spring = { type: "spring", stiffness: 380, damping: 30 } as const;
const under = (a: HTMLAnchorElement, on: boolean): void => {
const ul = a.querySelector<HTMLElement>(".nav__ul");
if (!ul) return;
animate(ul, { scaleX: on ? 1 : 0 }, spring);
};
for (const a of links) {
a.addEventListener("pointerenter", () => under(a, true));
a.addEventListener("pointerleave", () => under(a, false));
}
}
function initButtons(): void { function initButtons(): void {
const lift = { type: "spring", stiffness: 400, damping: 26 } as const; const lift = { type: "spring", stiffness: 400, damping: 26 } as const;
const tap = { type: "spring", stiffness: 600, damping: 22 } as const; const tap = { type: "spring", stiffness: 600, damping: 22 } as const;