You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
135 lines
4.1 KiB
135 lines
4.1 KiB
/*
|
|
* Skeleton — placeholder block.
|
|
*
|
|
* Shapes:
|
|
* - rect → rounded rectangle, sized by --_skeleton-{w,h}
|
|
* - circle → 1:1 ratio, fully rounded
|
|
* - text → stacked thin bars at staggered widths
|
|
*
|
|
* Animation: optional shimmer wave via background-position keyframes.
|
|
*/
|
|
[data-skeleton] {
|
|
/* Mix toward `neutral-solid` (which inverts luminance across modes) so the
|
|
* placeholder stays a visible subtle grey in BOTH light and dark — the bare
|
|
* `neutral-track` is ~white in light mode and vanishes on a light surface. */
|
|
--_skeleton-bg: color-mix(in oklab, var(--color-neutral-track), var(--color-neutral-solid) 16%);
|
|
--_skeleton-highlight: color-mix(in oklab, var(--color-neutral-track), var(--color-neutral-solid) 7%);
|
|
--_skeleton-size: 1rem;
|
|
--_skeleton-radius: var(--radius-md);
|
|
--_skeleton-duration: 1.4s;
|
|
|
|
display: block;
|
|
background: var(--_skeleton-bg);
|
|
border-radius: var(--_skeleton-radius);
|
|
inline-size: 100%;
|
|
block-size: var(--_skeleton-size);
|
|
overflow: hidden;
|
|
position: relative;
|
|
}
|
|
|
|
/* Sizes — intrinsic block-size when the consumer doesn't override. */
|
|
[data-skeleton][data-size='xs'] {
|
|
--_skeleton-size: 0.5rem;
|
|
}
|
|
[data-skeleton][data-size='sm'] {
|
|
--_skeleton-size: 0.75rem;
|
|
}
|
|
[data-skeleton][data-size='md'] {
|
|
--_skeleton-size: 1rem;
|
|
}
|
|
[data-skeleton][data-size='lg'] {
|
|
--_skeleton-size: 1.5rem;
|
|
}
|
|
[data-skeleton][data-size='xl'] {
|
|
--_skeleton-size: 2rem;
|
|
}
|
|
|
|
/* ── Shapes ────────────────────────────────────────────────────────── */
|
|
|
|
[data-skeleton][data-shape='rect'] {
|
|
--_skeleton-radius: var(--radius-md);
|
|
}
|
|
|
|
[data-skeleton][data-shape='circle'] {
|
|
--_skeleton-radius: 50%;
|
|
aspect-ratio: 1 / 1;
|
|
inline-size: var(--_skeleton-size);
|
|
}
|
|
|
|
[data-skeleton][data-shape='text'] {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: calc(var(--_skeleton-size) * 0.5);
|
|
background: transparent;
|
|
overflow: visible;
|
|
block-size: auto;
|
|
}
|
|
|
|
[data-skeleton-line] {
|
|
display: block;
|
|
block-size: var(--_skeleton-size, 1rem);
|
|
border-radius: var(--radius-sm);
|
|
background: var(--_skeleton-bg);
|
|
overflow: hidden;
|
|
position: relative;
|
|
}
|
|
|
|
/* ── Color accents ─────────────────────────────────────────────────── */
|
|
|
|
/* Colour comes from the shared palette forward (`--_skeleton-palette-track`):
|
|
any role / 33 scale / custom value tints the wash + shimmer highlight.
|
|
`'neutral'` (the default) never stamps `data-color`, so the base cross-mode
|
|
grey mix above stays untouched. */
|
|
[data-skeleton][data-color],
|
|
[data-skeleton][data-color-custom] {
|
|
--_skeleton-bg: color-mix(in srgb, var(--_skeleton-palette-track) 50%, transparent);
|
|
--_skeleton-highlight: color-mix(in srgb, var(--_skeleton-palette-track) 90%, white 8%);
|
|
}
|
|
|
|
/* ── Animation (shimmer wave) ──────────────────────────────────────── */
|
|
|
|
[data-skeleton][data-animated] {
|
|
background-image: linear-gradient(
|
|
var(--gradient-angle-to-r),
|
|
var(--_skeleton-bg) 0%,
|
|
var(--_skeleton-highlight) 50%,
|
|
var(--_skeleton-bg) 100%
|
|
);
|
|
background-size: 200% 100%;
|
|
animation: skeleton-shimmer var(--_skeleton-duration) ease-in-out infinite;
|
|
}
|
|
|
|
[data-skeleton][data-shape='text'][data-animated] {
|
|
background-image: none;
|
|
animation: none;
|
|
}
|
|
|
|
[data-skeleton][data-shape='text'][data-animated] [data-skeleton-line] {
|
|
background-image: linear-gradient(
|
|
var(--gradient-angle-to-r),
|
|
var(--_skeleton-bg) 0%,
|
|
var(--_skeleton-highlight) 50%,
|
|
var(--_skeleton-bg) 100%
|
|
);
|
|
background-size: 200% 100%;
|
|
animation: skeleton-shimmer var(--_skeleton-duration) ease-in-out infinite;
|
|
}
|
|
|
|
/* functional: continuous loading-shimmer sweep — machinery, not an event signature */
|
|
@keyframes skeleton-shimmer {
|
|
0% {
|
|
background-position: 200% 0;
|
|
}
|
|
100% {
|
|
background-position: -200% 0;
|
|
}
|
|
}
|
|
|
|
@media (prefers-reduced-motion: reduce) {
|
|
[data-skeleton][data-animated],
|
|
[data-skeleton][data-shape='text'][data-animated] [data-skeleton-line] {
|
|
animation: none;
|
|
background-image: none;
|
|
}
|
|
}
|