diff --git a/docs/src/modules/components/Demo.js b/docs/src/modules/components/Demo.js index c49a82d29b2653..397c780be4de3b 100644 --- a/docs/src/modules/components/Demo.js +++ b/docs/src/modules/components/Demo.js @@ -50,6 +50,7 @@ const styles = theme => ({ }, }, demo: { + margin: 'auto', borderRadius: theme.shape.borderRadius, backgroundColor: theme.palette.type === 'light' ? theme.palette.grey[200] : theme.palette.grey[900], @@ -349,6 +350,9 @@ class Demo extends React.Component { })} onMouseEnter={this.handleDemoHover} onMouseLeave={this.handleDemoHover} + style={{ + maxWidth: demoOptions.maxWidth, + }} > diff --git a/docs/src/pages/demos/app-bar/app-bar.md b/docs/src/pages/demos/app-bar/app-bar.md index b7da82d67e4599..d35331230c1c13 100644 --- a/docs/src/pages/demos/app-bar/app-bar.md +++ b/docs/src/pages/demos/app-bar/app-bar.md @@ -41,4 +41,4 @@ A side searchbar. ## Bottom App Bar -{{"demo": "pages/demos/app-bar/BottomAppBar.js", "iframe": true}} +{{"demo": "pages/demos/app-bar/BottomAppBar.js", "iframe": true, "maxWidth": 500}} diff --git a/docs/src/pages/demos/snackbars/ConsecutiveSnackbars.js b/docs/src/pages/demos/snackbars/ConsecutiveSnackbars.js index b19d1112b87122..ac0448641a2a0d 100644 --- a/docs/src/pages/demos/snackbars/ConsecutiveSnackbars.js +++ b/docs/src/pages/demos/snackbars/ConsecutiveSnackbars.js @@ -60,8 +60,8 @@ class ConsecutiveSnackbars extends React.Component { return (
- - + + { return (
- - + + - - ({ - root: { - position: 'relative', - overflow: 'hidden', - }, - appFrame: { - width: 360, - height: 360, - backgroundColor: theme.palette.background.paper, + '@global': { + body: { + backgroundColor: theme.palette.background.paper, + }, }, menuButton: { - marginRight: 20, - }, - button: { - marginBottom: theme.spacing(1), + marginRight: theme.spacing(2), }, 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, + [theme.breakpoints.down('xs')]: { + bottom: 90, + }, }, })); 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 ( -
- + +
@@ -85,31 +50,29 @@ function FabIntegrationSnackbar() { - Out of my way! + App Bar - + Archived} action={ - } className={classes.snackbar} />
-
+ ); } diff --git a/docs/src/pages/demos/snackbars/FabIntegrationSnackbar.tsx b/docs/src/pages/demos/snackbars/FabIntegrationSnackbar.tsx index 5c17dda66eba31..ed05c15ec0a56a 100644 --- a/docs/src/pages/demos/snackbars/FabIntegrationSnackbar.tsx +++ b/docs/src/pages/demos/snackbars/FabIntegrationSnackbar.tsx @@ -1,7 +1,7 @@ import React from 'react'; -import clsx from 'clsx'; import { makeStyles, Theme } from '@material-ui/core/styles'; import AppBar from '@material-ui/core/AppBar'; +import CssBaseline from '@material-ui/core/CssBaseline'; import Toolbar from '@material-ui/core/Toolbar'; import IconButton from '@material-ui/core/IconButton'; import MenuIcon from '@material-ui/icons/Menu'; @@ -12,67 +12,32 @@ 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, + '@global': { + body: { + backgroundColor: theme.palette.background.paper, + }, }, menuButton: { - marginRight: 20, - }, - button: { - marginBottom: theme.spacing(1), + marginRight: theme.spacing(2), }, 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, + [theme.breakpoints.down('xs')]: { + bottom: 90, + }, }, })); 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 ( -
- + +
@@ -85,31 +50,29 @@ function FabIntegrationSnackbar() { - Out of my way! + App Bar - + Archived} action={ - } className={classes.snackbar} />
-
+ ); } diff --git a/docs/src/pages/demos/snackbars/FadeSnackbar.js b/docs/src/pages/demos/snackbars/FadeSnackbar.js deleted file mode 100644 index e9f96f662fc1c0..00000000000000 --- a/docs/src/pages/demos/snackbars/FadeSnackbar.js +++ /dev/null @@ -1,33 +0,0 @@ -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/FadeSnackbar.tsx b/docs/src/pages/demos/snackbars/FadeSnackbar.tsx deleted file mode 100644 index e9f96f662fc1c0..00000000000000 --- a/docs/src/pages/demos/snackbars/FadeSnackbar.tsx +++ /dev/null @@ -1,33 +0,0 @@ -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/LongTextSnackbar.js b/docs/src/pages/demos/snackbars/LongTextSnackbar.js index 840186019de595..c1fe3b4165caf7 100644 --- a/docs/src/pages/demos/snackbars/LongTextSnackbar.js +++ b/docs/src/pages/demos/snackbars/LongTextSnackbar.js @@ -11,6 +11,9 @@ const action = ( ); const styles = theme => ({ + root: { + maxWidth: 600, + }, snackbar: { margin: theme.spacing(1), }, @@ -20,7 +23,7 @@ function LongTextSnackbar(props) { const { classes } = props; return ( -
+
createStyles({ + root: { + maxWidth: 600, + }, snackbar: { margin: theme.spacing(1), }, @@ -23,7 +26,7 @@ function LongTextSnackbar(props: Props) { const { classes } = props; return ( -
+
Top-Left Top-Left ; +} + +function GrowTransition(props) { + return ; +} + +function TransitionsSnackbar() { + const [state, setState] = React.useState({ + open: false, + Transition: Fade, + }); + + const handleClick = Transition => () => { + setState({ + open: true, + Transition, + }); + }; + + function handleClose() { + setState({ + ...state, + open: false, + }); + } + + return ( +
+ + + + I love snacks} + /> +
+ ); +} + +export default TransitionsSnackbar; diff --git a/docs/src/pages/demos/snackbars/TransitionsSnackbar.tsx b/docs/src/pages/demos/snackbars/TransitionsSnackbar.tsx new file mode 100644 index 00000000000000..6dd1a68079d700 --- /dev/null +++ b/docs/src/pages/demos/snackbars/TransitionsSnackbar.tsx @@ -0,0 +1,55 @@ +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'; +import Slide from '@material-ui/core/Slide'; +import Grow from '@material-ui/core/Grow'; +import { TransitionProps } from '@material-ui/core/transitions/transition'; + +function SlideTransition(props: TransitionProps) { + return ; +} + +function GrowTransition(props: TransitionProps) { + return ; +} + +function TransitionsSnackbar() { + const [state, setState] = React.useState({ + open: false, + Transition: Fade, + }); + + const handleClick = (Transition: React.ComponentType) => () => { + setState({ + open: true, + Transition, + }); + }; + + function handleClose() { + setState({ + ...state, + open: false, + }); + } + + return ( +
+ + + + I love snacks} + /> +
+ ); +} + +export default TransitionsSnackbar; diff --git a/docs/src/pages/demos/snackbars/snackbars.md b/docs/src/pages/demos/snackbars/snackbars.md index 95f9163fd91a58..85de24c49d1200 100644 --- a/docs/src/pages/demos/snackbars/snackbars.md +++ b/docs/src/pages/demos/snackbars/snackbars.md @@ -48,27 +48,27 @@ Some snackbars with varying message length. ### Consecutive Snackbars -Per [Google's guidelines](https://material.io/design/components/snackbars.html#snackbars-toasts-usage), when a second snackbar is triggered while the first is displayed, the first should start the contraction motion downwards before the second one animates upwards. +When multiple snackbar updates are necessary, they should appear one at a time. {{"demo": "pages/demos/snackbars/ConsecutiveSnackbars.js"}} -### Don't block the floating action button +### Snackbars and floating action buttons (FABs) -Move the floating action button vertically to accommodate the snackbar height. +Snackbars should appear above FABs (on mobile). -{{"demo": "pages/demos/snackbars/FabIntegrationSnackbar.js"}} +{{"demo": "pages/demos/snackbars/FabIntegrationSnackbar.js", "iframe": true, "maxWidth": 500}} -### Control Direction +### Change Transition -Change the direction of the transition. Slide is the default transition. +[Grow](/utils/transitions/#grow) is the default transition but you can use a different one. -{{"demo": "pages/demos/snackbars/DirectionSnackbar.js"}} +{{"demo": "pages/demos/snackbars/TransitionsSnackbar.js"}} -### Change Transition +### Control Slide direction -Use a different transition. +You can change the direction of the [Slide](/utils/transitions/#slide) transition. -{{"demo": "pages/demos/snackbars/FadeSnackbar.js"}} +{{"demo": "pages/demos/snackbars/DirectionSnackbar.js"}} ## Complementary projects @@ -79,6 +79,8 @@ For more advanced use cases you might be able to take advantage of: ![stars](https://img.shields.io/github/stars/iamhosseindhv/notistack.svg?style=social&label=Stars) ![npm downloads](https://img.shields.io/npm/dm/notistack.svg) -In the following example, we demonstrate how to use [notistack](https://github.com/iamhosseindhv/notistack). notistack makes it easy to display snackbars (so you don't have to deal with open/close state of them). It also enables you to stack them on top of one another. +In the following example, we demonstrate how to use [notistack](https://github.com/iamhosseindhv/notistack). +notistack makes it easy to display snackbars (so you don't have to deal with open/close state of them). +It also enables you to stack them on top of one another (but discouraged by the specification). {{"demo": "pages/demos/snackbars/IntegrationNotistack.js"}} diff --git a/packages/material-ui/src/Slide/Slide.js b/packages/material-ui/src/Slide/Slide.js index 19fa7e407a50b5..8dd707350e3cd1 100644 --- a/packages/material-ui/src/Slide/Slide.js +++ b/packages/material-ui/src/Slide/Slide.js @@ -70,7 +70,7 @@ export function setTranslateValue(props, node) { } /** - * The Slide transition is used by the [Snackbar](/demos/snackbars/) component. + * The Slide transition is used by the [Drawer](/demos/drawers/) component. * It uses [react-transition-group](https://github.com/reactjs/react-transition-group) internally. */ class Slide extends React.Component { diff --git a/packages/material-ui/src/Snackbar/Snackbar.js b/packages/material-ui/src/Snackbar/Snackbar.js index bd5e151fe0cd60..b33c58328775ba 100644 --- a/packages/material-ui/src/Snackbar/Snackbar.js +++ b/packages/material-ui/src/Snackbar/Snackbar.js @@ -7,19 +7,18 @@ import { duration } from '../styles/transitions'; import ClickAwayListener from '../ClickAwayListener'; import { capitalize, createChainedFunction } from '../utils/helpers'; import withForwardedRef from '../utils/withForwardedRef'; -import Slide from '../Slide'; +import Grow from '../Grow'; import SnackbarContent from '../SnackbarContent'; export const styles = theme => { - const gutter = 24; - const top = { top: 0 }; - const bottom = { bottom: 0 }; + const top1 = { top: 8 }; + const bottom1 = { bottom: 8 }; const right = { justifyContent: 'flex-end' }; const left = { justifyContent: 'flex-start' }; - const topSpace = { top: gutter }; - const bottomSpace = { bottom: gutter }; - const rightSpace = { right: gutter }; - const leftSpace = { left: gutter }; + const top3 = { top: 24 }; + const bottom3 = { bottom: 24 }; + const right3 = { right: 24 }; + const left3 = { left: 24 }; const center = { left: '50%', right: 'auto', @@ -32,63 +31,65 @@ export const styles = theme => { zIndex: theme.zIndex.snackbar, position: 'fixed', display: 'flex', - left: 0, - right: 0, + left: 8, + right: 8, justifyContent: 'center', alignItems: 'center', }, /* Styles applied to the root element if `anchorOrigin={{ 'top', 'center' }}`. */ anchorOriginTopCenter: { - ...top, - [theme.breakpoints.up('md')]: { + ...top1, + [theme.breakpoints.up('sm')]: { + ...top3, ...center, }, }, /* Styles applied to the root element if `anchorOrigin={{ 'bottom', 'center' }}`. */ anchorOriginBottomCenter: { - ...bottom, - [theme.breakpoints.up('md')]: { + ...bottom1, + [theme.breakpoints.up('sm')]: { + ...bottom3, ...center, }, }, /* Styles applied to the root element if `anchorOrigin={{ 'top', 'right' }}`. */ anchorOriginTopRight: { - ...top, + ...top1, ...right, - [theme.breakpoints.up('md')]: { + [theme.breakpoints.up('sm')]: { left: 'auto', - ...topSpace, - ...rightSpace, + ...top3, + ...right3, }, }, /* Styles applied to the root element if `anchorOrigin={{ 'bottom', 'right' }}`. */ anchorOriginBottomRight: { - ...bottom, + ...bottom1, ...right, - [theme.breakpoints.up('md')]: { + [theme.breakpoints.up('sm')]: { left: 'auto', - ...bottomSpace, - ...rightSpace, + ...bottom3, + ...right3, }, }, /* Styles applied to the root element if `anchorOrigin={{ 'top', 'left' }}`. */ anchorOriginTopLeft: { - ...top, + ...top1, ...left, - [theme.breakpoints.up('md')]: { + [theme.breakpoints.up('sm')]: { right: 'auto', - ...topSpace, - ...leftSpace, + ...top3, + ...left3, }, }, /* Styles applied to the root element if `anchorOrigin={{ 'bottom', 'left' }}`. */ anchorOriginBottomLeft: { - ...bottom, + ...bottom1, ...left, - [theme.breakpoints.up('md')]: { + [theme.breakpoints.up('sm')]: { right: 'auto', - ...bottomSpace, - ...leftSpace, + ...bottom3, + ...left3, }, }, }; @@ -408,7 +409,7 @@ Snackbar.defaultProps = { horizontal: 'center', }, disableWindowBlurListener: false, - TransitionComponent: Slide, + TransitionComponent: Grow, transitionDuration: { enter: duration.enteringScreen, exit: duration.leavingScreen, diff --git a/packages/material-ui/src/Snackbar/Snackbar.test.js b/packages/material-ui/src/Snackbar/Snackbar.test.js index 01659025013873..19e5c8441d02e2 100644 --- a/packages/material-ui/src/Snackbar/Snackbar.test.js +++ b/packages/material-ui/src/Snackbar/Snackbar.test.js @@ -3,7 +3,7 @@ import { assert } from 'chai'; import { spy, useFakeTimers } from 'sinon'; import { createMount, describeConformance, getClasses } from '@material-ui/core/test-utils'; import Snackbar from './Snackbar'; -import Slide from '../Slide'; +import Grow from '../Grow'; describe('', () => { let mount; @@ -381,9 +381,9 @@ describe('', () => { }); describe('prop: TransitionComponent', () => { - it('should use a Slide by default', () => { + it('should use a Grow by default', () => { const wrapper = mount(); - assert.strictEqual(wrapper.find(Slide).exists(), true, 'should use a Slide by default'); + assert.strictEqual(wrapper.find(Grow).exists(), true); }); it('accepts a different component that handles the transition', () => { diff --git a/packages/material-ui/src/SnackbarContent/SnackbarContent.js b/packages/material-ui/src/SnackbarContent/SnackbarContent.js index e5b94060cfe8a1..a141b9bfac1213 100644 --- a/packages/material-ui/src/SnackbarContent/SnackbarContent.js +++ b/packages/material-ui/src/SnackbarContent/SnackbarContent.js @@ -20,14 +20,12 @@ export const styles = theme => { display: 'flex', alignItems: 'center', flexWrap: 'wrap', - padding: '6px 24px', - [theme.breakpoints.up('md')]: { + padding: '6px 16px', + borderRadius: theme.shape.borderRadius, + flexGrow: 1, + [theme.breakpoints.up('sm')]: { + flexGrow: 'initial', minWidth: 288, - maxWidth: 568, - borderRadius: theme.shape.borderRadius, - }, - [theme.breakpoints.down('sm')]: { - flexGrow: 1, }, }, /* Styles applied to the message wrapper element. */ @@ -39,7 +37,7 @@ export const styles = theme => { display: 'flex', alignItems: 'center', marginLeft: 'auto', - paddingLeft: 24, + paddingLeft: 16, marginRight: -8, }, }; diff --git a/pages/api/slide.md b/pages/api/slide.md index ca90561cb63918..a91fa9275b45b1 100644 --- a/pages/api/slide.md +++ b/pages/api/slide.md @@ -12,7 +12,7 @@ filename: /packages/material-ui/src/Slide/Slide.js import Slide from '@material-ui/core/Slide'; ``` -The Slide transition is used by the [Snackbar](/demos/snackbars/) component. +The Slide transition is used by the [Drawer](/demos/drawers/) component. It uses [react-transition-group](https://github.com/reactjs/react-transition-group) internally. ## Props diff --git a/pages/api/snackbar.md b/pages/api/snackbar.md index 418ad524d49ab1..133ff8b2e2e569 100644 --- a/pages/api/snackbar.md +++ b/pages/api/snackbar.md @@ -37,7 +37,7 @@ import Snackbar from '@material-ui/core/Snackbar'; | onExiting | func | | Callback fired when the transition is exiting. | | open | bool | | If true, `Snackbar` is open. | | resumeHideDuration | number | | The number of milliseconds to wait before dismissing after user interaction. If `autoHideDuration` property isn't specified, it does nothing. If `autoHideDuration` property is specified but `resumeHideDuration` isn't, we default to `autoHideDuration / 2` ms. | -| TransitionComponent | elementType | Slide | The component used for the transition. | +| TransitionComponent | elementType | Grow | The component used for the transition. | | transitionDuration | union: number |
 { enter?: number, exit?: number }
| { enter: duration.enteringScreen, exit: duration.leavingScreen,} | The duration for the transition, in milliseconds. You may specify a single timeout for all transitions, or individually with an object. | | TransitionProps | object | | Properties applied to the `Transition` element. |