Implemented an example modal

This commit is contained in:
2018-07-06 07:45:40 +10:00
parent 3ea978e0b6
commit 0ded1b20ad
9 changed files with 298 additions and 12 deletions

View File

@ -49,9 +49,14 @@ class App extends React.Component {
let clazz = "c-app";
if(this.props.menuOpen) clazz += " is-menu-open ";
let modal;
if(this.props.modal.open) clazz += " is-modal-open";
if(this.props.modal.modal) modal = this.props.modal.modal;
let children = (
<div className={clazz} ref="app">
<Header />
{ modal }
<Routes onEntering={this.onEnteringBound} />
</div>
);
@ -66,7 +71,8 @@ class App extends React.Component {
const mapStateToProps = function(state) {
return {
menuOpen: state.menu.open
menuOpen: state.menu.open,
modal: state.modal
}
}

View File

@ -0,0 +1,38 @@
// Copyright (c) 2018 Dominic Masters
//
// MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
export const OPEN_MODAL = "OPEN_MODAL";
export const CLOSE_MODAL = "CLOSE_MODAL";
export function openModal(modal) {
return {
type: OPEN_MODAL,
modal
};
}
export function closeModal() {
return {
type: CLOSE_MODAL
}
}

66
public/modal/Modal.jsx Normal file
View File

@ -0,0 +1,66 @@
// Copyright (c) 2018 Dominic Masters
//
// MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
import React from 'react';
import { Button } from './../input/Input';
class Modal extends React.Component {
constructor(props) {
super(props);
}
render() {
let junk = [];
for(let x = 0; x < 1000; x++) {
junk.push(<div key={x}>Hello World</div>);
}
let buttons;
if(this.props.buttons || true) {
buttons = (
<div className="o-modal__box-footer">
<Button>Test</Button>
</div>
);
}
return (
<div className="o-modal">
<div className="o-modal__inner">
<div className="o-modal__backdrop"></div>
<div className="o-modal__box">
<div className="o-modal__box-body">
<div className="o-modal__box-body-inner">
{ junk }
</div>
</div>
{ buttons }
</div>
</div>
</div>
);
}
}
module.exports = Modal;

View File

@ -22,22 +22,60 @@
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
import React from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import Page, { PageBoundary } from './../Page';
import Section, { ImageSection } from './../../section/Section';
import FloatingContentBox from './../../content/FloatingContentBox';
import Image from './../../image/Image';
import { Title, Subtitle } from './../../typography/Typography';
import { Button } from './../../input/Input';
export default function() {
let lines = [];
for(let i = 0; i < 100; i++) {
lines.push(<br key={i} />);
import { openModal } from './../../actions/ModalActions';
import Modal from './../../modal/Modal';
class Homepage extends React.Component {
constructor(props) {
super(props)
}
return (
<Page style="home-page" title={0} className="p-home-page">
Welcome home
{ lines }
</Page>
);
testModal() {
console.log("oof");
this.props.openModal(
<Modal>
Hello Modal
</Modal>
);
}
render() {
let lines = [];
for(let i = 0; i < 20; i++) {
lines.push(<br key={i} />);
}
return (
<Page style="home-page" title={0} className="p-home-page">
Welcome home
{ lines }
<Button onClick={this.testModal.bind(this)}>
Test Modal
</Button>
</Page>
);
}
}
const mapStateToProps = (state) => {
return {
modal: state.modal
};
}
const mapDispatchToProps = (dispatch) => {
return bindActionCreators({
openModal: openModal
},dispatch);
}
export default connect(mapStateToProps, mapDispatchToProps)(Homepage);

View File

@ -0,0 +1,51 @@
// Copyright (c) 2018 Dominic Masters
//
// MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
import {
OPEN_MODAL,
CLOSE_MODAL
} from './../actions/ModalActions';
const initialState = {
open: false
}
const modal = function(state, action) {
if(typeof state === typeof undefined) {
state = initialState;
}
switch(action.type) {
case OPEN_MODAL:
state.open = true;
state.modal = action.modal;
return Object.assign({}, state);
case CLOSE_MODAL:
state.open = false;
return Object.assign({}, state);
default:
return state;
}
}
export default modal;

View File

@ -25,10 +25,12 @@ import { combineReducers } from 'redux';
import LanguageReducer from './LanguageReducer';
import MenuReducer from './MenuReducer';
import ModalReducer from './ModalReducer';
const rootReducer = combineReducers({
language: LanguageReducer,
menu: MenuReducer
menu: MenuReducer,
modal: ModalReducer
});
export default rootReducer;

View File

@ -68,6 +68,7 @@
@import './objects/_form.scss';
@import './objects/_input.scss';
@import './objects/_loader.scss';
@import './objects/_modal.scss';
@import './objects/_page-transition.scss';
@import './objects/_title.scss';
@import './objects/_video.scss';

View File

@ -0,0 +1,83 @@
/*
* Modal
* Popup box designed to alert, or offer a unique interaction method.
*
* Dependencies:
* styles/tools/_absolute-centering.scss
* styles/tools/_shadow.scss
* styles/settings/z.scss
*
* Version:
* 1.0.0 - 2018/07/05
*/
$o-modal--backdrop: rgba(0, 0, 0, 0.7);
$o-modal--background: white;
$o-modal--padding: 0.5em;
.o-modal {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: $s-z--modal;
&__inner {
position: relative;
width: 100%;
height: 100%;
}
&__backdrop {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
background: $o-modal--backdrop;
}
&__box {
@include t-absolute-center-x-y();
@extend %t-dp--shadow;
@extend %t-flexbox;
@include t-flex-wrap(wrap);
@include t-flex-direction(column);
@include t-align-items(flex-start);
@include t-align-content(flex-start);
background: $o-modal--background;
width: 100%;
height: 100%;
max-width: 95%;
max-height: 95%;
&-body {
width: 100%;
@include t-flex-grow(1);
position: relative;
/* Unfortunately flex can only get us half way there */
&-inner {//Hacks our content so it will never overflow its container.
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
overflow-y: auto;
padding: $o-modal--padding;
}
}
&-footer {
width: 100%;
padding: $o-modal--padding;
}
}
@include t-media-query($s-xsmall-up) {
&__box {
width: 800px;
height: 600px;
}
}
}

View File

@ -10,4 +10,5 @@ $s-z--background: -1; //Background Element
$s-z--navbar: 10; //Navbar
$s-z--menu: 15; //Hamburger Menu
$s-z--menu-button: 16; //Button to toggle menu.
$s-z--modal: 100; //Modals
$s-z--transition: 1; //The Z-Index of an element in transition