95 lines
1.9 KiB
Vue
95 lines
1.9 KiB
Vue
<script setup lang="ts">
|
|
const model = defineModel<string>()
|
|
|
|
defineProps<{
|
|
label: string
|
|
error?: string
|
|
}>()
|
|
</script>
|
|
|
|
<template>
|
|
<div class="input-group" :class="{ 'input-group--error': error }">
|
|
<input
|
|
class="input-field"
|
|
placeholder=" "
|
|
v-model="model"
|
|
/>
|
|
<label class="input-label">{{ label }}</label>
|
|
<div class="input-ink" />
|
|
<p v-if="error" class="input-error">{{ error }}</p>
|
|
</div>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.input-group {
|
|
position: relative;
|
|
margin-bottom: var(--space-lg);
|
|
}
|
|
|
|
.input-field {
|
|
width: 100%;
|
|
padding: 1rem 0 0.5rem;
|
|
font-size: 1.1rem;
|
|
font-family: var(--font-display);
|
|
color: var(--ink-900);
|
|
background: transparent;
|
|
border: none;
|
|
border-bottom: 2px solid var(--paper-300);
|
|
outline: none;
|
|
transition: border-color var(--duration-normal) ease;
|
|
}
|
|
|
|
.input-label {
|
|
position: absolute;
|
|
left: 0;
|
|
top: 1rem;
|
|
font-size: 1.1rem;
|
|
font-family: var(--font-display);
|
|
color: var(--ink-400);
|
|
pointer-events: none;
|
|
transition:
|
|
top var(--duration-normal) var(--ease-out-smooth),
|
|
font-size var(--duration-normal) var(--ease-out-smooth),
|
|
color var(--duration-normal) ease;
|
|
}
|
|
|
|
.input-field:focus + .input-label,
|
|
.input-field:not(:placeholder-shown) + .input-label {
|
|
top: -0.4rem;
|
|
font-size: 0.75rem;
|
|
color: var(--vermilion);
|
|
}
|
|
|
|
/* 墨水扩散效果 */
|
|
.input-ink {
|
|
position: absolute;
|
|
bottom: 0;
|
|
left: 50%;
|
|
width: 100%;
|
|
height: 2px;
|
|
background: var(--vermilion);
|
|
transform: scaleX(0) translateX(-50%);
|
|
transform-origin: center;
|
|
transition: transform var(--duration-normal) var(--ease-out-smooth);
|
|
}
|
|
|
|
.input-field:focus ~ .input-ink {
|
|
transform: scaleX(1) translateX(-50%);
|
|
}
|
|
|
|
/* 错误状态 */
|
|
.input-group--error .input-field {
|
|
border-bottom-color: var(--danger);
|
|
}
|
|
|
|
.input-group--error .input-ink {
|
|
background: var(--danger);
|
|
}
|
|
|
|
.input-error {
|
|
margin-top: var(--space-xs);
|
|
font-size: 0.8rem;
|
|
color: var(--danger);
|
|
}
|
|
</style>
|