Toast
StabilnyKrótkie, nieblokujące powiadomienie, które potwierdza akcję lub informuje o zdarzeniu w tle, a potem schodzi z drogi.
Instalacja
$ pnpm dlx shadcn@latest add https://www.prfct.dev/r/toast.jsonOwiń aplikację w Toaster jeden raz, możliwie wysoko w drzewie komponentów. Dostarcza on menedżera, renderuje obszar powiadomień w portalu i układa powiadomienia w stos w prawym dolnym rogu (na małych ekranach — na dole, pośrodku).
import { Toaster } from "@/components/ui/toast"
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>
<Toaster>{children}</Toaster>
</body>
</html>
)
}Użycie
import { toast } from "@/components/ui/toast"toast.add({
title: "Changes saved",
description: "Your profile is up to date.",
type: "success",
})toast to globalny menedżer, więc możesz go wywołać z obsługi zdarzeń, z callbacków server actions albo ze zwykłych modułów — bez żadnego hooka. Wewnątrz komponentów kolejkę odczytasz też przez useToastManager().
Przykłady
Typy
type wybiera ikonę i jej kolor: success, info, warning, error i loading. Powiadomienie bez typu nie ma ikony — to dobry wybór dla neutralnych potwierdzeń, takich jak Wysłano zaproszenie.
Z akcją
Daj powiadomieniu najwyżej jedną akcję — szybką drogę odwrotu lub podglądu, taką jak Cofnij czy Pokaż. Ta sama akcja musi być dostępna także gdzie indziej: powiadomienie może zniknąć, zanim ktokolwiek do niego dotrze.
const id = toast.add({
title: "Conversation archived",
timeout: 8000,
actionProps: {
children: "Undo",
onClick: () => {
toast.close(id)
restoreConversation()
},
},
})Promise
toast.promise pokazuje powiadomienie o ładowaniu, dopóki promise nie zostanie rozstrzygnięty, a potem zamienia to samo powiadomienie w komunikat o sukcesie lub błędzie. success i error mogą być funkcjami, które otrzymują wynik albo błąd.
toast.promise(publishPost(), {
loading: "Publishing post…",
success: (post) => ({ title: "Post published", description: post.url }),
error: (error) => ({ title: "Couldn't publish post", description: error.message }),
})Aktualizacja w miejscu
toast.add zwraca identyfikator. Przekaż go do toast.update, żeby zmienić tytuł, opis, typ lub czas wyświetlania powiadomienia, które jest już na ekranie — jedno zmieniające się powiadomienie czyta się lepiej niż stos trzech.
Trwałe
timeout: 0 utrzymuje powiadomienie na ekranie, dopóki ktoś go nie zamknie. Używaj tego oszczędnie, do stanów w tle, które trwają — na przykład braku połączenia z siecią — i łącz z priority: "high", żeby powiadomienie zostało odczytane od razu.
Układanie w stos
Naraz widać najwyżej trzy powiadomienia (limit w Toaster). Nowsze spychają starsze do tyłu, w zwarty stos; najechanie na stos lub przeniesienie na niego fokusu rozwija go, żeby każde powiadomienie dało się przeczytać i obsłużyć. Na urządzeniach dotykowych powiadomienie można odrzucić, przesuwając je w dół lub w prawo.
Wytyczne
Kiedy używać
- Aby potwierdzić, że to, co ktoś właśnie zrobił, się udało: zapisano, wysłano, skopiowano, zarchiwizowano.
- Aby przekazać wynik zadania w tle, które zakończyło się, gdy użytkownik zajmował się czymś innym.
- Aby dać krótką chwilę na wycofanie zmiany, na przykład przez Cofnij.
Kiedy nie używać
- Do błędów, które wymagają decyzji lub wprowadzenia danych — użyj Alert Dialog albo pokaż błąd bezpośrednio w treści, nie wyrywając użytkownika z kontekstu.
- Do informacji, które muszą pozostać widoczne — użyj Alert.
- Do komunikatów walidacji. Ich miejsce jest przy polu, które nie przeszło walidacji.
Wybór informacji zwrotnej
Czas wyświetlania
Domyślnie powiadomienie znika po 5 sekundach. Wydłuż ten czas dla powiadomień z akcją (8 sekund) albo z tekstem dłuższym niż jeden wiersz — o czasie decyduje tempo czytania, a nie pilność. Odliczanie zatrzymuje się, gdy kursor jest nad powiadomieniem lub ma ono fokus, więc nikt nie straci komunikatu w trakcie czytania.
Jak pisać
- Nazwij obiekt i wynik: Zarchiwizowano rozmowę, Przesłano 3 pliki. Pomiń „pomyślnie” — to mówi już ikona z ptaszkiem.
- Czas przeszły dla wyników, rzeczownik odczasownikowy dla trwającej pracy: Publikowanie wpisu… → Opublikowano wpis.
- Jeśli się da, zmieść się w jednym wierszu. Opisu używaj tylko do szczegółu, którego ktoś potrzebuje: dokąd coś trafiło, co się nie udało, czego spróbować.
- Nie powiadamiaj o tym, co już widać. Jeśli lista aktualizuje się na miejscu, to ona jest potwierdzeniem.
Dostępność
- Odczytywane, bez przejmowania fokusu. Powiadomienia renderują się w regionie na żywo. Powiadomienie z
priority: "low"(domyślnie) zostaje odczytane grzecznie, gdy czytnik skończy bieżącą wypowiedź;priority: "high"ją przerywa. Wysokiego priorytetu używaj tylko dla błędów i stanów, które wymagają natychmiastowej uwagi. - Dostępne z klawiatury. Obszar powiadomień jest punktem orientacyjnym (landmark); naciśnij F6, żeby przenieść do niego fokus. Fokus lub najechanie kursorem wstrzymuje wszystkie liczniki czasu.
- Nic istotnego nie istnieje wyłącznie w powiadomieniu. Akcje takie jak Cofnij muszą być dostępne także gdzie indziej, bo osoby korzystające z lupy ekranowej lub sterujące urządzeniem za pomocą przełączników mogą nie dotrzeć do powiadomienia, zanim zniknie.
- Ruch. Powiadomienia wsuwają się i układają w stos za pomocą transformacji; przy
prefers-reduced-motionpojawiają się i znikają bez ruchu.
| Klawisz | Działanie |
|---|---|
F6 | Przenosi fokus na najnowsze powiadomienie w obszarze powiadomień. |
TabShiftTab | Przechodzi między powiadomieniami i ich akcjami. |
Esc | Zamyka powiadomienie, na którym jest fokus. |
EnterSpacja | Aktywuje akcję lub przycisk zamykania, na którym jest fokus. |
Dokumentacja API
toast
Globalny menedżer powiadomień, utworzony przez createToastManager() z Base UI.
Opcje powiadomienia
Toaster
Dostarcza menedżera i renderuje obszar powiadomień. Przyjmuje wszystkie propsy Toast.Provider z Base UI.
Części
Toast, ToastContent, ToastTitle, ToastDescription, ToastAction, ToastClose, ToastViewport i ToastPortal są eksportowane na potrzeby własnych układów. Opakowują odpowiadające im części Base UI stylami prfct; ich propsy znajdziesz w dokumentacji Base UI.