Cannabis Freedom Index

Changelog ccdc7d6

better search ux

3 files of code, design or docs +38 −20 lines

Code, design and documents 3 files

source-archive.json +26 −14

Not shown: a picture, a generated file, or past the length shown per change.

src/layouts/Base.astro +10 −6
@@ -85,5 +85,6 @@ const schemas = jsonld ? [jsonld].flat() : [];
     </form>
     <ol class="search-results" id="searchResults" role="listbox"></ol>
-    <p class="search-hint" id="searchHint">Type a country, a year or a few words. <span><kbd>↑</kbd><kbd>↓</kbd> to move, <kbd>↵</kbd> to open.</span></p>
+    <p class="search-none" id="searchNone" hidden></p>
+    <p class="search-hint" id="searchHint"><span id="searchCount" aria-live="polite"></span> <span><kbd>↑</kbd><kbd>↓</kbd> to move, <kbd>↵</kbd> to open.</span></p>
   </dialog>
 
@@ -105,5 +106,5 @@ const schemas = jsonld ? [jsonld].flat() : [];
     (function () {
       var dialog = document.getElementById("siteSearch"), input = document.getElementById("searchInput");
-      var list = document.getElementById("searchResults"), hint = document.getElementById("searchHint");
+      var list = document.getElementById("searchResults"), hint = document.getElementById("searchHint"), none = document.getElementById("searchNone"), count = document.getElementById("searchCount");
       var rows = null, fuse = null, loading = null, shown = [], active = 0;
       var KIND = { c: "Country", p: "Page", a: "Article", h: "History" }, ORDER = { c: 0, p: 1, a: 2, h: 3 };
@@ -116,16 +117,19 @@ const schemas = jsonld ? [jsonld].flat() : [];
           fuse = new got[1](rows, { keys: [{ name: "k", weight: 2 }, { name: "h", weight: 1 }], useExtendedSearch: true, ignoreLocation: true, threshold: 0.3, minMatchCharLength: 2, includeScore: true });
           render();
-        }).catch(function () { hint.textContent = "The search index could not be loaded."; });
+        }).catch(function () { none.textContent = "The search index could not be loaded."; none.hidden = false; });
         return loading;
       }
       function render() {
         var words = fold(input.value).split(/\s+/).filter(Boolean);
-        if (!fuse || !words.length) { shown = []; list.innerHTML = ""; hint.hidden = false; return; }
+        if (!fuse || !words.length) { shown = []; list.innerHTML = ""; count.textContent = ""; if (fuse) none.hidden = true; return; }
         // In Fuse's extended search, words separated by spaces must all match (each one fuzzily).
         var q = words.join(" ");
         function rank(x) { var r = x.item; return x.score + ORDER[r.t] * 0.05 + (r.k === q ? -1 : r.k.indexOf(q) === 0 ? -0.5 : 0); }
         var found = fuse.search(q).sort(function (a, b) { return rank(a) - rank(b) || a.item.i - b.item.i; });
-        shown = found.slice(0, 40).map(function (x) { return x.item; }); active = 0; hint.hidden = shown.length > 0;
-        if (!shown.length) hint.textContent = "Nothing found for “" + input.value + "”.";
+        shown = found.slice(0, 40).map(function (x) { return x.item; }); active = 0;
+        // the line under the box appears only when a search comes back empty; the key hints stay put
+        none.hidden = shown.length > 0;
+        count.textContent = !found.length ? "" : found.length > shown.length ? "First " + shown.length + " of " + found.length + " results" : found.length + (found.length === 1 ? " result" : " results");
+        if (!shown.length) none.textContent = "Nothing found for “" + input.value + "”.";
         list.innerHTML = shown.map(function (r, i) {
           return '<li role="option" id="sr' + i + '"' + (i === 0 ? ' aria-selected="true"' : "") + '><a href="' + esc(dialog.dataset.base + r.u) + '" tabindex="-1">' +

src/styles/global.css +2 −0
@@ -1316,3 +1316,5 @@ details.segrow .segrow-top > span, .segrow:not(details) .segrow-top > span { fon
 .search-hint { margin: 0; padding: 14px 16px; color: var(--muted); font-size: 13px; display: flex; justify-content: space-between; gap: 16px; flex-wrap: wrap; }
 .search-hint kbd { margin-right: 3px; }
+.search-none { margin: 0; padding: 22px 16px; color: var(--text-2); font-size: 14px; border-bottom: 1px solid var(--border); }
+.search-none[hidden] { display: none; }
 .topbar .search-btn { margin-right: -12px; }

    ↑↓ to move, ↵ to open.