Skip to content

Commit

Permalink
[docs] Add Snackbars TypeScript Demos (#15087)
Browse files Browse the repository at this point in the history
* [docs] Add Snackbars TS demos

* rewriting ConsecutiveSnackbars to use hooks

* removing console logs

* moving changes for Consecutive snackbar out

* converting consecutive snackbars to ts
  • Loading branch information
sperry94 authored and oliviertassinari committed Mar 30, 2019
1 parent 9eec03e commit 7c03f10
Show file tree
Hide file tree
Showing 13 changed files with 729 additions and 14 deletions.
13 changes: 8 additions & 5 deletions docs/src/pages/demos/snackbars/ConsecutiveSnackbars.js
Original file line number Diff line number Diff line change
Expand Up @@ -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({
Expand Down Expand Up @@ -57,7 +60,7 @@ class ConsecutiveSnackbars extends React.Component {

render() {
const { classes } = this.props;
const { messageInfo } = this.state;
const { messageInfo = {} } = this.state;

return (
<div>
Expand Down
121 changes: 121 additions & 0 deletions docs/src/pages/demos/snackbars/ConsecutiveSnackbars.tsx
Original file line number Diff line number Diff line change
@@ -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<typeof styles>;

export interface State {
open: boolean;
messageInfo?: SnackbarMessage;
}

class ConsecutiveSnackbars extends React.Component<Props, State> {
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 (
<div>
<Button onClick={this.handleClick('message a')}>Show message A</Button>
<Button onClick={this.handleClick('message b')}>Show message B</Button>
<Snackbar
key={messageInfo.key}
anchorOrigin={{
vertical: 'bottom',
horizontal: 'left',
}}
open={this.state.open}
autoHideDuration={6000}
onClose={this.handleClose}
onExited={this.handleExited}
ContentProps={{
'aria-describedby': 'message-id',
}}
message={<span id="message-id">{messageInfo.message}</span>}
action={[
<Button key="undo" color="secondary" size="small" onClick={this.handleClose}>
UNDO
</Button>,
<IconButton
key="close"
aria-label="Close"
color="inherit"
className={classes.close}
onClick={this.handleClose}
>
<CloseIcon />
</IconButton>,
]}
/>
</div>
);
}
}

(ConsecutiveSnackbars as React.ComponentClass<Props>).propTypes = {
classes: PropTypes.object.isRequired,
} as any;

export default withStyles(styles)(ConsecutiveSnackbars);
162 changes: 162 additions & 0 deletions docs/src/pages/demos/snackbars/CustomizedSnackbars.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<SnackbarContent
className={clsx(classes[variant], className)}
aria-describedby="client-snackbar"
message={
<span id="client-snackbar" className={classes.message}>
<Icon className={clsx(classes.icon, classes.iconVariant)} />
{message}
</span>
}
action={[
<IconButton
edge="end"
key="close"
aria-label="Close"
color="inherit"
className={classes.close}
onClick={onClose}
>
<CloseIcon className={classes.icon} />
</IconButton>,
]}
{...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 (
<div>
<Button className={classes.margin} onClick={handleClick}>
Open success snackbar
</Button>
<Snackbar
anchorOrigin={{
vertical: 'bottom',
horizontal: 'left',
}}
open={open}
autoHideDuration={6000}
onClose={handleClose}
>
<MySnackbarContentWrapper
onClose={handleClose}
variant="success"
message="This is a success message!"
/>
</Snackbar>
<MySnackbarContentWrapper
variant="error"
className={classes.margin}
message="This is an error message!"
/>
<MySnackbarContentWrapper
variant="warning"
className={classes.margin}
message="This is a warning message!"
/>
<MySnackbarContentWrapper
variant="info"
className={classes.margin}
message="This is an information message!"
/>
<MySnackbarContentWrapper
variant="success"
className={classes.margin}
message="This is a success message!"
/>
</div>
);
}

export default CustomizedSnackbars;
11 changes: 7 additions & 4 deletions docs/src/pages/demos/snackbars/DirectionSnackbar.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 });
Expand Down
66 changes: 66 additions & 0 deletions docs/src/pages/demos/snackbars/DirectionSnackbar.tsx
Original file line number Diff line number Diff line change
@@ -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 <Slide {...props} direction="left" />;
}

function TransitionUp(props: TransitionProps) {
return <Slide {...props} direction="up" />;
}

function TransitionRight(props: TransitionProps) {
return <Slide {...props} direction="right" />;
}

function TransitionDown(props: TransitionProps) {
return <Slide {...props} direction="down" />;
}

export interface State {
open: boolean;
Transition?: React.ComponentType<TransitionProps>;
}

class DirectionSnackbar extends React.Component<void, State> {
constructor() {
super();

this.state = {
open: false,
};
}

handleClick = (Transition: React.ComponentType<TransitionProps>) => () => {
this.setState({ open: true, Transition });
};

handleClose = () => {
this.setState({ open: false });
};

render() {
return (
<div>
<Button onClick={this.handleClick(TransitionLeft)}>Right</Button>
<Button onClick={this.handleClick(TransitionUp)}>Up</Button>
<Button onClick={this.handleClick(TransitionRight)}>Left</Button>
<Button onClick={this.handleClick(TransitionDown)}>Down</Button>
<Snackbar
open={this.state.open}
onClose={this.handleClose}
TransitionComponent={this.state.Transition}
ContentProps={{
'aria-describedby': 'message-id',
}}
message={<span id="message-id">I love snacks</span>}
/>
</div>
);
}
}

export default DirectionSnackbar;
Loading

0 comments on commit 7c03f10

Please sign in to comment.