Przejdź do treści

Toast

Stabilny

Kró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.json

Owiń 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).

app/layout.tsx
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, errorloading. 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. successerror 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 (limitToaster). 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

KomponentZasięgBlokuje zadanie?Jak długo?Zastosowanie
FieldErrorJedno poleNieDo poprawieniaNieprawidłowe lub brakujące dane.
AlertStrona lub sekcjaNieDo zmiany sytuacjiLimity, awarie, podsumowania błędów formularza.
ToastCała aplikacjaNieKilka sekundPotwierdzenia i wyniki zadań w tle.
Alert DialogCała aplikacjaTakDo udzielenia odpowiedziDecyzje nieodwracalne lub niszczące dane.

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.
Wysłano fakturę INV-2041
Dostarczono na adres billing@acme.com
Dobrze.Krótko i konkretnie, a ton nadaje ikona.
Sukces!
Twoja akcja została pomyślnie zakończona.
Źle.Ogólnikowo i nadmiarowo — nie mówi nic, czego nie powiedziałby sam ptaszek.

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-motion pojawiają się i znikają bez ruchu.
KlawiszDział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.

PropTypDomyślnie
add(options)

Pokazuje powiadomienie i zwraca jego identyfikator. Przekazanie istniejącego identyfikatora aktualizuje to powiadomienie i uruchamia jego odliczanie od nowa.

(options: ToastOptions) => stringBrak wartości domyślnej
update(id, options)

Zmienia widoczne powiadomienie w miejscu.

(id: string, options: Partial<ToastOptions>) => voidBrak wartości domyślnej
close(id?)

Zamyka jedno powiadomienie, a wywołana bez identyfikatora — wszystkie.

(id?: string) => voidBrak wartości domyślnej
promise(promise, options)

Śledzi promise jednym powiadomieniem, które przechodzi od ładowania do sukcesu lub błędu.

(promise: Promise<T>, { loading, success, error }) => Promise<T>Brak wartości domyślnej

Opcje powiadomienia

PropTypDomyślnie
title

Treść komunikatu. Jeden krótki wiersz.

ReactNodeBrak wartości domyślnej
description

Opcjonalny szczegół wyświetlany pod tytułem.

ReactNodeBrak wartości domyślnej
type

Wybiera ikonę na początku. Pomiń w neutralnych powiadomieniach.

"success" | "info" | "warning" | "error" | "loading" | stringBrak wartości domyślnej
timeout

Liczba milisekund do automatycznego zamknięcia. 0 utrzymuje powiadomienie, dopóki ktoś go nie zamknie.

number5000
priority

Jak pilnie technologie wspomagające odczytują powiadomienie.

"low" | "high""low"
actionProps

Renderuje przycisk akcji; children to jego etykieta.

ComponentProps<'button'>Brak wartości domyślnej
id

Własny identyfikator. Dodanie powiadomienia z istniejącym identyfikatorem aktualizuje je.

stringBrak wartości domyślnej
onClose

Wywoływana, gdy powiadomienie zaczyna się zamykać.

() => voidBrak wartości domyślnej
onRemove

Wywoływana po animacji wyjścia, gdy powiadomienie opuszcza DOM.

() => voidBrak wartości domyślnej
data

Własne dane, dostępne dla własnego renderera powiadomień.

objectBrak wartości domyślnej

Toaster

Dostarcza menedżera i renderuje obszar powiadomień. Przyjmuje wszystkie propsy Toast.Provider z Base UI.

PropTypDomyślnie
timeout

Domyślny czas wyświetlania dla powiadomień, które nie ustawiają własnego.

number5000
limit

Maksymalna liczba powiadomień widocznych naraz. Starsze są ukryte, dopóki nie zwolni się miejsce.

number3
toastManager

Menedżer, którego zdarzeń nasłuchuje. Kolejne utworzysz przez createToastManager().

ToastManagertoast

Części

Toast, ToastContent, ToastTitle, ToastDescription, ToastAction, ToastClose, ToastViewportToastPortal 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.