1
0
mirror of https://github.com/chinchang/web-maker.git synced 2025-07-17 20:11:12 +02:00

add portals for modal

This commit is contained in:
Kushagra Gour
2018-06-17 17:31:01 +05:30
parent 6001a2fb18
commit ab8603bde1
6 changed files with 84 additions and 57 deletions

View File

@@ -55,6 +55,7 @@
"firebase": "^5.0.4", "firebase": "^5.0.4",
"preact": "^8.2.6", "preact": "^8.2.6",
"preact-compat": "^3.17.0", "preact-compat": "^3.17.0",
"preact-portal": "^1.1.3",
"preact-router": "^2.5.7", "preact-router": "^2.5.7",
"split.js": "^1.3.5" "split.js": "^1.3.5"
}, },

View File

@@ -37,6 +37,11 @@ export default class CssSettingsModal extends Component {
onBlur={cm => this.props.onChange(cm.getValue())} onBlur={cm => this.props.onChange(cm.getValue())}
/> />
</div> </div>
<div class="flex flex-h-end">
<button class="btn" onClick={this.props.closeHandler}>
Apply and Close
</button>
</div>
</Modal> </Modal>
); );
} }

View File

@@ -1,4 +1,5 @@
import { h, Component } from 'preact'; import { h, Component } from 'preact';
import Portal from 'preact-portal';
export default class Modal extends Component { export default class Modal extends Component {
componentDidMount() { componentDidMount() {
@@ -18,36 +19,42 @@ export default class Modal extends Component {
} }
} }
componentDidUpdate(prevProps) { componentDidUpdate(prevProps) {
document.body.classList[this.props.show ? 'add' : 'remove']( if (this.props.show != prevProps.show) {
'overlay-visible' document.body.classList[this.props.show ? 'add' : 'remove'](
); 'overlay-visible'
);
if (this.props.show && !prevProps.show) { if (this.props.show) {
this.overlayEl.querySelector('.js-modal__close-btn').focus(); // HACK: refs will evaluate on next tick due to portals
setTimeout(() => {
this.overlayEl.querySelector('.js-modal__close-btn').focus();
}, 0);
}
} }
} }
render() { render() {
if (!this.props.show) return null; if (!this.props.show) return null;
return ( return (
<div <Portal into="body">
class={`${this.props.extraClasses || ''} modal is-modal-visible`} <div
ref={el => (this.overlayEl = el)} class={`${this.props.extraClasses || ''} modal is-modal-visible`}
onClick={this.onOverlayClick.bind(this)} ref={el => (this.overlayEl = el)}
> onClick={this.onOverlayClick.bind(this)}
<div class="modal__content"> >
<button <div class="modal__content">
type="button" <button
onClick={this.props.closeHandler} type="button"
aria-label="Close modal" onClick={this.props.closeHandler}
title="Close" aria-label="Close modal"
class="js-modal__close-btn modal__close-btn" title="Close"
> class="js-modal__close-btn modal__close-btn"
Close >
</button> Close
{this.props.children} </button>
{this.props.children}
</div>
</div> </div>
</div> </Portal>
); );
} }
} }

View File

@@ -34,6 +34,7 @@ import KeyboardShortcutsModal from './KeyboardShortcutsModal';
import { takeScreenshot } from '../takeScreenshot'; import { takeScreenshot } from '../takeScreenshot';
import AskToImportModal from './AskToImportModal'; import AskToImportModal from './AskToImportModal';
import { Alerts } from './Alerts'; import { Alerts } from './Alerts';
import Portal from 'preact-portal';
if (module.hot) { if (module.hot) {
require('preact/debug'); require('preact/debug');
@@ -342,10 +343,6 @@ export default class App extends Component {
window.searchInput.focus(); window.searchInput.focus();
} else { } else {
window.searchInput.value = ''; window.searchInput.value = '';
// Give last focused editor, focus again
// if (editorWithFocus) {
// editorWithFocus.focus();
// }
} }
document.body.classList[this.state.isSavedItemPaneOpen ? 'add' : 'remove']( document.body.classList[this.state.isSavedItemPaneOpen ? 'add' : 'remove'](
'overlay-visible' 'overlay-visible'
@@ -413,12 +410,15 @@ export default class App extends Component {
this.setState({ isAddLibraryModalOpen: true }); this.setState({ isAddLibraryModalOpen: true });
} }
closeSavedItemsPane() { closeSavedItemsPane() {
if (this.editorWithFocus) { document.body.classList[this.state.isSavedItemPaneOpen ? 'add' : 'remove'](
this.editorWithFocus.focus(); 'overlay-visible'
} );
this.setState({ this.setState({
isSavedItemPaneOpen: false isSavedItemPaneOpen: false
}); });
if (this.editorWithFocus) {
this.editorWithFocus.focus();
}
} }
componentDidMount() { componentDidMount() {
document.body.style.height = `${window.innerHeight}px`; document.body.style.height = `${window.innerHeight}px`;
@@ -1095,7 +1095,9 @@ export default class App extends Component {
dontAskBtnClickHandler={this.dontAskToImportAnymore.bind(this)} dontAskBtnClickHandler={this.dontAskToImportAnymore.bind(this)}
/> />
<div class="modal-overlay" /> <Portal into="body">
<div class="modal-overlay" />
</Portal>
<svg <svg
version="1.1" version="1.1"

View File

@@ -15,7 +15,8 @@ body {
font-size: 87.5%; font-size: 87.5%;
/* speocifically for mobile when keyboard is open */ /* speocifically for mobile when keyboard is open */
position: relative; position: relative;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif, 'Segoe UI Emoji', 'Segoe UI Symbol'; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial,
sans-serif, 'Segoe UI Emoji', 'Segoe UI Symbol';
} }
h1 { h1 {
@@ -161,7 +162,7 @@ label {
margin-left: 8px; margin-left: 8px;
} }
a>svg { a > svg {
fill: rgba(255, 255, 255, 0.2); fill: rgba(255, 255, 255, 0.2);
} }
@@ -196,7 +197,8 @@ textarea {
} }
.btn--primary { .btn--primary {
background: var(--color-button) linear-gradient(180deg, rgba(0, 0, 0, 0.5) 0px, transparent); background: var(--color-button)
linear-gradient(180deg, rgba(0, 0, 0, 0.5) 0px, transparent);
color: white; color: white;
} }
@@ -222,7 +224,7 @@ textarea {
outline-offset: 1px; outline-offset: 1px;
} }
.btn-icon>svg { .btn-icon > svg {
width: 20px; width: 20px;
height: 20px; height: 20px;
fill: currentColor; fill: currentColor;
@@ -230,7 +232,7 @@ textarea {
margin-right: 8px; margin-right: 8px;
} }
.btn--big>svg { .btn--big > svg {
width: 25px; width: 25px;
height: 25px; height: 25px;
margin-right: 12px; margin-right: 12px;
@@ -240,7 +242,7 @@ textarea {
display: none; display: none;
} }
.is-loading>svg { .is-loading > svg {
display: none; display: none;
} }
@@ -336,7 +338,7 @@ body:not(.light-version).overlay-visible .main-container {
display: none; display: none;
} }
.layout-4 .code-side+.gutter { .layout-4 .code-side + .gutter {
display: none; display: none;
} }
@@ -423,7 +425,7 @@ body:not(.light-version).overlay-visible .main-container {
} }
.code-wrap__header-btn, .code-wrap__header-btn,
.code-wrap__header-btn>svg { .code-wrap__header-btn > svg {
width: 18px; width: 18px;
height: 18px; height: 18px;
} }
@@ -529,7 +531,7 @@ li.CodeMirror-hint-active {
/* When demo frame is in detached window */ /* When demo frame is in detached window */
body>#demo-frame { body > #demo-frame {
height: 100%; height: 100%;
/* Because console is no more here */ /* Because console is no more here */
} }
@@ -555,7 +557,7 @@ body>#demo-frame {
border-bottom: 1px solid rgba(255, 255, 255, 0.14); border-bottom: 1px solid rgba(255, 255, 255, 0.14);
} }
.main-header__btn-wrap>a { .main-header__btn-wrap > a {
font-size: 0.8em; font-size: 0.8em;
font-weight: bold; font-weight: bold;
line-height: 20px; line-height: 20px;
@@ -566,26 +568,30 @@ body>#demo-frame {
margin-left: 10px; margin-left: 10px;
padding: 0px 8px; padding: 0px 8px;
border: 1px solid rgba(0, 0, 0, 0.9); border: 1px solid rgba(0, 0, 0, 0.9);
background: linear-gradient( 180deg, rgba(0, 0, 0, 0.5) 0, rgba(255, 255, 255, 0.1) 100%); background: linear-gradient(
180deg,
rgba(0, 0, 0, 0.5) 0,
rgba(255, 255, 255, 0.1) 100%
);
/*text-shadow: 0px 1px 1px rgba(0,0,0,1);*/ /*text-shadow: 0px 1px 1px rgba(0,0,0,1);*/
box-shadow: 0 -1px 0px 0 rgba(255, 255, 255, 0.15); box-shadow: 0 -1px 0px 0 rgba(255, 255, 255, 0.15);
text-transform: uppercase; text-transform: uppercase;
} }
.main-header__btn-wrap>a>svg { .main-header__btn-wrap > a > svg {
fill: #9297b3; fill: #9297b3;
margin-right: 4px; margin-right: 4px;
} }
.main-header__btn-wrap>a.is-marked>svg { .main-header__btn-wrap > a.is-marked > svg {
fill: crimson; fill: crimson;
} }
.main-header__btn-wrap>a:hover { .main-header__btn-wrap > a:hover {
border-color: rgba(146, 151, 179, 0.5); border-color: rgba(146, 151, 179, 0.5);
} }
.main-header__btn-wrap>a.is-loading { .main-header__btn-wrap > a.is-loading {
pointer-events: none; pointer-events: none;
opacity: 0.4; opacity: 0.4;
} }
@@ -644,7 +650,7 @@ body>#demo-frame {
top: 2px; top: 2px;
} }
.footer a>svg { .footer a > svg {
transition: 0.3s ease; transition: 0.3s ease;
fill: rgba(255, 255, 255, 0.2); fill: rgba(255, 255, 255, 0.2);
} }
@@ -728,7 +734,7 @@ body>#demo-frame {
transition: 0.25s ease; transition: 0.25s ease;
} }
.modal__close-btn>svg { .modal__close-btn > svg {
fill: black; fill: black;
width: 30px; width: 30px;
height: 30px; height: 30px;
@@ -832,8 +838,9 @@ body>#demo-frame {
transform: translateX(0); transform: translateX(0);
} }
.is-modal-visible~.modal-overlay, .overlay-visible .modal-overlay,
.saved-items-pane.is-open~.modal-overlay { .is-modal-visible ~ .modal-overlay,
.saved-items-pane.is-open ~ .modal-overlay {
opacity: 1; opacity: 1;
visibility: visible; visibility: visible;
} }
@@ -926,7 +933,7 @@ body>#demo-frame {
animation-delay: 0.75s; animation-delay: 0.75s;
} }
.saved-item-tile:nth-child(n+12) { .saved-item-tile:nth-child(n + 12) {
animation-delay: 0.8s; animation-delay: 0.8s;
} }
@@ -1116,24 +1123,24 @@ body>#demo-frame {
background: white; background: white;
} }
.dropdown__menu>li>a { .dropdown__menu > li > a {
display: block; display: block;
padding: 6px 15px; padding: 6px 15px;
color: #333; color: #333;
cursor: pointer; cursor: pointer;
} }
.dropdown__menu>li.selected>a, .dropdown__menu > li.selected > a,
.dropdown__menu>li>a:hover { .dropdown__menu > li > a:hover {
background: var(--color-sidebar); background: var(--color-sidebar);
color: white; color: white;
} }
.dropdown__menu>li:not(:last-child) { .dropdown__menu > li:not(:last-child) {
border-bottom: 1px solid rgba(0, 0, 0, 0.05); border-bottom: 1px solid rgba(0, 0, 0, 0.05);
} }
.open>.dropdown__menu, .open > .dropdown__menu,
.dropdown__menu.is-open { .dropdown__menu.is-open {
opacity: 1; opacity: 1;
visibility: visible; visibility: visible;
@@ -1440,7 +1447,8 @@ body:not(.is-app) .show-when-app {
width: 80px; width: 80px;
height: 80px; height: 80px;
border-radius: 50%; border-radius: 50%;
background: white url('data:image/svg+xml;charset=UTF-8,<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="width:32px;height:32px" viewBox="0 0 24 24"><path fill="limegreen" d="M12,2A10,10 0 0,1 22,12A10,10 0 0,1 12,22A10,10 0 0,1 2,12A10,10 0 0,1 12,2M11,16.5L18,9.5L16.59,8.09L11,13.67L7.91,10.59L6.5,12L11,16.5Z" /></svg>'); background: white
url('data:image/svg+xml;charset=UTF-8,<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="width:32px;height:32px" viewBox="0 0 24 24"><path fill="limegreen" d="M12,2A10,10 0 0,1 22,12A10,10 0 0,1 12,22A10,10 0 0,1 2,12A10,10 0 0,1 12,2M11,16.5L18,9.5L16.59,8.09L11,13.67L7.91,10.59L6.5,12L11,16.5Z" /></svg>');
} }
.bookmarklet { .bookmarklet {

View File

@@ -7597,6 +7597,10 @@ preact-compat@^3.14.3, preact-compat@^3.17.0:
prop-types "^15.5.8" prop-types "^15.5.8"
standalone-react-addons-pure-render-mixin "^0.1.1" standalone-react-addons-pure-render-mixin "^0.1.1"
preact-portal@^1.1.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/preact-portal/-/preact-portal-1.1.3.tgz#22cdd3ecf6ad9aaa3f830607a9c6591de90aedb7"
preact-render-spy@^1.2.1: preact-render-spy@^1.2.1:
version "1.3.0" version "1.3.0"
resolved "https://registry.yarnpkg.com/preact-render-spy/-/preact-render-spy-1.3.0.tgz#f64b83f4de33d9696e69e5b08c4ae5e29decd6d1" resolved "https://registry.yarnpkg.com/preact-render-spy/-/preact-render-spy-1.3.0.tgz#f64b83f4de33d9696e69e5b08c4ae5e29decd6d1"