Loading Overlay
Covers a region while it loads: the content stays in place, dimmed and blocked, with a spinner and an announced label.
c2-loading-overlay covers a region while it refreshes, saves or recalculates: a card fetching new numbers, a table loading its next page, a form being submitted. The content stays where it is under a scrim with a spinner, so the layout does not jump, and it cannot be clicked, typed into or tabbed to until loading is removed. Use c2-skeleton when there is no content to show yet.
While loading, the content is inert and marked busy (aria-busy), and a polite live region beside it announces the label, the text of the label slot, or the translatable “Loading”. The spinner itself is hidden from assistive technology, so the region is announced once. --c2-loading-overlay--delay holds the overlay and its announcement back for loads that usually finish quickly, so they are neither seen nor heard; the content is blocked from the start either way. Put a label slot under the spinner to say what is happening, or replace the spinner with the indicator slot.
Import
import '@c2n/components/loading-overlay'Usage
Toggle loading from your code around the work:
const overlay = document.querySelector('c2-loading-overlay')
overlay.loading = true
try {
await refreshReport()
} finally {
overlay.loading = false
}The scrim takes the host’s border radius, so give the overlay the radius of the card it covers. If the user was typing in the covered region, move focus somewhere useful before loading starts: the browser drops focus from inert content.
First load and refresh
The overlay and c2-skeleton cover two different moments, and one wrapper can serve both. On the first load there is nothing to show yet: put skeletons in the region and leave loading off. Once the real content is in, turn loading on for each refresh, so the content stays readable and in place while it is blocked.
<c2-loading-overlay id="report" label="Refreshing the report">
<!-- First load: placeholders, the overlay stays off -->
<c2-skeleton variant="text" lines="3" label="Loading the report"></c2-skeleton>
</c2-loading-overlay>
<script type="module">
const report = document.querySelector('#report')
report.replaceChildren(renderReport(await fetchReport()))
async function refresh() {
report.loading = true
try {
report.replaceChildren(renderReport(await fetchReport()))
} finally {
report.loading = false
}
}
</script>Do not turn loading on over skeletons: a spinner over pulsing placeholders says “loading” twice, a labelled skeleton and the overlay would both be announced, and there is nothing under the scrim to protect.