notistack icon indicating copy to clipboard operation
notistack copied to clipboard

Error snackbar does not dissapear upon clicking the cross icon

Open ghost opened this issue 1 year ago • 3 comments

Expected Behavior

Upon clicking the close button, snackbar should disappear (This is the behavior seen in other libraries)

Current Behavior

Nothing happens the cross icon just confuses the user into believing it has some actions.

Context

I did hack the solution by myself, but I'd like this case to be covered in the documentation

Your Environment

Tech Version
Notistack v3.0.1
React 18.2
Browser Chrome

Demo

animation

Codesanbox

https://codesandbox.io/s/nostalgic-jennings-p60v3x?file=/MessageButtons.js

ghost avatar Jun 07 '23 10:06 ghost

This is because the close button isn't actually a close button; it's an icon that describes what type of snackbar pops up. If you do want the snackbar to close, you can use the action prop and pass in a function that closes it.

Here's a part of the documentation that shows how to do that: https://notistack.com/features/basic#actions

olabisi09 avatar Jun 20 '23 08:06 olabisi09

This is what I actually did

But this imperative way feels hacky

import { Box } from '@mui/material';
import { SnackbarKey, useSnackbar } from 'notistack';
import { useEffect, useRef } from 'react';

interface Props {
  snackbarKey: SnackbarKey;
}

const CloseSnackbarAction = ({ snackbarKey }: Props) => {
  const { closeSnackbar } = useSnackbar();

  const snackbarRef = useRef<HTMLDivElement>(null);

  useEffect(() => {
    const handleClick = () => closeSnackbar(snackbarKey);

    const snackbarParent = snackbarRef.current?.parentElement?.parentElement;

    if (snackbarParent && snackbarParent.className.includes('variantError')) {
      const snackBarSvgIcon = snackbarParent.childNodes[0]?.childNodes[0];
      snackBarSvgIcon?.addEventListener('click', handleClick);

      return () => snackBarSvgIcon?.removeEventListener('click', handleClick);
    }
  }, [closeSnackbar, snackbarKey]);

  return <Box ref={snackbarRef} />;
};

export default CloseSnackbarAction;

Feels like there should have been a better built in setup for this or something

ghost avatar Jun 21 '23 05:06 ghost

This is what I actually did

But this imperative way feels hacky

import { Box } from '@mui/material';
import { SnackbarKey, useSnackbar } from 'notistack';
import { useEffect, useRef } from 'react';

interface Props {
  snackbarKey: SnackbarKey;
}

const CloseSnackbarAction = ({ snackbarKey }: Props) => {
  const { closeSnackbar } = useSnackbar();

  const snackbarRef = useRef<HTMLDivElement>(null);

  useEffect(() => {
    const handleClick = () => closeSnackbar(snackbarKey);

    const snackbarParent = snackbarRef.current?.parentElement?.parentElement;

    if (snackbarParent && snackbarParent.className.includes('variantError')) {
      const snackBarSvgIcon = snackbarParent.childNodes[0]?.childNodes[0];
      snackBarSvgIcon?.addEventListener('click', handleClick);

      return () => snackBarSvgIcon?.removeEventListener('click', handleClick);
    }
  }, [closeSnackbar, snackbarKey]);

  return <Box ref={snackbarRef} />;
};

export default CloseSnackbarAction;

Feels like there should have been a better built in setup for this or something

Very hacky. I think they forgot about the close/dismiss. It should be an option e.g.:

enqueueSnackbar("This is a success message!", { variant: "success", closeable: true });

mapsmarketing avatar Dec 04 '23 06:12 mapsmarketing