feat(ui): Skeleton shimmer primitive

Assisted-by: Claude:claude-opus-4-8 [Claude Code]
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
This commit is contained in:
Ettore Di Giacinto
2026-06-18 10:32:07 +00:00
parent f31f311e38
commit b73b93850c
2 changed files with 36 additions and 0 deletions

View File

@@ -975,6 +975,26 @@
.spinner-md .spinner-ring { width: 24px; height: 24px; }
.spinner-lg .spinner-ring { width: 40px; height: 40px; }
/* Skeleton shimmer placeholders */
.skeleton {
display: block;
border-radius: var(--radius-sm);
background: linear-gradient(
100deg,
var(--color-surface-sunken) 30%,
var(--color-surface-hover) 50%,
var(--color-surface-sunken) 70%
);
background-size: 200% 100%;
animation: skeletonShimmer 1.4s ease-in-out infinite;
}
.skeleton--line { height: 0.85em; margin: 0.35em 0; width: 100%; }
.skeleton--block { height: 100%; width: 100%; border-radius: var(--radius-md); }
@keyframes skeletonShimmer {
from { background-position: 200% 0; }
to { background-position: -200% 0; }
}
/* Model selector */
.model-selector {
background: var(--color-bg-tertiary);

View File

@@ -0,0 +1,16 @@
// Content-shaped shimmer placeholders. Render `count` rows.
export default function Skeleton({ variant = 'line', width, height, count = 1, className = '' }) {
const items = Array.from({ length: count })
return (
<>
{items.map((_, i) => (
<span
key={i}
className={`skeleton skeleton--${variant} ${className}`.trim()}
style={{ width, height }}
aria-hidden="true"
/>
))}
</>
)
}