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:
@@ -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"
|
||||||
},
|
},
|
||||||
|
@@ -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>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@@ -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>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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"
|
||||||
|
@@ -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 {
|
||||||
|
@@ -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"
|
||||||
|
Reference in New Issue
Block a user