diff --git a/docs/content/3.components/button.md b/docs/content/3.components/button.md
index 3b53e050..5de5abfa 100644
--- a/docs/content/3.components/button.md
+++ b/docs/content/3.components/button.md
@@ -125,6 +125,40 @@ props:
---
::
+### Avatar
+
+Use the `avatar` prop to show an [Avatar](/components/avatar) inside the Button.
+
+::component-code
+---
+prettier: true
+props:
+ avatar:
+ src: 'https://github.com/nuxt.png'
+ size: md
+ color: neutral
+ variant: outline
+slots:
+ default: |
+
+ Button
+---
+::
+
+The `label` as prop or slot is optional so you can use the Button as an avatar-only button.
+
+::component-code
+---
+prettier: true
+props:
+ avatar:
+ src: 'https://github.com/nuxt.png'
+ size: md
+ color: neutral
+ variant: outline
+---
+::
+
### Loading
Use the `loading` prop to show a loading icon and disable the Button.
diff --git a/playground/app/pages/components/button.vue b/playground/app/pages/components/button.vue
index cc591736..3bc25774 100644
--- a/playground/app/pages/components/button.vue
+++ b/playground/app/pages/components/button.vue
@@ -32,10 +32,15 @@ function onClick() {
-
+
Loading
+
+
+ Loading auto
+
+
Loading
@@ -54,12 +59,25 @@ function onClick() {
color="neutral"
/>
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/runtime/components/Button.vue b/src/runtime/components/Button.vue
index 02bb2ff7..9149b2a6 100644
--- a/src/runtime/components/Button.vue
+++ b/src/runtime/components/Button.vue
@@ -5,6 +5,7 @@ import _appConfig from '#build/app.config'
import theme from '#build/ui/button'
import type { LinkProps } from './Link.vue'
import type { UseComponentIconsProps } from '../composables/useComponentIcons'
+import type { AvatarProps } from '../types'
import type { PartialString } from '../types/utils'
import { formLoadingInjectionKey } from '../composables/useFormField'
@@ -99,6 +100,7 @@ const ui = computed(() => button({
>
+
diff --git a/src/runtime/composables/useComponentIcons.ts b/src/runtime/composables/useComponentIcons.ts
index 4322b4c5..7a75ce76 100644
--- a/src/runtime/composables/useComponentIcons.ts
+++ b/src/runtime/composables/useComponentIcons.ts
@@ -1,9 +1,12 @@
import { computed, toValue, type MaybeRefOrGetter } from 'vue'
import { useAppConfig } from '#imports'
+import type { AvatarProps } from '../types'
export interface UseComponentIconsProps {
/** Display an icon based on the `leading` and `trailing` props. */
icon?: string
+ /** Display an avatar on the left side. */
+ avatar?: AvatarProps
/** When `true`, the icon will be displayed on the left side. */
leading?: boolean
/** Display an icon on the left side. */
diff --git a/src/theme/button.ts b/src/theme/button.ts
index 3f1293d8..ec127e0b 100644
--- a/src/theme/button.ts
+++ b/src/theme/button.ts
@@ -7,6 +7,7 @@ export default (options: Required) => ({
label: 'truncate',
leadingIcon: 'shrink-0',
leadingAvatar: 'shrink-0',
+ leadingAvatarSize: '',
trailingIcon: 'shrink-0'
},
variants: {
@@ -27,32 +28,38 @@ export default (options: Required) => ({
xs: {
base: 'px-2 py-1 text-xs gap-1',
leadingIcon: 'size-4',
+ leadingAvatarSize: '3xs',
trailingIcon: 'size-4'
},
sm: {
base: 'px-2.5 py-1.5 text-xs gap-1.5',
leadingIcon: 'size-4',
+ leadingAvatarSize: '3xs',
trailingIcon: 'size-4'
},
md: {
base: 'px-2.5 py-1.5 text-sm gap-1.5',
leadingIcon: 'size-5',
+ leadingAvatarSize: '2xs',
trailingIcon: 'size-5'
},
lg: {
base: 'px-3 py-2 text-sm gap-2',
leadingIcon: 'size-5',
+ leadingAvatarSize: '2xs',
trailingIcon: 'size-5'
},
xl: {
base: 'px-3 py-2 text-base gap-2',
leadingIcon: 'size-6',
+ leadingAvatarSize: 'xs',
trailingIcon: 'size-6'
}
},
block: {
true: {
base: 'w-full justify-center',
+ leadingAvatarSize: 'xs',
trailingIcon: 'ms-auto'
}
},
diff --git a/test/components/Button.spec.ts b/test/components/Button.spec.ts
index dbfe7e50..4bdda5d6 100644
--- a/test/components/Button.spec.ts
+++ b/test/components/Button.spec.ts
@@ -25,7 +25,13 @@ describe('Button', () => {
['with leadingIcon', { props: { leadingIcon: 'i-heroicons-arrow-left' } }],
['with trailing and icon', { props: { trailing: true, icon: 'i-heroicons-arrow-right' } }],
['with trailingIcon', { props: { trailingIcon: 'i-heroicons-arrow-right' } }],
+ ['with avatar', { props: { avatar: { src: 'https://github.com/benjamincanac.png' } } }],
+ ['with avatar and leadingIcon', { props: { avatar: { src: 'https://github.com/benjamincanac.png' }, leadingIcon: 'i-heroicons-arrow-left' } }],
+ ['with avatar and trailingIcon', { props: { avatar: { src: 'https://github.com/benjamincanac.png' }, trailingIcon: 'i-heroicons-arrow-right' } }],
['with loading', { props: { loading: true } }],
+ ['with loading and avatar', { props: { loading: true, avatar: { src: 'https://github.com/benjamincanac.png' } } }],
+ ['with loading trailing', { props: { loading: true, trailing: true } }],
+ ['with loading trailing and avatar', { props: { loading: true, trailing: true, avatar: { src: 'https://github.com/benjamincanac.png' } } }],
['with loadingIcon', { props: { loading: true, loadingIcon: 'i-heroicons-sparkles' } }],
['with disabled', { props: { label: 'Button', disabled: true } }],
['with disabled and with link', { props: { label: 'Button', disabled: true, to: '/link' } }],
diff --git a/test/components/__snapshots__/Button.spec.ts.snap b/test/components/__snapshots__/Button.spec.ts.snap
index 9bea54a2..afb8c76f 100644
--- a/test/components/__snapshots__/Button.spec.ts.snap
+++ b/test/components/__snapshots__/Button.spec.ts.snap
@@ -1,5 +1,25 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
+exports[`Button > renders with avatar and leadingIcon correctly 1`] = `
+""
+`;
+
+exports[`Button > renders with avatar and trailingIcon correctly 1`] = `
+""
+`;
+
+exports[`Button > renders with avatar correctly 1`] = `
+""
+`;
+
exports[`Button > renders with block correctly 1`] = `
""
`;
+exports[`Button > renders with loading and avatar correctly 1`] = `
+""
+`;
+
exports[`Button > renders with loading correctly 1`] = `
""
`;
+exports[`Button > renders with loading trailing and avatar correctly 1`] = `
+""
+`;
+
+exports[`Button > renders with loading trailing correctly 1`] = `
+""
+`;
+
exports[`Button > renders with loadingIcon correctly 1`] = `
"