diff --git a/docs/content/2.components/badge.md b/docs/content/2.components/badge.md
index 27e2f490..c495b1c7 100644
--- a/docs/content/2.components/badge.md
+++ b/docs/content/2.components/badge.md
@@ -141,6 +141,74 @@ Badge
You can customize the whole [preset](#preset) by using the `ui` prop.
::
+### Icon
+
+Use any icon from [Iconify](https://icones.js.org) by setting the `icon` prop by using this pattern: `i-{collection_name}-{icon_name}`.
+
+Use the `leading` and `trailing` props to set the icon position or the `leading-icon` and `trailing-icon` props to set a different icon for each position.
+
+::component-card
+---
+props:
+ icon: 'i-heroicons-rocket-launch'
+ size: 'sm'
+ color: 'primary'
+ variant: 'solid'
+ label: Badge
+ trailing: false
+options:
+ - name: variant
+ restriction: only
+ values:
+ - solid
+excludedProps:
+ - icon
+ - label
+---
+::
+
+## Slots
+
+### `leading`
+
+Use the `#leading` slot to set the content of the leading icon.
+
+::component-card
+---
+slots:
+ leading:
+baseProps:
+ color: 'gray'
+props:
+ label: Badge
+ color: 'gray'
+excludedProps:
+ - color
+---
+
+#leading
+ :u-avatar{src="https://avatars.githubusercontent.com/u/739984?v=4" size="3xs"}
+::
+
+### `trailing`
+
+Use the `#trailing` slot to set the content of the trailing icon.
+
+::component-card
+---
+slots:
+ trailing:
+props:
+ label: Badge
+ color: 'gray'
+excludedProps:
+ - color
+---
+
+#trailing
+ :u-icon{name="i-heroicons-rocket-launch" class="w-4 h-4"}
+::
+
## Props
:component-props
diff --git a/src/runtime/components/elements/Badge.vue b/src/runtime/components/elements/Badge.vue
index d24ffe22..833175c7 100644
--- a/src/runtime/components/elements/Badge.vue
+++ b/src/runtime/components/elements/Badge.vue
@@ -1,6 +1,18 @@
- {{ label }}
+
+
+
+
+
+
+ {{ label }}
+
+
+
+
+
+
@@ -8,6 +20,7 @@
import { computed, toRef, defineComponent } from 'vue'
import type { PropType } from 'vue'
import { twMerge, twJoin } from 'tailwind-merge'
+import UIcon from '../elements/Icon.vue'
import { useUI } from '../../composables/useUI'
import { mergeConfig } from '../../utils'
import { useInjectButtonGroup } from '../../composables/useButtonGroup'
@@ -19,6 +32,9 @@ import { badge } from '#ui/ui.config'
const config = mergeConfig(appConfig.ui.strategy, appConfig.ui.badge, badge)
export default defineComponent({
+ components: {
+ UIcon
+ },
inheritAttrs: false,
props: {
size: {
@@ -49,6 +65,26 @@ export default defineComponent({
type: [String, Number],
default: null
},
+ icon: {
+ type: String,
+ default: null
+ },
+ leadingIcon: {
+ type: String,
+ default: null
+ },
+ trailingIcon: {
+ type: String,
+ default: null
+ },
+ trailing: {
+ type: Boolean,
+ default: false
+ },
+ leading: {
+ type: Boolean,
+ default: false
+ },
class: {
type: [String, Object, Array] as PropType,
default: () => ''
@@ -63,6 +99,14 @@ export default defineComponent({
const { size, rounded } = useInjectButtonGroup({ ui, props })
+ const isLeading = computed(() => {
+ return (props.icon && props.leading) || (props.icon && !props.trailing) || !props.trailing || props.leadingIcon
+ })
+
+ const isTrailing = computed(() => {
+ return (props.icon && props.trailing) || props.trailing || props.trailingIcon
+ })
+
const badgeClass = computed(() => {
const variant = ui.value.color?.[props.color as string]?.[props.variant as string] || ui.value.variant[props.variant]
@@ -71,13 +115,42 @@ export default defineComponent({
ui.value.font,
rounded.value,
ui.value.size[size.value],
+ ui.value.gap[size.value],
variant?.replaceAll('{color}', props.color)
), props.class)
})
+ const leadingIconName = computed(() => {
+ return props.leadingIcon || props.icon
+ })
+
+ const trailingIconName = computed(() => {
+ return props.trailingIcon || props.icon
+ })
+
+ const leadingIconClass = computed(() => {
+ return twJoin(
+ ui.value.icon.base,
+ ui.value.icon.size[size.value]
+ )
+ })
+
+ const trailingIconClass = computed(() => {
+ return twJoin(
+ ui.value.icon.base,
+ ui.value.icon.size[size.value]
+ )
+ })
+
return {
attrs,
- badgeClass
+ isLeading,
+ isTrailing,
+ badgeClass,
+ leadingIconName,
+ trailingIconName,
+ leadingIconClass,
+ trailingIconClass
}
}
})
diff --git a/src/runtime/ui.config/elements/badge.ts b/src/runtime/ui.config/elements/badge.ts
index c89de515..3769fe4f 100644
--- a/src/runtime/ui.config/elements/badge.ts
+++ b/src/runtime/ui.config/elements/badge.ts
@@ -8,6 +8,12 @@ export default {
md: 'text-sm px-2 py-1',
lg: 'text-sm px-2.5 py-1.5'
},
+ gap: {
+ xs: 'gap-0.5',
+ sm: 'gap-1',
+ md: 'gap-1',
+ lg: 'gap-1.5'
+ },
color: {
white: {
solid: 'ring-1 ring-inset ring-gray-300 dark:ring-gray-700 text-gray-900 dark:text-white bg-white dark:bg-gray-900'
@@ -25,6 +31,15 @@ export default {
soft: 'bg-{color}-50 dark:bg-{color}-400 dark:bg-opacity-10 text-{color}-500 dark:text-{color}-400',
subtle: 'bg-{color}-50 dark:bg-{color}-400 dark:bg-opacity-10 text-{color}-500 dark:text-{color}-400 ring-1 ring-inset ring-{color}-500 dark:ring-{color}-400 ring-opacity-25 dark:ring-opacity-25'
},
+ icon: {
+ base: 'flex-shrink-0',
+ size: {
+ xs: 'h-4 w-4',
+ sm: 'h-4 w-4',
+ md: 'h-5 w-5',
+ lg: 'h-5 w-5'
+ }
+ },
default: {
size: 'sm',
variant: 'solid',