feat: Added badge component

This commit is contained in:
Ilya Sosidka
2022-09-03 10:23:50 +03:00
parent fd177ef3e6
commit ac84ca2353
10 changed files with 264 additions and 30 deletions

View File

@@ -1,15 +1,114 @@
<script setup> <script setup>
import BadgeExample from './examples/BadgeExample.vue' import BadgeTypesExample from './examples/BadgeTypesExample.vue'
import BadgeSizesExample from './examples/BadgeSizesExample.vue'
import BadgeLinksExample from './examples/BadgeLinksExample.vue'
import BadgeIconsExample from './examples/BadgeIconsExample.vue'
import BadgeOnlyIconsExample from './examples/BadgeOnlyIconsExample.vue'
</script> </script>
# Badge # Badge
#### Use Tailwind CSS badges as elements to show counts or labels separately or inside other components
---
:::tip
Original reference: [https://flowbite.com/docs/components/badge/](https://flowbite.com/docs/components/badge/)
:::
The badge component can be used to complement other elements such as buttons or text elements as a label or to show the count of a given data, such as the number of comments for an article or how much time has passed by since a comment has been made.
Alternatively, badges can also be used as standalone elements that link to a certain page by using the anchor tag instead of a span element.
## Default badge
Prop type
<BadgeTypesExample />
```vue ```vue
<script setup> <script setup>
import { Badge } from 'flowbite-vue' import { Badge } from 'flowbite-vue'
</script> </script>
<template> <template>
<Badge></Badge> <Badge />
<Badge type="dark" />
<Badge type="red" />
<Badge type="green" />
<Badge type="yellow" />
<Badge type="indigo" />
<Badge type="purple" />
<Badge type="pink" />
</template> </template>
``` ```
<BadgeExample /> ## Large badges
Prop size
<BadgeSizesExample />
```vue
<script setup>
import { Badge } from 'flowbite-vue'
</script>
<template>
<Badge />
<Badge type="dark" />
<Badge type="red" />
<Badge type="green" />
<Badge type="yellow" />
<Badge type="indigo" />
<Badge type="purple" />
<Badge type="pink" />
</template>
```
## Badges as links
You can also use badges as anchor elements to link to another page.
Prop href
```vue
<script setup>
import { Badge } from 'flowbite-vue'
</script>
<template>
<Badge href="#">Link</Badge>
</template>
```
<BadgeLinksExample />
## Badges with icon
You can also use SVG icons inside the badge elements.
slot icon
```vue
<script setup>
import { Badge } from 'flowbite-vue'
</script>
<template>
<Badge>
<template #icon>
<svg aria-hidden="true" class="mr-1 w-3 h-3" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm1-12a1 1 0 10-2 0v4a1 1 0 00.293.707l2.828 2.829a1 1 0 101.415-1.415L11 9.586V6z" clip-rule="evenodd"></path></svg>
</template>
Default
</Badge>
</template>
```
<BadgeIconsExample />
## Badge with icon only
```vue
<script setup>
import { Badge } from 'flowbite-vue'
</script>
<template>
<Badge>
<template #icon>
<svg aria-hidden="true" class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm1-12a1 1 0 10-2 0v4a1 1 0 00.293.707l2.828 2.829a1 1 0 101.415-1.415L11 9.586V6z" clip-rule="evenodd"></path></svg>
</template>
</Badge>
</template>
```
<BadgeOnlyIconsExample />

View File

@@ -1,8 +0,0 @@
<template>
<div class="vp-raw flex flex-col">
<Badge></Badge>
</div>
</template>
<script setup>
import { Badge } from '../../../../src/index'
</script>

View File

@@ -0,0 +1,19 @@
<template>
<div class="vp-raw flex items-end">
<Badge>
<template #icon>
<svg aria-hidden="true" class="mr-1 w-3 h-3" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm1-12a1 1 0 10-2 0v4a1 1 0 00.293.707l2.828 2.829a1 1 0 101.415-1.415L11 9.586V6z" clip-rule="evenodd"></path></svg>
</template>
Default
</Badge>
<Badge type="dark" size="sm">
<template #icon>
<svg aria-hidden="true" class="mr-1 w-3 h-3" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm1-12a1 1 0 10-2 0v4a1 1 0 00.293.707l2.828 2.829a1 1 0 101.415-1.415L11 9.586V6z" clip-rule="evenodd"></path></svg>
</template>
Dark
</Badge>
</div>
</template>
<script setup>
import Badge from '@/components/Badge/Badge.vue'
</script>

View File

@@ -0,0 +1,9 @@
<template>
<div class="vp-raw flex items-end">
<Badge href="#">Link</Badge>
<Badge size="sm" href="#">Link</Badge>
</div>
</template>
<script setup>
import { Badge } from '../../../../src/index'
</script>

View File

@@ -0,0 +1,22 @@
<template>
<div class="vp-raw flex items-end">
<Badge>
<template #icon>
<svg aria-hidden="true" class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm1-12a1 1 0 10-2 0v4a1 1 0 00.293.707l2.828 2.829a1 1 0 101.415-1.415L11 9.586V6z" clip-rule="evenodd"></path></svg>
</template>
</Badge>
<Badge type="dark">
<template #icon>
<svg aria-hidden="true" class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm1-12a1 1 0 10-2 0v4a1 1 0 00.293.707l2.828 2.829a1 1 0 101.415-1.415L11 9.586V6z" clip-rule="evenodd"></path></svg>
</template>
</Badge>
<Badge type="green" size="sm">
<template #icon>
<svg aria-hidden="true" class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm1-12a1 1 0 10-2 0v4a1 1 0 00.293.707l2.828 2.829a1 1 0 101.415-1.415L11 9.586V6z" clip-rule="evenodd"></path></svg>
</template>
</Badge>
</div>
</template>
<script setup>
import Badge from '@/components/Badge/Badge.vue'
</script>

View File

@@ -0,0 +1,15 @@
<template>
<div class="vp-raw flex">
<Badge size="sm">Default</Badge>
<Badge type="dark" size="sm">Dark</Badge>
<Badge type="red" size="sm">Red</Badge>
<Badge type="green" size="sm">Green</Badge>
<Badge type="yellow" size="sm">Yellow</Badge>
<Badge type="indigo" size="sm">Indigo</Badge>
<Badge type="purple" size="sm">Purple</Badge>
<Badge type="pink" size="sm">Pink</Badge>
</div>
</template>
<script setup>
import { Badge } from '../../../../src/index'
</script>

View File

@@ -0,0 +1,15 @@
<template>
<div class="vp-raw flex">
<Badge>Default</Badge>
<Badge type="dark">Dark</Badge>
<Badge type="red">Red</Badge>
<Badge type="green">Green</Badge>
<Badge type="yellow">Yellow</Badge>
<Badge type="indigo">Indigo</Badge>
<Badge type="purple">Purple</Badge>
<Badge type="pink">Pink</Badge>
</div>
</template>
<script setup>
import { Badge } from '../../../../src/index'
</script>

View File

@@ -1,33 +1,33 @@
<template> <template>
<span class="bg-blue-100 text-blue-800 text-xs font-semibold mr-2 px-2.5 py-0.5 rounded dark:bg-blue-200 dark:text-blue-800">Default</span> <component :is="wrapperType" :class="badgeClasses" :href="href">
<slot name="icon"/>
<slot name="default" />
</component>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { computed, toRefs } from 'vue' import { computed, toRefs, useSlots } from 'vue'
import type { PropType } from 'vue' import type { PropType } from 'vue'
import type { BadgeType, BadgeSize } from './types'
import { useBadgeClasses } from '@/components/Badge/composables/useBadgeClasses'
const props = defineProps({ const props = defineProps({
children: { type: {
type: Array, type: String as PropType<BadgeType>,
default() { default: 'default',
return []
},
}, },
color: { size: {
type: String, // 'failure' | 'gray' | 'indigo' | 'info' | 'pink' | 'purple' | 'success' type: String as PropType<BadgeSize>,
default: 'info', default: 'xs',
}, },
href: { href: {
type: String, type: String,
default: '', default: null,
},
icon: {
type: String,
default: '',
},
size: {
type: String, // 'xs' | 'sm'
default: 'xs',
}, },
}) })
const slots = useSlots()
const isContentEmpty = computed(() => !slots.default)
const wrapperType = computed(() => props.href ? 'a' : 'span')
const { badgeClasses } = useBadgeClasses(toRefs(props), { isContentEmpty })
</script> </script>

View File

@@ -0,0 +1,61 @@
import type { BadgeType, BadgeSize } from '../types'
import { computed } from 'vue'
import type { Ref } from 'vue'
import classNames from 'classnames'
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 onlyIconClasses = 'p-1 rounded-full mr-2'
const badgeTextClasses: Record<BadgeType, string> = {
default: 'text-blue-800 dark:text-blue-800',
dark: 'text-gray-800 dark:bg-gray-700',
red: 'text-red-800 dark:text-red-900',
green: 'text-green-800 dark:text-green-900',
yellow: 'text-yellow-800 dark:text-yellow-900',
indigo: 'text-indigo-800 dark:text-indigo-900',
purple: 'text-purple-800 dark:text-purple-900',
pink: 'text-pink-800 dark:text-pink-900',
}
const badgeTypeClasses: Record<BadgeType, string> = {
default: 'bg-blue-100 dark:bg-blue-200',
dark: 'bg-gray-100 dark:bg-gray-700',
red: 'bg-red-100 dark:bg-red-200',
green: 'bg-green-100 dark:bg-green-200',
yellow: 'bg-yellow-100 dark:bg-yellow-200',
indigo: 'bg-indigo-100 dark:bg-indigo-200',
purple: 'bg-purple-100 dark:bg-purple-200',
pink: 'bg-pink-100 dark:bg-pink-200',
}
const badgeSizeClasses: Record<BadgeSize, string> = {
xs: 'text-xs font-semibold',
sm: 'text-sm font-medium',
}
export type UseBadgeClassesProps = {
type: Ref<BadgeType>
size: Ref<BadgeSize>
href: Ref<string>
}
export type UseBadgeClassesOptions = {
isContentEmpty: Ref<boolean>
}
export function useBadgeClasses(props: UseBadgeClassesProps, options: UseBadgeClassesOptions): {
badgeClasses: Ref<string>
} {
const badgeClasses = computed<string>(() => {
return classNames(
badgeSizeClasses[props.size.value],
props.href.value ? '' : badgeTypeClasses[props.type.value],
props.href.value ? '' : badgeTextClasses[props.type.value],
props.href.value ? badgeLinkClasses : '',
options.isContentEmpty.value ? onlyIconClasses : defaultBadgeClasses,
)
})
return {
badgeClasses,
}
}

View File

@@ -0,0 +1,2 @@
export type BadgeType = 'default' | 'dark' | 'red' | 'green' | 'yellow' | 'indigo' | 'purple' | 'pink'
export type BadgeSize = 'xs' | 'sm'