diff --git a/docs/src/pages/demos/snackbars/ConsecutiveSnackbars.js b/docs/src/pages/demos/snackbars/ConsecutiveSnackbars.js
index 53abfd8207e54a..d953f8ac4d2d8e 100644
--- a/docs/src/pages/demos/snackbars/ConsecutiveSnackbars.js
+++ b/docs/src/pages/demos/snackbars/ConsecutiveSnackbars.js
@@ -15,10 +15,13 @@ const styles = theme => ({
class ConsecutiveSnackbars extends React.Component {
queue = [];
- state = {
- open: false,
- messageInfo: {},
- };
+ constructor(props) {
+ super(props);
+
+ this.state = {
+ open: false,
+ };
+ }
handleClick = message => () => {
this.queue.push({
@@ -57,7 +60,7 @@ class ConsecutiveSnackbars extends React.Component {
render() {
const { classes } = this.props;
- const { messageInfo } = this.state;
+ const { messageInfo = {} } = this.state;
return (
diff --git a/docs/src/pages/demos/snackbars/ConsecutiveSnackbars.tsx b/docs/src/pages/demos/snackbars/ConsecutiveSnackbars.tsx
new file mode 100644
index 00000000000000..dfd5580f6ad668
--- /dev/null
+++ b/docs/src/pages/demos/snackbars/ConsecutiveSnackbars.tsx
@@ -0,0 +1,121 @@
+import React, { SyntheticEvent } from 'react';
+import PropTypes, { number } from 'prop-types';
+import { createStyles, withStyles, WithStyles, Theme } from '@material-ui/core/styles';
+import Button from '@material-ui/core/Button';
+import Snackbar from '@material-ui/core/Snackbar';
+import IconButton from '@material-ui/core/IconButton';
+import CloseIcon from '@material-ui/icons/Close';
+import { string } from 'parsimmon';
+
+const styles = (theme: Theme) =>
+ createStyles({
+ close: {
+ padding: theme.spacing(0.5),
+ },
+ });
+
+export interface SnackbarMessage {
+ message: string;
+ key: number;
+}
+
+export type Props = WithStyles
;
+
+export interface State {
+ open: boolean;
+ messageInfo?: SnackbarMessage;
+}
+
+class ConsecutiveSnackbars extends React.Component {
+ queue: SnackbarMessage[] = [];
+
+ constructor(props: Props) {
+ super(props);
+
+ this.state = {
+ open: false,
+ };
+ }
+
+ handleClick = (message: string) => () => {
+ this.queue.push({
+ message,
+ key: new Date().getTime(),
+ });
+
+ if (this.state.open) {
+ // immediately begin dismissing current message
+ // to start showing new one
+ this.setState({ open: false });
+ } else {
+ this.processQueue();
+ }
+ };
+
+ processQueue = () => {
+ if (this.queue.length > 0) {
+ this.setState({
+ messageInfo: this.queue.shift(),
+ open: true,
+ });
+ }
+ };
+
+ handleClose = (event: SyntheticEvent | MouseEvent, reason?: string) => {
+ if (reason === 'clickaway') {
+ return;
+ }
+ this.setState({ open: false });
+ };
+
+ handleExited = () => {
+ this.processQueue();
+ };
+
+ render() {
+ const { classes } = this.props;
+ const { messageInfo = {} as SnackbarMessage } = this.state;
+
+ return (
+
+
+
+ {messageInfo.message}}
+ action={[
+ ,
+
+
+ ,
+ ]}
+ />
+
+ );
+ }
+}
+
+(ConsecutiveSnackbars as React.ComponentClass).propTypes = {
+ classes: PropTypes.object.isRequired,
+} as any;
+
+export default withStyles(styles)(ConsecutiveSnackbars);
diff --git a/docs/src/pages/demos/snackbars/CustomizedSnackbars.tsx b/docs/src/pages/demos/snackbars/CustomizedSnackbars.tsx
new file mode 100644
index 00000000000000..97cb04ea8e6094
--- /dev/null
+++ b/docs/src/pages/demos/snackbars/CustomizedSnackbars.tsx
@@ -0,0 +1,162 @@
+import React, { SyntheticEvent } from 'react';
+import PropTypes from 'prop-types';
+import clsx from 'clsx';
+import Button from '@material-ui/core/Button';
+import CheckCircleIcon from '@material-ui/icons/CheckCircle';
+import ErrorIcon from '@material-ui/icons/Error';
+import InfoIcon from '@material-ui/icons/Info';
+import CloseIcon from '@material-ui/icons/Close';
+import green from '@material-ui/core/colors/green';
+import amber from '@material-ui/core/colors/amber';
+import IconButton from '@material-ui/core/IconButton';
+import Snackbar from '@material-ui/core/Snackbar';
+import SnackbarContent from '@material-ui/core/SnackbarContent';
+import WarningIcon from '@material-ui/icons/Warning';
+import { makeStyles, Theme } from '@material-ui/core/styles';
+
+const variantIcon = {
+ success: CheckCircleIcon,
+ warning: WarningIcon,
+ error: ErrorIcon,
+ info: InfoIcon,
+};
+
+const useStyles1 = makeStyles((theme: Theme) => ({
+ success: {
+ backgroundColor: green[600],
+ },
+ error: {
+ backgroundColor: theme.palette.error.dark,
+ },
+ info: {
+ backgroundColor: theme.palette.primary.dark,
+ },
+ warning: {
+ backgroundColor: amber[700],
+ },
+ icon: {
+ fontSize: 20,
+ },
+ iconVariant: {
+ opacity: 0.9,
+ marginRight: theme.spacing(1),
+ },
+ message: {
+ display: 'flex',
+ alignItems: 'center',
+ },
+}));
+
+export interface Props {
+ className?: string;
+ message?: string;
+ onClose?: () => void;
+ variant: keyof typeof variantIcon;
+}
+
+function MySnackbarContentWrapper(props: Props) {
+ const classes = useStyles1();
+ const { className, message, onClose, variant, ...other } = props;
+ const Icon = variantIcon[variant];
+
+ return (
+
+
+ {message}
+
+ }
+ action={[
+
+
+ ,
+ ]}
+ {...other}
+ />
+ );
+}
+
+MySnackbarContentWrapper.propTypes = {
+ className: PropTypes.string,
+ message: PropTypes.node,
+ onClose: PropTypes.func,
+ variant: PropTypes.oneOf(['success', 'warning', 'error', 'info']).isRequired,
+};
+
+const useStyles2 = makeStyles((theme: Theme) => ({
+ margin: {
+ margin: theme.spacing(1),
+ },
+}));
+
+function CustomizedSnackbars() {
+ const classes = useStyles2();
+ const [open, setOpen] = React.useState(false);
+
+ function handleClick() {
+ setOpen(true);
+ }
+
+ function handleClose(event?: SyntheticEvent, reason?: string) {
+ if (reason === 'clickaway') {
+ return;
+ }
+
+ setOpen(false);
+ }
+
+ return (
+
+
+
+
+
+
+
+
+
+
+ );
+}
+
+export default CustomizedSnackbars;
diff --git a/docs/src/pages/demos/snackbars/DirectionSnackbar.js b/docs/src/pages/demos/snackbars/DirectionSnackbar.js
index d1af62e229158c..c4d2027a3d5247 100644
--- a/docs/src/pages/demos/snackbars/DirectionSnackbar.js
+++ b/docs/src/pages/demos/snackbars/DirectionSnackbar.js
@@ -20,10 +20,13 @@ function TransitionDown(props) {
}
class DirectionSnackbar extends React.Component {
- state = {
- open: false,
- Transition: null,
- };
+ constructor() {
+ super();
+
+ this.state = {
+ open: false,
+ };
+ }
handleClick = Transition => () => {
this.setState({ open: true, Transition });
diff --git a/docs/src/pages/demos/snackbars/DirectionSnackbar.tsx b/docs/src/pages/demos/snackbars/DirectionSnackbar.tsx
new file mode 100644
index 00000000000000..0557f16e49c899
--- /dev/null
+++ b/docs/src/pages/demos/snackbars/DirectionSnackbar.tsx
@@ -0,0 +1,66 @@
+import React from 'react';
+import Button from '@material-ui/core/Button';
+import Snackbar from '@material-ui/core/Snackbar';
+import Slide from '@material-ui/core/Slide';
+import { TransitionProps } from '@material-ui/core/transitions/transition';
+
+function TransitionLeft(props: TransitionProps) {
+ return ;
+}
+
+function TransitionUp(props: TransitionProps) {
+ return ;
+}
+
+function TransitionRight(props: TransitionProps) {
+ return ;
+}
+
+function TransitionDown(props: TransitionProps) {
+ return ;
+}
+
+export interface State {
+ open: boolean;
+ Transition?: React.ComponentType;
+}
+
+class DirectionSnackbar extends React.Component {
+ constructor() {
+ super();
+
+ this.state = {
+ open: false,
+ };
+ }
+
+ handleClick = (Transition: React.ComponentType) => () => {
+ this.setState({ open: true, Transition });
+ };
+
+ handleClose = () => {
+ this.setState({ open: false });
+ };
+
+ render() {
+ return (
+
+
+
+
+
+ I love snacks}
+ />
+
+ );
+ }
+}
+
+export default DirectionSnackbar;
diff --git a/docs/src/pages/demos/snackbars/FabIntegrationSnackbar.tsx b/docs/src/pages/demos/snackbars/FabIntegrationSnackbar.tsx
new file mode 100644
index 00000000000000..5c17dda66eba31
--- /dev/null
+++ b/docs/src/pages/demos/snackbars/FabIntegrationSnackbar.tsx
@@ -0,0 +1,116 @@
+import React from 'react';
+import clsx from 'clsx';
+import { makeStyles, Theme } from '@material-ui/core/styles';
+import AppBar from '@material-ui/core/AppBar';
+import Toolbar from '@material-ui/core/Toolbar';
+import IconButton from '@material-ui/core/IconButton';
+import MenuIcon from '@material-ui/icons/Menu';
+import Typography from '@material-ui/core/Typography';
+import Button from '@material-ui/core/Button';
+import Fab from '@material-ui/core/Fab';
+import AddIcon from '@material-ui/icons/Add';
+import Snackbar from '@material-ui/core/Snackbar';
+
+const useStyles = makeStyles((theme: Theme) => ({
+ root: {
+ position: 'relative',
+ overflow: 'hidden',
+ },
+ appFrame: {
+ width: 360,
+ height: 360,
+ backgroundColor: theme.palette.background.paper,
+ },
+ menuButton: {
+ marginRight: 20,
+ },
+ button: {
+ marginBottom: theme.spacing(1),
+ },
+ fab: {
+ position: 'absolute',
+ bottom: theme.spacing(2),
+ right: theme.spacing(2),
+ },
+ fabMoveUp: {
+ transform: 'translate3d(0, -46px, 0)',
+ transition: theme.transitions.create('transform', {
+ duration: theme.transitions.duration.enteringScreen,
+ easing: theme.transitions.easing.easeOut,
+ }),
+ },
+ fabMoveDown: {
+ transform: 'translate3d(0, 0, 0)',
+ transition: theme.transitions.create('transform', {
+ duration: theme.transitions.duration.leavingScreen,
+ easing: theme.transitions.easing.sharp,
+ }),
+ },
+ snackbar: {
+ position: 'absolute',
+ },
+ snackbarContent: {
+ width: 360,
+ },
+}));
+
+function FabIntegrationSnackbar() {
+ const classes = useStyles();
+ const [open, setOpen] = React.useState(false);
+
+ function handleClick() {
+ setOpen(true);
+ }
+
+ function handleClose() {
+ setOpen(false);
+ }
+
+ const fabClassName = clsx(classes.fab, open ? classes.fabMoveUp : classes.fabMoveDown);
+
+ return (
+
+
+
+
+
+
+
+
+
+ Out of my way!
+
+
+
+
+
+
+
Archived}
+ action={
+
+ }
+ className={classes.snackbar}
+ />
+
+
+ );
+}
+
+export default FabIntegrationSnackbar;
diff --git a/docs/src/pages/demos/snackbars/FadeSnackbar.tsx b/docs/src/pages/demos/snackbars/FadeSnackbar.tsx
new file mode 100644
index 00000000000000..e9f96f662fc1c0
--- /dev/null
+++ b/docs/src/pages/demos/snackbars/FadeSnackbar.tsx
@@ -0,0 +1,33 @@
+import React from 'react';
+import Button from '@material-ui/core/Button';
+import Snackbar from '@material-ui/core/Snackbar';
+import Fade from '@material-ui/core/Fade';
+
+function FadeSnackbar() {
+ const [open, setOpen] = React.useState(false);
+
+ function handleClick() {
+ setOpen(true);
+ }
+
+ function handleClose() {
+ setOpen(false);
+ }
+
+ return (
+
+
+ I love snacks}
+ />
+
+ );
+}
+
+export default FadeSnackbar;
diff --git a/docs/src/pages/demos/snackbars/IntegrationNotistack.js b/docs/src/pages/demos/snackbars/IntegrationNotistack.js
index 941cf0df5246b9..1f657aa48327f7 100644
--- a/docs/src/pages/demos/snackbars/IntegrationNotistack.js
+++ b/docs/src/pages/demos/snackbars/IntegrationNotistack.js
@@ -4,12 +4,16 @@ import Button from '@material-ui/core/Button';
import { SnackbarProvider, withSnackbar } from 'notistack';
class App extends React.Component {
+ static propTypes = {
+ enqueueSnackbar: PropTypes.func.isRequired,
+ };
+
handleClick = () => {
this.props.enqueueSnackbar('I love snacks.');
};
handleClickVariant = variant => () => {
- // variant could be success, error, warning or info
+ // variant could be success, error, warning, info, or default
this.props.enqueueSnackbar('This is a warning message!', { variant });
};
@@ -23,10 +27,6 @@ class App extends React.Component {
}
}
-App.propTypes = {
- enqueueSnackbar: PropTypes.func.isRequired,
-};
-
const MyApp = withSnackbar(App);
function IntegrationNotistack() {
diff --git a/docs/src/pages/demos/snackbars/IntegrationNotistack.tsx b/docs/src/pages/demos/snackbars/IntegrationNotistack.tsx
new file mode 100644
index 00000000000000..914048cbb2753f
--- /dev/null
+++ b/docs/src/pages/demos/snackbars/IntegrationNotistack.tsx
@@ -0,0 +1,40 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import Button from '@material-ui/core/Button';
+import { SnackbarProvider, VariantType, withSnackbar, withSnackbarProps } from 'notistack';
+
+class App extends React.Component {
+ static propTypes = {
+ enqueueSnackbar: PropTypes.func.isRequired,
+ };
+
+ handleClick = () => {
+ this.props.enqueueSnackbar('I love snacks.');
+ };
+
+ handleClickVariant = (variant: VariantType) => () => {
+ // variant could be success, error, warning, info, or default
+ this.props.enqueueSnackbar('This is a warning message!', { variant });
+ };
+
+ render() {
+ return (
+
+
+
+
+ );
+ }
+}
+
+const MyApp = withSnackbar(App);
+
+function IntegrationNotistack() {
+ return (
+
+
+
+ );
+}
+
+export default IntegrationNotistack;
diff --git a/docs/src/pages/demos/snackbars/LongTextSnackbar.tsx b/docs/src/pages/demos/snackbars/LongTextSnackbar.tsx
new file mode 100644
index 00000000000000..741f64005d367f
--- /dev/null
+++ b/docs/src/pages/demos/snackbars/LongTextSnackbar.tsx
@@ -0,0 +1,56 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import Button from '@material-ui/core/Button';
+import { createStyles, withStyles, WithStyles, Theme } from '@material-ui/core/styles';
+import SnackbarContent from '@material-ui/core/SnackbarContent';
+
+const action = (
+
+);
+
+const styles = (theme: Theme) =>
+ createStyles({
+ snackbar: {
+ margin: theme.spacing(1),
+ },
+ });
+
+export type Props = WithStyles;
+
+function LongTextSnackbar(props: Props) {
+ const { classes } = props;
+
+ return (
+
+
+
+
+
+
+ );
+}
+
+LongTextSnackbar.propTypes = {
+ classes: PropTypes.object.isRequired,
+} as any;
+
+export default withStyles(styles)(LongTextSnackbar);
diff --git a/docs/src/pages/demos/snackbars/PositionedSnackbar.js b/docs/src/pages/demos/snackbars/PositionedSnackbar.js
index 2ef54d46b36f3a..278d64f1adab01 100644
--- a/docs/src/pages/demos/snackbars/PositionedSnackbar.js
+++ b/docs/src/pages/demos/snackbars/PositionedSnackbar.js
@@ -8,6 +8,7 @@ function PositionedSnackbar() {
vertical: 'top',
horizontal: 'center',
});
+
const { vertical, horizontal, open } = state;
const handleClick = newState => () => {
diff --git a/docs/src/pages/demos/snackbars/PositionedSnackbar.tsx b/docs/src/pages/demos/snackbars/PositionedSnackbar.tsx
new file mode 100644
index 00000000000000..ad93e21eb5467d
--- /dev/null
+++ b/docs/src/pages/demos/snackbars/PositionedSnackbar.tsx
@@ -0,0 +1,50 @@
+import React from 'react';
+import Button from '@material-ui/core/Button';
+import Snackbar, { SnackbarOrigin } from '@material-ui/core/Snackbar';
+
+export interface State extends SnackbarOrigin {
+ open: boolean;
+}
+
+function PositionedSnackbar() {
+ const [state, setState] = React.useState({
+ open: false,
+ vertical: 'top',
+ horizontal: 'center',
+ });
+ const { vertical, horizontal, open } = state;
+
+ const handleClick = (newState: SnackbarOrigin) => () => {
+ setState({ open: true, ...newState });
+ };
+
+ function handleClose() {
+ setState({ ...state, open: false });
+ }
+
+ return (
+
+
+
+
+
+
+
+ I love snacks}
+ />
+
+ );
+}
+
+export default PositionedSnackbar;
diff --git a/docs/src/pages/demos/snackbars/SimpleSnackbar.tsx b/docs/src/pages/demos/snackbars/SimpleSnackbar.tsx
new file mode 100644
index 00000000000000..a71c8931369552
--- /dev/null
+++ b/docs/src/pages/demos/snackbars/SimpleSnackbar.tsx
@@ -0,0 +1,64 @@
+import React from 'react';
+import { makeStyles, Theme } from '@material-ui/core/styles';
+import Button from '@material-ui/core/Button';
+import Snackbar from '@material-ui/core/Snackbar';
+import IconButton from '@material-ui/core/IconButton';
+import CloseIcon from '@material-ui/icons/Close';
+
+const useStyles = makeStyles((theme: Theme) => ({
+ close: {
+ padding: theme.spacing(0.5),
+ },
+}));
+
+function SimpleSnackbar() {
+ const classes = useStyles();
+ const [open, setOpen] = React.useState(false);
+
+ function handleClick() {
+ setOpen(true);
+ }
+
+ function handleClose(event: React.SyntheticEvent | React.MouseEvent, reason?: string) {
+ if (reason === 'clickaway') {
+ return;
+ }
+
+ setOpen(false);
+ }
+
+ return (
+
+
+ Note archived}
+ action={[
+ ,
+
+
+ ,
+ ]}
+ />
+
+ );
+}
+
+export default SimpleSnackbar;