feat: add lazy loading, skeleton cards, and pull-to-refresh

This commit is contained in:
2026-02-04 11:53:12 +01:00
parent 2ffbfdf3e1
commit 3643bed7ca
6 changed files with 199 additions and 13 deletions

View File

@@ -0,0 +1,79 @@
/**
* Skeleton Card Component
* Shows a loading placeholder for listing cards
*/
class SkeletonCard extends HTMLElement {
connectedCallback() {
this.render()
}
render() {
this.innerHTML = /* html */`
<div class="skeleton-image"></div>
<div class="skeleton-info">
<div class="skeleton-title"></div>
<div class="skeleton-price"></div>
<div class="skeleton-location"></div>
</div>
`
}
}
customElements.define('skeleton-card', SkeletonCard)
const style = document.createElement('style')
style.textContent = /* css */`
skeleton-card {
display: block;
background: var(--color-bg-secondary);
border: 1px solid var(--color-border);
border-radius: var(--radius-md);
overflow: hidden;
}
skeleton-card .skeleton-image {
aspect-ratio: 1;
background: var(--color-bg-tertiary);
animation: skeleton-pulse 1.5s ease-in-out infinite;
}
skeleton-card .skeleton-info {
padding: var(--space-sm);
}
skeleton-card .skeleton-title,
skeleton-card .skeleton-price,
skeleton-card .skeleton-location {
background: var(--color-bg-tertiary);
border-radius: var(--radius-sm);
animation: skeleton-pulse 1.5s ease-in-out infinite;
}
skeleton-card .skeleton-title {
height: 1rem;
width: 80%;
margin-bottom: var(--space-xs);
}
skeleton-card .skeleton-price {
height: 1rem;
width: 50%;
margin-bottom: var(--space-xs);
}
skeleton-card .skeleton-location {
height: 0.75rem;
width: 60%;
}
@keyframes skeleton-pulse {
0%, 100% {
opacity: 1;
}
50% {
opacity: 0.5;
}
}
`
document.head.appendChild(style)