[#160] Add auto-resizing textareas
in order to prevent users from having to scroll in secrets Signed-off-by: Knut Ahlers <knut@ahlers.me>
This commit is contained in:
parent
f2a7af30b2
commit
98268f1457
3 changed files with 80 additions and 5 deletions
|
@ -31,11 +31,11 @@
|
|||
>
|
||||
<div class="col-12 mb-3">
|
||||
<label for="createSecretData">{{ $t('label-secret-data') }}</label>
|
||||
<textarea
|
||||
<grow-area
|
||||
id="createSecretData"
|
||||
v-model="secret"
|
||||
class="form-control"
|
||||
rows="5"
|
||||
:rows="2"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
|
@ -117,6 +117,7 @@
|
|||
|
||||
import appCrypto from '../crypto.js'
|
||||
import { bytesToHuman } from '../helpers'
|
||||
import GrowArea from './growarea.vue'
|
||||
import OTSMeta from '../ots-meta'
|
||||
|
||||
const defaultExpiryChoices = [
|
||||
|
@ -147,6 +148,8 @@ const passwordCharset = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRS
|
|||
const passwordLength = 20
|
||||
|
||||
export default {
|
||||
components: { GrowArea },
|
||||
|
||||
computed: {
|
||||
canCreate() {
|
||||
return (this.secret.trim().length > 0 || this.selectedFileMeta.length > 0) && !this.maxFileSizeExceeded && !this.invalidFilesSelected
|
||||
|
|
71
src/components/growarea.vue
Normal file
71
src/components/growarea.vue
Normal file
|
@ -0,0 +1,71 @@
|
|||
<template>
|
||||
<textarea
|
||||
ref="area"
|
||||
v-model="data"
|
||||
style="resize: none;"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
created() {
|
||||
this.data = this.value
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
data: '',
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
changeSize() {
|
||||
const verticalBorderSize = this.getStyle('borderTopWidth') + this.getStyle('borderBottomWidth') || 0
|
||||
const verticalPaddingSize = this.getStyle('paddingTop') + this.getStyle('paddingBottom') || 0
|
||||
|
||||
const smallestHeight = this.getStyle('lineHeight') * this.rows + verticalBorderSize + verticalPaddingSize
|
||||
this.$refs.area.style.height = `${smallestHeight}px`
|
||||
|
||||
const newHeight = this.$refs.area.scrollHeight + verticalBorderSize
|
||||
this.$refs.area.style.height = `${newHeight}px`
|
||||
},
|
||||
|
||||
getStyle(name) {
|
||||
return parseInt(getComputedStyle(this.$refs.area, null)[name])
|
||||
},
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.changeSize()
|
||||
},
|
||||
|
||||
name: 'GrowArea',
|
||||
|
||||
props: {
|
||||
rows: {
|
||||
default: 4,
|
||||
type: Number,
|
||||
},
|
||||
|
||||
value: {
|
||||
default: '',
|
||||
type: String,
|
||||
},
|
||||
},
|
||||
|
||||
watch: {
|
||||
data(to, from) {
|
||||
this.changeSize()
|
||||
if (to !== from) {
|
||||
this.$emit('input', to)
|
||||
}
|
||||
},
|
||||
|
||||
value(to) {
|
||||
if (to !== this.data) {
|
||||
this.data = to
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
|
@ -27,11 +27,11 @@
|
|||
v-if="secret"
|
||||
class="input-group mb-3"
|
||||
>
|
||||
<textarea
|
||||
<grow-area
|
||||
class="form-control"
|
||||
readonly
|
||||
:value="secret"
|
||||
rows="4"
|
||||
:rows="4"
|
||||
/>
|
||||
<div class="d-flex align-items-start p-0">
|
||||
<div
|
||||
|
@ -85,10 +85,11 @@ import appClipboardButton from './clipboard-button.vue'
|
|||
import appCrypto from '../crypto.js'
|
||||
import appQrButton from './qr-button.vue'
|
||||
import { bytesToHuman } from '../helpers'
|
||||
import GrowArea from './growarea.vue'
|
||||
import OTSMeta from '../ots-meta'
|
||||
|
||||
export default {
|
||||
components: { appClipboardButton, appQrButton },
|
||||
components: { GrowArea, appClipboardButton, appQrButton },
|
||||
|
||||
data() {
|
||||
return {
|
||||
|
|
Loading…
Reference in a new issue