<section aria-busy="true" aria-describedby="loading-status">
<div class="spinner" aria-hidden="true"></div>
<p id="loading-status" class="sr-only" aria-live="polite">
Loading user list, please wait.
</p>
<!-- Content gets injected here -->
</section>
<script>
async function loadData() {
const section = document.querySelector('[aria-busy]');
section.setAttribute('aria-busy', 'true');
const data = await fetch('/api/users').then(r => r.json());
section.innerHTML = renderUsers(data);
section.setAttribute('aria-busy', 'false');
// Optionally announce completion
document.getElementById('loading-status').textContent = `Loaded ${data.length} users.`;
}
</script>
<style>
.spinner {
width: 24px; height: 24px;
border: 3px solid #e5e7eb;
border-top-color: #3b82f6;
border-radius: 50%;
animation: spin 0.8s linear infinite;
margin: 20px auto;
}
@keyframes spin { to { transform: rotate(360deg); } }
[aria-busy="false"] .spinner { display: none; }
</style>
Create a free account and build your private vault. Share publicly whenever you want.