feat(ui): add debounce helper and skeleton polish

This commit is contained in:
matt 2025-10-07 11:35:43 -07:00
parent bf40be41fb
commit b7bfc4ca09
9 changed files with 449 additions and 719 deletions

View file

@ -3,7 +3,7 @@
{ 'name': display_name, 'name_lower': lower, 'owned': bool, 'tags': list[str] }
]
#}
<div class="alts" style="margin-top:.35rem; padding:.5rem; border:1px solid var(--border); border-radius:8px; background:#0f1115;">
<div class="alts" style="margin-top:.35rem; padding:.5rem; border:1px solid var(--border); border-radius:8px; background:#0f1115;" data-skeleton data-skeleton-label="Pulling alternatives…" data-skeleton-delay="450">
<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:.25rem; gap:.5rem; flex-wrap:wrap;">
<strong>Alternatives</strong>
{% set toggle_q = '0' if require_owned else '1' %}
@ -18,7 +18,7 @@
{% if not items or items|length == 0 %}
<div class="muted">No alternatives found{{ ' (owned only)' if require_owned else '' }}.</div>
{% else %}
<ul style="list-style:none; padding:0; margin:0; display:grid; gap:.25rem;">
<ul class="alt-list">
{% for it in items %}
{% set badge = '✔' if it.owned else '✖' %}
{% set title = 'Owned' if it.owned else 'Not owned' %}

View file

@ -20,7 +20,9 @@
<span>Commander</span>
<input type="text" name="commander" required placeholder="Type a commander name" value="{{ form.commander if form else '' }}" autofocus autocomplete="off" autocapitalize="off" spellcheck="false"
role="combobox" aria-autocomplete="list" aria-controls="newdeck-candidates"
hx-get="/build/new/candidates" hx-trigger="input changed delay:150ms" hx-target="#newdeck-candidates" hx-sync="this:replace" />
hx-get="/build/new/candidates" hx-trigger="debouncedinput change" hx-target="#newdeck-candidates" hx-sync="this:replace"
data-hx-debounce="220" data-hx-debounce-events="input"
data-hx-debounce-flush="blur" />
</label>
<small class="muted" style="display:block; margin-top:.25rem;">Start typing to see matches, then select one to load themes.</small>
<div id="newdeck-candidates" class="muted" style="font-size:12px; min-height:1.1em;"></div>

View file

@ -2,7 +2,7 @@
{% set labels = ['Choose Commander','Tags & Bracket','Ideal Counts','Review','Build'] %}
{% set index = step_index if step_index is defined else i if i is defined else 1 %}
{% set total = step_total if step_total is defined else n if n is defined else 5 %}
<nav class="stage-nav" aria-label="Build stages">
<nav class="stage-nav" aria-label="Build stages" data-skeleton data-skeleton-label="Refreshing stages…" data-skeleton-delay="400">
<ol>
{% for idx in range(1, total+1) %}
{% set name = labels[idx-1] if (labels|length)>=idx else ('Step ' ~ idx) %}

View file

@ -9,7 +9,7 @@
<a href="{{ return_url }}" class="btn" style="margin-left:auto;">← Back to Commanders</a>
{% endif %}
</div>
<div id="wizard">
<div id="wizard" data-skeleton data-skeleton-label="Preparing build surfaces…" data-skeleton-delay="420" aria-live="polite">
<!-- Wizard content will load here after the modal submit starts the build. -->
<noscript><p>Enable JavaScript to build a deck.</p></noscript>
</div>

View file

@ -4,7 +4,8 @@
<div id="theme-picker" class="theme-picker" hx-get="/themes/fragment/list?limit=20&offset=0" hx-trigger="load" hx-target="#theme-results" hx-swap="innerHTML" role="region" aria-label="Theme picker">
<div class="theme-picker-controls">
<input type="text" id="theme-search" placeholder="Search themes or synergies" aria-label="Search"
hx-get="/themes/fragment/list" hx-target="#theme-results" hx-trigger="keyup changed delay:250ms" name="q" />
hx-get="/themes/fragment/list" hx-target="#theme-results" hx-trigger="debouncedinput change" name="q"
data-hx-debounce="260" data-hx-debounce-events="input,keyup" data-hx-debounce-flush="blur" data-hx-debounce-group="theme-search" />
<select id="theme-archetype" name="archetype" hx-get="/themes/fragment/list" hx-target="#theme-results" hx-trigger="change">
<option value="">All Archetypes</option>
{% if archetypes %}{% for a in archetypes %}<option value="{{ a }}">{{ a }}</option>{% endfor %}{% endif %}