Skip to content

Commit

Permalink
#307: MessageEditor is responsive
Browse files Browse the repository at this point in the history
  • Loading branch information
manusa committed Jun 1, 2019
1 parent 9462df9 commit ba3337a
Show file tree
Hide file tree
Showing 2 changed files with 105 additions and 54 deletions.
105 changes: 58 additions & 47 deletions client/src/components/message-editor/message-editor.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -78,53 +78,55 @@ class MessageEditor extends Component {
<input
type="file" multiple="multiple" className={mainCss['message-editor__file-dialog-input']}
ref={this.fileDialogRef} onChange={this.handleOnFileDialogChange} />
<div className={mainCss['message-editor__header']}>
<form ref={this.headerFormRef}>
<HeaderAddress id={'to'} addresses={to} onAddressAdd={this.handleAddAddress}
onAddressRemove={this.handleRemoveAddress}
onAddressMove={this.handleMoveAddress}
getAddresses={this.props.getAddresses} label={t('messageEditor.to')} />
<HeaderAddress id={'cc'} addresses={cc} onAddressAdd={this.handleAddAddress}
onAddressRemove={this.handleRemoveAddress}
onAddressMove={this.handleMoveAddress}
getAddresses={this.props.getAddresses} label={t('messageEditor.cc')} />
<HeaderAddress id={'bcc'} addresses={bcc} onAddressAdd={this.handleAddAddress}
onAddressRemove={this.handleRemoveAddress}
onAddressMove={this.handleMoveAddress}
getAddresses={this.props.getAddresses} label={t('messageEditor.bcc')} />
<div className={mainCss['message-editor__header-subject']}>
<input type={'text'} placeholder={t('messageEditor.subject')}
value={subject} onChange={this.handleOnSubjectChange} />
</div>
</form>
</div>
<div className={mainCss['message-editor__wrapper']} onClick={() => this.editorWrapperClick()}>
<div className={mainCss['message-editor__container']}>
<Editor
ref={this.editorRef}
initialValue={content}
onEditorChange={this.handleEditorChange}
onSelectionChange={this.handleSelectionChange}
// Force initial content (reply messages) to be persisted in IndexedDB with base64/datauri embedded images
onInit={() => this.getEditor().uploadImages().then(() => this.getEditor().fire('Change'))}
onPaste={event => this.editorPaste(event)}
inline={true}
init={EDITOR_CONFIG}
/>
<div className={mainCss['message-editor__attachments']}>
{attachments.map((a, index) =>
<div key={index} className={mainCss['message-editor__attachment']}>
<span className={mainCss['message-editor__file-name']}>{a.fileName}</span>
<span className={mainCss['message-editor__size']}>({prettySize(a.size, 0)})</span>
<Button className={mainCss['message-editor__delete']}
iconClassName={mainCss['message-editor__delete-icon']} icon={'delete'}
onClick={() => this.removeAttachment(a)}/>
</div>
)}
<div className={mainCss['message-editor__mobile-wrapper']} onClick={event => this.editorWrapperClick(event)}>
<div className={mainCss['message-editor__header']}>
<form ref={this.headerFormRef}>
<HeaderAddress id={'to'} addresses={to} onAddressAdd={this.handleAddAddress}
onAddressRemove={this.handleRemoveAddress}
onAddressMove={this.handleMoveAddress}
getAddresses={this.props.getAddresses} label={t('messageEditor.to')} />
<HeaderAddress id={'cc'} addresses={cc} onAddressAdd={this.handleAddAddress}
onAddressRemove={this.handleRemoveAddress}
onAddressMove={this.handleMoveAddress}
getAddresses={this.props.getAddresses} label={t('messageEditor.cc')} />
<HeaderAddress id={'bcc'} addresses={bcc} onAddressAdd={this.handleAddAddress}
onAddressRemove={this.handleRemoveAddress}
onAddressMove={this.handleMoveAddress}
getAddresses={this.props.getAddresses} label={t('messageEditor.bcc')} />
<div className={mainCss['message-editor__header-subject']}>
<input type={'text'} placeholder={t('messageEditor.subject')}
value={subject} onChange={this.handleOnSubjectChange} />
</div>
</form>
</div>
<div className={mainCss['message-editor__wrapper']}>
<div className={mainCss['message-editor__container']}>
<Editor
ref={this.editorRef}
initialValue={content}
onEditorChange={this.handleEditorChange}
onSelectionChange={this.handleSelectionChange}
// Force initial content (reply messages) to be persisted in IndexedDB with base64/datauri embedded images
onInit={() => this.getEditor().uploadImages().then(() => this.getEditor().fire('Change'))}
onPaste={event => this.editorPaste(event)}
inline={true}
init={EDITOR_CONFIG}
/>
<div className={mainCss['message-editor__attachments']}>
{attachments.map((a, index) =>
<div key={index} className={mainCss['message-editor__attachment']}>
<span className={mainCss['message-editor__file-name']}>{a.fileName}</span>
<span className={mainCss['message-editor__size']}>({prettySize(a.size, 0)})</span>
<Button className={mainCss['message-editor__delete']}
iconClassName={mainCss['message-editor__delete-icon']} icon={'delete'}
onClick={() => this.removeAttachment(a)}/>
</div>
)}
</div>
</div>
<MessageEditorButtons
editor={this.getEditor()} editorState={this.state.editorState} parentSetState={this.handleSetState}/>
</div>
<MessageEditorButtons
editor={this.getEditor()} editorState={this.state.editorState} parentSetState={this.handleSetState}/>
</div>
<div className={mainCss['message-editor__action-buttons']}>
<button
Expand Down Expand Up @@ -275,8 +277,17 @@ class MessageEditor extends Component {
return null;
}

editorWrapperClick() {
this.getEditor().focus();
/**
* When clicking on editor's white space, content editor gets focus.
* @param event
*/
editorWrapperClick(event) {
if (event.target === event.currentTarget
|| event.target.classList.contains(mainCss['message-editor__wrapper'])
|| event.target.classList.contains(mainCss['message-editor__container'])
) {
this.getEditor().focus();
}
}

/**
Expand Down
54 changes: 47 additions & 7 deletions client/src/styles/pages/_message-editor.scss
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
@import '../partials/variables';
@import '@material/button/variables';
@import '@material/chips/variables';
@import '@material/chips/mixins';

Expand All @@ -7,18 +8,16 @@ $editor-container-padding: 8px !default;
$editor-background-color: white !default;
$editor-outline-color: $editor-color !default;
$editor-border-color: lighten($editor-outline-color, 50%) !default;
$editor-bottom-spacing: $default-spacing / 2;
$header-field-spacing: $default-spacing / 2 !default;
$header-label-color: lighten($base-color, 25%) !default;
$header-chip-fill-color: white !default;
$header-chip-outline-color: transparentize($editor-outline-color, 0.75) !default;
$header-chip-margin: 2px 6px 2px 0;
$header-chip-height: 25px;

$action-buttons-height: 48px;
.message-editor {
$self: &;
display: flex;
flex-direction: column;
padding: $default-spacing;
background-color: $editor-background-color;

& &__drop-zone {
Expand Down Expand Up @@ -59,7 +58,10 @@ $header-chip-height: 25px;
}

& &__header {

@media screen and (max-width: $material-responsive-breakpoint-tablet-min) {
margin-left: $default-spacing;
margin-right: $default-spacing;
}
input,
input:focus {
border: 0;
Expand Down Expand Up @@ -139,10 +141,17 @@ $header-chip-height: 25px;
flex: 1;
height: 1px;
min-height: 1px;

display: flex;
flex-direction: column;
border: 1px solid $editor-border-color;
@media screen and (max-width: $material-responsive-breakpoint-tablet-min) {
height: initial;
min-height: initial;
margin-left: $default-spacing;
margin-right: $default-spacing;
border: 0;
border-top: 1px solid $editor-border-color;
}

& #{$self}__container {
flex: 1;
Expand Down Expand Up @@ -196,7 +205,14 @@ $header-chip-height: 25px;
margin: auto $editor-container-padding $editor-container-padding $editor-container-padding;
display: flex;
flex-direction: row;

@media screen and (max-width: $material-responsive-breakpoint-tablet-min) {
position: fixed;
margin: 0;
height: $mdc-button-height;
bottom: $editor-bottom-spacing + $action-buttons-height;
left: 16px;
right: 16px;
}
& #{$self}__button {
min-width: auto;
color: $editor-color;
Expand Down Expand Up @@ -224,7 +240,31 @@ $header-chip-height: 25px;
}
}

& &__mobile-wrapper {
position: absolute;
top: $default-spacing;
left: $default-spacing;
bottom: #{$editor-bottom-spacing + $action-buttons-height};
right: $default-spacing;
display: flex;
flex-direction: column;

@media screen and (max-width: $material-responsive-breakpoint-tablet-min) {
display: block;
top: 0;
left: 0;
bottom: #{$editor-bottom-spacing + $mdc-button-height + $action-buttons-height};
right: 0;
overflow-y: auto;
}
}

& &__action-buttons {
position: absolute;
left: $default-spacing;
right: $default-spacing;
bottom: $editor-bottom-spacing;
height: $action-buttons-height;
display: flex;
align-items: center;
justify-content: flex-start;
Expand Down

0 comments on commit ba3337a

Please sign in to comment.