sonner icon indicating copy to clipboard operation
sonner copied to clipboard

Default classNames are not working for other variants

Open imopbuilder opened this issue 1 year ago • 15 comments

'use client';

import { useTheme } from 'next-themes';
import { Toaster } from 'sonner';

export function ToastProvider() {
	const { theme } = useTheme();

	return (
		<Toaster
			toastOptions={{
				classNames: {
					toast: '!border-border',
				},
			}}
			theme={theme as 'light' | 'dark' | 'system'}
			richColors
		/>
	);
}

When the classNames for toast are changed then the error default styles are also changed even when the error styles are not being touched

imopbuilder avatar Nov 30 '23 06:11 imopbuilder

That's expected, if you want differrent styling for different toast types you can use it like this:

<Toaster
  toastOptions={{
    unstyled: true,
    classNames: {
      error: 'bg-red-400',
      success: 'text-green-400',
      warning: 'text-yellow-400',
      info: 'bg-blue-400',
    },
  }}
/>

emilkowalski avatar Nov 30 '23 16:11 emilkowalski

No the styling is applied for all variants when applied to toast variant ignoring the default styling for other variants

imopbuilder avatar Nov 30 '23 17:11 imopbuilder

Again, that's expected. Everything you apply to toast is also applied to all toast types.

emilkowalski avatar Nov 30 '23 18:11 emilkowalski

I want to change the default style of the toast when we call the toast like this

toast('Event has been created')

because I would like to apply the shadcn themes for the toast when the default toast is being called and it should not change the styling of the other variants

imopbuilder avatar Dec 01 '23 08:12 imopbuilder

@emilkowalski can I make a PR for the default property which takes the styling in the classNames so that it will not effect the other variants

imopbuilder avatar Dec 02 '23 12:12 imopbuilder

@imopbuilder Of course, go for it!

emilkowalski avatar Dec 02 '23 16:12 emilkowalski

@imopbuilder Of course, go for it!

sure I will start working on it

imopbuilder avatar Dec 03 '23 03:12 imopbuilder

@emilkowalski I have made a PR #245 by add the default property to the types and also to the state

imopbuilder avatar Dec 03 '23 05:12 imopbuilder

This is still an issue as the type: 'default' was removed in this commit.

I'm trying to apply styling to each variant, while also styling the default to allow usage of toast().

However, applying classes to classNames.toast overwrites the variant styling. The default classname is useless as the toastType is undefined, so it doesn't apply any styles.

export const Toaster = (props: ToasterProps) => (
  <Sonner.Toaster
    toastOptions={{
      classNames: {
        error: "bg-red",
        success: "bg-green",
        warning: "bg-yellow",
        info: "bg-blue",
        // default classes are never applied
        default: "bg-white",
        // can't use bg-white here because it overwrites variant classes
        // toast: "bg-white",
      },
      unstyled: true,
    }}
    {...props}
  />
)

Is there a reason default type was removed?

FYI I'm working around this by checking for toasts that don't have the data-type attribute on them:

[data-sonner-toaster] li:not([data-type]) {
    @apply bg-white;
  }

justinnais avatar Jan 05 '24 02:01 justinnais

@justinnais yes the property has been removed in the commit but the types are not updated hence the default type is undefined but you can refer to this link where shadcn-ui used sonner toast to changed the styles for the toast() without affecting other variants

Shadcn-ui sonner toast (take a look at the manual installation)

Here is the implementation

// Toaster.tsx

"use client"

import { useTheme } from "next-themes"
import { Toaster as Sonner } from "sonner"

type ToasterProps = React.ComponentProps<typeof Sonner>

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

  return (
    <Sonner
      theme={theme as ToasterProps["theme"]}
      className="toaster group"
      toastOptions={{
        classNames: {
          toast:
            "group toast group-[.toaster]:bg-background group-[.toaster]:text-foreground group-[.toaster]:border-border group-[.toaster]:shadow-lg",
          description: "group-[.toast]:text-muted-foreground",
          actionButton:
            "group-[.toast]:bg-primary group-[.toast]:text-primary-foreground",
          cancelButton:
            "group-[.toast]:bg-muted group-[.toast]:text-muted-foreground",
        },
      }}
      {...props}
    />
  )
}

export { Toaster }

Make sure to add richColors in the toastOptions

imopbuilder avatar Jan 05 '24 03:01 imopbuilder

@imopbuilder richColors overrides the colors that I am passing into the class names, which isn't what I'm after unfortunately. I had a play with the tailwind group classes but it doesn't solve the issue of the toast class overriding all of the variant classes.

Should the default type be removed entirely, or should the prop be added back to the default toast?

justinnais avatar Jan 08 '24 00:01 justinnais

However, applying classes to classNames.toast overwrites the variant styling.

export const Toaster = (props: ToasterProps) => (
  <Sonner.Toaster
    toastOptions={{
      classNames: {
        error: "bg-red",
        success: "bg-green",
        warning: "bg-yellow",
        info: "bg-blue",
        // This variant should be applied first in the chain, not last, so that any similarly defined style above takes precedence
        // Currently none of the other variants work as they will all appear white
        // toast: "bg-white",
      },
      unstyled: true,
    }}
    {...props}
  />
)

Do we have an update on this? This is pretty frustrating to work around. Intuitively any of the styling for the "variant" toasts (error, success, warning, info) should be applied after the "default" toast (toast).

wadeamaral avatar Feb 03 '24 09:02 wadeamaral

This is fixed in #324. You can now style with the default key, those styles will be overidden by any type specific ones.

emilkowalski avatar Feb 03 '24 11:02 emilkowalski

This is fixed in #324. You can now style with the default key, those styles will be overidden by any type specific ones.

Just a heads up that I pulled the latest version 1.4.1 and it seems the "error" variant is still using the background color as styled in either "toast" or "default". The "success" variant is working correctly however.

I also wanted to say thank you for a wonderful toast component.

wadeamaral avatar Feb 24 '24 02:02 wadeamaral

This is fixed in #324. You can now style with the default key, those styles will be overidden by any type specific ones.

Just a heads up that I pulled the latest version 1.4.1 and it seems the "error" variant is still using the background color as styled in either "toast" or "default". The "success" variant is working correctly however.

I also wanted to say thank you for a wonderful toast component.

I had the same issue and I realised that the issue was due to my class name for my error variant (bg-error-background) is before my default variant (bg-foreground) *Notice alphabet e comes before alphabet f.

The fix is to provide custom cn function via cn prop that includes tw-merge so that the ordering of the class name will be correct. If you are coming from shadcn, you can just do

'use client';

import { cn } from '@/lib/utils';

// ...

<Sonner
  // ...
  cn={cn}
  // ...
/>

Hopefully that helps!

junwen-k avatar Mar 26 '24 12:03 junwen-k