javascriptreactjschakra-ui

How do I make toast notification with a custom placement?


According to the documentation for Chakra UI Toast

We are supposed to be able to control the default location toasts appear using the following snippet

const toaster = createToaster({
  placement: "top-end",
})

I can create regular toasts just fine using

// other imports omitted
import { toaster, Toaster } from "./components/toaster";

function App() {

  return (
    <>
      <Toaster />
      <Button
        marginLeft={5}
        onClick={() => {
          toaster.create({ title: "This is a regular toast", type: "error" });
        }}
      >
    </>
  )
}

The above works just fine. When I try to implement my own toaster, so that I can control placement, timing etc., I am not getting any visible changes

import { Toaster } from "./components/toaster";

function App() {
  const configedToaster = createToaster({
    placement: "top-end",
  });

  return (
    <>
      <Toaster />
      <Button
        onClick={() => {
          configedToaster.success({ title: "Test", description: "error" });
        }}
      >
        Hello, I'm special toast
      </Button>
    </>
   )
}

Here is my sandbox code: https://codesandbox.io/p/sandbox/wk86tt showing both toast methods with separate buttons. The standard one works fine but the custom one does not appear to render anything.

How do I make toast notifications with a custom toaster? I am not trying to dynamically assign location but change the default behavior at its inception. I assumed that regardless of how it was defined that it would use the same <Toaster/> hence why it only appeared the once.


Solution

  • Hi you can go the Toaster component and change the placement you want

    
    "use client";
    // import React from "react";
    
    import {
      Toaster as ChakraToaster,
      Portal,
      Spinner,
      Stack,
      Toast,
      createToaster,
    } from "@chakra-ui/react";
    
    export const toaster = createToaster({
      placement: "bottom-end", <-- change placement you wanthere
      pauseOnPageIdle: true,
    });
    
    export const Toaster = () => {
      return (
        <Portal>
          <ChakraToaster toaster={toaster} insetInline={{ mdDown: "4" }}>
            {(toast) => (
              <Toast.Root width={{ md: "sm" }}>
                {toast.type === "loading" ? (
                  <Spinner size="sm" color="blue.solid" />
                ) : (
                  <Toast.Indicator />
                )}
                <Stack gap="1" flex="1" maxWidth="100%">
                  {toast.title && <Toast.Title>{toast.title}</Toast.Title>}
                  {toast.description && (
                    <Toast.Description>{toast.description}</Toast.Description>
                  )}
                </Stack>
                {toast.action && (
                  <Toast.ActionTrigger>{toast.action.label}</Toast.ActionTrigger>
                )}
                {toast.meta?.closable && <Toast.CloseTrigger />}
              </Toast.Root>
            )}
          </ChakraToaster>
        </Portal>
      );
    };
    
    

    Here is what it's look like: codesandbox