Add loader title hint for SPA navigation feedback

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
root
2025-12-26 22:29:45 +00:00
parent b54484c7ed
commit f08d3de0c8
3 changed files with 57 additions and 4 deletions

View File

@@ -491,9 +491,11 @@ class Rsx {
}
// Collect any extra parameters for query string
// Filter out internal parameters that should not appear in URLs
const internal_params = ['_loader_title_hint'];
const query_params = {};
for (const key in params) {
if (!used_params[key]) {
if (!used_params[key] && !internal_params.includes(key)) {
query_params[key] = params[key];
}
}

View File

@@ -465,7 +465,19 @@ class Spa {
console_debug('Spa', 'Intercepting link click: ' + href);
e.preventDefault();
Spa.dispatch(href, { history: 'auto' });
// Check for loader title hint - provides immediate title feedback while page loads
const loader_title_hint = link.getAttribute('data-loader-title-hint');
const dispatch_options = { history: 'auto' };
if (loader_title_hint) {
// Set document title immediately for instant feedback
document.title = loader_title_hint;
dispatch_options.loader_title_hint = loader_title_hint;
console_debug('Spa', 'Loader title hint: ' + loader_title_hint);
}
Spa.dispatch(href, dispatch_options);
} else {
console_debug('Spa', 'No SPA route match, letting server handle: ' + href);
}
@@ -514,6 +526,7 @@ class Spa {
history: options.history || 'auto',
scroll: 'scroll' in options ? options.scroll : undefined,
triggers: options.triggers !== false,
loader_title_hint: options.loader_title_hint || null,
};
console_debug('Spa', 'Dispatching to: ' + url + ' (history: ' + opts.history + ')');
@@ -660,18 +673,25 @@ class Spa {
const action_class = route_match.action_class;
const action_name = action_class.name;
// Merge loader title hint into action args if provided
// This allows the action to show a placeholder title while loading
let action_args = route_match.args;
if (opts.loader_title_hint) {
action_args = { ...route_match.args, _loader_title_hint: opts.loader_title_hint };
}
// Log successful SPA navigation
console.warn('[Spa.dispatch] Executing SPA navigation', {
url: url,
path: parsed.path,
params: route_match.args,
params: action_args,
action: action_name,
layouts: target_layouts,
history_mode: opts.history
});
// Resolve layout chain - find divergence point and reuse matching layouts
await Spa._resolve_layout_chain(target_layouts, action_name, route_match.args, url);
await Spa._resolve_layout_chain(target_layouts, action_name, action_args, url);
// Scroll Restoration #1: Immediate (after action starts)
// This occurs synchronously after the action component is created

View File

@@ -523,6 +523,37 @@ NAVIGATION
Spa.action.reload(); // Reload current action
Spa.layout.update_nav(); // Call layout method
Loader Title Hint:
When navigating from a list to a detail page, you can provide a hint
for the page title to display while the action loads its data. This
provides immediate visual feedback instead of showing a blank or
generic title during the loading state.
Add data-loader-title-hint attribute to links:
<a href="<%= Rsx.Route('Contacts_View_Action', {id: contact.id}) %>"
data-loader-title-hint="<%= contact.name %>">
<%= contact.name %>
</a>
When the link is clicked:
1. document.title is immediately set to the hint value
2. The hint is passed to the action as this.args._loader_title_hint
3. Action can use the hint while loading, then replace with real title
Using the Hint in Actions:
async page_title() {
// Show hint while loading, real title when data is ready
if (this.is_loading() && this.args._loader_title_hint) {
return this.args._loader_title_hint;
}
return `Contact: ${this.data.contact.name}`;
}
The _loader_title_hint parameter is automatically filtered from URLs
generated by Rsx.Route(), so it never appears in the browser address
bar or generated links.
SESSION VALIDATION
After each SPA navigation (except initial load and back/forward), the client
validates its state against the server by calling Rsx.validate_session().