Skip to content

Commit

Permalink
Allow customising container styles (#172)
Browse files Browse the repository at this point in the history
* Fixes #170 - Allow customising snackbar container

* Minor improvements

* Minor doc improvement
  • Loading branch information
iamhosseindhv authored Oct 5, 2019
1 parent b19d5b4 commit e0b8a4b
Show file tree
Hide file tree
Showing 7 changed files with 69 additions and 34 deletions.
6 changes: 5 additions & 1 deletion src/SnackbarContainer.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,9 @@ const styles = theme => ({
});

const SnackbarContainer = React.memo((props) => {
const { classes, anchorOrigin, dense, ...other } = props;
const {
classes, className, anchorOrigin, dense, ...other
} = props;

const combinedClassname = classNames(
classes.root,
Expand All @@ -55,6 +57,7 @@ const SnackbarContainer = React.memo((props) => {
classes[`${anchorOrigin.vertical}${dense ? 'Dense' : ''}`],
classes[`${anchorOrigin.horizontal}${dense ? 'Dense' : ''}`],
{ [classes.reverseColumns]: anchorOrigin.vertical === 'bottom' },
className,
);

return (
Expand All @@ -64,6 +67,7 @@ const SnackbarContainer = React.memo((props) => {

SnackbarContainer.propTypes = {
classes: PropTypes.object.isRequired,
className: PropTypes.string,
dense: PropTypes.bool.isRequired,
anchorOrigin: PropTypes.shape({
horizontal: PropTypes.oneOf(['left', 'center', 'right']).isRequired,
Expand Down
3 changes: 2 additions & 1 deletion src/SnackbarItem/SnackbarItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ 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, getCollapseClasses } from './SnackbarItem.util';
import { getTransitionDirection, getSnackbarClasses, getCollapseClasses } from './SnackbarItem.util';
import styles from './SnackbarItem.styles';
import { capitalise } from '../utils/constants';


class SnackbarItem extends Component {
Expand Down
5 changes: 2 additions & 3 deletions src/SnackbarItem/SnackbarItem.styles.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { muiClasses } from './SnackbarItem.util';
import { SNACKBAR_INDENTS } from '../utils/constants';
import { SNACKBAR_INDENTS, allClasses } from '../utils/constants';

const styles = theme => ({
...muiClasses,
...allClasses.mui,
base: {
fontSize: '0.875rem',
lineHeight: '1.46429em',
Expand Down
22 changes: 3 additions & 19 deletions src/SnackbarItem/SnackbarItem.util.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import classNames from 'classnames';
import { allClasses } from '../utils/constants';

const DIRECTION = {
right: 'left',
Expand All @@ -7,18 +8,6 @@ const DIRECTION = {
top: 'down',
};

export const muiClasses = {
root: {},
anchorOriginTopCenter: {},
anchorOriginBottomCenter: {},
anchorOriginTopRight: {},
anchorOriginBottomRight: {},
anchorOriginTopLeft: {},
anchorOriginBottomLeft: {},
};

export const capitalise = text => text.charAt(0).toUpperCase() + text.slice(1);

export const getTransitionDirection = (anchorOrigin) => {
if (anchorOrigin.horizontal !== 'center') {
return DIRECTION[anchorOrigin.horizontal];
Expand All @@ -27,16 +16,11 @@ export const getTransitionDirection = (anchorOrigin) => {
};

/**
* @param {object} classes
* @param {object} anchOrigin
* @param {boolean} arrogant
* @param {boolean} dense
* @return {object}
* Filter classes object and return keys that are allowed in material-ui snackbar classes prop
*/
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)
.filter(key => allClasses.mui[key] !== undefined)
.reduce((obj, key) => ({
...obj,
[key]: classes[key],
Expand Down
30 changes: 24 additions & 6 deletions src/SnackbarProvider.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,22 @@ import React, { Component } from 'react';
import PropTypes from 'prop-types';
import Slide from '@material-ui/core/Slide';
import SnackbarContext from './SnackbarContext';
import { MESSAGES, defaultIconVariant, originKeyExtractor } from './utils/constants';
import { MESSAGES, defaultIconVariant, originKeyExtractor, allClasses } from './utils/constants';
import SnackbarItem from './SnackbarItem';
import SnackbarContainer from './SnackbarContainer';
import warning from './utils/warning';


/**
* Omit SnackbarContainer class keys that are not needed for SnakcbarItem
*/
const getClasses = classes => (
Object.keys(classes).filter(key => !allClasses.container[key]).reduce((obj, key) => ({
...obj,
[key]: classes[key],
}), {})
);

class SnackbarProvider extends Component {
constructor(props) {
super(props);
Expand All @@ -21,8 +32,8 @@ class SnackbarProvider extends Component {

queue = [];

componentWillUnmount() {
this.queue = []
componentWillUnmount = () => {
this.queue = [];
}

/**
Expand Down Expand Up @@ -170,7 +181,7 @@ class SnackbarProvider extends Component {
};

render() {
const { children, maxSnack, dense, ...props } = this.props;
const { classes, children, maxSnack, dense, ...props } = this.props;
const { contextValue } = this.state;

const categ = this.state.snacks.reduce((acc, current) => {
Expand All @@ -188,14 +199,20 @@ class SnackbarProvider extends Component {
<SnackbarContext.Provider value={contextValue}>
{children}
{Object.entries(categ).map(([origin, snacks]) => (
<SnackbarContainer key={origin} dense={dense} anchorOrigin={snacks[0].anchorOrigin}>
<SnackbarContainer
key={origin}
dense={dense}
anchorOrigin={snacks[0].anchorOrigin}
className={classes[`containerAnchorOrigin${origin}`]}
>
{snacks.map(snack => (
<SnackbarItem
{...props}
key={snack.key}
dense={dense}
snack={snack}
iconVariant={iconVariant}
classes={getClasses(classes)}
onClose={this.handleCloseSnack}
onExited={this.handleExitedSnack}
/>
Expand All @@ -214,7 +231,7 @@ SnackbarProvider.propTypes = {
*/
children: PropTypes.node.isRequired,
/**
* Override or extend the styles applied to the component.
* Override or extend the styles applied to the container component or Snackbars.
*/
classes: PropTypes.object,
/**
Expand Down Expand Up @@ -338,6 +355,7 @@ SnackbarProvider.defaultProps = {
dense: false,
preventDuplicate: false,
hideIconVariant: false,
classes: {},
iconVariant: {},
anchorOrigin: {
vertical: 'bottom',
Expand Down
13 changes: 10 additions & 3 deletions src/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,16 @@ export interface OptionsObject extends Omit<SnackbarProps, 'open' | 'message' |
action?: SnackbarContentProps['action'] | ((key: OptionsObject['key']) => React.ReactNode);
}

export type NotistackClassKey = 'variantSuccess' | 'variantError' | 'variantInfo' | 'variantWarning';

type CombinedClassKey = NotistackClassKey | SnackbarClassKey;
export type ContainerClassKey =
| 'containerAnchorOriginTopCenter'
| 'containerAnchorOriginBottomCenter'
| 'containerAnchorOriginTopRight'
| 'containerAnchorOriginBottomRight'
| 'containerAnchorOriginTopLeft'
| 'containerAnchorOriginBottomLeft';

export type VariantClassKey = 'variantSuccess' | 'variantError' | 'variantInfo' | 'variantWarning';
export type CombinedClassKey = VariantClassKey | ContainerClassKey | SnackbarClassKey;

export interface WithSnackbarProps {
enqueueSnackbar: (message: string | React.ReactNode, options?: OptionsObject) => OptionsObject['key'] | null;
Expand Down
24 changes: 23 additions & 1 deletion src/utils/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,26 @@ const InfoIcon = props => (
</SvgIcon>
);

export const allClasses = {
mui: {
root: {},
anchorOriginTopCenter: {},
anchorOriginBottomCenter: {},
anchorOriginTopRight: {},
anchorOriginBottomRight: {},
anchorOriginTopLeft: {},
anchorOriginBottomLeft: {},
},
container: {
containerAnchorOriginTopCenter: {},
containerAnchorOriginBottomCenter: {},
containerAnchorOriginTopRight: {},
containerAnchorOriginBottomRight: {},
containerAnchorOriginTopLeft: {},
containerAnchorOriginBottomLeft: {},
},
};

const iconStyles = {
opacity: 0.9,
fontSize: 20,
Expand All @@ -57,4 +77,6 @@ export const SNACKBAR_INDENTS = {
snackbar: { default: 6, dense: 2 },
};

export const originKeyExtractor = anchor => `${anchor.vertical}-${anchor.horizontal}`;
export const capitalise = text => text.charAt(0).toUpperCase() + text.slice(1);

export const originKeyExtractor = anchor => `${capitalise(anchor.vertical)}${capitalise(anchor.horizontal)}`;

0 comments on commit e0b8a4b

Please sign in to comment.