# ZeenTextInput
Компонент текстового input для форм
# Примеры:
Input:
Disabled
Input с ошибкой:
Input с текстом, что все верно:
Input с типом email и кастомными цветами и ошибкой:
Input c иконкой:
Input c типом пароль и иконкой:
# props
Название | Тип | Обязательный | По умолчанию | Описание |
---|---|---|---|---|
value | string | + | то, что указано в data родителя | |
placeholder | string | - | - | |
required | boolean | - | false | если true, то при инпуту добавится атрибут required |
name | string | - | - | |
type | string | - | 'text' | |
error | string | - | '' | если значение truthy, то отобразится переданный текст и сменится цвет лейбла и бордера |
correct | string | - | '' | если значение truthy, то отобразится переданный текст и сменится цвет лейбла и бордера |
color | object | - | {} | объект с кастомными цветами (подробнее см.ниже) |
Благодаря v-bind="$attrs" поддерживаются дополнительные атрибуты.
# Кастомные цвета в объекте color
Обработка цветов осуществляется миксином InputColorMixin
Название | Тип | Обязательный | По умолчанию |
---|---|---|---|
textColor | цвет текста инпута | - | берет значение из темы ($input-text-color) |
backgroundColor | цвет фона инпута | - | берет значение из темы ($input-background-color) |
borderFocusColor | цвет бордера инпута при фокусе | - | берет значение из темы ($input-main-color) |
errorColor | цвет лейбла и бордера при truthy error | - | берет значение из темы ($input-error-color) |
correctColor | цвет лейбла и бордера при truthy correct | - | берет значение из темы ($input-correct-color) |
# Иконки
Компонент имеет именованный слот btn. В него можно подставлять иконки, кнопки и другие элементы. Позиционируется с правой стороны инпута по центру. Если слот пустой, то этот элемент не рендерится, иначе - инпуту добавляется дополнительный класс для увеличения padding-right.
# Source Code - исходный код компонента
<template>
<div
:id="`zeen-text-input-${componentId}`"
:key="componentId"
class="zeen-text-input"
:class="{
'zeen-text-input_error': error,
'zeen-text-input_correct': correct,
}"
>
<label v-if="error || correct" class="zeen-text-input__label" :for="componentId">{{ error || correct }}</label>
<div class="zeen-text-input__wrapper">
<input
class="zeen-text-input__input"
:class="{
'zeen-text-input__input_with-btn': hasBtnSlot,
'zeen-text-input__input_with-two-btn': hasTwoBtnSlot,
'zeen-text-input__input_password': type === 'password',
'zeen-text-input__input_no-radius': noRadius,
}"
:value="value"
:placeholder="placeholder"
:required="required"
:disabled="disabled"
:name="name"
:type="type"
@input="onInput"
@keyup.enter="$emit('handleKeypress')"
v-bind="$attrs"
:id="componentId"
:key="`input-${componentId}`"
/>
<div class="zeen-text-input__btn" v-if="hasBtnSlot">
<slot name="btn"></slot>
<slot name="img"></slot>
</div>
</div>
</div>
</template>
<script>
import componentIdSsr from '../../../mixins/componentIdSsr'
export default {
name: 'ZeenTextInput',
mixins: [componentIdSsr],
props: {
value: {
type: [String, Number],
required: false,
default: null,
},
placeholder: {
type: String,
required: false,
},
required: {
type: Boolean,
required: false,
},
disabled: {
type: Boolean,
required: false,
},
name: {
type: String,
required: false,
},
type: {
type: String,
default: 'text',
},
error: {
type: String,
default: '',
},
correct: {
type: String,
default: '',
},
color: {
type: Object,
default: () => {
return {}
},
},
noRadius: {
type: Boolean,
default: false,
},
},
methods: {
onInput(e) {
this.$emit('input', e.target.value)
},
},
computed: {
hasBtnSlot() {
return !!this.$slots.btn
},
hasTwoBtnSlot() {
return this.$slots.btn && this.$slots?.btn?.length > 1
},
},
}
</script>
<style lang="scss">
:root {
/* Размеры кнопки */
--text-input-label-size: var(--main-input-label-size);
--text-input-label-line-height: 1.4;
/* Цвета кнопки */
--text-input-label-base-color: var(--input-main-placeholder-color);
--text-input-label-error-color: var(--input-error-color);
--text-input-label-correct-color: var(--input-correct-color);
--text-input-border-base-focus-color: var(--input-main-color);
--text-input-color: var(--input-main-value-color);
--text-input-background: var(--input-background-color);
--text-input-border-color: transparent;
--text-input-border-error-color: var(--text-input-label-error-color);
--text-input-border-correct-color: var(--text-input-label-correct-color);
--text-input-placeholder-color: var(--input-main-placeholder-color);
--text-input-placeholder-disable-color: var(--input-placeholder-disable-color);
}
</style>
<style lang="scss" scoped>
.zeen-text-input {
--text-input-label-color: var(--text-input-label-base-color);
--text-input-border-focus-color: var(--text-input-border-base-focus-color);
&_error {
--text-input-label-color: var(--text-input-label-error-color);
--text-input-border-focus-color: var(--text-input-border-error-color);
--text-input-border-color: var(--text-input-border-focus-color);
}
&_correct {
--text-input-label-color: var(--text-input-label-correct-color);
--text-input-border-focus-color: var(--text-input-border-correct-color);
--text-input-border-color: var(--text-input-border-focus-color);
}
&__label {
display: block;
font-size: var(--text-input-label-size);
line-height: var(--text-input-label-line-height);
color: var(--text-input-label-color);
margin: 0 0 var(--main-input-label-offset-bottom) var(--main-input-label-offset-left);
}
&__wrapper {
position: relative;
}
&__input {
width: 100%;
box-sizing: border-box;
border-radius: var(--text-input-border-radius);
border: var(--text-input-border-width) solid var(--text-input-border-color);
padding: var(--text-input-vertical-padding) var(--text-input-horizontal-padding);
font-size: var(--text-input-text-size);
line-height: 1.5;
-webkit-appearance: none;
outline: none;
color: var(--text-input-color);
background: var(--text-input-background);
&::placeholder {
font-size: inherit;
line-height: inherit;
}
&:focus {
border-color: var(--text-input-border-focus-color);
}
&:disabled {
--text-input-border-color: transparent;
&::placeholder {
--text-input-placeholder-color: var(--text-input-placeholder-disable-color);
}
}
&::placeholder {
color: var(--text-input-placeholder-color);
}
&_with-btn {
padding-right: 50px;
}
&_with-two-btn {
padding-right: 100px;
}
&_no-radius {
border-radius: 0;
}
}
&__btn {
position: absolute;
right: 25px;
top: 50%;
transform: translate(0, -50%);
display: flex;
align-items: center;
}
}
</style>