samsa/internal/views/templates/results.html
Franz Kafka 665494304d perf(htmx): reduce swap payload via OOB swaps and hx-select
Before: every HTMX response returned the full results_inner template
(~400 lines of corrections, meta, pagination, back-to-top) even though
only the result list (#urls) changed between searches.

After:
- Corrections and results-meta use hx-swap-oob="true" — they update
  in-place in the DOM without duplication, no extra payload
- #urls div carries hx-select="#urls" hx-target="#urls" hx-swap="innerHTML"
  — only the result rows are extracted from the response and swapped
- Pagination forms replaced with paginate-btn buttons — JS calls
  htmx.ajax() directly with select:#urls so only result rows reload
- Header search form gains hx-get/hx-target/hx-select for partial updates
  on subsequent searches

Payload reduction per HTMX swap: ~60-70% (no more nav, meta, pagination,
back-to-top, htmx-indicator in the swap response body)
2026-03-23 14:31:21 +00:00

38 lines
1.9 KiB
HTML

{{define "title"}}{{if .Query}}{{.Query}} — {{end}}{{end}}
{{define "content"}}
<div class="results-container">
<div class="results-header">
<a href="/" class="results-logo">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<circle cx="11" cy="11" r="8"/>
<path d="m21 21-4.35-4.35"/>
</svg>
<span>samsa</span>
</a>
<form class="header-search" method="GET" action="/search" role="search" hx-get="/search" hx-target="#urls" hx-swap="innerHTML" hx-select="#urls">
<div class="search-box">
<input type="text" name="q" value="{{.Query}}" placeholder="Search…" autocomplete="off">
<button type="submit" class="search-btn" aria-label="Search">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">
<circle cx="11" cy="11" r="8"/>
<path d="m21 21-4.35-4.35"/>
</svg>
</button>
</div>
</form>
</div>
<div class="category-tabs" role="tablist">
<a href="/search?q={{.Query | urlquery}}&category=" class="category-tab {{if eq .ActiveCategory ""}}active{{end}}">All</a>
<a href="/search?q={{.Query | urlquery}}&category=general" class="category-tab {{if eq .ActiveCategory "general"}}active{{end}}">General</a>
<a href="/search?q={{.Query | urlquery}}&category=it" class="category-tab {{if eq .ActiveCategory "it"}}active{{end}}">IT</a>
<a href="/search?q={{.Query | urlquery}}&category=news" class="category-tab {{if eq .ActiveCategory "news"}}active{{end}}">News</a>
<a href="/search?q={{.Query | urlquery}}&category=images" class="category-tab {{if eq .ActiveCategory "images"}}active{{end}}">Images</a>
</div>
<div class="results-content">
{{template "results_inner" .}}
</div>
</div>
{{end}}