Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 12 additions & 9 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<html lang="en" class="no-js">
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; script-src 'sha256-e2g5HkZP+fghbsY1m7moq4GopOo7zRRaAHNyQ2Q7oSI=' 'sha256-NgUcRWqgRxmvoXsdf9DJT4dQ5AOna/qzI6dDicudC9k=' 'sha256-QSGzxNSepdjMBRwnovEOJlbbTDp+rqYlcPfhcB+fgnQ=' 'sha256-yDk9g0p1zFFAzRAKzvh9BO3odtKg96amzKsWG0jpax4='; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self'; base-uri 'none'; form-action 'none'">
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; script-src 'sha256-e2g5HkZP+fghbsY1m7moq4GopOo7zRRaAHNyQ2Q7oSI=' 'sha256-NgUcRWqgRxmvoXsdf9DJT4dQ5AOna/qzI6dDicudC9k=' 'sha256-QSGzxNSepdjMBRwnovEOJlbbTDp+rqYlcPfhcB+fgnQ=' 'sha256-rrFBsqTHVoUIsbIMbJ9438/R1TuU4x9Aw7xFQONRI9U='; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self'; base-uri 'none'; form-action 'none'">
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
<title>Hive Commons</title>
<meta name="description" content="Hive Commons supports Hive: governed AI-agent fleets with Jira Data Center work sources, The Commons, swarms, Claude Code, GitHub Copilot, vLLM, llm-d and more.">
Expand Down Expand Up @@ -1146,14 +1146,17 @@ <h2 id="infra-thanks-title">Thanks to the organizations that power Hive Commons<
}
function stop() { clearInterval(timer); timer = null; }
function restart() { stop(); start(); }
root.addEventListener('mouseenter', function () { pointerPaused = true; stop(); });
root.addEventListener('mouseleave', function () { pointerPaused = false; start(); });
root.addEventListener('focusin', function () { focusPaused = true; stop(); });
root.addEventListener('focusout', function (e) {
if (!root.contains(e.relatedTarget)) {
focusPaused = false;
start();
}
[root, controls].forEach(function (el) {
if (!el) return;
el.addEventListener('mouseenter', function () { pointerPaused = true; stop(); });
el.addEventListener('mouseleave', function () { pointerPaused = false; start(); });
el.addEventListener('focusin', function () { focusPaused = true; stop(); });
el.addEventListener('focusout', function (e) {
if (!root.contains(e.relatedTarget) && !(controls && controls.contains(e.relatedTarget))) {
focusPaused = false;
start();
}
});
});
document.addEventListener('visibilitychange', function () { document.hidden ? stop() : start(); });
if (reduceMotion.addEventListener) {
Expand Down
16 changes: 16 additions & 0 deletions scripts/carousels.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -789,6 +789,22 @@ test("projects pause: pointer hovering then external focusout stays paused until
assert.deepEqual(t.timers.intervals(), [PROJECT_ADVANCE_MS], "resumes once neither is inside");
});

test("projects pause: hovering or focusing the external Prev/Next controls pauses auto-advance", () => {
const t = bootProjects();
t.controls.dispatch("mouseenter");
assert.deepEqual(t.timers.intervals(), [], "hover on controls pauses");
t.controls.dispatch("mouseleave");
assert.deepEqual(t.timers.intervals(), [PROJECT_ADVANCE_MS], "leaving controls resumes");
t.controls.dispatch("focusin");
assert.deepEqual(t.timers.intervals(), [], "focus on controls pauses");
t.controls.dispatch("focusout", { relatedTarget: t.root });
assert.deepEqual(t.timers.intervals(), [], "focus moving into the carousel stays paused");
t.root.dispatch("focusout", { relatedTarget: t.next });
assert.deepEqual(t.timers.intervals(), [], "focus moving back to the controls stays paused");
t.controls.dispatch("focusout", { relatedTarget: null });
assert.deepEqual(t.timers.intervals(), [PROJECT_ADVANCE_MS], "resumes once focus leaves both");
});

test("projects reduced-motion toggle: stops and resumes auto-advance", () => {
const t = bootProjects();
t.mq.set(true);
Expand Down
Loading