shadcn/ui’de geçici bildirim (toast) göstermenin güncel yolu Sonner bileşenidir: npx shadcn@latest add sonner ile eklenen Toaster bileşenini kök layout’a bir kez koyarsınız, ardından uygulamanın herhangi bir yerinde sonner paketinden gelen toast() fonksiyonunu çağırırsınız. Eski toast bileşeni belgede açıkça kullanımdan kaldırılmış (deprecated) olarak işaretlidir ve yerine Sonner önerilir.

Bu yazıda Sonner’ın kurulumunu, shadcn’in components/ui/sonner.tsx dosyasında Sonner’a neler eklediğini, bildirim türlerini, açıklama ve aksiyon butonunu, promise bildirimlerini ve eski toast bileşeninden geçişi anlatıyoruz. Kaynak, depo kopyası 19 Aralık 2025 tarihli shadcn/ui belgeleri ve resmî örnek dosyalarıdır. Serinin tamamı için shadcn/ui öğrenme rehberi sayfasına bakabilirsiniz.

Sonner nedir, shadcn ne ekler?

Sonner nedir, shadcn ne ekler? --normal-bg, --normal-text, --normal-border, --border-radius

Belge Sonner’ı “React için görüş sahibi (opinionated) bir toast bileşeni” olarak tanıtır; kütüphaneyi emilkowalski geliştirir ve sürdürür. shadcn/ui Aralık 2023 sürüm notlarında Sonner’ı eklerken onu “ihtiyaç duyacağınız son toast bileşeni” diye anar. Önemli ayrım şudur: bildirimleri gösteren, sıraya koyan ve canlandıran asıl motor sonner npm paketidir. shadcn’in projenize kopyaladığı sonner.tsx dosyası ise bu paketin Toaster bileşenini saran ince bir katmandır.

Bu sarmalayıcı üç iş yapar. Birincisi, next-themes paketinin useTheme hook’uyla etkin temayı okur ve Sonner’a theme olarak verir; tema bilgisi gelmezse varsayılan "system" kullanılır. İkincisi, başarı, bilgi, uyarı, hata ve yükleniyor durumları için lucide-react ikonlarını atar. Üçüncüsü, Sonner’ın CSS değişkenlerini shadcn tema değişkenlerine bağlar. Böylece bildirimler, sitenizin geri kalanıyla aynı renk ve köşe yuvarlaklığını kullanır.

Sonner değişkeniBağlandığı shadcn değişkeniAnlamı
--normal-bgvar(--popover)Bildirimin arka planı
--normal-textvar(--popover-foreground)Bildirim metni
--normal-bordervar(--border)Kenarlık rengi
--border-radiusvar(--radius)Köşe yuvarlaklığı

Bu eşleme, bildirimlerin açılır pencerelerle (popover) aynı yüzey rengini kullandığı anlamına gelir. Temanızda --popover değerini değiştirdiğinizde bildirimler de değişir. Tema değişkenlerinin tamamı shadcn tema yazısında listeleniyor.

Kurulum

CLI ile kurulum iki adımdır: bileşeni eklemek ve Toaster bileşenini uygulamanın kök düzenine yerleştirmek.

bash
npx shadcn@latest add sonner

Next.js App Router’da kök düzen app/layout.tsx dosyasıdır. Belgedeki örnekte Toaster, body içinde ana içerikten sonra konur:

typescript
import { Toaster } from "@/components/ui/sonner"

export default function RootLayout({ children }) {
  return (
    <html lang="tr">
      <head />
      <body>
        <main>{children}</main>
        <Toaster />
      </body>
    </html>
  )
}

Elle kurulumda önce iki paket kurulur, sonra sonner.tsx kaynak kodu projeye kopyalanır ve yine Toaster layout’a eklenir. Belgenin elle kurulum sekmesindeki örnekte Toaster ana içerikten önce yazılmıştır; iki sekmedeki sıra farklıdır, ama her ikisinde de Toaster body içinde ve tek bir kez yer alır.

bash
npm install sonner next-themes

Kurulumdaki next-themes bağımlılığı, sonner.tsx içindeki useTheme çağrısı içindir. Next.js’te koyu modu zaten next-themes ile kurduysanız bildirimler de otomatik olarak aynı temayı izler. React 19 uyumluluk tablosunda sonner paketi sorunsuz çalışanlar arasında listelenir.

components/ui/sonner.tsx dosyası

Belgenin “2025-10-13 Icons” sürüm notu, Sonner bileşeninin ikonları lucide setinden alacak şekilde güncellendiğini ve mevcut projelerde sonner.tsx dosyasının buna göre düzenlenmesi gerektiğini söyler. Depodaki güncel dosya şöyledir:

typescript
"use client"

import {
  CircleCheckIcon,
  InfoIcon,
  Loader2Icon,
  OctagonXIcon,
  TriangleAlertIcon,
} from "lucide-react"
import { useTheme } from "next-themes"
import { Toaster as Sonner, type ToasterProps } from "sonner"

const Toaster = ({ ...props }: ToasterProps) => {
  const { theme = "system" } = useTheme()

  return (
    <Sonner
      theme={theme as ToasterProps["theme"]}
      className="toaster group"
      icons={{
        success: <CircleCheckIcon className="size-4" />,
        info: <InfoIcon className="size-4" />,
        warning: <TriangleAlertIcon className="size-4" />,
        error: <OctagonXIcon className="size-4" />,
        loading: <Loader2Icon className="size-4 animate-spin" />,
      }}
      style={
        {
          "--normal-bg": "var(--popover)",
          "--normal-text": "var(--popover-foreground)",
          "--normal-border": "var(--border)",
          "--border-radius": "var(--radius)",
        } as React.CSSProperties
      }
      {...props}
    />
  )
}

export { Toaster }

Dosyanın birkaç ayrıntısı pratikte önemlidir. "use client" satırı, hook kullandığı için bileşeni istemci bileşeni yapar; böylece sunucu bileşeni olan bir layout içinde güvenle kullanılabilir. Bileşen ToasterProps tipindeki bütün prop’ları alır ve en sona {...props} ile aktarır. Bu, <Toaster /> üzerine yazacağınız her Sonner ayarının (konum gibi) çalışacağı, hatta isterseniz icons ya da theme değerini ezebileceğiniz anlamına gelir. Hangi ayarların bulunduğunu belge listelemez; Sonner’ın kendi belgesine (sonner.emilkowal.ski) yönlendirir.

Yükleniyor ikonu animate-spin ile döner; diğer ikonlar size-4 ile sabit boyuttadır. İkonları başka bir setle değiştirmek isterseniz bu dosyayı düzenlemeniz yeterlidir; shadcn’in genel yaklaşımında kod sizindir.

ThemeProvider ile birlikte kullanmak

Sonner belgesindeki layout örneğinde tema sağlayıcısı görünmez; koyu mod belgesindeki Next.js örneğinde ise body içinde {children} değerini saran bir ThemeProvider bulunur ve html etiketine suppressHydrationWarning eklenir. useTheme bir React bağlam (context) hook’u olduğu için, Toaster bileşeninin etkin temayı okuyabilmesi için onu bu sağlayıcının içine yerleştirmeniz mantıklıdır. İki belgenin örneklerini birleştiren bir app/layout.tsx şöyle görünebilir:

typescript
import { ThemeProvider } from "@/components/theme-provider"
import { Toaster } from "@/components/ui/sonner"

export default function RootLayout({ children }) {
  return (
    <html lang="tr" suppressHydrationWarning>
      <head />
      <body>
        <ThemeProvider
          attribute="class"
          defaultTheme="system"
          enableSystem
          disableTransitionOnChange
        >
          <main>{children}</main>
          <Toaster />
        </ThemeProvider>
      </body>
    </html>
  )
}

ThemeProvider ayarları (attribute="class", defaultTheme="system", enableSystem, disableTransitionOnChange) koyu mod belgesinden olduğu gibi alınmıştır. Burada components/theme-provider.tsx dosyasının, koyu mod belgesindeki gibi next-themes sağlayıcısını saran küçük bir istemci bileşeni olarak önceden oluşturulduğu varsayılır.

Next.js dışındaki projeler

sonner.tsx doğrudan next-themes paketinden içe aktarır. Vite projelerinde shadcn’in koyu mod belgesi next-themes yerine kendi ThemeProvider bileşenini ve @/components/theme-provider içinden gelen bir useTheme hook’unu kurdurur; bu hook da "dark", "light" ve "system" değerlerini kullanır. Dosya projenizde olduğu için, tema bilgisini o hook’tan okuyacak şekilde içe aktarmayı değiştirebilirsiniz. Belge bu uyarlamayı ayrıca göstermez; Vite koyu mod kurulumu dark mode yazısında anlatılıyor.

İlk bildirim

Kullanım iki satırdır: toast fonksiyonunu sonner paketinden içe aktarır ve bir metinle çağırırsınız. Dikkat edin, içe aktarma @/components/ui/sonner dosyasından değil doğrudan paketin kendisinden yapılır; projenizdeki dosya yalnızca Toaster bileşenini dışa aktarır.

typescript
import { toast } from "sonner"

toast("Etkinlik oluşturuldu.")

Resmî demo, bildirimi bir butonla tetikler ve iki ek seçenek kullanır: başlığın altında görünen bir description ve bildirimin üzerinde bir buton gösteren action. action nesnesi bir label ve bir onClick fonksiyonu taşır; demoda bu buton “Undo” (geri al) işlevi görür:

typescript
"use client"

import { toast } from "sonner"

import { Button } from "@/components/ui/button"

export function EtkinlikBildirimi() {
  return (
    <Button
      variant="outline"
      onClick={() =>
        toast("Etkinlik oluşturuldu", {
          description: "3 Aralık 2023 Pazar, 09:00",
          action: {
            label: "Geri al",
            onClick: () => console.log("Geri al"),
          },
        })
      }
    >
      Bildirimi göster
    </Button>
  )
}

toast() bir olay işleyicisinden çağrıldığı için bileşen istemci bileşenidir. Buton varyantları için Button yazısına bakabilirsiniz. “Geri al” gibi bir aksiyon, kullanıcının geri alınabilir bir işlemi (silme, arşivleme) hemen iptal etmesine olanak verdiği için onay penceresine göre daha akıcı bir deneyim sunabilir; geri alınamayan işlemler için ise Alert Dialog daha uygundur.

Bildirim türleri

Bildirim türleri: toast("..."), toast.success("..."), toast.info("..."), toast.warning("...")

Belgedeki “Examples” bölümü, Sonner’ın hazır türlerini altı butonla gösterir. Her tür, sonner.tsx dosyasında atanan ikonla birlikte görünür:

typescript
"use client"

import { toast } from "sonner"

import { Button } from "@/components/ui/button"

export function BildirimTurleri() {
  return (
    <div className="flex flex-wrap gap-2">
      <Button variant="outline" onClick={() => toast("Etkinlik oluşturuldu")}>
        Varsayılan
      </Button>
      <Button
        variant="outline"
        onClick={() => toast.success("Etkinlik oluşturuldu")}
      >
        Başarılı
      </Button>
      <Button
        variant="outline"
        onClick={() =>
          toast.info("Etkinlik saatinden 10 dakika önce alanda olun")
        }
      >
        Bilgi
      </Button>
      <Button
        variant="outline"
        onClick={() =>
          toast.warning("Etkinlik başlangıcı 08:00'den önce olamaz")
        }
      >
        Uyarı
      </Button>
      <Button
        variant="outline"
        onClick={() => toast.error("Etkinlik oluşturulamadı")}
      >
        Hata
      </Button>
    </div>
  )
}
ÇağrıKullanım amacısonner.tsx içindeki ikon
toast("...")Nötr bildirimAtanmış ikon yok
toast.success("...")İşlem başarıyla tamamlandıCircleCheckIcon
toast.info("...")BilgilendirmeInfoIcon
toast.warning("...")UyarıTriangleAlertIcon
toast.error("...")HataOctagonXIcon
toast.promise(...)Süren işlem: yükleniyor, sonra başarı ya da hataLoader2Icon (dönen), ardından sonuç ikonu

Promise bildirimleri

En kullanışlı türlerden biri toast.promise’tir. Bir promise döndüren fonksiyon ve üç durum için mesajlar alır: beklerken loading, başarıda success, hatada error. success düz metin olabileceği gibi promise’in çözdüğü veriyi alan bir fonksiyon da olabilir. Resmî örnekte iki saniye sonra { name: "Event" } nesnesiyle çözülen bir promise kullanılır ve başarı mesajı bu addan üretilir:

typescript
toast.promise<{ name: string }>(
  () =>
    new Promise((resolve) =>
      setTimeout(() => resolve({ name: "Etkinlik" }), 2000)
    ),
  {
    loading: "Yükleniyor...",
    success: (data) => `${data.name} oluşturuldu`,
    error: "Hata",
  }
)

Burada <{ name: string }> tip parametresi, success fonksiyonundaki data değişkeninin tipini belirler. Gerçek bir uygulamada setTimeout yerine bir API isteği, örneğin form gönderimi gelir: kullanıcı “Yükleniyor...” mesajını görür, istek bitince aynı bildirim başarı ya da hata mesajına dönüşür. Yükleniyor ikonu, sonner.tsx dosyasındaki Loader2Icon ile dönerek gösterilir.

Küçük bir örnek: form gönderiminden sonra bildirim

Bildirimler en çok bir işlemin sonucunu duyurmak için kullanılır. Aşağıdaki örnek, bir kaydetme fonksiyonunu toast.promise ile sarar. kaydet fonksiyonu sizin API çağrınızı temsil eder; promise reddedilirse error mesajı gösterilir.

typescript
"use client"

import { toast } from "sonner"

import { Button } from "@/components/ui/button"

async function kaydet(): Promise<{ baslik: string }> {
  // Burada API isteğinizi yapın.
  return { baslik: "Profil" }
}

export function KaydetButonu() {
  return (
    <Button
      onClick={() =>
        toast.promise(kaydet, {
          loading: "Kaydediliyor...",
          success: (data) => `${data.baslik} kaydedildi`,
          error: "Kaydedilemedi, lütfen tekrar deneyin",
        })
      }
    >
      Kaydet
    </Button>
  )
}

Bu örnek, resmî promise örneğiyle aynı yapıyı kullanır: ilk argüman promise döndüren bir fonksiyon, ikincisi üç durum mesajıdır. Next.js’te form gönderimini Server Action ile yapıyorsanız, sonuç bildirimi için Server Actions ile form yazısına de göz atın.

Sonner mı, Alert mi?

shadcn’de kullanıcıya mesaj vermenin iki yaygın yolu vardır ve karıştırılmaları kolaydır. Eski toast sayfasının kısa tanımı, bu bileşen ailesinin amacını iyi özetler: kısa süre görünen, özlü bir mesaj. Sonner bildirimleri sayfanın akışının dışında, bir köşede belirir ve bir süre sonra kaybolur; “kaydedildi”, “kopyalandı”, “silindi, geri al” gibi işlem sonuçları için uygundur.

Alert ise sayfanın içine yerleşen, siz kaldırana kadar orada duran bir uyarı kutusudur; belgedeki tanımıyla kullanıcının dikkatini çeken bir “callout”tır. Formun üstündeki “ödemeniz işlenemedi” mesajı ya da oturum süresinin dolduğunu bildiren kutu bu türdendir. Kullanıcının mesajı okuması ve buna göre davranması gerekiyorsa, kaybolan bir bildirim yerine sayfada kalan bir Alert daha güvenlidir. Alert, Badge ve diğer durum bileşenleri geri bildirim bileşenleri yazısında anlatılıyor.

Eski toast bileşeni ve Sonner’a geçiş

Eski toast bileşeni ve Sonner’a geçiş: npx shadcn@latest add sonner ile yeni bileşeni ekleyin., Kök layout’taki eski toaster bileşenini kaldırıp yerine @/components/ui/sonner...

Belgedeki Toast sayfası tek bir bilgi kutusundan ibarettir: toast bileşeni kullanımdan kaldırılmıştır ve Sonner belgesine bakılması önerilir. Eski bileşenin belgesini arayanlar için sayfa, shadcn’in v3 sitesindeki eski belgeye bağlantı verir. Kaldırma kararı Şubat 2025 Tailwind v4 sürüm notlarında da yazılıdır: aynı güncellemede toast bileşeninin Sonner lehine kullanımdan kaldırıldığı belirtilir.

Eski bileşenin projenizde nasıl göründüğünü anlamak için sürüm notlarındaki eski bir CLI örneği ipucu verir: toast bileşeni components/ui/use-toast.ts ve components/ui/toaster.tsx gibi dosyalardan oluşuyordu. Bu dosyalar ve useToast tarzı çağrılar görüyorsanız eski yapıyı kullanıyorsunuz demektir. Belge adım adım bir geçiş kılavuzu vermez; Sonner belgesinin gösterdiği yapıya göre geçiş genel olarak şöyle özetlenebilir:

  • npx shadcn@latest add sonner ile yeni bileşeni ekleyin.
  • Kök layout’taki eski toaster bileşenini kaldırıp yerine @/components/ui/sonner içinden gelen <Toaster /> bileşenini koyun.
  • Bildirim çağrılarını sonner paketinden içe aktarılan toast(), toast.success(), toast.error() gibi fonksiyonlarla değiştirin.
  • Eski toast dosyalarını başka bir yerde kullanılmadığından emin olduktan sonra silin.

Sık yapılan hatalar

  • Toaster bileşenini eklememek. toast() çağrısı tek başına yeterli değildir; bildirimlerin çizileceği <Toaster /> layout’ta bulunmalıdır. Kurulumun ikinci adımı tam olarak budur.
  • Toaster bileşenini birden çok kez koymak. Belgede tek bir Toaster kök layout’a eklenir. Her sayfaya ayrıca eklemek gereksizdir.
  • toast fonksiyonunu yanlış yerden içe aktarmak. Doğru içe aktarma import { toast } from "sonner" biçimindedir; @/components/ui/sonner yalnızca Toaster verir.
  • Sunucu bileşeninden toast() çağırmak. Bildirim tarayıcıda gösterilir; çağrı istemci bileşenindeki bir olay işleyicisinden ya da efektten yapılmalıdır.
  • Eski ikon setiyle kalmak. 13 Ekim 2025 notundan önce eklenmiş bir sonner.tsx kullanıyorsanız, belge dosyayı lucide ikonlarını içeren yeni sürümle güncellemenizi önerir.
  • Kullanımdan kalkmış toast bileşeniyle yeni proje başlatmak. Belge yeni projeler için Sonner’ı gösterir.

Sık Sorulan Sorular

shadcn toast ile Sonner arasındaki fark nedir?

Toast eski, kullanımdan kaldırılmış bileşendir; belgesi yalnızca Sonner’a yönlendiren bir nottan ibarettir. Sonner ise güncel, önerilen bildirim bileşenidir ve sonner npm paketinin üzerine kurulur.

Bildirimler koyu temaya nasıl uyum sağlar?

sonner.tsx etkin temayı next-themes paketinden okuyup Sonner’a verir, renkleri de --popover, --popover-foreground ve --border değişkenlerine bağlar. Koyu modu shadcn belgesindeki gibi kurduysanız bildirimler de buna uyar.

Bildirimin konumunu ya da süresini değiştirebilir miyim?

shadcn belgesi bu ayarları listelemez. Toaster bileşeni aldığı tüm prop’ları Sonner’a aktardığı için, Sonner’ın kendi belgesinde tanımlı ayarları <Toaster /> üzerinde kullanabilirsiniz.

Bildirime buton ekleyebilir miyim?

Evet. toast() çağrısının ikinci argümanına action: { label, onClick } nesnesi verirsiniz; resmî demo bunu “Undo” butonu için kullanır.

Marka adları sahiplerine aittir. Bu yazı bağımsız bir teknik rehberdir; adı geçen kuruluşlarla bayilik veya ortaklık ilişkisi bulunduğu anlamına gelmez.

İlgili içerikler: shadcn/ui öğrenme rehberi · Dark mode kurulumu · Tema ve CSS değişkenleri · Alert, Badge, Progress, Skeleton, Spinner · Dialog ve Alert Dialog · Yenilikler ve sürüm geçmişi