diff --git a/src/SnackbarContainer.js b/src/SnackbarContainer.js index a2966840..caf72518 100644 --- a/src/SnackbarContainer.js +++ b/src/SnackbarContainer.js @@ -6,6 +6,7 @@ import { SNACKBAR_INDENTS } from './utils/constants'; const styles = theme => ({ root: { + boxSizing: 'border-box', display: 'flex', maxHeight: '100%', maxWidth: '100%', @@ -15,36 +16,24 @@ const styles = theme => ({ height: 'auto', width: 'auto', minWidth: 288, - transition: theme.transitions.create(['padding']), + transition: theme.transitions.create(['top', 'right', 'bottom', 'left'], { easing: 'ease' }), [theme.breakpoints.down('sm')]: { width: '100%', - paddingLeft: '0 !important', - paddingRight: '0 !important', }, }, reverseColumns: { flexDirection: 'column-reverse' }, - topPadding: { paddingTop: SNACKBAR_INDENTS.default.view }, - topDensePadding: { paddingTop: SNACKBAR_INDENTS.dense.view }, - - bottomPadding: { paddingBottom: SNACKBAR_INDENTS.default.view }, - bottomDensePadding: { paddingBottom: SNACKBAR_INDENTS.dense.view }, - - leftPadding: { paddingLeft: SNACKBAR_INDENTS.default.view }, - leftDensePadding: { paddingLeft: SNACKBAR_INDENTS.dense.view }, - - rightPadding: { paddingRight: SNACKBAR_INDENTS.default.view }, - rightDensePadding: { paddingRight: SNACKBAR_INDENTS.dense.view }, - - top: { top: 0 }, - bottom: { bottom: 0 }, - left: { left: 0 }, - right: { right: 0 }, + top: { top: SNACKBAR_INDENTS.default.container }, + topDense: { top: SNACKBAR_INDENTS.dense.container }, + bottom: { bottom: (SNACKBAR_INDENTS.default.container - SNACKBAR_INDENTS.default.snackbar) }, + bottomDense: { bottom: (SNACKBAR_INDENTS.dense.container - SNACKBAR_INDENTS.dense.snackbar) }, + left: { left: SNACKBAR_INDENTS.default.container }, + leftDense: { left: SNACKBAR_INDENTS.dense.container }, + right: { right: SNACKBAR_INDENTS.default.container }, + rightDense: { right: SNACKBAR_INDENTS.dense.container }, center: { - [theme.breakpoints.up('md')]: { - left: '50%', - transform: 'translateX(-50%)', - }, + left: '50%', + transform: 'translateX(-50%)', }, }); @@ -55,8 +44,8 @@ const SnackbarContainer = React.memo((props) => { classes.root, classes[anchorOrigin.vertical], classes[anchorOrigin.horizontal], - classes[`${anchorOrigin.vertical}${dense ? 'Dense' : ''}Padding`], - classes[`${anchorOrigin.horizontal}${dense ? 'Dense' : ''}Padding`], + classes[`${anchorOrigin.vertical}${dense ? 'Dense' : ''}`], + classes[`${anchorOrigin.horizontal}${dense ? 'Dense' : ''}`], { [classes.reverseColumns]: anchorOrigin.vertical === 'bottom' }, ); diff --git a/src/SnackbarItem/SnackbarItem.js b/src/SnackbarItem/SnackbarItem.js index c51729d1..2728f175 100644 --- a/src/SnackbarItem/SnackbarItem.js +++ b/src/SnackbarItem/SnackbarItem.js @@ -3,12 +3,20 @@ import classNames from 'classnames'; import PropTypes from 'prop-types'; import { withStyles } from '@material-ui/core/styles'; import Snackbar from '@material-ui/core/Snackbar'; +import Collapse from '@material-ui/core/Collapse'; import SnackbarContent from '@material-ui/core/SnackbarContent'; -import { capitalise, getTransitionDirection, getSnackbarClasses } from './SnackbarItem.util'; +import { capitalise, getTransitionDirection, getSnackbarClasses, getCollapseClasses } from './SnackbarItem.util'; import styles from './SnackbarItem.styles'; class SnackbarItem extends Component { + constructor(props) { + super(props); + this.state = { + collapsed: true, + }; + } + handleClose = key => (event, reason) => { const { onClose, snack: { onClose: singleOnClose } } = this.props; if (reason === 'clickaway') return; @@ -68,38 +76,45 @@ class SnackbarItem extends Component { } return ( - - {snackChildren || ( - - {!hideIconVariant ? icon : null} - {snack.message} - - )} - action={finalAction} - /> - )} - + this.setState(({ collapsed }) => ({ collapsed: !collapsed })), + }} + {...other} + {...singleSnackProps} + anchorOrigin={anchorOrigin} + open={snack.open} + classes={getSnackbarClasses(classes)} + onClose={this.handleClose(key)} + > + {snackChildren || ( + + {!hideIconVariant ? icon : null} + {snack.message} + + )} + action={finalAction} + /> + )} + + ); } } diff --git a/src/SnackbarItem/SnackbarItem.styles.js b/src/SnackbarItem/SnackbarItem.styles.js index 069dd49f..2bbbcf77 100644 --- a/src/SnackbarItem/SnackbarItem.styles.js +++ b/src/SnackbarItem/SnackbarItem.styles.js @@ -1,16 +1,7 @@ import green from '@material-ui/core/colors/green'; import amber from '@material-ui/core/colors/amber'; import { muiClasses } from './SnackbarItem.util'; -import { TRANSITION_DELAY, TRANSITION_DOWN_DURATION, SNACKBAR_INDENTS } from '../utils/constants'; - -export const transitionStyles = { - WebKitTransition: `all ${TRANSITION_DOWN_DURATION}ms`, - MozTransition: `all ${TRANSITION_DOWN_DURATION}ms`, - msTransition: `all ${TRANSITION_DOWN_DURATION}ms`, - OTransition: `all ${TRANSITION_DOWN_DURATION}ms`, - transition: `all ${TRANSITION_DOWN_DURATION * 5}ms`, - transitionDelay: `${TRANSITION_DELAY}ms`, -}; +import { SNACKBAR_INDENTS } from '../utils/constants'; const styles = theme => ({ ...muiClasses, @@ -46,31 +37,16 @@ const styles = theme => ({ right: 0, bottom: 0, left: 0, - // ...transitionStyles, - '&:nth-last-child(1n+2)': { - marginBottom: SNACKBAR_INDENTS.default.snackbar, - }, }, - wrappedRootReverseFirstChild: { - '&:nth-last-child(1n+2)': { - marginBottom: 0, - }, - '&:nth-child(1n+2)': { - marginBottom: SNACKBAR_INDENTS.default.snackbar, - }, + collapseContainer: { + transition: theme.transitions.create(['height'], { easing: 'ease' }), }, - wrappedRootDense: { - '&:nth-last-child(1n+2)': { - marginBottom: SNACKBAR_INDENTS.dense.snackbar, - }, + collapseWrapped: { + marginBottom: SNACKBAR_INDENTS.default.snackbar, + transition: theme.transitions.create(['margin-bottom'], { easing: 'ease' }), }, - wrappedRootReverseFirstChildDense: { - '&:nth-last-child(1n+2)': { - marginBottom: 0, - }, - '&:nth-child(1n+2)': { - marginBottom: SNACKBAR_INDENTS.dense.snackbar, - }, + collapseWrappedDense: { + marginBottom: SNACKBAR_INDENTS.dense.snackbar, }, }); diff --git a/src/SnackbarItem/SnackbarItem.util.js b/src/SnackbarItem/SnackbarItem.util.js index de8326d8..94fa73ab 100644 --- a/src/SnackbarItem/SnackbarItem.util.js +++ b/src/SnackbarItem/SnackbarItem.util.js @@ -33,7 +33,7 @@ export const getTransitionDirection = (anchorOrigin) => { * @param {boolean} dense * @return {object} */ -export const getSnackbarClasses = (classes, anchOrigin, dense) => { +export const getSnackbarClasses = (classes) => { // filter classes object and return keys that are allowed in material-ui snackbar classes prop const snackbarMuiClasses = Object.keys(classes) .filter(key => muiClasses[key] !== undefined) @@ -42,14 +42,22 @@ export const getSnackbarClasses = (classes, anchOrigin, dense) => { [key]: classes[key], }), {}); - const rootClasses = classNames(snackbarMuiClasses.root, classes.wrappedRoot, { - [classes.wrappedRootDense]: dense, - [classes.wrappedRootReverseFirstChild]: anchOrigin.vertical === 'bottom', - [classes.wrappedRootReverseFirstChildDense]: dense && anchOrigin.vertical === 'bottom', - }); + const rootClasses = classNames(snackbarMuiClasses.root, classes.wrappedRoot); return { ...snackbarMuiClasses, root: rootClasses, }; }; + +export const getCollapseClasses = (classes, dense) => { + + const rootClasses = classNames(classes.collapseWrapped, { + [classes.collapseWrappedDense]: dense, + }); + + return { + container: classes.collapseContainer, + wrapper: rootClasses, + }; +}; diff --git a/src/SnackbarProvider.js b/src/SnackbarProvider.js index b30334ac..3d7a373d 100644 --- a/src/SnackbarProvider.js +++ b/src/SnackbarProvider.js @@ -2,7 +2,7 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; import Slide from '@material-ui/core/Slide'; import SnackbarContext from './SnackbarContext'; -import { TRANSITION_DELAY, TRANSITION_DOWN_DURATION, MESSAGES, iconVariant, originKeyExtractor } from './utils/constants'; +import { MESSAGES, iconVariant, originKeyExtractor } from './utils/constants'; import SnackbarItem from './SnackbarItem'; import SnackbarContainer from './SnackbarContainer'; import warning from './utils/warning'; @@ -158,12 +158,9 @@ class SnackbarProvider extends Component { * @param {object} event - The event source of the callback */ handleExitedSnack = (event, key) => { - const enterDelay = TRANSITION_DELAY + TRANSITION_DOWN_DURATION + 40; this.setState( - ({ snacks }) => ({ - snacks: snacks.filter(item => item.key !== key), - }), - () => setTimeout(this.handleDisplaySnack, enterDelay), + ({ snacks }) => ({ snacks: snacks.filter(item => item.key !== key) }), + () => this.handleDisplaySnack(), ); if (this.props.onExited) this.props.onExited(event, key); diff --git a/src/index.d.ts b/src/index.d.ts index 207a8550..584e1665 100644 --- a/src/index.d.ts +++ b/src/index.d.ts @@ -7,8 +7,6 @@ type ClassNameMap = Record; export type VariantType = 'default' | 'error' | 'success' | 'warning' | 'info'; -export type RenderVariants = 'default'| 'wrapped'; - export interface OptionsObject extends Omit { key?: string | number; variant?: VariantType; @@ -42,7 +40,6 @@ export interface SnackbarProviderProps extends Omit React.ReactNode); - renderVariant?: RenderVariants; } export const SnackbarProvider: React.ComponentType; diff --git a/src/utils/constants.js b/src/utils/constants.js index 9c59a4ca..fe35b43b 100644 --- a/src/utils/constants.js +++ b/src/utils/constants.js @@ -48,17 +48,13 @@ export const iconVariant = { info: , }; -export const TRANSITION_DELAY = 150; - -export const TRANSITION_DOWN_DURATION = 200; - export const MESSAGES = { NO_PERSIST_ALL: 'WARNING - notistack: Reached maxSnack while all enqueued snackbars have \'persist\' flag. Notistack will dismiss the oldest snackbar anyway to allow other ones in the queue to be presented.', }; export const SNACKBAR_INDENTS = { - default: { view: 20, snackbar: 12 }, - dense: { view: 0, snackbar: 4 }, + default: { view: 20, snackbar: 12, container: 12 }, + dense: { view: 0, snackbar: 4, container: 4 }, }; export const originKeyExtractor = anchor => `${anchor.vertical}-${anchor.horizontal}`;