GrSkeleton
Берут, когда контента ещё нет.
Обзор
Когда брать
- контента ещё нет — заглушка повторяет его форму, и раскладка не прыгает при появлении данных;
- загрузка первой отрисовки — карточка, список, таблица: пользователь видит структуру до данных;
- заглушек несколько —
countповторяет строку нужное число раз; - форма нестандартная —
variantдаёт полосу, блок или круг под аватар.
Когда взять другое
| Нужно | Берите |
|---|---|
| Контент уже есть, но обновляется | GrLoading |
| Известна доля выполненного | GrProgressBar |
| Загрузка закончилась, данных нет | GrEmptyState |
| Ожидание внутри кнопки | GrButton с loading |
Скелетон честен только тогда, когда повторяет будущую раскладку. Три одинаковые полосы вместо таблицы из шести колонок обманывают дважды: сначала обещают не то, потом дают прыжок раскладки.
Варианты все тона и виды — настоящим компонентом
variant
circletextrect
Playground контролы выводятся из API, а не пишутся руками
Загружается…
0 изменено· состояние — в адресе
<GrSkeleton>Текст</GrSkeleton>Примеры 3 у каждого — живое демо и его код
Список клиентов, который не прыгает
Заглушка повторяет настоящую строку — круг под аватар, короткая и длинная линии под имя и адрес, пилюля под тариф, — и каждая строка держит одну высоту в обоих состояниях, поэтому данные сменяют заглушку без прыжка. Заглушки
aria-hidden: список объявляетaria-busy, а живая строка говорит, что загрузилось.Customers Loading customersКарточки справочного центра
Обложка — блок:
variant="rect"со скруглением карточки черезrounded, в высоту картинки. Подводка — абзац::count="2"укорачивает последнюю строку, и блок читается текстом, а не стопкой полос. Приprefers-reduced-motionпульсация останавливается совсем.Help centre · Billing Loading articlesПоказатели, которые пересчитываются
Форму даёт
variant, размер — показатель, который заглушка подменяет: короткая линия под подпись, блок высотой в число и пилюля под изменение. Каждое место держит высоту строки своего текста, и плитки не сдвигаются, когда приходят цифры.October so far Recalculating
API порождается из пакета · разойтись не может
Props
| Prop | Type | по умолчанию | Описание |
|---|---|---|---|
variant | "circle" | "text" | "rect" | undefined | "text" | Форма, а не размеры: `width`/`height` остаются на потребителе, потому что высота заглушки диктуется соседним контентом, а не шкалой компонента. |
count | number | undefined | 1 | Сколько заглушек подряд. Больше одной — они уезжают в общую обёртку. |
width | string | undefined | undefined | Ширина, CSS-длина. По умолчанию `100%`, у круга — `2.5rem`; без неё последняя из нескольких текстовых строк короче остальных. |
height | string | undefined | undefined | Высота, CSS-длина. По умолчанию `12px`, у круга — равна ширине. |
rounded | string | undefined | undefined | Радиус точечно. Не задан — берётся из `variant`. |
Типы
Все экспортируемые типы подпути, по файлам, где они объявлены. Имена, дженерики и тела читаются из файлов деклараций пакета и разойтись не могут.
import type { GrSkeletonProps, GrSkeletonVariant } from '@feugene/granularity/components/GrSkeleton'Файлdist/types/components/GrSkeleton/GrSkeleton.vue.d.ts
GrSkeleton — заглушка-плейсхолдер для загружающегося контента.
Помечен aria-hidden="true", чтобы скринридер не озвучивал «пустой» узел;
внешний контейнер обычно имеет aria-busy="true" + aria-live.
interface GrSkeletonProps {
/**
* Форма, а не размеры: `width`/`height` остаются на потребителе, потому что
* высота заглушки диктуется соседним контентом, а не шкалой компонента.
*/
variant?: GrSkeletonVariant;
/** Высота, CSS-длина. По умолчанию `12px`, у круга — равна ширине. */
height?: string;
/**
* Ширина, CSS-длина. По умолчанию `100%`, у круга — `2.5rem`; без неё последняя из
* нескольких текстовых строк короче остальных.
*/
width?: string;
/** Радиус точечно. Не задан — берётся из `variant`. */
rounded?: string;
/** Сколько заглушек подряд. Больше одной — они уезжают в общую обёртку. */
count?: number;
}Файлdist/types/components/GrSkeleton/grSkeletonStyles.d.ts
type GrSkeletonVariant = typeof GR_SKELETON_VARIANTS[number];Файлdist/types/components/GrSkeleton/config.d.ts
const grSkeletonConfig: import("@feugene/granum/contract").GranumComponentDescriptor<"GrSkeleton">;Использование из прозы библиотеки
Форма — вариантом, размеры — потребителем
variant | Радиус | Для чего |
|---|---|---|
text (по умолчанию) | --gr-radius-full | строка текста |
rect | --gr-radius-md | блок: карточка, кнопка, картинка |
circle | --gr-radius-full | аватар, иконка |
Вариант задаёт только форму. width и height остаются на потребителе:
высоту заглушки диктует контент, который она подменяет, а не шкала компонента.
Дефолт — 100% × 12px, у круга — 2.5rem.
Круг — единственная форма, где размеры связаны: height повторяет width, пока
её не задали явно. Иначе одна заданная сторона превращала бы круг в овал.
rounded перекрывает радиус варианта точечно — например, когда у карточки
приложения свой крупный радиус.
Блок из нескольких строк
<GrSkeleton :count="3" />count рисует N заглушек в общей сетке. У text последняя строка короче
(60%): блок читается как абзац, а не как список одинаковых полос. У rect и
circle все элементы одинаковые — «недописанной строки» у них не бывает.
Заданный width сильнее этого правила.
Одна заглушка (count по умолчанию) рендерится без обёртки — ровно тем же
узлом, что и раньше.
Доступность
Заглушка целиком помечена aria-hidden="true" — и одиночная, и обёртка группы.
Озвучивать «пустой» узел незачем; о том, что идёт загрузка, сообщает контейнер:
aria-busy="true" и живой регион с текстом. Так это сделано внутри пакета —
см. состояние loading у GrStatistic и GrTable.
Движение
Пульсация — собственный @keyframes компонента, и под
prefers-reduced-motion: reduce она выключается полностью (animation: none),
а не ускоряется: бесконечная анимация — это движение, которого пользователь
попросил не показывать. Контракт движения целиком — ../motion.md.
<style> у компонента без scoped намеренно: правило висит на атрибуте
[data-gr-skeleton], поэтому доезжает и до заглушек, отрисованных внутри других
компонентов пакета.
Пропы этого примера