Перейти до вмісту
tatetUI

Toast

Черга сповіщень, доступна з будь-якого місця без прокидання пропсів.

Стан черги оголошено на рівні модуля, тому useToast() — singleton: усі виклики в застосунку працюють з однією чергою. Показати повідомлення можна звідки завгодно, не заводячи Pinia-стор і нічого не прокидаючи через дерево.

Приклад

Повідомлення для кожної ситуації

Спробуйте взаємодію

Змахніть картку вбік, щоб закрити. Від трьох повідомлень з’явиться «Очистити всі». Наведення, фокус і дотик призупиняють автозакриття. F8 переводить фокус до сповіщень, F8 чи Escape — назад.

Використання

const toast = useToast()

toast.success('Зміни збережено')
toast.error('Не вдалося зберегти')

// Прибрати всі повідомлення та їхні таймери, включно з duration: 0.
toast.dismissAll()

// Кнопки дій під повідомленням: дії — дані тоста, а не слот, бо черга
// живе в composable поза шаблоном. Клік по дії сам тост не закриває —
// закривайте через dismiss(id), коли потрібно.
const id = toast.info('Файл завеликий', {
  duration: 0,
  actions: [
    { label: 'Стиснути', onClick: () => compress() },
    { label: 'Закрити', onClick: () => toast.dismiss(id) },
  ],
})

// Тост на час запиту: «Зберігаю…» без автозакриття, потім success чи
// error у тій самій картці. Повертає той самий проміс.
await toast.promise(save(), {
  loading: 'Зберігаю…',
  success: 'Збережено',
  error: (reason) => `Не вдалося: ${String(reason)}`,
})

// Або вручну: змінити тост на місці, не закриваючи й не показуючи новий.
const upload = toast.loading('Завантаження…')
toast.update(upload, { type: 'success', message: 'Файл завантажено' })

Контейнер UiToaster монтується рівно один раз, зазвичай в app.vue. Де стоїть стос на екрані від 768px, задає проп placement (top-right за замовчуванням, bottom-right, bottom-center): у застосунку з кнопками в шапці знизу сповіщення не перекривають елементи керування. На вужчому екрані стос завжди знизу на всю ширину. Коли знизу екрана стоїть власна панель (плеєр, панель керування), підніміть стос змінною --toaster-offset-bottom на <html>: document.documentElement.style.setProperty('--toaster-offset-bottom', '88px').

API

Props

НазваТипТиповоОпис
placementtop-rightbottom-rightbottom-center"top-right"Де стоїть стос сповіщень на екрані від 768px: `top-right` (за замовчуванням), `bottom-right` або `bottom-center`. У застосунках із кнопками в шапці знизу не перекриває елементи керування. На вужчому екрані стос завжди знизу на всю ширину.

useToast()

МетодПризначення
show(options): numberДодає повідомлення й повертає його id. Опції: message, title, type, duration, actions.
success / info / warning / error(message, options?): numberСкорочені виклики для відповідного статусу.
loading(message, options?): numberСтан очікування без автозакриття. Завершіть через update або dismiss.
update(id, patch): voidЗмінює тост на місці й перезапускає відлік. Зміна типу без duration бере тривалість нового типу. Закритий тост не воскресає.
promise(task, { loading, success, error }, options?): Promiseloading на час проміса, потім success чи error у тій самій картці. success і error можуть бути функціями від результату. Повертає той самий проміс.
dismiss(id): voidЗакриває одне повідомлення та скасовує його таймер.
dismissAll(): voidОчищає всю чергу й усі таймери. Безпечний для порожньої черги.
pause(id) / resume(id): voidПризупиняє або відновлює автозакриття; після відновлення лишається щонайменше секунда.

toasts — спільний реактивний список у порядку надходження. Дії не закривають Toast автоматично; duration: 0 залишає його до ручного закриття.

Типова тривалість — за типом: 3 с, попередження 5 с, помилка 6 с. Тост із actions живе щонайменше 10 с: за три секунди треба прочитати, вирішити і дотягтися до «Скасувати», з клавіатури — ще й дістатися області через F8.

На сервері show нічого не додає і повертає -1: черга — спільний singleton модуля, і тост, піднятий під час рендеру одного запиту, потрапляв би в HTML наступного.

Вигляд

Картка має ту саму анатомію й метрики, що й UiAlert: іконка тону, заголовок, текст, хрестик, text-sm і p-3. Тон передає лише іконка, а поверхня нейтральна, як в інших оверлеїв: тост висить над довільним вмістом, і відділяє його тінь, а не заливка. Тому черга з різних статусів не перетворюється на строкатий стос.

Черга та мобільні пристрої

На екранах від 768 px Toast з’являються зверху праворуч, до 375 px завширшки. На телефоні — знизу, із полями та відступом від системної панелі. Висота області обмежена: до 70% екрана на комп’ютері й 50% на мобільному. Довга черга прокручується, а панель керування лишається доступною.

Від трьох повідомлень з’являються лічильник і «Очистити всі». Кнопка прибирає також постійні повідомлення. Нові Toast додаються в кінець; список слідує за ними лише тоді, коли ви вже перебуваєте біля кінця.

Свайп ліворуч або праворуч на 48 px закриває окрему картку. Короткий або скасований жест повертає її на місце. Вертикальний рух прокручує список. Натискання кнопок дій не починає свайп.

Поки курсор, фокус або дотик перебувають у черзі, автозакриття всіх її повідомлень призупинене, включно з новими. Відлік продовжиться після завершення всіх взаємодій.

Коли використовувати

Для результату дії, який не вимагає реакції: збережено, надіслано, скопійовано.

Коли НЕ використовувати

Не повідомляйте тостом про те, що потребує рішення. Тост зникає — питання лишається. Для цього є useConfirm().

Не дублюйте тостом помилку поля форми: її місце під самим полем, де видно, що виправляти.

Доступність

Текст оголошується через два live-регіони контейнера, що існують від монтування: помилки — aria-live="assertive", решта — polite, щоб не перебивати те, що людина читає. Самі картки live-регіонами не є: регіон, вставлений у DOM разом із текстом, скрінрідери оголошують ненадійно. Оновлення через update чи promise оголошується так само.

Поява Toast не перехоплює фокус. F8 переводить фокус в область сповіщень, звідки Tab іде кнопками тостів; F8 чи Escape повертають фокус туди, звідки прийшли. Працює й під відкритою модалкою: область поза пасткою фокуса, а Escape в ній модалку не закриває.

Кнопки мають видимий індикатор фокуса. Хрестик і дії компактні, як в Alert, а на дотику кожну добудовує невидима зона 45×45 px — палець не промахується повз «Закрити» в текст повідомлення. Системне налаштування зменшеного руху прибирає анімації переміщення.

Тривалість різна за типом: помилка тримається 6 секунд, попередження 5, решта 3. Помилку треба встигнути прочитати, а не побачити спалах на місці, де щойно щось пішло не так.

Контейнер має data-overlay-ignore — маркер, який поважає useFocusTrap. Без нього тости, що з'явилися під відкритою модалкою, отримали б inert разом з рештою фону, і закрити їх було б неможливо.

Що виправлено проти вихідної версії

Таймер автозакриття тепер скасовується при ручному. Раніше він лишався жити: користувач закривав тост хрестиком, а через секунду спрацьовував відкладений splice і зносив інший тост, який на той час опинився на його місці в масиві.

Тони беруть токени статусів. Вихідна версія малювала попередження білим по bg-amber-500 — контраст ≈1.9:1, тобто найгірше читабельним було саме те повідомлення, яке найважливіше прочитати.