Merge pull request #2868 from matrix-org/dbkr/dialog_redesign

Design tweaks to dialogs
pull/21833/head
David Baker 2019-04-08 09:33:34 +01:00 committed by GitHub
commit 3fe6d51fbe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 76 additions and 52 deletions

View File

@ -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

View File

@ -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 {

View File

@ -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";

View File

@ -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;
}

View File

@ -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;
}
}
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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;

View File

@ -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,

View File

@ -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 }

View File

@ -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>
);

View File

@ -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'