From 974a7249bdf90ae593a77a7fb226a829ab72a19c Mon Sep 17 00:00:00 2001 From: Ilya Artamonov Date: Fri, 8 Sep 2023 20:19:12 +0300 Subject: [PATCH] feat: Replaced class merge with tailwind-merge in Input component --- package-lock.json | 15 +++++ package.json | 1 + src/components/Input/Input.vue | 57 +++++++++++++------ .../Input/composables/useInputClasses.ts | 53 ++++++++--------- 4 files changed, 82 insertions(+), 44 deletions(-) diff --git a/package-lock.json b/package-lock.json index b099f20..8a0ca0c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,6 +15,7 @@ "flowbite": "1.5.4", "lodash-es": "4.17.21", "nanoid": "4.0.0", + "tailwind-merge": "^1.14.0", "tailwindcss": "^3" }, "devDependencies": { @@ -4450,6 +4451,15 @@ "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", "dev": true }, + "node_modules/tailwind-merge": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-1.14.0.tgz", + "integrity": "sha512-3mFKyCo/MBcgyOTlrY8T7odzZFx+w+qKSMAmdFzRvqBfLlSigU6TZnlFHK0lkMwj9Bj8OYU+9yW9lmGuS0QEnQ==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/dcastil" + } + }, "node_modules/tailwindcss": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.2.4.tgz", @@ -8612,6 +8622,11 @@ "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", "dev": true }, + "tailwind-merge": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-1.14.0.tgz", + "integrity": "sha512-3mFKyCo/MBcgyOTlrY8T7odzZFx+w+qKSMAmdFzRvqBfLlSigU6TZnlFHK0lkMwj9Bj8OYU+9yW9lmGuS0QEnQ==" + }, "tailwindcss": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.2.4.tgz", diff --git a/package.json b/package.json index 0f772ae..fdc4c45 100644 --- a/package.json +++ b/package.json @@ -72,6 +72,7 @@ "flowbite": "1.5.4", "lodash-es": "4.17.21", "nanoid": "4.0.0", + "tailwind-merge": "^1.14.0", "tailwindcss": "^3" }, "engines": { diff --git a/src/components/Input/Input.vue b/src/components/Input/Input.vue index 7e2b88b..77e07ce 100644 --- a/src/components/Input/Input.vue +++ b/src/components/Input/Input.vue @@ -5,20 +5,12 @@
- +
-

+

@@ -31,15 +23,38 @@ import { ValidationStatus, type InputSize } from '@/components/Input/types' import { useInputClasses } from '@/components/Input/composables/useInputClasses' import { computed, toRefs } from 'vue' import { useVModel } from '@vueuse/core' +import { twMerge } from 'tailwind-merge' interface InputProps { - label?: string; - disabled?: boolean; - type?: 'button' | 'checkbox' | 'color' | 'date' | 'datetime-local' | 'email' | 'file' | 'hidden' | 'image' | 'month' | 'number' | 'password' | 'radio' | 'range' | 'reset' | 'search' | 'submit' | 'tel' | 'text' | 'time' | 'url' | 'week'; - size?: InputSize; - required?: boolean; - modelValue: string; - validationStatus?: ValidationStatus; + label?: string + disabled?: boolean + type?: + | 'button' + | 'checkbox' + | 'color' + | 'date' + | 'datetime-local' + | 'email' + | 'file' + | 'hidden' + | 'image' + | 'month' + | 'number' + | 'password' + | 'radio' + | 'range' + | 'reset' + | 'search' + | 'submit' + | 'tel' + | 'text' + | 'time' + | 'url' + | 'week' + size?: InputSize + required?: boolean + modelValue: string + validationStatus?: ValidationStatus } const props = withDefaults(defineProps(), { @@ -56,5 +71,11 @@ 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' : '')) +const validationWrapperClasses = computed(() => { + return twMerge( + 'mt-2 text-sm', + props.validationStatus === ValidationStatus.Success ? 'text-green-600 dark:text-green-500' : '', + props.validationStatus === ValidationStatus.Error ? 'text-red-600 dark:text-red-500' : '', + ) +}) diff --git a/src/components/Input/composables/useInputClasses.ts b/src/components/Input/composables/useInputClasses.ts index fcee23e..5f8ef9b 100644 --- a/src/components/Input/composables/useInputClasses.ts +++ b/src/components/Input/composables/useInputClasses.ts @@ -1,47 +1,48 @@ import type { Ref } from 'vue' import { computed } from 'vue' import { ValidationStatus, type InputSize } from '@/components/Input/types' -import { simplifyTailwindClasses } from '@/utils/simplifyTailwindClasses' - +import { twMerge } from 'tailwind-merge' // LABEL 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' +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' const disabledInputClasses = 'cursor-not-allowed bg-gray-100' const inputSizeClasses: Record = { - lg: 'p-4', - md: 'p-2.5 text-sm', - sm: 'p-2 text-sm', + lg: 'p-4', + md: 'p-2.5 text-sm', + 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 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 - disabled: Ref - validationStatus: Ref + size: Ref + disabled: Ref + validationStatus: Ref } export function useInputClasses(props: UseInputClassesProps): { - inputClasses: Ref - labelClasses: Ref + inputClasses: Ref + labelClasses: Ref } { - const inputClasses = computed(() => { - 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 inputClasses = computed(() => { + const vs = props.validationStatus.value + const classByStatus = vs === ValidationStatus.Success ? successInputClasses : vs == ValidationStatus.Error ? errorInputClasses : '' + return twMerge(defaultInputClasses, classByStatus, inputSizeClasses[props.size.value], props.disabled.value ? disabledInputClasses : '') + }) - const labelClasses = computed(() => { - 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 - }) + const labelClasses = computed(() => { + 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 twMerge(baseLabelClasses, classByStatus) + }) - return { - inputClasses, - labelClasses, - } + return { + inputClasses, + labelClasses, + } }