Merge pull request #2868 from matrix-org/dbkr/dialog_redesign
Design tweaks to dialogspull/21833/head
commit
3fe6d51fbe
|
@ -59,7 +59,6 @@ src/languageHandler.js
|
|||
src/linkify-matrix.js
|
||||
src/Markdown.js
|
||||
src/MatrixClientPeg.js
|
||||
src/Modal.js
|
||||
src/notifications/ContentRules.js
|
||||
src/notifications/PushRuleVectorState.js
|
||||
src/notifications/VectorPushRulesDefinitions.js
|
||||
|
|
|
@ -118,7 +118,7 @@ textarea {
|
|||
background-color: transparent;
|
||||
color: $input-darker-fg-color;
|
||||
border-radius: 4px;
|
||||
border: 1px solid #c1c1c1;
|
||||
border: 1px solid $dialog-close-fg-color;
|
||||
// these things should probably not be defined
|
||||
// globally
|
||||
margin: 9px;
|
||||
|
@ -267,14 +267,18 @@ textarea {
|
|||
font-weight: 300;
|
||||
font-size: 15px;
|
||||
position: relative;
|
||||
padding: 40px 58px 36px 58px;
|
||||
width: 60%;
|
||||
padding: 25px 30px 30px 30px;
|
||||
max-width: 704px;
|
||||
box-shadow: 2px 15px 30px 0 $dialog-shadow-color;
|
||||
max-height: 80%;
|
||||
box-shadow: 2px 15px 30px 0 $dialog-shadow-color;
|
||||
border-radius: 4px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.mx_Dialog_fixedWidth {
|
||||
width: 60vw;
|
||||
}
|
||||
|
||||
.mx_Dialog_staticWrapper .mx_Dialog {
|
||||
z-index: 4010;
|
||||
}
|
||||
|
@ -317,13 +321,13 @@ textarea {
|
|||
|
||||
.mx_Dialog_header {
|
||||
position: relative;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.mx_Dialog_title {
|
||||
font-weight: bold;
|
||||
font-size: 22px;
|
||||
line-height: 36px;
|
||||
color: $primary-fg-color;
|
||||
color: $dialog-title-fg-color;
|
||||
}
|
||||
|
||||
.mx_Dialog_header.mx_Dialog_headerWithButton > .mx_Dialog_title {
|
||||
|
@ -338,13 +342,14 @@ textarea {
|
|||
mask: url('$(res)/img/feather-customised/cancel.svg');
|
||||
mask-repeat: no-repeat;
|
||||
mask-position: center;
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
background-color: $primary-fg-color;
|
||||
mask-size: cover;
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
background-color: $dialog-close-fg-color;
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
top: 20px;
|
||||
right: 20px;
|
||||
top: 4px;
|
||||
right: 0px;
|
||||
}
|
||||
|
||||
.mx_Dialog_content {
|
||||
|
@ -355,6 +360,7 @@ textarea {
|
|||
}
|
||||
|
||||
.mx_Dialog_buttons {
|
||||
margin-top: 20px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
|
@ -370,6 +376,10 @@ textarea {
|
|||
background-color: $button-secondary-bg-color;
|
||||
}
|
||||
|
||||
.mx_Dialog button:last-child {
|
||||
margin-right: 0px;
|
||||
}
|
||||
|
||||
.mx_Dialog button:hover, .mx_Dialog input[type="submit"]:hover {
|
||||
@mixin mx_DialogButton_hover;
|
||||
}
|
||||
|
@ -381,6 +391,7 @@ textarea {
|
|||
.mx_Dialog button.mx_Dialog_primary, .mx_Dialog input[type="submit"].mx_Dialog_primary {
|
||||
color: $accent-fg-color;
|
||||
background-color: $accent-color;
|
||||
min-width: 156px;
|
||||
}
|
||||
|
||||
.mx_Dialog button.danger, .mx_Dialog input[type="submit"].danger {
|
||||
|
|
|
@ -47,11 +47,11 @@
|
|||
@import "./views/context_menus/_StatusMessageContextMenu.scss";
|
||||
@import "./views/context_menus/_TagTileContextMenu.scss";
|
||||
@import "./views/context_menus/_TopLeftMenu.scss";
|
||||
@import "./views/dialogs/_AddressPickerDialog.scss";
|
||||
@import "./views/dialogs/_Analytics.scss";
|
||||
@import "./views/dialogs/_BugReportDialog.scss";
|
||||
@import "./views/dialogs/_ChangelogDialog.scss";
|
||||
@import "./views/dialogs/_ChatCreateOrReuseChatDialog.scss";
|
||||
@import "./views/dialogs/_ChatInviteDialog.scss";
|
||||
@import "./views/dialogs/_ConfirmUserActionDialog.scss";
|
||||
@import "./views/dialogs/_CreateGroupDialog.scss";
|
||||
@import "./views/dialogs/_CreateRoomDialog.scss";
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
Copyright 2016 OpenMarket Ltd
|
||||
Copyright 2019 New Vector Ltd
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
@ -15,8 +16,8 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
/* Using a textarea for this element, to circumvent autofill */
|
||||
.mx_ChatInviteDialog_input,
|
||||
.mx_ChatInviteDialog_input:focus
|
||||
.mx_AddressPickerDialog_input,
|
||||
.mx_AddressPickerDialog_input:focus
|
||||
{
|
||||
height: 26px;
|
||||
font-size: 14px;
|
||||
|
@ -34,11 +35,11 @@ limitations under the License.
|
|||
word-wrap: nowrap;
|
||||
}
|
||||
|
||||
.mx_ChatInviteDialog .mx_Dialog_content {
|
||||
.mx_AddressPickerDialog .mx_Dialog_content {
|
||||
min-height: 50px
|
||||
}
|
||||
|
||||
.mx_ChatInviteDialog_inputContainer {
|
||||
.mx_AddressPickerDialog_inputContainer {
|
||||
border-radius: 3px;
|
||||
border: solid 1px $input-border-color;
|
||||
line-height: 36px;
|
||||
|
@ -51,19 +52,19 @@ limitations under the License.
|
|||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.mx_ChatInviteDialog_error {
|
||||
.mx_AddressPickerDialog_error {
|
||||
margin-top: 10px;
|
||||
color: $warning-color;
|
||||
}
|
||||
|
||||
.mx_ChatInviteDialog_cancel {
|
||||
.mx_AddressPickerDialog_cancel {
|
||||
position: absolute;
|
||||
right: 11px;
|
||||
top: 13px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.mx_ChatInviteDialog_cancel object {
|
||||
.mx_AddressPickerDialog_cancel object {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
|
@ -21,7 +21,7 @@ limitations under the License.
|
|||
height: 80%;
|
||||
border-radius: 4px;
|
||||
padding-top: 0;
|
||||
padding-right: 0;
|
||||
padding-right: 30px;
|
||||
padding-left: 0;
|
||||
|
||||
.mx_TabbedView {
|
||||
|
@ -31,7 +31,7 @@ limitations under the License.
|
|||
.mx_TabbedView .mx_SettingsTab {
|
||||
box-sizing: border-box;
|
||||
min-width: 580px;
|
||||
padding-right: 130px;
|
||||
padding-right: 100px;
|
||||
|
||||
// Put some padding on the bottom to avoid the settings tab from
|
||||
// colliding harshly with the dialog when scrolled down.
|
||||
|
@ -43,5 +43,8 @@ limitations under the License.
|
|||
margin-top: 16px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
.mx_Dialog_fixedWidth {
|
||||
width: 90vw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,4 +30,6 @@ limitations under the License.
|
|||
.mx_UploadConfirmDialog_imagePreview {
|
||||
max-height: 300px;
|
||||
max-width: 100%;
|
||||
border-radius: 4px;
|
||||
border: 1px solid $dialog-close-fg-color;
|
||||
}
|
||||
|
|
|
@ -72,7 +72,7 @@ $avatar-bg-color: $bg-color;
|
|||
|
||||
$h3-color: $primary-fg-color;
|
||||
|
||||
$dialog-title-fg-color: #454545;
|
||||
$dialog-title-fg-color: $base-text-color;
|
||||
$dialog-backdrop-color: #000;
|
||||
$dialog-shadow-color: rgba(0, 0, 0, 0.48);
|
||||
$dialog-close-fg-color: #9fa9ba;
|
||||
|
|
|
@ -106,10 +106,10 @@ $avatar-bg-color: #ffffff;
|
|||
|
||||
$h3-color: #3d3b39;
|
||||
|
||||
$dialog-title-fg-color: #2e2f32;
|
||||
$dialog-title-fg-color: #45474a;
|
||||
$dialog-backdrop-color: rgba(46, 48, 51, 0.38);
|
||||
$dialog-shadow-color: rgba(0, 0, 0, 0.48);
|
||||
$dialog-close-fg-color: #9fa9ba;
|
||||
$dialog-close-fg-color: #c1c1c1;
|
||||
|
||||
$dialog-background-bg-color: #e9e9e9;
|
||||
$lightbox-background-bg-color: #000;
|
||||
|
|
30
src/Modal.js
30
src/Modal.js
|
@ -75,10 +75,9 @@ const AsyncWrapper = React.createClass({
|
|||
},
|
||||
|
||||
render: function() {
|
||||
const {loader, ...otherProps} = this.props;
|
||||
if (this.state.component) {
|
||||
const Component = this.state.component;
|
||||
return <Component {...otherProps} />;
|
||||
return <Component {...this.props} />;
|
||||
} else if (this.state.error) {
|
||||
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
|
||||
const DialogButtons = sdk.getComponent('views.elements.DialogButtons');
|
||||
|
@ -158,7 +157,7 @@ class ModalManager {
|
|||
}
|
||||
|
||||
createDialog(Element, ...rest) {
|
||||
return this.createDialogAsync(new Promise(resolve => resolve(Element)), ...rest);
|
||||
return this.createDialogAsync(Promise.resolve(Element), ...rest);
|
||||
}
|
||||
|
||||
createTrackedDialogAsync(analyticsAction, analyticsInfo, ...rest) {
|
||||
|
@ -193,36 +192,35 @@ class ModalManager {
|
|||
* also be removed from the stack. This is not compatible
|
||||
* with being a priority modal. Only one modal can be
|
||||
* static at a time.
|
||||
* @returns {object} Object with 'close' parameter being a function that will close the dialog
|
||||
*/
|
||||
createDialogAsync(prom, props, className, isPriorityModal, isStaticModal) {
|
||||
const self = this;
|
||||
const modal = {};
|
||||
|
||||
// never call this from onFinished() otherwise it will loop
|
||||
//
|
||||
// nb explicit function() rather than arrow function, to get `arguments`
|
||||
const closeDialog = function() {
|
||||
if (props && props.onFinished) props.onFinished.apply(null, arguments);
|
||||
const i = self._modals.indexOf(modal);
|
||||
const closeDialog = (...args) => {
|
||||
if (props && props.onFinished) props.onFinished.apply(null, args);
|
||||
const i = this._modals.indexOf(modal);
|
||||
if (i >= 0) {
|
||||
self._modals.splice(i, 1);
|
||||
this._modals.splice(i, 1);
|
||||
}
|
||||
|
||||
if (self._priorityModal === modal) {
|
||||
self._priorityModal = null;
|
||||
if (this._priorityModal === modal) {
|
||||
this._priorityModal = null;
|
||||
|
||||
// XXX: This is destructive
|
||||
self._modals = [];
|
||||
this._modals = [];
|
||||
}
|
||||
|
||||
if (self._staticModal === modal) {
|
||||
self._staticModal = null;
|
||||
if (this._staticModal === modal) {
|
||||
this._staticModal = null;
|
||||
|
||||
// XXX: This is destructive
|
||||
self._modals = [];
|
||||
this._modals = [];
|
||||
}
|
||||
|
||||
self._reRender();
|
||||
this._reRender();
|
||||
};
|
||||
|
||||
// don't attempt to reuse the same AsyncWrapper for different dialogs,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Copyright 2015, 2016 OpenMarket Ltd
|
||||
Copyright 2017, 2018 New Vector Ltd
|
||||
Copyright 2017, 2018, 2019 New Vector Ltd
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
@ -566,7 +566,7 @@ module.exports = React.createClass({
|
|||
rows="1"
|
||||
id="textinput"
|
||||
ref="textinput"
|
||||
className="mx_ChatInviteDialog_input"
|
||||
className="mx_AddressPickerDialog_input"
|
||||
onChange={this.onQueryChanged}
|
||||
placeholder={this.props.placeholder}
|
||||
defaultValue={this.props.value}
|
||||
|
@ -578,7 +578,7 @@ module.exports = React.createClass({
|
|||
let addressSelector;
|
||||
if (this.state.error) {
|
||||
const validTypeDescriptions = this.props.validAddressTypes.map((t) => _t(addressTypeName[t]));
|
||||
error = <div className="mx_ChatInviteDialog_error">
|
||||
error = <div className="mx_AddressPickerDialog_error">
|
||||
{ _t("You have entered an invalid address.") }
|
||||
<br />
|
||||
{ _t("Try using one of the following valid address types: %(validTypesList)s.", {
|
||||
|
@ -586,9 +586,9 @@ module.exports = React.createClass({
|
|||
}) }
|
||||
</div>;
|
||||
} else if (this.state.searchError) {
|
||||
error = <div className="mx_ChatInviteDialog_error">{ this.state.searchError }</div>;
|
||||
error = <div className="mx_AddressPickerDialog_error">{ this.state.searchError }</div>;
|
||||
} else if (this.state.query.length > 0 && filteredSuggestedList.length === 0 && !this.state.busy) {
|
||||
error = <div className="mx_ChatInviteDialog_error">{ _t("No results") }</div>;
|
||||
error = <div className="mx_AddressPickerDialog_error">{ _t("No results") }</div>;
|
||||
} else {
|
||||
addressSelector = (
|
||||
<AddressSelector ref={(ref) => {this.addressSelector = ref;}}
|
||||
|
@ -601,13 +601,13 @@ module.exports = React.createClass({
|
|||
}
|
||||
|
||||
return (
|
||||
<BaseDialog className="mx_ChatInviteDialog" onKeyDown={this.onKeyDown}
|
||||
<BaseDialog className="mx_AddressPickerDialog" onKeyDown={this.onKeyDown}
|
||||
onFinished={this.props.onFinished} title={this.props.title}>
|
||||
<div className="mx_ChatInviteDialog_label">
|
||||
<div className="mx_AddressPickerDialog_label">
|
||||
<label htmlFor="textinput">{ this.props.description }</label>
|
||||
</div>
|
||||
<div className="mx_Dialog_content">
|
||||
<div className="mx_ChatInviteDialog_inputContainer">{ query }</div>
|
||||
<div className="mx_AddressPickerDialog_inputContainer">{ query }</div>
|
||||
{ error }
|
||||
{ addressSelector }
|
||||
{ this.props.extraNode }
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Copyright 2017 Vector Creations Ltd
|
||||
Copyright 2018 New Vector Ltd
|
||||
Copyright 2018, 2019 New Vector Ltd
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
@ -55,6 +55,11 @@ export default React.createClass({
|
|||
// CSS class to apply to dialog div
|
||||
className: PropTypes.string,
|
||||
|
||||
// if true, dialog container is 60% of the viewport width. Otherwise,
|
||||
// the container will have no fixed size, allowing its contents to
|
||||
// determine its size. Default: true.
|
||||
fixedWidth: PropTypes.bool,
|
||||
|
||||
// Title for the dialog.
|
||||
title: PropTypes.node.isRequired,
|
||||
|
||||
|
@ -72,6 +77,7 @@ export default React.createClass({
|
|||
getDefaultProps: function() {
|
||||
return {
|
||||
hasCancel: true,
|
||||
fixedWidth: true,
|
||||
};
|
||||
},
|
||||
|
||||
|
@ -113,7 +119,10 @@ export default React.createClass({
|
|||
|
||||
return (
|
||||
<FocusTrap onKeyDown={this._onKeyDown}
|
||||
className={this.props.className}
|
||||
className={classNames({
|
||||
[this.props.className]: true,
|
||||
'mx_Dialog_fixedWidth': this.props.fixedWidth,
|
||||
})}
|
||||
role="dialog"
|
||||
aria-labelledby='mx_BaseDialog_title'
|
||||
// This should point to a node describing the dialog.
|
||||
|
@ -131,8 +140,8 @@ export default React.createClass({
|
|||
{ this.props.title }
|
||||
</div>
|
||||
{ this.props.headerButton }
|
||||
{ cancelButton }
|
||||
</div>
|
||||
{ cancelButton }
|
||||
{ this.props.children }
|
||||
</FocusTrap>
|
||||
);
|
||||
|
|
|
@ -87,6 +87,7 @@ export default class UploadConfirmDialog extends React.Component {
|
|||
|
||||
return (
|
||||
<BaseDialog className='mx_UploadConfirmDialog'
|
||||
fixedWidth={false}
|
||||
onFinished={this._onCancelClick}
|
||||
title={title}
|
||||
contentId='mx_Dialog_content'
|
||||
|
|
Loading…
Reference in New Issue