Textarea.vue
2.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
<script setup>
/**
* Textarea —— 受控多行输入框(v-model)。用于 JSON params、长文本消息等。
*/
defineProps({
/** 受控值。 */
modelValue: { type: String, default: '' },
/** 可见行数。 */
rows: { type: Number, default: 4 },
/** 占位文案。 */
placeholder: { type: String, default: '' },
/** 禁用态。 */
disabled: { type: Boolean, default: false },
/** 非法态:描边转 danger 色,并置 aria-invalid。 */
invalid: { type: Boolean, default: false },
})
const emit = defineEmits(['update:modelValue'])
/**
* 转发输入值。
* @param {Event} e
* @returns {void}
*/
function onInput(e) {
emit('update:modelValue', /** @type {HTMLTextAreaElement} */ (e.target).value)
}
</script>
<template>
<textarea
class="drama-textarea"
:class="{ 'is-invalid': invalid }"
:rows="rows"
:value="modelValue"
:placeholder="placeholder"
:disabled="disabled"
:aria-invalid="invalid ? 'true' : 'false'"
@input="onInput"
/>
</template>
<style scoped>
.drama-textarea {
box-sizing: border-box;
width: 100%;
padding: var(--drama-space-md);
border: 1px solid var(--drama-color-border);
border-radius: var(--drama-radius-sm);
background-color: var(--drama-color-surface);
color: var(--drama-color-text);
font-family: var(--drama-font-family-body);
font-size: var(--drama-font-size-sm);
line-height: 1.5;
resize: vertical;
outline: none;
transition: border-color 0.15s ease, box-shadow 0.15s ease, opacity 0.15s ease;
}
.drama-textarea::placeholder {
color: var(--drama-color-text-muted);
}
.drama-textarea:hover:not(:disabled):not(:focus) {
border-color: var(--drama-color-border-strong);
}
.drama-textarea:focus {
border-color: var(--drama-color-primary);
box-shadow: 0 0 0 2px color-mix(in srgb, var(--drama-color-primary) 18%, transparent);
}
.drama-textarea:disabled {
opacity: 0.55;
cursor: not-allowed;
}
.drama-textarea.is-invalid {
border-color: var(--drama-color-danger);
}
.drama-textarea.is-invalid:focus {
box-shadow: 0 0 0 2px color-mix(in srgb, var(--drama-color-danger) 18%, transparent);
}
</style>