Merge branch 'main' into breadcrumb-component
# Conflicts: # docs/.vitepress/config.ts
This commit is contained in:
@@ -38,6 +38,7 @@ function getComponents() {
|
||||
{ text: 'Avatar', link: 'components/avatar/avatar.md' },
|
||||
{ text: 'Breadcrumb', link: 'components/breadcrumb/breadcrumb.md' },
|
||||
{ text: 'Button', link: '/components/button/button.md' },
|
||||
{ text: 'Badge', link: 'components/badge/badge.md' },
|
||||
{ text: 'Button Group', link: '/components/buttonGroup/buttonGroup.md' },
|
||||
{ text: 'Dropdown', link: '/components/dropdown/dropdown.md' },
|
||||
{ text: 'Spinner', link: '/components/spinner/spinner.md' },
|
||||
@@ -46,7 +47,7 @@ function getComponents() {
|
||||
{ text: 'Toast', link: 'components/toast/toast.md' },
|
||||
|
||||
{ text: '- Accordion', link: 'components/accordion/accordion.md' },
|
||||
{ text: '- Badge', link: 'components/badge/badge.md' },
|
||||
{ text: '- Breadcrumb', link: 'components/breadcrumb/breadcrumb.md' },
|
||||
{ text: '- Card', link: 'components/card/card.md' },
|
||||
{ text: '- Carousel', link: 'components/carousel/carousel.md' },
|
||||
{ text: '- Footer', link: 'components/footer/footer.md' },
|
||||
|
||||
@@ -1,15 +1,114 @@
|
||||
<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>
|
||||
# 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
|
||||
<script setup>
|
||||
import { Badge } from 'flowbite-vue'
|
||||
</script>
|
||||
<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>
|
||||
```
|
||||
|
||||
<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 />
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
<template>
|
||||
<div class="vp-raw flex flex-col">
|
||||
<Badge></Badge>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { Badge } from '../../../../src/index'
|
||||
</script>
|
||||
19
docs/components/badge/examples/BadgeIconsExample.vue
Normal file
19
docs/components/badge/examples/BadgeIconsExample.vue
Normal 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>
|
||||
9
docs/components/badge/examples/BadgeLinksExample.vue
Normal file
9
docs/components/badge/examples/BadgeLinksExample.vue
Normal 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>
|
||||
22
docs/components/badge/examples/BadgeOnlyIconsExample.vue
Normal file
22
docs/components/badge/examples/BadgeOnlyIconsExample.vue
Normal 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>
|
||||
15
docs/components/badge/examples/BadgeSizesExample.vue
Normal file
15
docs/components/badge/examples/BadgeSizesExample.vue
Normal 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>
|
||||
15
docs/components/badge/examples/BadgeTypesExample.vue
Normal file
15
docs/components/badge/examples/BadgeTypesExample.vue
Normal 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>
|
||||
@@ -1,33 +1,33 @@
|
||||
<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>
|
||||
<script lang="ts" setup>
|
||||
import { computed, toRefs } from 'vue'
|
||||
import { computed, toRefs, useSlots } from 'vue'
|
||||
import type { PropType } from 'vue'
|
||||
import type { BadgeType, BadgeSize } from './types'
|
||||
import { useBadgeClasses } from '@/components/Badge/composables/useBadgeClasses'
|
||||
|
||||
const props = defineProps({
|
||||
children: {
|
||||
type: Array,
|
||||
default() {
|
||||
return []
|
||||
},
|
||||
type: {
|
||||
type: String as PropType<BadgeType>,
|
||||
default: 'default',
|
||||
},
|
||||
color: {
|
||||
type: String, // 'failure' | 'gray' | 'indigo' | 'info' | 'pink' | 'purple' | 'success'
|
||||
default: 'info',
|
||||
size: {
|
||||
type: String as PropType<BadgeSize>,
|
||||
default: 'xs',
|
||||
},
|
||||
href: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
icon: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
size: {
|
||||
type: String, // 'xs' | 'sm'
|
||||
default: 'xs',
|
||||
default: null,
|
||||
},
|
||||
})
|
||||
|
||||
const slots = useSlots()
|
||||
const isContentEmpty = computed(() => !slots.default)
|
||||
const wrapperType = computed(() => props.href ? 'a' : 'span')
|
||||
|
||||
const { badgeClasses } = useBadgeClasses(toRefs(props), { isContentEmpty })
|
||||
</script>
|
||||
|
||||
61
src/components/Badge/composables/useBadgeClasses.ts
Normal file
61
src/components/Badge/composables/useBadgeClasses.ts
Normal 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,
|
||||
}
|
||||
}
|
||||
2
src/components/Badge/types.ts
Normal file
2
src/components/Badge/types.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export type BadgeType = 'default' | 'dark' | 'red' | 'green' | 'yellow' | 'indigo' | 'purple' | 'pink'
|
||||
export type BadgeSize = 'xs' | 'sm'
|
||||
Reference in New Issue
Block a user