Стану завантаження та очікування
1) Навіщо керувати очікуванням
Користувач повинен розуміти три речі:- (1) що дія почалася, (2) скільки це займе і (3) що робити, якщо щось пішло не так.
- Хороший стан завантаження знижує тривогу, утримує фокус і економить час.
2) Вибір патерна: skeleton, progress, spinner, streaming
Skeleton - коли відома структура майбутнього контенту, але немає даних. Запобігає CLS.
Progress bar (детермінований) - коли відомий обсяг або етапи (наприклад, аплоад, KYC).
Indeterminate progress - коли тривалість невідома, але процес реальний (ініціалізація).
Spinner - тільки як короткий індикатор до 600-800 мс; далі - skeleton/прогрес/текст.
Streaming/partial render - віддаємо дані частинами (SSR/сегменти) і показуємо готові зони відразу.
Правило: не залишайте користувача на «порожньому місці». Якщо більше 1 с - дайте структуру і сенс.
3) Тимчасові пороги і бюджети (орієнтири)
≤ 100 мс - миттєвий візуальний відгук: 'busy'на кнопці/полі.
≤ 1000 мс - skeleton/індикатор + текст «Завантажуємо»....
10 с - ескалація: пропозиція «Продовжити в фоні», повідомлення, лог про статус.
4) Мікро-патерни миттєвого відгуку
Переводимо контроль в «busy» відразу (анімація ≤ 100 мс), блокуємо повторні кліки.
Текст кнопки змінюємо на «Відправляємо»..., показуємо тост «Запит прийнятий» (опціонально).
При поверненні фокусу на поле - локальний skeleton в зоні результату.
5) Skeleton без «стрибків»
Малюйте 1:1 форму майбутнього контенту: висоти блоків, пропорції медіа ('aspect-ratio').
Анімація shimmer: 1200-1600 мс, амплітуда яскравості ≤ 20%, без строба.
На великих списках - віртуалізація + обмеження кількості скелетонів в DOM.
css
.skeleton{position:relative; background:var(--bg-elevated); border-radius:12px; overflow:hidden}
.skeleton::after{
content:"";position:absolute; inset:0;
background:linear-gradient(90deg,transparent,rgba(255,255,255,.1),transparent);
animation:shimmer 1. 4s infinite;
}
@keyframes shimmer{from{transform:translateX(-100%)}to{transform:translateX(100%)}}
6) Прогрес і етапи