Skip to content

Commit

Permalink
Remove snackbar height calculation
Browse files Browse the repository at this point in the history
  • Loading branch information
iamhosseindhv committed Sep 21, 2019
1 parent 1ec03a2 commit c42289e
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 130 deletions.
104 changes: 34 additions & 70 deletions src/SnackbarItem/SnackbarItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,13 @@ import React, { Component } from 'react';
import classNames from 'classnames';
import PropTypes from 'prop-types';
import { withStyles } from '@material-ui/core/styles';
import RootRef from '@material-ui/core/RootRef';
import Snackbar from '@material-ui/core/Snackbar';
import SnackbarContent from '@material-ui/core/SnackbarContent';
import { styles, getTransitionStyles } from './SnackbarItem.styles';
import { capitalise, getTransitionDirection, getSnackbarClasses } from './SnackbarItem.util';
import { RENDER_VARIANTS } from '../utils/constants';
import styles from './SnackbarItem.styles';


class SnackbarItem extends Component {
constructor(props) {
super(props);
this.ref = React.createRef();
}

handleClose = key => (event, reason) => {
const { onClose, snack: { onClose: singleOnClose } } = this.props;
if (reason === 'clickaway') return;
Expand All @@ -29,26 +22,15 @@ class SnackbarItem extends Component {
onExited(event, key);
};

componentDidMount = () => {
const { onSetHeight, snack } = this.props;
const height = this.ref.current && this.ref.current.clientHeight;
onSetHeight(snack.key, height);
};

render() {
const {
classes,
action,
anchorOrigin,
ContentProps = {},
hideIconVariant,
preventDuplicate,
iconVariant,
offset,
snack,
style,
onSetHeight,
renderVariant,
dense,
...other
} = this.props;
Expand All @@ -61,6 +43,7 @@ class SnackbarItem extends Component {
variant = 'default',
action: singleAction,
ContentProps: singleContentProps = {},
anchorOrigin,
...singleSnackProps
} = snack;

Expand All @@ -74,16 +57,6 @@ class SnackbarItem extends Component {

const ariaDescribedby = contentProps['aria-describedby'] || 'client-snackbar';

const anchOrigin = {
[RENDER_VARIANTS.default]: singleSnackProps.anchorOrigin || anchorOrigin,
[RENDER_VARIANTS.wrapped]: anchorOrigin,
}[renderVariant];

const transitionStyles = {
[RENDER_VARIANTS.default]: getTransitionStyles(offset, anchOrigin),
[RENDER_VARIANTS.wrapped]: {},
}[renderVariant];

let finalAction = contentProps.action;
if (typeof finalAction === 'function') {
finalAction = contentProps.action(key);
Expand All @@ -95,51 +68,44 @@ class SnackbarItem extends Component {
}

return (
<RootRef rootRef={this.ref}>
<Snackbar
TransitionProps={{
direction: getTransitionDirection(anchOrigin),
}}
style={{
...style,
...transitionStyles,
}}
{...other}
{...singleSnackProps}
anchorOrigin={anchOrigin}
open={snack.open}
classes={getSnackbarClasses(classes, renderVariant, dense, anchOrigin)}
onClose={this.handleClose(key)}
onExited={this.handleExited(key)}
>
{snackChildren || (
<SnackbarContent
className={classNames(
classes.base,
classes[`variant${capitalise(variant)}`],
(!hideIconVariant && icon) ? classes.lessPadding : null,
className,
)}
{...contentProps}
aria-describedby={ariaDescribedby}
message={(
<span id={ariaDescribedby} className={classes.message}>
{!hideIconVariant ? icon : null}
{snack.message}
</span>
)}
action={finalAction}
/>
)}
</Snackbar>
</RootRef>
<Snackbar
TransitionProps={{
direction: getTransitionDirection(anchorOrigin),
}}
{...other}
{...singleSnackProps}
anchorOrigin={anchorOrigin}
open={snack.open}
classes={getSnackbarClasses(classes, anchorOrigin, dense)}
onClose={this.handleClose(key)}
onExited={this.handleExited(key)}
>
{snackChildren || (
<SnackbarContent
className={classNames(
classes.base,
classes[`variant${capitalise(variant)}`],
(!hideIconVariant && icon) ? classes.lessPadding : null,
className,
)}
{...contentProps}
aria-describedby={ariaDescribedby}
message={(
<span id={ariaDescribedby} className={classes.message}>
{!hideIconVariant ? icon : null}
{snack.message}
</span>
)}
action={finalAction}
/>
)}
</Snackbar>
);
}
}

SnackbarItem.propTypes = {
classes: PropTypes.object.isRequired,
offset: PropTypes.number.isRequired,
snack: PropTypes.shape({
message: PropTypes.oneOfType([
PropTypes.string,
Expand All @@ -162,9 +128,7 @@ SnackbarItem.propTypes = {
}).isRequired,
hideIconVariant: PropTypes.bool.isRequired,
preventDuplicate: PropTypes.bool.isRequired,
renderVariant: PropTypes.oneOf(Object.keys(RENDER_VARIANTS)).isRequired,
dense: PropTypes.bool.isRequired,
onSetHeight: PropTypes.func.isRequired,
onClose: PropTypes.func.isRequired,
onExited: PropTypes.func.isRequired,
};
Expand Down
42 changes: 15 additions & 27 deletions src/SnackbarItem/SnackbarItem.styles.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,16 @@ 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`,
};

export const styles = theme => ({
const styles = theme => ({
...muiClasses,
base: {
fontSize: '0.875rem',
Expand All @@ -31,31 +39,32 @@ export const styles = theme => ({
display: 'flex',
alignItems: 'center',
},
wrappedRenderVariant: {
wrappedRoot: {
position: 'relative',
transform: 'translateX(0)',
top: 0,
right: 0,
bottom: 0,
left: 0,
// ...transitionStyles,
'&:nth-last-child(1n+2)': {
marginBottom: SNACKBAR_INDENTS.default.snackbar,
},
},
wrappedRenderVariantReverseFirstChild: {
wrappedRootReverseFirstChild: {
'&:nth-last-child(1n+2)': {
marginBottom: 0,
},
'&:nth-child(1n+2)': {
marginBottom: SNACKBAR_INDENTS.default.snackbar,
},
},
wrappedRenderVariantDense: {
wrappedRootDense: {
'&:nth-last-child(1n+2)': {
marginBottom: SNACKBAR_INDENTS.dense.snackbar,
},
},
wrappedRenderVariantReverseFirstChildDense: {
wrappedRootReverseFirstChildDense: {
'&:nth-last-child(1n+2)': {
marginBottom: 0,
},
Expand All @@ -65,25 +74,4 @@ export const styles = theme => ({
},
});

/**
* @param {object} anchorOrigin - how snack is postioned. e.g.
* { vertical: 'bottom', horizontal: 'left' }
* @param {number} level - Level on which snakcbar should be displayed
* (when snackbars are stacked on top of eachother)
* @returns {object}
*/
export const getTransitionStyles = (offset, anchorOrigin) => (
Object.assign(
{
[anchorOrigin.vertical]: offset,
},
{
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}ms`,
transitionDelay: `${TRANSITION_DELAY}ms`,
},
)
);
export default styles;
50 changes: 17 additions & 33 deletions src/SnackbarItem/SnackbarItem.util.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import classNames from 'classnames';
import { defaultAnchorOrigin, RENDER_VARIANTS } from '../utils/constants';

const DIRECTION = {
right: 'left',
Expand All @@ -18,54 +17,39 @@ export const muiClasses = {
anchorOriginBottomLeft: {},
};

/**
* returns transition direction according the the given anchor origin
* @param {object} anchorOrigin
*/
export const getTransitionDirection = (anchorOrigin = defaultAnchorOrigin) => {
export const capitalise = text => text.charAt(0).toUpperCase() + text.slice(1);

export const getTransitionDirection = (anchorOrigin) => {
if (anchorOrigin.horizontal !== 'center') {
return DIRECTION[anchorOrigin.horizontal];
}
return DIRECTION[anchorOrigin.vertical];
};

/**
* Capitalises a piece of string
* @param {string} text
*/
export const capitalise = text => text.charAt(0).toUpperCase() + text.slice(1);

/**
* Filteres classes object and returns the keys that are allowed
* in material-ui snackbar classes prop
* @param {object} classes
* @param {object} anchOrigin
* @param {boolean} arrogant
* @param {boolean} dense
* @return {object}
*/
export const getMuiClasses = classes => (
Object.keys(classes)
export const getSnackbarClasses = (classes, anchOrigin, dense) => {
// 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)
.reduce((obj, key) => ({
...obj,
[key]: classes[key],
}), {})
);
}), {});

/**
* Add wrappedRenderVariant class to root classes of Snackbar if renderVariant is "wrapped"
* @param {object} classes
* @param {RENDER_VARIANTS} renderVariant
* @return {object}
*/
export const getSnackbarClasses = (classes, renderVariant, dense, anchOrigin) => {
const snackbarMuiClasses = getMuiClasses(classes);
const rootClasses = classNames({
[snackbarMuiClasses.root]: true,
[classes.wrappedRenderVariant]: renderVariant === RENDER_VARIANTS.wrapped,
[classes.wrappedRenderVariantDense]: renderVariant === RENDER_VARIANTS.wrapped && dense,
[classes.wrappedRenderVariantReverseFirstChild]: renderVariant === RENDER_VARIANTS.wrapped && anchOrigin.vertical === 'bottom',
[classes.wrappedRenderVariantReverseFirstChildDense]: renderVariant === RENDER_VARIANTS.wrapped && dense && anchOrigin.vertical === 'bottom',
const rootClasses = classNames(snackbarMuiClasses.root, classes.wrappedRoot, {
[classes.wrappedRootDense]: dense,
[classes.wrappedRootReverseFirstChild]: anchOrigin.vertical === 'bottom',
[classes.wrappedRootReverseFirstChildDense]: dense && anchOrigin.vertical === 'bottom',
});

return {
...snackbarMuiClasses,
...{ root: rootClasses },
root: rootClasses,
};
};

0 comments on commit c42289e

Please sign in to comment.