Skip to content

Commit 67bb0e3

Browse files
kckernclaude
andcommitted
feat(web): the home search box reacts the moment Enter is pressed
A search on live takes 7-12 s (/covenant), during which the page gave no sign anything happened. On Enter the box now pulses, turns read-only and shows a progress cursor until the next page loads; a second Enter and an empty box are ignored, and Back restores it. The page at rest is unchanged (browser suite 0.000% on /). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent b5b6e37 commit 67bb0e3

2 files changed

Lines changed: 31 additions & 0 deletions

File tree

‎apps/web/src/presentation/views/home.ejs‎

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,18 @@
2020
border: 1px solid black;
2121
box-shadow: 0 0 10px #492517;
2222
}
23+
/* Shown the moment Enter is pressed, until the next page arrives (a search can take seconds) */
24+
input.searching {
25+
color: #777 !important;
26+
cursor: progress;
27+
background: linear-gradient(90deg, #fff 0%, #efe6dc 50%, #fff 100%);
28+
background-size: 200% 100%;
29+
animation: searching 1s linear infinite;
30+
}
31+
@keyframes searching {
32+
from { background-position: 100% 0; }
33+
to { background-position: -100% 0; }
34+
}
2335
div { font-weight: bold; }
2436
a.button {
2537
position: relative;
@@ -89,12 +101,21 @@
89101
}
90102
if (e.which == 13) {
91103
var term = $("#searchbox").val();
104+
if ($("#searchbox").hasClass("searching") || !term.trim()) return false;
92105
if (term.match(/\\d+/g) == null) {
93106
term = term.trim().replace(/\\s+/gi, ".");
94107
}
108+
$("#searchbox").addClass("searching").prop("readonly", true);
109+
document.body.style.cursor = "progress";
95110
window.location.href = term;
96111
}
97112
});
113+
114+
// Coming back with the Back button restores the page from cache: make the box usable again.
115+
$(window).on("pageshow", function () {
116+
$("#searchbox").removeClass("searching").prop("readonly", false);
117+
document.body.style.cursor = "";
118+
});
98119
});
99120
</script>
100121

‎apps/web/test/unit/homeView.test.js‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,13 @@ test('the Install Now button is styled as on live (home.php a.button)', async ()
1919
const decls = rule[1].replace(/\/\*[\s\S]*?\*\//g, '').split(';').map(d => d.replace(/\s+/g, ' ').trim().replace(/\s*:\s*/, ':')).filter(Boolean);
2020
expect(decls).toEqual(LIVE_BUTTON);
2121
});
22+
23+
// A search can take seconds; the box must react the moment Enter is pressed (checked in Chromium
24+
// by hand: class, readonly and progress cursor are set before the next page loads).
25+
test('the search box shows it is searching on Enter and recovers on Back', async () => {
26+
const html = await ejs.renderFile(HOME, { config: {} });
27+
expect(html).toMatch(/input\.searching\s*\{[^}]*animation:\s*searching/);
28+
expect(html).toContain('$("#searchbox").addClass("searching").prop("readonly", true);');
29+
expect(html).toMatch(/hasClass\("searching"\) \|\| !term\.trim\(\)\) return false;/);
30+
expect(html).toMatch(/on\("pageshow"[\s\S]*removeClass\("searching"\)/);
31+
});

0 commit comments

Comments
 (0)