refactor: Replaced classNames with tailwind merge in badge component

This commit is contained in:
Ilya Artamonov
2023-09-25 19:38:41 +03:00
parent 15039b5c61
commit f78f29dee4
2 changed files with 56 additions and 57 deletions

View File

@@ -1,33 +1,28 @@
<template> <template>
<component :is="wrapperType" :class="badgeClasses" :href="href"> <component :is="wrapperType" :class="badgeClasses" :href="href">
<slot name="icon"/> <slot name="icon" />
<slot name="default" /> <slot name="default" />
</component> </component>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { computed, toRefs, useSlots } from 'vue' import { computed, useSlots } from 'vue'
import type { PropType } from 'vue'
import type { BadgeType, BadgeSize } from './types' import type { BadgeType, BadgeSize } from './types'
import { useBadgeClasses } from '@/components/Badge/composables/useBadgeClasses' import { useBadgeClasses } from '@/components/Badge/composables/useBadgeClasses'
const props = defineProps({ interface IBadgeProps {
type: { type?: BadgeType
type: String as PropType<BadgeType>, size?: BadgeSize
default: 'default', href?: string | null
}, }
size: { const props = withDefaults(defineProps<IBadgeProps>(), {
type: String as PropType<BadgeSize>, type: 'default',
default: 'xs', size: 'xs',
}, href: null,
href: {
type: String,
default: null,
},
}) })
const slots = useSlots() const slots = useSlots()
const isContentEmpty = computed(() => !slots.default) const isContentEmpty = computed(() => !slots.default)
const wrapperType = computed(() => props.href ? 'a' : 'span') const wrapperType = computed(() => (props.href ? 'a' : 'span'))
const { badgeClasses } = useBadgeClasses(toRefs(props), { isContentEmpty }) const { badgeClasses } = useBadgeClasses(props, { isContentEmpty })
</script> </script>

View File

@@ -1,61 +1,65 @@
import type { BadgeType, BadgeSize } from '../types' import type { BadgeType, BadgeSize } from '../types'
import { computed } from 'vue' import { computed, type Ref, useAttrs } from 'vue'
import type { Ref } from 'vue' import { twMerge } from 'tailwind-merge'
import classNames from 'classnames'
const defaultBadgeClasses = 'mr-2 px-2.5 py-0.5 rounded flex items-center justify-center' const defaultBadgeClasses = 'mr-2 px-2.5 py-0.5 rounded flex items-center justify-center'
const badgeLinkClasses = 'bg-blue-100 hover:bg-blue-200 text-blue-800 dark:text-blue-800 dark:hover:bg-blue-300' const badgeLinkClasses = 'bg-blue-100 hover:bg-blue-200 text-blue-800 dark:text-blue-800 dark:hover:bg-blue-300'
const onlyIconClasses = 'p-1 rounded-full mr-2' const onlyIconClasses = 'p-1 rounded-full mr-2'
const badgeTextClasses: Record<BadgeType, string> = { const badgeTextClasses: Record<BadgeType, string> = {
default: 'text-blue-800 dark:text-blue-800', default: 'text-blue-800 dark:text-blue-800',
dark: 'text-gray-800 dark:bg-gray-700', dark: 'text-gray-800 dark:bg-gray-700',
red: 'text-red-800 dark:text-red-900', red: 'text-red-800 dark:text-red-900',
green: 'text-green-800 dark:text-green-900', green: 'text-green-800 dark:text-green-900',
yellow: 'text-yellow-800 dark:text-yellow-900', yellow: 'text-yellow-800 dark:text-yellow-900',
indigo: 'text-indigo-800 dark:text-indigo-900', indigo: 'text-indigo-800 dark:text-indigo-900',
purple: 'text-purple-800 dark:text-purple-900', purple: 'text-purple-800 dark:text-purple-900',
pink: 'text-pink-800 dark:text-pink-900', pink: 'text-pink-800 dark:text-pink-900',
} }
const badgeTypeClasses: Record<BadgeType, string> = { const badgeTypeClasses: Record<BadgeType, string> = {
default: 'bg-blue-100 dark:bg-blue-200', default: 'bg-blue-100 dark:bg-blue-200',
dark: 'bg-gray-100 dark:bg-gray-700', dark: 'bg-gray-100 dark:bg-gray-700',
red: 'bg-red-100 dark:bg-red-200', red: 'bg-red-100 dark:bg-red-200',
green: 'bg-green-100 dark:bg-green-200', green: 'bg-green-100 dark:bg-green-200',
yellow: 'bg-yellow-100 dark:bg-yellow-200', yellow: 'bg-yellow-100 dark:bg-yellow-200',
indigo: 'bg-indigo-100 dark:bg-indigo-200', indigo: 'bg-indigo-100 dark:bg-indigo-200',
purple: 'bg-purple-100 dark:bg-purple-200', purple: 'bg-purple-100 dark:bg-purple-200',
pink: 'bg-pink-100 dark:bg-pink-200', pink: 'bg-pink-100 dark:bg-pink-200',
} }
const badgeSizeClasses: Record<BadgeSize, string> = { const badgeSizeClasses: Record<BadgeSize, string> = {
xs: 'text-xs font-semibold', xs: 'text-xs font-semibold',
sm: 'text-sm font-medium', sm: 'text-sm font-medium',
} }
export type UseBadgeClassesProps = { export type UseBadgeClassesProps = {
type: Ref<BadgeType> type: BadgeType
size: Ref<BadgeSize> size: BadgeSize
href: Ref<string> href: string | null
} }
export type UseBadgeClassesOptions = { export type UseBadgeClassesOptions = {
isContentEmpty: Ref<boolean> isContentEmpty: Ref<boolean>
} }
export function useBadgeClasses(props: UseBadgeClassesProps, options: UseBadgeClassesOptions): { export function useBadgeClasses(
badgeClasses: Ref<string> props: UseBadgeClassesProps,
options: UseBadgeClassesOptions,
): {
badgeClasses: Ref<string>
} { } {
const badgeClasses = computed<string>(() => { const attrs = useAttrs()
return classNames( const badgeClasses = computed<string>(() => {
badgeSizeClasses[props.size.value], return twMerge(
props.href.value ? '' : badgeTypeClasses[props.type.value], badgeSizeClasses[props.size],
props.href.value ? '' : badgeTextClasses[props.type.value], props.href ? '' : badgeTypeClasses[props.type],
props.href.value ? badgeLinkClasses : '', props.href ? '' : badgeTextClasses[props.type],
options.isContentEmpty.value ? onlyIconClasses : defaultBadgeClasses, props.href ? badgeLinkClasses : '',
) options.isContentEmpty.value ? onlyIconClasses : defaultBadgeClasses,
}) attrs.class as string,
return { )
badgeClasses, })
} return {
badgeClasses,
}
} }