Offer the searches from before while you type

Searches are kept in local storage and the five that best fit what is in
the box are offered under it: the ones it starts, then the ones it starts
a word of, then the ones it appears in anywhere, most recently searched
first. Walk them with the arrows, take one with enter or a tap, dismiss
with escape. The part that matched is picked out, and rows are built from
text nodes -- these strings are the reader's own and they are going back
on screen.

The box searches as you type, so there is no submit to record and storing
every pause would fill the list with the way to a query rather than the
query: a new entry swallows the ones it grew out of ("hot", "hote",
"hotel" leaves "hotel"), and going back to something shorter adds
nothing. Enter records straight away, since that is a reader saying they
meant it.

That turned up a bug the suggestions would have run into constantly: a
search started while the box's own last search was still out was dropped
-- loadVideos saw a load running and returned -- leaving the grid on the
previous query. Changing the result set now stops the load that is
running before starting the next one.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MPZFnNdHbPGDTqQUNiE4ZN
This commit is contained in:
Simon
2026-09-22 14:52:50 +00:00
parent 553d610e5b
commit f977852253
7 changed files with 569 additions and 2 deletions

View File

@@ -191,6 +191,53 @@ body.theme-light .top-bar {
color: var(--text-primary);
}
/* Recent searches, under the box. The drawers' colours, but laid over the page
background rather than letting it through: this one hangs over thumbnails,
and a title showing through a suggestion is a title you try to read. */
.search-suggest {
position: absolute;
top: calc(100% + 8px);
left: 0;
right: 0;
z-index: 120;
padding: 6px;
border: 1px solid var(--border);
border-radius: var(--radius-lg);
background: linear-gradient(var(--bg-secondary), var(--bg-secondary)), var(--bg-primary);
box-shadow: 0 18px 40px var(--shadow);
overflow: hidden;
}
.search-suggest-row {
display: block;
width: 100%;
padding: 9px 12px;
border: none;
border-radius: var(--radius-sm);
background: none;
color: var(--text-secondary);
font-family: inherit;
font-size: 13px;
text-align: left;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
cursor: pointer;
transition: background 0.15s ease, color 0.15s ease;
}
.search-suggest-row:hover,
.search-suggest-row.is-active {
background: var(--bg-tertiary);
color: var(--text-primary);
}
/* The part that matched what is typed, so the eye can see why a row is here. */
.search-suggest-hit {
color: var(--accent);
font-weight: 600;
}
.actions {
display: flex;
gap: 12px;