140 lines
3.8 KiB
Vue
140 lines
3.8 KiB
Vue
<template>
|
|
<textarea
|
|
:id="id"
|
|
:value="modelValue"
|
|
:placeholder="placeholder"
|
|
:disabled="disabled"
|
|
:required="required"
|
|
:rows="rows"
|
|
:class="textareaClasses"
|
|
:aria-invalid="error ? 'true' : null"
|
|
@input="onInput"
|
|
></textarea>
|
|
</template>
|
|
|
|
<script lang="ts">
|
|
import { defineComponent, computed, PropType } from 'vue';
|
|
|
|
export default defineComponent({
|
|
name: 'VTextarea',
|
|
props: {
|
|
modelValue: {
|
|
type: String,
|
|
required: true,
|
|
},
|
|
placeholder: {
|
|
type: String,
|
|
default: null,
|
|
},
|
|
disabled: {
|
|
type: Boolean,
|
|
default: false,
|
|
},
|
|
required: {
|
|
type: Boolean,
|
|
default: false,
|
|
},
|
|
rows: {
|
|
type: Number,
|
|
default: 3,
|
|
},
|
|
error: {
|
|
type: Boolean,
|
|
default: false,
|
|
},
|
|
id: {
|
|
type: String,
|
|
default: null,
|
|
},
|
|
},
|
|
emits: ['update:modelValue'],
|
|
setup(props, { emit }) {
|
|
const textareaClasses = computed(() => [
|
|
'form-input', // Re-use .form-input styles from VInput if they are generic enough
|
|
'textarea', // Specific class for textarea if needed for overrides or additions
|
|
{ 'error': props.error },
|
|
]);
|
|
|
|
const onInput = (event: Event) => {
|
|
const target = event.target as HTMLTextAreaElement;
|
|
emit('update:modelValue', target.value);
|
|
};
|
|
|
|
return {
|
|
textareaClasses,
|
|
onInput,
|
|
};
|
|
},
|
|
});
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
// Assuming .form-input is defined globally or imported, providing base styling.
|
|
// If VInput.vue's <style> is not scoped, .form-input might be available.
|
|
// If it is scoped, or you want VTextarea to be independent, redefine or import.
|
|
// For this example, let's assume .form-input styles from VInput might apply if global,
|
|
// or we can duplicate/abstract them.
|
|
|
|
// Minimal re-definition or import of .form-input (if not globally available)
|
|
// If VInput.scss is structured to be importable (e.g. using @use or if not scoped):
|
|
// @import 'VInput.scss'; // (path dependent) - this won't work directly with scoped SFC styles normally
|
|
|
|
// Let's add some basic .form-input like styles here for completeness,
|
|
// assuming they are not inherited or globally available from VInput.vue's styles.
|
|
// Ideally, these would be part of a shared SCSS utility file.
|
|
.form-input {
|
|
display: block;
|
|
width: 100%;
|
|
padding: 0.5em 0.75em;
|
|
font-size: 1rem;
|
|
font-family: inherit;
|
|
line-height: 1.5;
|
|
color: #212529;
|
|
background-color: #fff;
|
|
background-clip: padding-box;
|
|
border: 1px solid #ced4da;
|
|
border-radius: 0.25rem;
|
|
transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
|
|
|
|
&:focus {
|
|
border-color: #80bdff;
|
|
outline: 0;
|
|
box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);
|
|
}
|
|
|
|
&::placeholder {
|
|
color: #6c757d;
|
|
opacity: 1;
|
|
}
|
|
|
|
&[disabled],
|
|
&[readonly] { // readonly is not a prop here, but good for general form-input style
|
|
background-color: #e9ecef;
|
|
opacity: 1;
|
|
cursor: not-allowed;
|
|
}
|
|
|
|
&.error {
|
|
border-color: #dc3545;
|
|
&:focus {
|
|
border-color: #dc3545;
|
|
box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.25);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Textarea specific styles
|
|
.textarea {
|
|
// Override line-height if needed, or ensure it works well with multi-line text.
|
|
// line-height: 1.5; // Usually inherited correctly from .form-input
|
|
// May add min-height or resize behavior if desired:
|
|
// resize: vertical; // Allow vertical resize, disable horizontal
|
|
min-height: calc(1.5em * var(--v-textarea-rows, 3) + 1em + 2px); // Approx based on rows, padding, border
|
|
}
|
|
|
|
// CSS variable for rows to potentially influence height if needed by .textarea class
|
|
// This is an alternative way to use props.rows in CSS if you need more complex calculations.
|
|
// For direct attribute binding like :rows="rows", this is not strictly necessary.
|
|
// :style="{ '--v-textarea-rows': rows }" could be bound to the textarea element.
|
|
</style>
|