press-flash.ts
// Activation feedback, shared across widgets: the "sw-pressed" flash class that
// acknowledges a successful activation for --sw-press-ms, so keyboard triggers
// (Enter/Space, hotkeys) are as visible as a mouse press. The duration is one
// system-wide design token, read from the live cascade at flash time -- so an
// accessibility mode can slow every flash by restyling one custom property.
//
// Consumers and their class carriers:
// - sw-button flashes its host element (and manages its own pointer-held
// "sw-held" class beside it); its styles render both.
// - Megacolumn hosts with plain activatable rows call flashPress(rowElement)
// when they act on a forwarded activation; the row-flavored .sw-pressed
// rendering lives in megacolumnStyles, beside the focus washes it must outrank.
export const PRESSED_CLASS = "sw-pressed";
// The flash duration, resolved from the cascade at el. Throws when the property
// does not resolve (tokens not installed, or a detached element): a feedback
// system that silently picks its own duration would hide exactly the
// misconfiguration it exists to surface.
export function pressMs(el: Element): number {
const raw = getComputedStyle(el).getPropertyValue("--sw-press-ms").trim();
const m = /^(\d+(?:\.\d+)?)(m?s)$/.exec(raw);
if (m === null) {
throw new Error(
`press-flash: --sw-press-ms did not resolve on <${el.tagName.toLowerCase()}> `
+ `(got "${raw}"); are the design tokens installed?`,
);
}
const n = Number(m[1]);
return m[2] === "s" ? n * 1000 : n;
}
const timers = new WeakMap<HTMLElement, number>();
// Show the pressed look on el for --sw-press-ms. A re-flash while one is still
// showing re-arms the timer, so rapid activations read as sustained activity
// instead of getting cut short by the first flash's expiry.
export function flashPress(el: HTMLElement): void {
el.classList.add(PRESSED_CLASS);
window.clearTimeout(timers.get(el));
timers.set(
el,
window.setTimeout(() => {
el.classList.remove(PRESSED_CLASS);
timers.delete(el);
}, pressMs(el)),
);
}
packages/yukey/src/press-flash.ts · 2.0 KiB · f2166ce42f