feat(input): Setting validation status and message. (#172)

* feat(input): Setting validation status and message.

* Update src/components/Input/composables/useInputClasses.ts

* Update docs/components/input/examples/InputValidationExample.vue

* Update docs/components/input/examples/InputValidationExample.vue

* Update docs/components/input.md

* Update docs/components/input.md

---------

Co-authored-by: Ilya Artamonov <ilya.sosidka@gmail.com>
This commit is contained in:
Nguyễn Hồng Quân
2023-09-09 00:07:48 +07:00
committed by GitHub
parent df27de24d6
commit 580bf14504
9 changed files with 82 additions and 12 deletions

View File

@@ -18,15 +18,18 @@
<slot name="suffix" />
</div>
</div>
<p v-if="$slots.validationMessage" class="mt-2 text-sm" :class="validationWrapperClasses">
<slot name="validationMessage" />
</p>
<p v-if="$slots.helper" class="mt-2 text-sm text-gray-500 dark:text-gray-400">
<slot name="helper" />
</p>
</div>
</template>
<script lang="ts" setup>
import type { InputSize } from '@/components/Input/types'
import { ValidationStatus, type InputSize } from '@/components/Input/types'
import { useInputClasses } from '@/components/Input/composables/useInputClasses'
import { toRefs } from 'vue'
import { computed, toRefs } from 'vue'
import { useVModel } from '@vueuse/core'
interface InputProps {
@@ -36,6 +39,7 @@ interface InputProps {
size?: InputSize;
required?: boolean;
modelValue: string;
validationStatus?: ValidationStatus;
}
const props = withDefaults(defineProps<InputProps>(), {
@@ -45,9 +49,12 @@ const props = withDefaults(defineProps<InputProps>(), {
size: 'md',
required: false,
modelValue: '',
validationStatus: undefined,
})
const model = useVModel(props, 'modelValue')
const { inputClasses, labelClasses } = useInputClasses(toRefs(props))
const validationWrapperClasses = computed(() => props.validationStatus === ValidationStatus.Success ? 'text-green-600 dark:text-green-500' : (props.validationStatus === ValidationStatus.Error ? 'text-red-600 dark:text-red-500' : ''))
</script>

View File

@@ -1,10 +1,10 @@
import type { Ref } from 'vue'
import { computed } from 'vue'
import type { InputSize } from '@/components/Input/types'
import { ValidationStatus, type InputSize } from '@/components/Input/types'
import { simplifyTailwindClasses } from '@/utils/simplifyTailwindClasses'
// LABEL
const defaultLabelClasses = 'block mb-2 text-sm font-medium text-gray-900 dark:text-gray-300'
const baseLabelClasses = 'block mb-2 text-sm font-medium'
// INPUT
const defaultInputClasses = 'bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500'
@@ -15,9 +15,13 @@ const inputSizeClasses: Record<InputSize, string> = {
sm: 'p-2 text-sm',
}
const successInputClasses = 'bg-green-50 border-green-500 dark:border-green-500 text-green-900 dark:text-green-400 placeholder-green-700 dark:placeholder-green-500 focus:ring-green-500 focus:border-green-500'
const errorInputClasses = 'bg-red-50 border-red-500 text-red-900 placeholder-red-700 focus:ring-red-500 focus:border-red-500 dark:text-red-500 dark:placeholder-red-500 dark:border-red-500'
export type UseInputClassesProps = {
size: Ref<InputSize>
disabled: Ref<boolean>
validationStatus: Ref<ValidationStatus | undefined>
}
export function useInputClasses(props: UseInputClassesProps): {
@@ -25,11 +29,15 @@ export function useInputClasses(props: UseInputClassesProps): {
labelClasses: Ref<string>
} {
const inputClasses = computed(() => {
return simplifyTailwindClasses(defaultInputClasses, inputSizeClasses[props.size.value], props.disabled.value ? disabledInputClasses : '')
const vs = props.validationStatus.value
const classByStatus = vs === ValidationStatus.Success ? successInputClasses : (vs == ValidationStatus.Error ? errorInputClasses : '')
return simplifyTailwindClasses(defaultInputClasses, classByStatus, inputSizeClasses[props.size.value], props.disabled.value ? disabledInputClasses : '')
})
const labelClasses = computed(() => {
return defaultLabelClasses
const vs = props.validationStatus.value
const classByStatus = vs === ValidationStatus.Success ? 'text-green-700 dark:text-green-500' : (vs == ValidationStatus.Error ? 'text-red-700 dark:text-red-500' : 'text-gray-900 dark:text-gray-300')
return baseLabelClasses + ' ' + classByStatus
})
return {

View File

@@ -1 +1,6 @@
export type InputSize = 'sm' | 'md' | 'lg'
export enum ValidationStatus {
Success = 'success',
Error = 'error',
}