mirror of
https://github.com/Foundry376/Mailspring.git
synced 2025-01-01 13:14:16 +08:00
Clean up modals, add nice animation when modals appear ✨
This commit is contained in:
parent
5eca04bec1
commit
0ea7227f3a
9 changed files with 79 additions and 52 deletions
|
@ -32,8 +32,8 @@ class PreferencesIdentity extends React.Component {
|
|||
component: (
|
||||
<BillingModal source="preferences" />
|
||||
),
|
||||
height: 575,
|
||||
width: 412,
|
||||
width: BillingModal.IntrinsicWidth,
|
||||
height: BillingModal.IntrinsicHeight,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,9 @@ import Actions from '../flux/actions'
|
|||
import IdentityStore from '../flux/stores/identity-store'
|
||||
|
||||
export default class BillingModal extends React.Component {
|
||||
static IntrinsicWidth = 412;
|
||||
static IntrinsicHeight = 535;
|
||||
|
||||
static propTypes = {
|
||||
upgradeUrl: React.PropTypes.string,
|
||||
source: React.PropTypes.string,
|
||||
|
|
|
@ -10,7 +10,7 @@ const TipsBackgroundEl = document.createElement('tutorial-tip-background');
|
|||
|
||||
const TipsContainerEl = document.createElement('div');
|
||||
TipsContainerEl.classList.add('tooltips-container');
|
||||
document.body.appendChild(TipsContainerEl);
|
||||
document.body.insertBefore(TipsContainerEl, document.body.children[0]);
|
||||
|
||||
|
||||
class TipsStoreCls extends NylasStore {
|
||||
|
|
|
@ -28,23 +28,23 @@ export default class FeatureUsedUpModal extends React.Component {
|
|||
componentWillUnmount() {
|
||||
this._mounted = false;
|
||||
}
|
||||
|
||||
onGoToFeatures = () => {
|
||||
shell.openExternal("https://getmerani.com/pro");
|
||||
};
|
||||
|
||||
onUpgrade = (e) => {
|
||||
e.stopPropagation();
|
||||
Actions.openModal({
|
||||
component: (
|
||||
<BillingModal source="feature-limit" upgradeUrl={this.state.upgradeUrl} />
|
||||
),
|
||||
width: BillingModal.IntrinsicWidth,
|
||||
height: BillingModal.IntrinsicHeight,
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const gotoFeatures = () => {
|
||||
shell.openExternal("https://getmerani.com/pro");
|
||||
};
|
||||
|
||||
const upgrade = (e) => {
|
||||
e.stopPropagation();
|
||||
Actions.openModal({
|
||||
component: (
|
||||
<BillingModal source="feature-limit" upgradeUrl={this.state.upgradeUrl} />
|
||||
),
|
||||
height: 575,
|
||||
width: 412,
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={`feature-usage-modal ${this.props.modalClass}`}>
|
||||
<div className="feature-header">
|
||||
|
@ -68,10 +68,12 @@ export default class FeatureUsedUpModal extends React.Component {
|
|||
<li>Unlimited Reminders</li>
|
||||
<li>Unlimited Mail Merge</li>
|
||||
</ul>
|
||||
<p>… plus <a onClick={gotoFeatures}>dozens of other features</a></p>
|
||||
<p>… plus <a onClick={this.onGoToFeatures}>dozens of other features</a></p>
|
||||
</div>
|
||||
|
||||
<button className="btn btn-cta btn-emphasis" onClick={upgrade}>Upgrade</button>
|
||||
<button className="btn btn-cta btn-emphasis" onClick={this.onUpgrade}>
|
||||
Upgrade
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
|
|
@ -19,11 +19,21 @@ class Modal extends React.Component {
|
|||
this.state = {
|
||||
offset: 0,
|
||||
dimensions: {},
|
||||
animateClass: false,
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this._focusImportantElement();
|
||||
this._mounted = true;
|
||||
window.requestAnimationFrame(() => {
|
||||
if (!this._mounted) { return; }
|
||||
this.setState({animateClass: true});
|
||||
});
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this._mounted = false;
|
||||
}
|
||||
|
||||
_focusImportantElement = () => {
|
||||
|
@ -55,17 +65,7 @@ class Modal extends React.Component {
|
|||
boxShadow: "0 10px 20px rgba(0,0,0,0.19), inset 0 0 1px rgba(0,0,0,0.5)",
|
||||
borderRadius: "5px",
|
||||
};
|
||||
const containerStyle = {
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
height: "100%",
|
||||
width: "100%",
|
||||
zIndex: 1000,
|
||||
position: "absolute",
|
||||
backgroundColor: "rgba(255,255,255,0.58)",
|
||||
};
|
||||
return {containerStyle, modalStyle};
|
||||
return {modalStyle};
|
||||
};
|
||||
|
||||
_onKeyDown = (event) => {
|
||||
|
@ -76,17 +76,16 @@ class Modal extends React.Component {
|
|||
|
||||
render() {
|
||||
const {children, height, width} = this.props;
|
||||
const {containerStyle, modalStyle} = this._computeModalStyles(height, width);
|
||||
const {modalStyle} = this._computeModalStyles(height, width);
|
||||
|
||||
return (
|
||||
<div
|
||||
style={containerStyle}
|
||||
className="modal-container"
|
||||
className={`modal-container ${this.state.animateClass && 'animate'}`}
|
||||
onKeyDown={this._onKeyDown}
|
||||
onClick={() => Actions.closeModal()}
|
||||
>
|
||||
<div
|
||||
className="modal nylas-modal-container"
|
||||
className="modal"
|
||||
style={modalStyle}
|
||||
onClick={(event) => event.stopPropagation()}
|
||||
>
|
||||
|
|
|
@ -67,12 +67,7 @@ class FeatureUsageStore extends NylasStore {
|
|||
this._usub();
|
||||
}
|
||||
|
||||
async asyncUseFeature(feature, {lexicon = {}} = {}) {
|
||||
if (this._isUsable(feature)) {
|
||||
this._markFeatureUsed(feature);
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
displayUpgradeModal(feature, {lexicon}) {
|
||||
const {headerText, rechargeText} = this._modalText(feature, lexicon);
|
||||
|
||||
Actions.openModal({
|
||||
|
@ -88,6 +83,15 @@ class FeatureUsageStore extends NylasStore {
|
|||
/>
|
||||
),
|
||||
});
|
||||
}
|
||||
|
||||
async asyncUseFeature(feature, {lexicon = {}} = {}) {
|
||||
if (this._isUsable(feature)) {
|
||||
this._markFeatureUsed(feature);
|
||||
return true;
|
||||
}
|
||||
|
||||
this.displayUpgradeModal(feature, {lexicon});
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
this._waitForModalClose.push({resolve, reject, feature})
|
||||
|
|
|
@ -9,7 +9,7 @@ const CONTAINER_ID = "nylas-modal-container";
|
|||
|
||||
function createContainer(id) {
|
||||
const element = document.createElement(id);
|
||||
document.body.appendChild(element);
|
||||
document.body.insertBefore(element, document.body.children[0]);
|
||||
return element;
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ const CONTAINER_ID = "nylas-popover-container";
|
|||
|
||||
function createContainer(id) {
|
||||
const element = document.createElement(id);
|
||||
document.body.appendChild(element);
|
||||
document.body.insertBefore(element, document.body.children[0]);
|
||||
return element;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,21 +1,40 @@
|
|||
@import "ui-variables";
|
||||
|
||||
.nylas-modal-container {
|
||||
.modal-container {
|
||||
perspective: 1000px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height:100%;
|
||||
width: 100%;
|
||||
z-index: 1000;
|
||||
position: absolute;
|
||||
z-index: 40;
|
||||
|
||||
.modal-close {
|
||||
margin: 6px;
|
||||
}
|
||||
background-color: rgba(255,255,255,0.0);
|
||||
transition: background-color 100ms ease-out;
|
||||
|
||||
.modal {
|
||||
position: absolute;
|
||||
background-color: @background-primary;
|
||||
border-radius: @border-radius-base;
|
||||
box-shadow: 0 10px 20px rgba(0, 0, 0, 0.20), 0 0 1px rgba(0, 0, 0, 0.7);
|
||||
transform-origin: top;
|
||||
z-index: 40;
|
||||
opacity: 0;
|
||||
transform: translateY(10px) rotateX(-7deg);
|
||||
transition: transform 360ms ease-out, opacity 240ms ease-out;
|
||||
|
||||
.modal-close {
|
||||
margin: 6px;
|
||||
}
|
||||
}
|
||||
|
||||
&.animate {
|
||||
background-color: rgba(255,255,255,0.58);
|
||||
.modal {
|
||||
opacity: 1;
|
||||
transform: translateY(0) rotateX(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@media (-webkit-min-device-pixel-ratio: 2) {
|
||||
.modal-close {
|
||||
margin: 12px;
|
||||
|
|
Loading…
Reference in a new issue