Give the search a zero-result state, hide the strip while filtering
The client filter only toggles card.hidden, so a query matching nothing left the list area blank while the unfiltered "Continue reading" strip stayed populated above it — the screen contradicted itself and read as a crash. list.html now carries a hidden no-match block; applyFilter counts visible cards, fills the query in with textContent, and hides .recent for the duration of a filter. The Clear-search button is handled by a delegated click listener so it survives an htmx tab swap. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -4,17 +4,43 @@
|
||||
function applyFilter() {
|
||||
var box = document.getElementById("search");
|
||||
if (!box) return;
|
||||
var needle = box.value.trim().toLowerCase();
|
||||
document.querySelectorAll(".card").forEach(function (card) {
|
||||
var query = box.value.trim();
|
||||
var needle = query.toLowerCase();
|
||||
var cards = document.querySelectorAll(".card");
|
||||
var visible = 0;
|
||||
cards.forEach(function (card) {
|
||||
var title = (card.dataset.title || "").toLowerCase();
|
||||
card.hidden = needle !== "" && title.indexOf(needle) === -1;
|
||||
if (!card.hidden) visible++;
|
||||
});
|
||||
|
||||
// The strip is never filtered, so leaving it up during a search puts
|
||||
// non-matching covers above an empty list and the screen contradicts
|
||||
// itself.
|
||||
var recent = document.querySelector(".recent");
|
||||
if (recent) recent.hidden = needle !== "";
|
||||
|
||||
// An empty bucket already explains itself server-side; this only speaks
|
||||
// when the filter is what emptied the screen.
|
||||
var none = document.getElementById("no-match");
|
||||
if (none) {
|
||||
none.hidden = !(needle !== "" && cards.length > 0 && visible === 0);
|
||||
if (!none.hidden) none.querySelector(".no-match-q").textContent = query;
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener("input", function (e) {
|
||||
if (e.target && e.target.id === "search") applyFilter();
|
||||
});
|
||||
|
||||
document.addEventListener("click", function (e) {
|
||||
if (!e.target || !e.target.classList.contains("clear-search")) return;
|
||||
var box = document.getElementById("search");
|
||||
box.value = "";
|
||||
applyFilter();
|
||||
box.focus();
|
||||
});
|
||||
|
||||
// htmx replaces the list on a tab switch, so re-apply to the new cards.
|
||||
document.body.addEventListener("htmx:afterSwap", applyFilter);
|
||||
})();
|
||||
|
||||
@@ -591,6 +591,17 @@ button { cursor: pointer; }
|
||||
}
|
||||
.empty strong { font: 400 20px var(--font-display); color: var(--paper); }
|
||||
.empty.hot strong { color: var(--ember); }
|
||||
.empty .clear-search {
|
||||
align-self: flex-start;
|
||||
margin-top: 4px;
|
||||
height: 44px;
|
||||
padding: 0 16px;
|
||||
border: 1px solid var(--field-line);
|
||||
background: transparent;
|
||||
color: var(--paper-dim);
|
||||
font: 400 16px var(--font-display);
|
||||
}
|
||||
.empty .clear-search:hover { color: var(--paper); border-color: var(--paper); }
|
||||
.empty p {
|
||||
margin: 0;
|
||||
max-width: 44ch;
|
||||
|
||||
Reference in New Issue
Block a user