[#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:
Knut Ahlers 2023-12-15 17:13:58 +01:00
parent f2a7af30b2
commit 98268f1457
No known key found for this signature in database
GPG Key ID: D91C3E91E4CAD6F5
3 changed files with 80 additions and 5 deletions

View File

@ -31,11 +31,11 @@
> >
<div class="col-12 mb-3"> <div class="col-12 mb-3">
<label for="createSecretData">{{ $t('label-secret-data') }}</label> <label for="createSecretData">{{ $t('label-secret-data') }}</label>
<textarea <grow-area
id="createSecretData" id="createSecretData"
v-model="secret" v-model="secret"
class="form-control" class="form-control"
rows="5" :rows="2"
/> />
</div> </div>
<div <div
@ -117,6 +117,7 @@
import appCrypto from '../crypto.js' import appCrypto from '../crypto.js'
import { bytesToHuman } from '../helpers' import { bytesToHuman } from '../helpers'
import GrowArea from './growarea.vue'
import OTSMeta from '../ots-meta' import OTSMeta from '../ots-meta'
const defaultExpiryChoices = [ const defaultExpiryChoices = [
@ -147,6 +148,8 @@ const passwordCharset = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRS
const passwordLength = 20 const passwordLength = 20
export default { export default {
components: { GrowArea },
computed: { computed: {
canCreate() { canCreate() {
return (this.secret.trim().length > 0 || this.selectedFileMeta.length > 0) && !this.maxFileSizeExceeded && !this.invalidFilesSelected return (this.secret.trim().length > 0 || this.selectedFileMeta.length > 0) && !this.maxFileSizeExceeded && !this.invalidFilesSelected

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

View File

@ -27,11 +27,11 @@
v-if="secret" v-if="secret"
class="input-group mb-3" class="input-group mb-3"
> >
<textarea <grow-area
class="form-control" class="form-control"
readonly readonly
:value="secret" :value="secret"
rows="4" :rows="4"
/> />
<div class="d-flex align-items-start p-0"> <div class="d-flex align-items-start p-0">
<div <div
@ -85,10 +85,11 @@ import appClipboardButton from './clipboard-button.vue'
import appCrypto from '../crypto.js' import appCrypto from '../crypto.js'
import appQrButton from './qr-button.vue' import appQrButton from './qr-button.vue'
import { bytesToHuman } from '../helpers' import { bytesToHuman } from '../helpers'
import GrowArea from './growarea.vue'
import OTSMeta from '../ots-meta' import OTSMeta from '../ots-meta'
export default { export default {
components: { appClipboardButton, appQrButton }, components: { GrowArea, appClipboardButton, appQrButton },
data() { data() {
return { return {