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,
+ }
}