Feature: ResizableTextArea in widget and dashboard (#969)

* Create ResizableTextArea component
* Rubocop fixes and spec fixes

Co-authored-by: Sojan <sojan@pepalo.com>
This commit is contained in:
Pranav Raj S
2020-06-18 15:17:45 +05:30
committed by GitHub
parent 04f6460afb
commit 963f173730
11 changed files with 208 additions and 185 deletions

View File

@@ -3,7 +3,7 @@
border-bottom: 0;
margin: $space-normal;
margin-top: 0;
max-height: $space-jumbo * 2;
max-height: $space-mega * 3;
transition: height 2s $ease-in-out-cubic;
.reply-box__top {
@@ -68,13 +68,14 @@
padding: 0 $space-small;
}
>textarea {
> textarea {
@include ghost-input();
@include margin(0);
background: transparent;
// Override min-height : 50px in foundation
//
min-height: 1rem;
max-height: $space-mega * 2.4;
min-height: 4rem;
resize: none;
}
}

View File

@@ -13,13 +13,12 @@
v-on-clickaway="hideEmojiPicker"
:on-click="emojiOnClick"
/>
<textarea
<resizable-text-area
ref="messageInput"
v-model="message"
rows="1"
class="input"
type="text"
:placeholder="$t(messagePlaceHolder())"
:min-height="4"
@focus="onFocus"
@blur="onBlur"
/>
@@ -93,12 +92,14 @@ import FileUpload from 'vue-upload-component';
import EmojiInput from '../emoji/EmojiInput';
import CannedResponse from './CannedResponse';
import ResizableTextArea from 'shared/components/ResizableTextArea';
export default {
components: {
EmojiInput,
CannedResponse,
FileUpload,
ResizableTextArea,
},
mixins: [clickaway],
data() {

View File

@@ -0,0 +1,56 @@
<template>
<textarea
ref="textarea"
:placeholder="placeholder"
:value="value"
@input="onInput"
@focus="onFocus"
@blur="onBlur"
/>
</template>
<script>
export default {
props: {
placeholder: {
type: String,
default: '',
},
value: {
type: String,
default: '',
},
minHeight: {
type: Number,
default: 3.2,
},
},
watch: {
value() {
this.resizeTextarea();
},
},
methods: {
resizeTextarea() {
if (!this.value) {
this.$el.style.height = `${this.minHeight}rem`;
} else {
this.$el.style.height = `${this.$el.scrollHeight}px`;
}
},
onInput(event) {
this.$emit('input', event.target.value);
this.resizeTextarea();
},
onBlur() {
this.$emit('blur');
},
onFocus() {
this.$emit('focus');
},
focus() {
this.$refs.textarea.focus();
},
},
};
</script>

View File

@@ -1,56 +0,0 @@
<template>
<resizable-textarea>
<textarea
class="form-input user-message-input"
:placeholder="placeholder"
:value="value"
@input="$emit('input', $event.target.value)"
@focus="onFocus"
@blur="onBlur"
/>
</resizable-textarea>
</template>
<script>
import ResizableTextarea from 'widget/components/ResizableTextarea.vue';
export default {
components: {
ResizableTextarea,
},
props: {
placeholder: {
type: String,
default: '',
},
value: {
type: String,
default: '',
},
},
methods: {
onBlur() {
this.toggleTyping('off');
},
onFocus() {
this.toggleTyping('on');
},
toggleTyping(typingStatus) {
this.$store.dispatch('conversation/toggleUserTyping', { typingStatus });
},
},
};
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="scss">
@import '~widget/assets/scss/variables.scss';
.user-message-input {
border: 0;
height: $space-large;
min-height: $space-large;
resize: none;
padding-top: $space-small;
}
</style>

View File

@@ -1,8 +1,11 @@
<template>
<div class="chat-message--input">
<chat-input-area
<resizable-text-area
v-model="userInput"
:placeholder="$t('CHAT_PLACEHOLDER')"
class="form-input user-message-input"
@focus="onFocus"
@blur="onBlur"
/>
<div class="button-wrap">
<chat-attachment-button
@@ -34,7 +37,7 @@ import emojione from 'emojione';
import { mixin as clickaway } from 'vue-clickaway';
import ChatSendButton from 'widget/components/ChatSendButton.vue';
import ChatAttachmentButton from 'widget/components/ChatAttachment.vue';
import ChatInputArea from 'widget/components/ChatInputArea.vue';
import ResizableTextArea from 'shared/components/ResizableTextArea';
import EmojiInput from 'dashboard/components/widgets/emoji/EmojiInput';
export default {
@@ -42,8 +45,8 @@ export default {
components: {
ChatAttachmentButton,
ChatSendButton,
ChatInputArea,
EmojiInput,
ResizableTextArea,
},
mixins: [clickaway],
props: {
@@ -109,6 +112,16 @@ export default {
`${this.userInput}${emoji.shortname} `
);
},
onBlur() {
this.toggleTyping('off');
},
onFocus() {
this.toggleTyping('on');
},
toggleTyping(typingStatus) {
this.$store.dispatch('conversation/toggleUserTyping', { typingStatus });
},
},
};
</script>
@@ -140,4 +153,13 @@ export default {
display: flex;
align-items: center;
}
.user-message-input {
border: 0;
height: $space-large;
min-height: $space-large;
max-height: 2.4 * $space-mega;
resize: none;
padding-top: $space-small;
}
</style>

View File

@@ -1,26 +0,0 @@
<script>
export default {
mounted() {
this.$nextTick(() => {
this.$el.setAttribute(
'style',
`height: ${this.$el.scrollHeight}px;overflow-y:hidden;`
);
});
this.$el.addEventListener('input', this.resizeTextarea);
},
beforeDestroy() {
this.$el.removeEventListener('input', this.resizeTextarea);
},
methods: {
resizeTextarea(event) {
event.target.style.height = '3.2rem';
event.target.style.height = `${event.target.scrollHeight}px`;
},
},
render() {
return this.$slots.default[0];
},
};
</script>

View File

@@ -43,6 +43,7 @@ export default {
line-height: 1.5;
padding: $space-slab $space-normal $space-slab $space-normal;
text-align: left;
word-break: break-word;
> a {
color: $color-primary;

View File

@@ -80,7 +80,7 @@ class MailPresenter < SimpleDelegator
{
reply: content[0..(index - 1)].strip,
quoted_text: content[index..-1].strip
quoted_text: content[index..].strip
}
end