All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 5m35s
- Server sends sexp source text, client (sexp.js) renders everything - SexpExpr marker class for nested sexp composition in serialize() - sexp_page() HTML shell with data-mount="body" for full page loads - sexp_response() returns text/sexp for OOB/partial responses - ~app-body layout component replaces ~app-layout (no raw!) - ~rich-text is the only component using raw! (for CMS HTML content) - Fragment endpoints return text/sexp, auto-wrapped in SexpExpr - All _*_html() helpers converted to _*_sexp() returning sexp source - Head auto-hoist: sexp.js moves meta/title/link/script[ld+json] from rendered body to document.head automatically - Unknown components render warning box instead of crashing page - Component kwargs preserve AST for lazy rendering (fixes <> in kwargs) - Fix unterminated paren in events/sexp/tickets.sexpr Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
84 lines
2.6 KiB
HTML
84 lines
2.6 KiB
HTML
{# Shared search input macros for filter UIs #}
|
|
|
|
{% macro search_mobile(current_local_href, search, search_count, hx_select) -%}
|
|
<div
|
|
id="search-mobile-wrapper"
|
|
class="flex flex-row gap-2 items-center flex-1 min-w-0 pr-2"
|
|
>
|
|
<input
|
|
id="search-mobile"
|
|
type="text"
|
|
name="search"
|
|
aria-label="search"
|
|
class="text-base md:text-sm col-span-5 rounded-md px-3 py-2 mb-2 w-full min-w-0 max-w-full border-2 border-stone-200 placeholder-shown:border-stone-200 [&:not(:placeholder-shown)]:border-yellow-200"
|
|
sx-preserve
|
|
value="{{ search|default('', true) }}"
|
|
placeholder="search"
|
|
sx-trigger="input changed delay:300ms"
|
|
sx-target="#main-panel"
|
|
|
|
sx-select="{{hx_select}}, #search-mobile-wrapper, #search-desktop-wrapper"
|
|
sx-get="{{ (current_local_href ~ {'search': None}|qs)|host }}"
|
|
sx-swap="outerHTML"
|
|
sx-push-url="true"
|
|
sx-headers='{"X-Origin":"search-mobile", "X-Search":"true"}'
|
|
sx-sync="this:replace"
|
|
autocomplete="off"
|
|
>
|
|
|
|
<div
|
|
id="search-count-mobile"
|
|
aria-label="search count"
|
|
{% if not search_count %}
|
|
class="text-xl text-red-500"
|
|
{% endif %}
|
|
>
|
|
{% if search %}
|
|
{{search_count}}
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
{%- endmacro %}
|
|
|
|
{% macro search_desktop(current_local_href, search, search_count, hx_select) -%}
|
|
<div
|
|
id="search-desktop-wrapper"
|
|
class="flex flex-row gap-2 items-center"
|
|
>
|
|
<input
|
|
id="search-desktop"
|
|
type="text"
|
|
name="search"
|
|
aria-label="search"
|
|
class="w-full mx-1 my-3 px-3 py-2 text-md rounded-xl border-2 shadow-sm border-white placeholder-shown:border-white [&:not(:placeholder-shown)]:border-yellow-200"
|
|
sx-preserve
|
|
value="{{ search|default('', true) }}"
|
|
placeholder="search"
|
|
sx-trigger="input changed delay:300ms"
|
|
sx-target="#main-panel"
|
|
|
|
sx-select="{{hx_select}}, #search-mobile-wrapper, #search-desktop-wrapper"
|
|
sx-get="{{ (current_local_href ~ {'search': None}|qs)|host}}"
|
|
sx-swap="outerHTML"
|
|
sx-push-url="true"
|
|
sx-headers='{"X-Origin":"search-desktop", "X-Search":"true"}'
|
|
sx-sync="this:replace"
|
|
|
|
autocomplete="off"
|
|
>
|
|
|
|
<div
|
|
id="search-count-desktop"
|
|
aria-label="search count"
|
|
{% if not search_count %}
|
|
class="text-xl text-red-500"
|
|
{% endif %}
|
|
>
|
|
{% if search %}
|
|
{{search_count}}
|
|
{% endif %}
|
|
{{zap_filter}}
|
|
</div>
|
|
</div>
|
|
{%- endmacro %}
|