Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix regression on using React.Node as Snackbar message #549

Merged
merged 4 commits into from
Mar 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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