From 17466e64952a15df7ef5420e39d09b973d09300f Mon Sep 17 00:00:00 2001 From: Hossein Dehnokhalaji Date: Wed, 8 Mar 2023 22:30:57 +0000 Subject: [PATCH] Fix regression on using React.Node as Snackbar message (#549) * Use constant value for ariaDescribedby * Correctly detect react element as snackbar message * Update types and typedoc * Update CHANGELOG --- CHANGELOG.md | 8 +++++++ src/SnackbarProvider/SnackbarProvider.tsx | 23 ++++++++++++------- src/types.ts | 4 ++-- .../MaterialDesignContent.tsx | 6 +++-- typedoc.json | 18 +++++++++++---- 5 files changed, 43 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 80b5dcd..16472a7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ Thanks to all contributers who improved notistack by opening an issue/PR. +### `notistack@3.0.1` +###### March 8, 2023 +* **@alexander7161** Restore aria-describedby prop on SnackbarContent [#547](https://github.com/iamhosseindhv/notistack/pull/547) +* **@sodenn** Fix regression on using React.Node as Snackbar message [#548](https://github.com/iamhosseindhv/notistack/issues/548) + +
+ + ### `notistack@3.0.0` ###### March 6, 2023 ### New features diff --git a/src/SnackbarProvider/SnackbarProvider.tsx b/src/SnackbarProvider/SnackbarProvider.tsx index 1b4fbde..c404716 100644 --- a/src/SnackbarProvider/SnackbarProvider.tsx +++ b/src/SnackbarProvider/SnackbarProvider.tsx @@ -1,4 +1,4 @@ -import React, { Component } from 'react'; +import React, { Component, isValidElement } from 'react'; import { createPortal } from 'react-dom'; import clsx from 'clsx'; import SnackbarContext from '../SnackbarContext'; @@ -15,12 +15,16 @@ import { InternalSnack, OptionsObject, SharedProps, + SnackbarMessage, } from '../types'; import createChainedFunction from '../utils/createChainedFunction'; const isOptions = ( - messageOrOptions: string | (OptionsObject & { message?: string }) -): messageOrOptions is OptionsObject & { message?: string } => typeof messageOrOptions !== 'string'; + messageOrOptions: SnackbarMessage | (OptionsObject & { message?: SnackbarMessage }) +): messageOrOptions is OptionsObject & { message?: SnackbarMessage } => { + const isMessage = typeof messageOrOptions === 'string' || isValidElement(messageOrOptions); + return !isMessage; +}; type Reducer = (state: State) => State; type SnacksByPosition = { [key: string]: InternalSnack[] }; @@ -59,15 +63,18 @@ class SnackbarProvider extends Component { * Returns generated or user defined key referencing the new snackbar or null */ enqueueSnackbar = ( - messageOrOptions: string | (OptionsObject & { message?: string }), + messageOrOptions: SnackbarMessage | (OptionsObject & { message?: SnackbarMessage }), optsOrUndefined: OptionsObject = {} ): SnackbarKey => { + if (messageOrOptions === undefined || messageOrOptions === null) { + throw new Error('enqueueSnackbar called with invalid argument'); + } + const opts = isOptions(messageOrOptions) ? messageOrOptions : optsOrUndefined; - let message: string | undefined = messageOrOptions as string; - if (isOptions(messageOrOptions)) { - message = messageOrOptions.message; - } + const message: SnackbarMessage | undefined = isOptions(messageOrOptions) + ? messageOrOptions.message + : messageOrOptions; const { key, preventDuplicate, ...options } = opts; diff --git a/src/types.ts b/src/types.ts index 7c99d3b..54dbe7d 100644 --- a/src/types.ts +++ b/src/types.ts @@ -155,7 +155,7 @@ export type VariantType = keyof VariantMap; export type SnackbarKey = string | number; export type CloseReason = 'timeout' | 'maxsnack' | 'instructed'; -export type SnackbarMessage = string; +export type SnackbarMessage = string | React.ReactNode; export type SnackbarAction = React.ReactNode | ((key: SnackbarKey) => React.ReactNode); export type SnackbarContentCallback = | React.ReactNode @@ -400,7 +400,7 @@ type OptionsWithExtraProps = VariantMap[V] extends true interface EnqueueSnackbar { (options: OptionsWithExtraProps & { message?: SnackbarMessage }): SnackbarKey; - (message: string, options?: OptionsWithExtraProps): SnackbarKey; + (message: SnackbarMessage, options?: OptionsWithExtraProps): SnackbarKey; } export interface ProviderContext { diff --git a/src/ui/MaterialDesignContent/MaterialDesignContent.tsx b/src/ui/MaterialDesignContent/MaterialDesignContent.tsx index 8186d6d..cd8139f 100644 --- a/src/ui/MaterialDesignContent/MaterialDesignContent.tsx +++ b/src/ui/MaterialDesignContent/MaterialDesignContent.tsx @@ -49,6 +49,8 @@ const classes = makeStyles({ }, }); +const ariaDescribedby = 'notistack-snackbar'; + const MaterialDesignContent = forwardRef((props, forwardedRef) => { const { id, @@ -72,7 +74,7 @@ const MaterialDesignContent = forwardRef((pr ((pr className )} > -
+
{!hideIconVariant ? icon : null} {message}
diff --git a/typedoc.json b/typedoc.json index d9baa5d..1d21725 100644 --- a/typedoc.json +++ b/typedoc.json @@ -2080,8 +2080,9 @@ "isExported": true }, "type": { - "type": "intrinsic", - "name": "string" + "type": "reference", + "id": 305, + "name": "SnackbarMessage" } }, { @@ -8065,8 +8066,17 @@ } ], "type": { - "type": "intrinsic", - "name": "string" + "type": "union", + "types": [ + { + "type": "intrinsic", + "name": "string" + }, + { + "type": "reference", + "name": "React.ReactNode" + } + ] } }, {