API Feedback classes
Unpoly adds CSS classes to interactive elements that are loading content, and to the fragments they are targeting.
Styling these "feedback classes" is one way to instantly signal that a user interaction has been registered and that the app is working.
Feedback when following links
We have a link targeting a fragment #target:
<a href="/path" up-target="#target">Link</a>
<div id="target">
Initial content
</div>
When the user clicks on the link, the link is instantly assigned the .up-active class.
The targeted fragment (the #target element) gets the .up-loading class:
<a href="/bar" up-target="#target" class="up-active">Bar</a> <!-- mark: class="up-active" -->
<div id="target" class="up-loading"> <!-- mark: class="up-loading" -->
Initial content
</div>
Consider styling .up-active and .up-loading
to signal that the app is working.
Classes are removed when the request ends
Feedback classes remain set while the request is loading.
Once the response is received the .up-active and .up-loading classes are removed:
<a href="/path" up-target="#target">Link</a>
<div id="target">
New content from server
</div>
Feedback classes will also be removed if the request ends for any other reason, such as the server rendering an error code or when the request is aborted. See How previews end for more examples of what terminates a request.
Conveying feedback with CSS styles
To instantly signal that a user interaction has been registered, consider highlighting active links and submit buttons in your CSS:
.up-active:is(a, [up-follow], input[type=submit], button[type=submit], button:not([type])) {
outline: 2px solid blue;
}
To convey which parts of the page have a pending update, consider styling targeted fragments:
.up-loading {
opacity: 0.6;
}
You can show a hidden loading message while a form is submitting:
.spinner {
display: none;
form.up-active & {
display: block;
}
}
If these CSS rules are not enough, see Loading state for a variety of other strategies. In particular, previews give you access to both the origin and targeted elements, and allow you to make arbitrary changes to the page while a request is loading.
Feedback when submitting forms
We have a form targeting a fragment #target:
<form action="/action" up-target="#target">
<input type="text" name="email">
<button type="submit">Submit</button>
</form>
<div id="target">
Initial content
</div>
When the user clicks the submit button, both the button and the form are marked as .up-active
while the form is submitting. The targeted fragment is marked as .up-loading:
<form action="/action" up-target="#target" class="up-active"> <!-- mark: class="up-active" -->
<input type="text" name="email">
<button type="submit" class="up-active">Submit</button> <!-- mark: class="up-active" -->
</form>
<div id="target" class="up-loading"> <!-- mark: class="up-loading" -->
Initial content
</div>
Consider styling .up-active and .up-loading
to signal that the app is working.
Fields can be active origins
Sometimes a form is not submitted by pressing a submit button, but by interacting with an input field:
- The user submits by pressing
Returninside a focused field. - A field with
[up-autosubmit]is changed - A field with
[up-validate]is changed
In these cases, that field is considered the origin element that
caused the submission. It is also marked as .up-active, in addition to the form and its default submit button:
<form action="/action" up-submit class="up-active"> <!-- mark: up-active -->
<input type="text" name="email" class="up-active"> <!-- mark: up-active -->
<button type="submit" class="up-active">Submit</button> <!-- mark: up-active -->
</form>
Feedback during cache revalidation
When rendering content from a stale cache entry, Unpoly automatically reloads the fragment to ensure that the user never sees expired content.
During this cache revalidation Unpoly will mark the targeted fragment as .up-revalidating:
<div id="target" class="up-revalidating"> <!-- mark: class="up-revalidating" -->
Possibly stale content
</div>
Note that the .up-loading and .up-active classes are not set during cache revalidation.
Feedback classes from JavaScript
When rendering from JavaScript, Unpoly will set .up-active on the origin element
that caused the interaction. For example, when following a link with up.follow(), that link
will be .up-active while loading:
up.follow(link)
In situations where Unpoly cannot guess the origin, you can pass it as an { origin } option.
For example, when a button click causes a render pass, that button should be the origin:
up.on('click', '.my-button', function(event) {
up.render({ url: '/path', origin: event.target, feedback: true }) // mark: origin
})
Custom feedback classes
To set additional classes on activated origins, push a class name to up.status.config.activeClasses:
up.status.config.activeClasses.push('activated')
To set additional classes on targeted fragments that are loading new content, push
a class name to up.status.config.loadingClasses:
up.status.config.loadingClasses.push('fetching')
To set additional classes during cache revalidation, push a class name to up.status.config.revalidatingClasses:
up.status.config.revalidatingClasses.push('checking')
Disabling feedback classes
To disable feedback classes, set an
[up-feedback=false] attribute:
<a href="/path" up-follow up-feedback="false">Link</a> <!-- mark: up-feedback="false" -->
From JavaScript you may pass an { feedback: false } option:
up.follow(link, { feedback: false }) // mark: { feedback: false }
