Skip to content

Commit 32b10bf

Browse files
committed
fix: getting logo interaction working with touch
1 parent 56068c0 commit 32b10bf

1 file changed

Lines changed: 58 additions & 4 deletions

File tree

website/src/components/HdiLogo.astro

Lines changed: 58 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,9 @@
9090
// so CSS transitions on color have existing elements to animate between.
9191
function applyClasses() {
9292
logoPre.querySelectorAll<HTMLElement>(".hero-logo-letter").forEach((el) => {
93-
el.classList.toggle("hovered", el.dataset.key === hoveredKey);
93+
const key = el.dataset.key!;
94+
el.classList.toggle("hovered", key === hoveredKey);
95+
el.classList.toggle("pressed", pressedKeys.has(key));
9496
});
9597
}
9698

@@ -102,12 +104,24 @@
102104
return col < 6 ? "h" : col < 12 ? "d" : col < 18 ? "i" : null;
103105
}
104106

107+
function keyFromTouch(touch: Touch): string | null {
108+
const rect = logoPre.getBoundingClientRect();
109+
const col = Math.floor((touch.clientX - rect.left) / (rect.width / 19));
110+
return col < 6 ? "h" : col < 12 ? "d" : col < 18 ? "i" : null;
111+
}
112+
105113
// Mouse
106114
logoPre.addEventListener("mousemove", (e) => {
107115
const key = keyFromMouse(e);
108-
if (key === hoveredKey) return;
109-
hoveredKey = key;
110-
applyClasses(); // class-only update — preserves spans so transition fires
116+
if (key !== hoveredKey) {
117+
hoveredKey = key;
118+
applyClasses();
119+
}
120+
if (e.buttons === 1) {
121+
pressedKeys.clear();
122+
if (key) pressedKeys.add(key);
123+
render();
124+
}
111125
});
112126
logoPre.addEventListener("mouseleave", () => {
113127
if (hoveredKey === null) return;
@@ -127,6 +141,43 @@
127141
render();
128142
});
129143

144+
// Touch
145+
logoPre.addEventListener(
146+
"touchstart",
147+
(e) => {
148+
e.preventDefault();
149+
pressedKeys.clear();
150+
for (const touch of e.touches) {
151+
const key = keyFromTouch(touch);
152+
if (key) pressedKeys.add(key);
153+
}
154+
render();
155+
},
156+
{ passive: false },
157+
);
158+
logoPre.addEventListener(
159+
"touchmove",
160+
(e) => {
161+
e.preventDefault();
162+
pressedKeys.clear();
163+
for (const touch of e.touches) {
164+
const key = keyFromTouch(touch);
165+
if (key) pressedKeys.add(key);
166+
}
167+
render();
168+
},
169+
{ passive: false },
170+
);
171+
document.addEventListener("touchend", () => {
172+
if (pressedKeys.size === 0) return;
173+
pressedKeys.clear();
174+
render();
175+
});
176+
document.addEventListener("touchcancel", () => {
177+
pressedKeys.clear();
178+
render();
179+
});
180+
130181
// Keyboard — skip when focus is in a text input to avoid interfering with typing
131182
const KEYS = new Set(["h", "d", "i"]);
132183
const isTextField = (t: EventTarget | null) =>
@@ -163,6 +214,9 @@
163214
&.hovered {
164215
color: var(--mauve);
165216
}
217+
&.pressed {
218+
color: var(--mauve);
219+
}
166220
}
167221
}
168222
</style>

0 commit comments

Comments
 (0)