keanu-weblite/src/components/InputControl.vue

166 lines
3 KiB
Vue
Raw Normal View History

<template>
<div :class="{ 'input-field': true, errored: modelValue !== null && modelValue.length <= 0 }">
<input
ref="input"
type="text"
:value="modelValue"
@input="$emit('update:modelValue', $event.target.value)"
v-on:blur="onBlur"
/>
<div class="placeholder-container">
<div :class="{ placeholder: true, large: !modelValue || modelValue.length == 0 }">
{{ label }}
</div>
<div class="error-message" v-if="modelValue !== null && modelValue.length <= 0">{{ error }}</div>
</div>
<div class="slot">
<slot></slot>
</div>
</div>
</template>
<script>
export default {
name: "InputControl",
model: {
prop: "modelValue",
event: "update:modelValue",
},
props: {
label: {
type: String,
default: function() {
return "";
},
},
error: {
type: String,
default: function() {
return "";
},
},
disabled: {
type: Boolean,
default: function() {
return false;
},
},
modelValue: {
type: String,
default: function() {
return null;
},
},
},
methods: {
focus() {
this.$refs.input.focus();
},
onBlur() {
if (this.modelValue === null) {
this.$emit("update:modelValue", "");
}
},
},
};
</script>
<style lang="scss">
@import "@/assets/css/chat.scss";
.input-field {
width: 100%;
display: flex;
position: relative;
min-height: 48px;
background: #f5f5f5;
border-radius: 4px;
transition: background-color 0.4s, box-shadow 0.4s;
margin-bottom: 12px;
&.errored {
border: 1px solid #e31b00;
}
&:focus-within {
background: white;
box-shadow: 0px 1px 4px rgba(0, 0, 0, 0.25);
}
.placeholder-container {
position: absolute;
top: 8px;
left: 16px;
right: 16px;
display: flex;
}
.placeholder {
text-align: start;
font-family: "Inter";
font-style: normal;
font-weight: 400;
user-select: none;
pointer-events: none;
font-size: 12px;
line-height: 117%;
letter-spacing: 0.4px;
margin-right: 4px;
}
.error-message {
color: #e31b00;
font-family: "Inter";
font-style: normal;
font-weight: 400;
font-size: 12px;
line-height: 117%;
letter-spacing: 0.4px;
}
&:not(:focus-within) .placeholder.large {
position: absolute;
left: 0px;
right: 0px;
top: 14px;
font-size: 16px;
color: rgba(0, 0, 0, 0.7);
margin-right: 0px;
&:only-child {
top: 8px;
}
}
input {
font-family: "Inter";
font-style: normal;
font-weight: 400;
font-size: 16px;
line-height: 117%;
letter-spacing: 0.4px;
color: #000000;
position: absolute;
top: 20px;
left: 16px;
right: 16px;
bottom: 0;
width: 100%;
&:focus {
top: 20px;
}
&:focus,
&:focus-visible {
border: none;
outline: none;
}
}
.slot {
position: absolute;
right: 16px;
align-self: center;
}
}
</style>