commit a5c79d2e7b71b6f896cb054cfaf89f8f1c874ee8
parent 2d4964582bb427d63881a6f6cd5b3b09f35264a9
Author: Silas Brack <silasbrack@gmail.com>
Date: Thu, 11 Jun 2026 12:38:17 +0200
feat: add Datastar loading indicators to interactive elements
Adds data-indicator attributes to vote buttons, search form, and
settings tabs per Datastar Tao guidance. Vote buttons are disabled
during requests, search shows a "Searching..." indicator, and
settings tabs show "Loading..." while fetching tab content.
Also cleans up unused patch_elements_with_selector function.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Diffstat:
6 files changed, 22 insertions(+), 6 deletions(-)
diff --git a/src/sse.rs b/src/sse.rs
@@ -4,10 +4,6 @@ pub fn patch_elements(html: &str) -> Response {
patch_elements_with_options(html, None, None)
}
-pub fn patch_elements_with_selector(html: &str, selector: &str) -> Response {
- patch_elements_with_options(html, Some(selector), None)
-}
-
fn patch_elements_with_options(
html: &str,
selector: Option<&str>,
diff --git a/static/style.css b/static/style.css
@@ -584,6 +584,13 @@ select.valid {
}
.site-footer a { color: var(--color-text-secondary); }
+/* Loading indicators */
+.loading-indicator {
+ color: var(--color-text-secondary);
+ font-size: 0.875rem;
+ padding: 4px 0;
+}
+
/* Responsive */
@media (max-width: 640px) {
:root { --max-width: 100%; }
diff --git a/static/style.css.gz b/static/style.css.gz
Binary files differ.
diff --git a/templates/search.html b/templates/search.html
@@ -1,8 +1,12 @@
<div class="search-page">
<h2>Search</h2>
- <form class="search-form" data-on:submit__prevent="@post('/search', {contentType: 'form'})" data-on:input__debounce.500ms="@post('/search', {contentType: 'form'})" >
+ <form class="search-form"
+ data-on:submit__prevent="@post('/search', {contentType: 'form'})"
+ data-on:input__debounce.500ms="@post('/search', {contentType: 'form'})"
+ data-indicator:searching>
<input type="search" name="search" placeholder="Search stories..." autofocus />
- <button type="submit">Search</button>
+ <button type="submit" data-attr:disabled="$searching">Search</button>
</form>
+ <div data-show="$searching" class="loading-indicator">Searching...</div>
<div id="search-results"></div>
</div>
diff --git a/templates/settings_page.html b/templates/settings_page.html
@@ -26,6 +26,7 @@
id="general-tab"
href="/settings?tab=general"
data-on:click__prevent="@get('/settings/tab?tab=general')"
+ data-indicator:loadingTab
>
General
</a>
@@ -35,6 +36,7 @@
id="categories-tab"
href="/settings?tab=categories"
data-on:click__prevent="@get('/settings/tab?tab=categories')"
+ data-indicator:loadingTab
>
Categories
</a>
@@ -44,6 +46,7 @@
id="sections-tab"
href="/settings?tab=sections"
data-on:click__prevent="@get('/settings/tab?tab=sections')"
+ data-indicator:loadingTab
>
Sections
</a>
@@ -53,6 +56,7 @@
id="content-filter-tab"
href="/settings?tab=content-filter"
data-on:click__prevent="@get('/settings/tab?tab=content-filter')"
+ data-indicator:loadingTab
>
Content Filter
</a>
@@ -62,6 +66,7 @@
id="syncing-tab"
href="/settings?tab=syncing"
data-on:click__prevent="@get('/settings/tab?tab=syncing')"
+ data-indicator:loadingTab
>
Syncing
</a>
@@ -71,6 +76,7 @@
id="experimental-tab"
href="/settings?tab=experimental"
data-on:click__prevent="@get('/settings/tab?tab=experimental')"
+ data-indicator:loadingTab
>
Experimental
</a>
@@ -79,6 +85,7 @@
</nav>
</div>
<hr />
+ <div data-show="$loadingTab" class="loading-indicator">Loading...</div>
{% include "settings_tab.html" %}
<footer>
<a href="/" role="button" class="secondary">Cancel</a>
diff --git a/templates/vote_button.html b/templates/vote_button.html
@@ -2,5 +2,7 @@
<button
class="vote-btn{% if voted %} voted{% endif %}"
data-on:click="@post('/vote/{{ target_type }}/{{ target_id }}')"
+ data-indicator:voting
+ data-attr:disabled="$voting"
>▲</button>
</span>