<body>
<div id="root"></div>
</body>
/* Index */
body {
margin: 0;
padding: 0;
font-family: sans-serif;
background-color: #222;
}
/* App */
.App {
text-align: center;
}
/* Header */
.Logo {
animation: App-logo-spin infinite 20s linear;
height: 80px;
}
.Header {
background-color: #222;
height: 150px;
padding: 20px;
color: white;
}
@keyframes App-logo-spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
/* Button */
button {
background-color: #306B7B;
border: none;
cursor: pointer;
color: white;
padding: 15px 32px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
margin-left: 10px;
}
.Button-alert {
background-color: #AEA53B;
}
/* Notification Container */
.Notification-container {
position: fixed;
width: 320px;
padding: 0 10px 10px;
z-index: 1;
box-sizing: border-box;
height: auto;
/* `Top-right` is the default */
top: 0px;
bottom: auto;
left: auto;
right: 0px;
}
.Bottom-right {
top: auto;
bottom: 0px;
left: auto;
right: 0px;
}
.Bottom-left {
top: auto;
bottom: 0px;
left: 0px;
right: auto;
}
.Top-left {
top: 0px;
bottom: auto;
left: 0px;
right: auto;
}
/* Notification */
.Info {
position: relative;
width: 100%;
font-size: 16px;
margin: 10px 0 0;
padding: 10px;
box-sizing: border-box;
opacity: 1;
transition: 0.3s ease-in-out;
transform: translate3d(0px, 0px, 0px);
will-change: transform, opacity;
background: #ADEBFC;
color: #2E6C7D; /* 50% darker http://www.hexcolortool.com */
}
.Alert {
background: #FBF06C;
color: #7C7100; /* 50% darker http://www.hexcolortool.com */
}
.Warning {
background: #E26F53;
color: #630000; /* 50% darker http://www.hexcolortool.com */
}
/* Modal */
.Modal {
display: none;
position: fixed;
z-index: 1;
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: auto;
background-color: rgb(0,0,0);
background-color: rgba(0,0,0,0.4);
}
/* background to close the modal when clicking outside of `Modal-content` */
.Modal-close {
position: fixed;
z-index: -1;
width: 100%;
height: 100%;
}
.Modal-content {
background-color: #fefefe;
margin: 15% auto;
padding: 20px;
width: 80%;
}
.Close {
color: #aaa;
float: right;
font-size: 28px;
font-weight: bold;
}
.Close:hover,
.Close:focus {
color: black;
text-decoration: none;
cursor: pointer;
}
class App extends React.Component {
constructor() {
super();
this.toggleMode = this.toggleMode.bind(this);
this.addNotification = this.addNotification.bind(this);
this.removeNotification = this.removeNotification.bind(this);
this.state = {
notificationArr: [],
key: 0,
modal: false
};
}
toggleMode() {
if (!this.state.modal) {
this.removeAllNotifications();
}
this.setState(prevState => ({
modal: prevState.modal = !prevState.modal
}));
}
removeAllNotifications() {
this.setState(prevState => ({
notificationArr: prevState.notificationArr = []
}));
}
showModal() {
const modal = document.getElementById('SpecialModal');
modal.style.display = 'block';
}
addNotification() {
const notification =
<Notification
key={this.state.key}
/*
Define `props` values of your notification here.
Choose the `type` prop between:
- Alert (yellow)
- Warning (red)
If you don't set a `text`, `type` or `time` value, the default
values will be active.
The default value for `type` is: `Info` (blue).
The default value for `text` is: `Lorem ipsum`.
The default value for `time` is: `3000` (3s).
*/
type=""
text="Love in form of an notification"
time="8000"
/>;
// state updates may be asynchronous, so use the second form of `setState()`
this.setState(prevState => ({
// http://stackoverflow.com/questions/26253351/correct-modification-of-state-arrays-in-reactjs
notificationArr: prevState.notificationArr.concat(notification),
key: prevState.key + 1
}));
this.timeoutNotification(notification.props.time);
}
timeoutNotification(time) {
const delay = time ? time : 3000;
setTimeout(this.removeNotification, delay);
}
removeNotification() {
const arr = this.state.notificationArr;
const arrLength = arr.length;
// Use `slice()` because it doesn't mutate the original array,
// it's good for React state handling and functional programming.
const newArr = arrLength ? arr.slice(0, arrLength - 1) : [];
this.setState(prevState => ({
notificationArr: prevState.notificationArr = newArr
}));
}
render() {
const notifications = this.state.notificationArr;
const isModal = this.state.modal;
return (
<div className="App">
<Header />
{isModal ? (
<div>
<Button class="Button-alert" text="Notification Mode" onClick={this.toggleMode} />
<Button text="React Modal" onClick={this.showModal} />
<Modal />
</div>
) : (
<div>
<Button class="Button-alert" text="Modal Mode" onClick={this.toggleMode} />
<Button text="React Notification" onClick={this.addNotification} />
<NotificationContainer
/*
Define the `position` of the notification here.
Choose between:
- Bottom-right
- Bottom-left
- Top-left
If you don't set a value, the default value: `Top-right`
will be active.
*/
position="Top-left">
{notifications}
</NotificationContainer>
</div>
)}
</div>
);
}
}
class Header extends React.Component {
render() {
return (
<div className="Header">
<img src="https://agile-basin-61855.herokuapp.com/static/media/logo.5d5d9eef.svg" className="Logo" alt="logo" />
</div>
);
}
}
class Button extends React.Component {
render() {
return (
<button className={this.props.class} onClick={this.props.onClick}>
{this.props.text}
</button>
);
}
}
class NotificationContainer extends React.Component {
render() {
const position = this.props.position ? ' ' + this.props.position : '';
return (
<div className={"Notification-container" + position}>
{this.props.children}
</div>
);
}
}
class Notification extends React.Component {
render() {
const type = this.props.type ? ' ' + this.props.type : '';
const text = this.props.text ? this.props.text : 'Lorem ipsum';
return (
<div className={"Info" + type}>
<p>{text}</p>
</div>
);
}
}
class Modal extends React.Component {
hideModal() {
const modal = document.getElementById('SpecialModal');
modal.style.display = 'none';
}
render() {
return (
<div id="SpecialModal" className="Modal">
<div className="Modal-close" onClick={this.hideModal}></div>
<div className="Modal-content">
<span className="Close" onClick={this.hideModal}>×</span>
<p>A very interesting message in a large nice modal</p>
</div>
</div>
);
}
}
ReactDOM.render(
<App />,
document.getElementById('root')
);
View Compiled
This Pen doesn't use any external CSS resources.