Skip to content

Commit

Permalink
Fix regression on using React.Node as Snackbar message (#549)
Browse files Browse the repository at this point in the history
* Use constant value for ariaDescribedby

* Correctly detect react element as snackbar message

* Update types and typedoc

* Update CHANGELOG
  • Loading branch information
iamhosseindhv authored Mar 8, 2023
1 parent 4c5a1d4 commit 17466e6
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 16 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
Thanks to all contributers who improved notistack by opening an issue/PR.

### `[email protected]`
###### 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)

<br />


### `[email protected]`
###### March 6, 2023
### New features
Expand Down
23 changes: 15 additions & 8 deletions src/SnackbarProvider/SnackbarProvider.tsx
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -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[] };
Expand Down Expand Up @@ -59,15 +63,18 @@ class SnackbarProvider extends Component<SnackbarProviderProps, State> {
* 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;

Expand Down
4 changes: 2 additions & 2 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -400,7 +400,7 @@ type OptionsWithExtraProps<V extends VariantType> = VariantMap[V] extends true

interface EnqueueSnackbar {
<V extends VariantType>(options: OptionsWithExtraProps<V> & { message?: SnackbarMessage }): SnackbarKey;
<V extends VariantType>(message: string, options?: OptionsWithExtraProps<V>): SnackbarKey;
<V extends VariantType>(message: SnackbarMessage, options?: OptionsWithExtraProps<V>): SnackbarKey;
}

export interface ProviderContext {
Expand Down
6 changes: 4 additions & 2 deletions src/ui/MaterialDesignContent/MaterialDesignContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ const classes = makeStyles({
},
});

const ariaDescribedby = 'notistack-snackbar';

const MaterialDesignContent = forwardRef<HTMLDivElement, CustomContentProps>((props, forwardedRef) => {
const {
id,
Expand All @@ -72,7 +74,7 @@ const MaterialDesignContent = forwardRef<HTMLDivElement, CustomContentProps>((pr
<SnackbarContent
ref={forwardedRef}
role="alert"
aria-describedby="notistack-snackbar"
aria-describedby={ariaDescribedby}
style={style}
className={clsx(
ComponentClasses.MuiContent,
Expand All @@ -83,7 +85,7 @@ const MaterialDesignContent = forwardRef<HTMLDivElement, CustomContentProps>((pr
className
)}
>
<div id="notistack-snackbar" className={classes.message}>
<div id={ariaDescribedby} className={classes.message}>
{!hideIconVariant ? icon : null}
{message}
</div>
Expand Down
18 changes: 14 additions & 4 deletions typedoc.json
Original file line number Diff line number Diff line change
Expand Up @@ -2080,8 +2080,9 @@
"isExported": true
},
"type": {
"type": "intrinsic",
"name": "string"
"type": "reference",
"id": 305,
"name": "SnackbarMessage"
}
},
{
Expand Down Expand Up @@ -8065,8 +8066,17 @@
}
],
"type": {
"type": "intrinsic",
"name": "string"
"type": "union",
"types": [
{
"type": "intrinsic",
"name": "string"
},
{
"type": "reference",
"name": "React.ReactNode"
}
]
}
},
{
Expand Down

0 comments on commit 17466e6

Please sign in to comment.