Examples
Basic
| Prop | Default | Type | Description |
|---|---|---|---|
label | - | string | The label of the button. |
You can also use default slot to set the button label. Refer to slots for more information.
Preview
Code
<template>
<NButton label="Button" />
</template>
Variant
| Prop | Default | Type | Description |
|---|---|---|---|
btn | solid | {variant} | The variant of the button. |
| Variant | Description |
|---|---|
solid | The default variant. |
outline | The outline variant. |
soft | The soft variant. |
ghost | The ghost variant. |
link | The link variant. |
text | The text variant. |
~ | The unstyle or base variant |
Preview
Code
<template>
<div class="flex flex-wrap gap-4">
<NButton
label="Button Solid"
btn="solid"
/>
<NButton
label="Button Outline"
btn="outline"
/>
<NButton
label="Button Soft"
btn="soft"
/>
<NButton
label="Button Ghost"
btn="ghost"
/>
<NButton
label="Button Link"
btn="link"
/>
<NButton
label="Button text"
btn="text"
/>
<NButton
label="Button Base"
btn="~"
/>
</div>
</template>
Color
| Prop | Default | Type | Description |
|---|---|---|---|
btn | {variant}-primary | {variant}-{color} | The color of the button. |
Preview
Code
Dynamic colors:
Color with states:Custom colors using utilities:
Static colors:<template>
<div class="flex flex-col gap-4">
<span class="text-sm font-medium">Dynamic colors:</span>
<div class="flex flex-col gap-4">
<div class="flex flex-col gap-4 md:flex-row">
<NButton
label="solid-primary"
btn="solid-primary"
/>
<NButton
label="outline-lime"
btn="outline-lime"
/>
<NButton
label="link-yellow"
btn="link-yellow"
/>
<NButton
label="soft-red"
btn="soft-red"
/>
<NButton
label="ghost-orange"
btn="ghost-orange"
/>
</div>
<NSeparator />
<span class="text-sm font-medium">Color with states:</span>
<div class="flex flex-col gap-4 md:flex-row">
<NButton
btn="solid-error hover:solid-success"
label="hover me"
/>
<NButton
label="you can add transition too"
class="transition delay-300 ease-in-out"
btn="soft-error hover:soft-success"
/>
<NButton
btn="active:outline-fuchsia"
label="click me"
/>
<NButton
label="click me"
btn="outline-pink focus:outline-blue"
/>
</div>
<NSeparator />
<span class="text-sm font-medium">Custom colors using utilities:</span>
<div class="flex flex-col gap-2 md:flex-row">
<NButton
btn="~"
class="from-primary to-$c-brand-next bg-gradient-to-r text-white hover:from-pink-500 hover:to-yellow-500"
label="gradient color"
/>
<NButton
btn="~"
class="from-primary-500 via-primary-600 to-primary-700 bg-gradient-to-r text-white shadow-lg shadow-primary-500/50 hover:bg-gradient-to-br dark:shadow-lg dark:shadow-primary-800/80 dark:focus:ring-primary-800"
label="glowing effect"
/>
</div>
</div>
<NSeparator />
<span class="text-sm font-medium">Static colors:</span>
<div class="flex flex-col gap-4">
<div class="flex flex-col gap-2 md:flex-row">
<NButton
label="solid-gray"
btn="solid-gray"
/>
<NButton
label="soft-gray"
btn="soft-gray"
/>
<NButton
label="outline-gray"
btn="outline-gray"
/>
<NButton
label="ghost-gray"
btn="ghost-gray"
/>
<NButton
label="link-gray"
btn="link-gray"
/>
<NButton
label="text-gray"
btn="text-gray"
/>
</div>
<div class="flex flex-col gap-2 md:flex-row">
<NButton
label="solid-white"
btn="solid-white"
/>
<NButton
label="ghost-white"
btn="ghost-white"
/>
<NButton
label="outline-white"
btn="outline-white"
/>
</div>
<div class="flex flex-col gap-2 md:flex-row">
<NButton
label="solid-black"
btn="solid-black"
/>
<NButton
label="soft-black"
btn="soft-black"
/>
<NButton
label="link-black"
btn="link-black"
/>
<NButton
label="text-black"
btn="text-black"
/>
</div>
<div class="flex flex-col gap-2 md:flex-row">
<NButton
label="ghost-muted"
btn="ghost-muted"
/>
<NButton
label="link-muted"
btn="link-muted"
/>
<NButton
label="text-muted"
btn="text-muted"
/>
</div>
<div class="flex flex-col gap-2 md:flex-row">
<NButton
label="soft-accent"
btn="soft-accent"
/>
<NButton
label="text-accent"
btn="text-accent"
/>
<NButton
label="link-accent"
btn="link-accent"
/>
</div>
</div>
</div>
</template>
Size
| Prop | Default | Type | Description |
|---|---|---|---|
size | sm | string | Allows you to change the size of the button. |
🚀 Adjust input size freely using any size, breakpoints (e.g.,
sm:sm, xs:lg), or states (e.g.,hover:lg, focus:3xl).
The padding, icons, and text-size of the input scale are dynamically adjusted based on the size property. To customize the text-size and padding simultaneously, you can use utility classes.
Preview
Code
<template>
<div class="flex-1 space-x-4 space-y-2">
<NButton
size="xs"
label="button xs"
/>
<NButton
size="sm"
label="button sm (default)"
/>
<NButton
size="md"
label="button md"
/>
<NButton
size="lg"
label="button lg"
/>
<NButton
size="xl"
label="button xl"
/>
<NButton
size="3vw"
label="button 3vw"
/>
<NButton
size="1cm"
label="button 1cm"
/>
<NButton
class="px-8 py-10 text-xs"
label="custom size"
/>
<NButton
size="18px hover:40px"
btn="solid hover:outline-lime"
label="hover me 18px->40px"
/>
</div>
</template>
Rounded
| Prop | Default | Type | Description |
|---|---|---|---|
rounded | md | string | Set the button to have rounded corners. |
Preview
Code
<script setup lang="ts">
const examples = [
{
rounded: 'none',
},
{
rounded: 'sm',
},
{
rounded: 'md',
},
{
rounded: 'lg',
},
{
rounded: 't-xl sm:r-xl',
},
{
rounded: '3xl',
},
{
rounded: 'b-full',
},
{
rounded: 's-3xl',
},
]
</script>
<template>
<div class="flex flex-wrap items-center gap-4">
<NButton
v-for="example in examples"
:key="example.rounded"
:label="example.rounded"
:rounded="example.rounded"
/>
</div>
</template>
Square
| Prop | Default | Type | Description |
|---|---|---|---|
square | true | boolean, string | Sets the button to have the same width and height, and removes the padding. If you provide an empty value or true, it will use 2.5em. |
You can also provide a custom value to the square prop to set the width and height of the button, e.g., square="3em".
Preview
Code
<template>
<div class="flex flex-wrap items-start gap-4">
<NButton
label="Button"
square
btn="solid-orange"
/>
<NButton
label="Button"
square="16"
btn="solid-lime"
/>
<NButton
label="Button"
square="24"
btn="solid-pink"
/>
<NButton
label="Button"
square="32"
btn="solid-purple"
/>
<NButton
label="Button"
square="40"
btn="solid-red"
/>
</div>
</template>
Icon
| Prop | Default | Type | Description |
|---|---|---|---|
icon | - | boolean | Force the label to be an icon. |
leading | - | string | Display leading icon. |
trailing | - | string | Display trailing icon. |
If icon is true, the button will automatically be set to square by default. If you want to disable this behavior, you can set square to false.
Read more in Icon component
Preview
Code
Icon buttons with and without square preset Icon with states Leading icon with label Trailing icon with label
<template>
<div class="flex flex-col gap-4">
<span class="text-sm font-medium">
Icon buttons with and without square preset
</span>
<div class="flex flex-row gap-2">
<NButton
:square="false"
label="i-heroicons-arrow-down-tray-20-solid"
icon
/>
<NButton
label="i-heroicons-arrow-down-tray-20-solid"
icon
btn="soft"
/>
</div>
<NSeparator />
<span class="text-sm font-medium">
Icon with states
</span>
<div class="flex flex-row gap-2">
<NButton
label="i-heroicons-bell-20-solid group-hover:i-heroicons-bell-alert-20-solid"
icon
btn="solid-black"
class="group rounded-none"
/>
<NButton
label="i-heroicons-envelope-20-solid group-focus:i-heroicons-envelope-open-20-solid"
icon
btn="outline-green focus:outline-yellow"
class="group rounded-full"
/>
</div>
<NSeparator />
<span class="text-sm font-medium">
Leading icon with label
</span>
<div class="flex flex-col gap-2 sm:flex-row">
<NButton
trailing="i-logos-google-icon"
btn="solid-gray"
label="Sign in with Google"
/>
<NButton
leading="i-logos-facebook"
btn="solid-white"
label="Sign in with Facebook"
/>
<NButton
leading="i-logos-github-icon"
btn="solid-black"
label="Sign in with Github"
/>
</div>
<NSeparator />
<span class="text-sm font-medium">
Trailing icon with label
</span>
<div class="flex flex-col gap-2 sm:flex-row">
<NButton
trailing="i-heroicons-at-symbol-20-solid"
btn="outline"
label="Subscribe now"
/>
<NButton
trailing="i-heroicons-arrow-right-on-rectangle-20-solid"
label="Login"
/>
</div>
</div>
</template>
Link
| Prop | Default | Type | Description |
|---|---|---|---|
to | - | string | The link to navigate to. |
Read more in Link component
Preview
Code
<template>
<div class="flex flex-wrap gap-4">
<NButton
btn="solid-black"
label="Previous page"
leading="i-heroicons-arrow-small-left-20-solid"
to="/components/badge"
/>
<NButton
btn="solid-black"
label="Next page"
trailing="i-heroicons-arrow-small-right-20-solid"
to="/components/dropdown-menu"
/>
<NButton
to="https://github.com/una-ui/una-ui"
target="_blank"
btn="outline-pink"
class="rounded-none"
leading="i-heroicons-star-20-solid text-yellow text-sm"
label="Star us on GitHub"
/>
<NButton
btn="link"
label="Back to top"
leading="i-heroicons-arrow-small-up-20-solid"
active-class="btn-link-lime"
to="#examples"
/>
</div>
</template>
Block
| Prop | Default | Type | Description |
|---|---|---|---|
block | - | boolean | Set the button to have full width. |
Preview
Code
<template>
<div class="flex gap-4">
<NButton
label="Normal"
/>
<NButton
block
label="Block"
/>
</div>
</template>
Disabled
| Prop | Default | Type | Description |
|---|---|---|---|
disabled | - | boolean | Set the button to disabled. |
Preview
Code
<template>
<div class="flex flex-wrap gap-4">
<NButton
disabled
label="Disabled"
/>
<NButton
btn="outline"
disabled
label="Disabled"
/>
<NButton
btn="link"
disabled
label="Disabled"
/>
<NButton
btn="ghost"
disabled
label="Disabled"
/>
<NButton
btn="soft"
disabled
label="Disabled"
/>
<NButton
btn="text"
disabled
label="Disabled"
/>
<NButton
btn="solid-black"
disabled
label="Disabled"
/>
<NButton
btn="solid-white"
disabled
label="Disabled"
/>
</div>
</template>
Loading
| Prop | Default | Type | Description |
|---|---|---|---|
loading | - | boolean | Set the button to loading state. |
loading-placement | leading | leading, trailing, label | Set the loading icon placement. |
By default, the disabled state is triggered when the button is loading.
Preview
Code
<script setup lang="ts">
const loading = ref(true)
function toggleLoading() {
loading.value = !loading.value
}
</script>
<template>
<div class="flex flex-col gap-4">
<div>
<NButton
btn="solid-gray"
:label="`Turn ${loading ? 'off' : 'on'} loading`"
@click="toggleLoading"
/>
</div>
<NSeparator />
<div class="flex flex-col gap-4 sm:flex-row">
<NButton
:loading="loading"
:label="loading ? 'Leading...' : 'Leading'"
@click="toggleLoading"
/>
<NButton
btn="soft-green"
loading-placement="label"
:loading="loading"
:una="{
btnLoadingIcon: 'i-tabler-loader-3',
}"
label="Label Loading"
@click="toggleLoading"
/>
<NButton
btn="solid-black"
loading-placement="trailing"
:loading="loading"
:una="{
btnLoadingIcon: 'i-tabler-loader',
}"
:label="loading ? 'Trailing...' : 'Trailing'"
@click="toggleLoading"
/>
</div>
<NSeparator />
<div class="flex flex-col gap-4 sm:flex-row">
<NButton
btn="soft-yellow"
:class="{ 'animate-pulse': loading }"
:loading="loading"
:label="loading ? 'Downloading...' : 'Download'"
leading="i-heroicons-cloud-arrow-down-20-solid"
@click="toggleLoading"
/>
<NButton
btn="link-orange"
loading-placement="label"
:loading="loading"
:una="{
btnLoadingIcon: 'i-heroicons-cloud-arrow-down-20-solid',
btnLoading: 'animate-pulse',
}"
icon
label="i-tabler-download"
@click="toggleLoading"
/>
<NButton
btn="solid-white"
loading-placement="label"
:loading="loading"
:una="{
btnLoadingIcon: 'i-tabler-reload',
}"
label="Refresh"
@click="toggleLoading"
/>
</div>
</div>
</template>
Slots
Default
| Name | Props | Description |
|---|---|---|
default | - | The button label. |
Leading
| Name | Props | Description |
|---|---|---|
leading | - | The leading icon. |
Preview
Code
<template>
<NButton btn="outline" class="rounded-full" label="View">
<template #leading>
<!-- TODO convert to NAvatar soon -->
<span class="rounded-full bg-base">
<img
class="h-5"
src="https://avatars.githubusercontent.com/u/33350692?s=400&u=49395c835e8197ae2ee42ca02c95e828d8f64239&v=4"
>
</span>
</template>
</NButton>
</template>
Trailing
| Name | Props | Description |
|---|---|---|
trailing | - | The trailing icon. |
Preview
Code
<template>
<NButton label="Login">
<template #trailing>
<NIcon name="i-heroicons-arrow-right-on-rectangle-20-solid" />
</template>
</NButton>
</template>
Loading
| Name | Props | Description |
|---|---|---|
loading | - | The loading icon. |
Preview
Code
<template>
<NButton
loading
label="Button"
>
<template #loading>
<span class="animate-pulse rounded-full bg-base">
<img
class="h-5"
src="https://avatars.githubusercontent.com/u/33350692?s=400&u=49395c835e8197ae2ee42ca02c95e828d8f64239&v=4"
>
</span>
</template>
</NButton>
</template>
Presets
shortcuts/btn.ts
type BtnPrefix = 'btn'
export const staticBtn: Record<`${BtnPrefix}-${string}` | BtnPrefix, string> = {
// config
'btn-default-variant': 'btn-solid',
'btn-loading-icon': 'i-loading',
// base
'btn': 'btn-rectangle bg-transparent transition-colors leading-1.4285714285714286em shrink-0 gap-x-0.5714285714285714em rounded-md whitespace-nowrap inline-flex justify-center items-center btn-disabled font-medium',
'btn-disabled': 'disabled:n-disabled',
'btn-label': '',
'btn-icon-label': 'size-1.1428571428571428em',
'btn-leading': 'size-1.1428571428571428em',
'btn-trailing': 'size-1.1428571428571428em',
'btn-loading': 'animate-spin size-1.1428571428571428em',
'btn-rectangle': 'h-2.5714285714285716em px-1.1428571428571428em py-0.5714285714285714em',
'btn-square': 'square-2.5714285714285716em p-0',
// options
'btn-block': 'w-full',
'btn-reverse': 'flex-row-reverse',
// variants
'btn-solid-white': 'bg-base text-base ring-1 ring-base ring-inset shadow-sm btn-focus hover:bg-muted',
'btn-ghost-white': 'text-base btn-focus hover:bg-$c-gray-50',
'btn-outline-white': 'text-base ring-1 ring-base ring-inset btn-focus hover:bg-$c-gray-50',
'btn-solid-gray': 'bg-$c-gray-50 text-$c-gray-800 ring-1 ring-base ring-inset shadow-sm btn-focus hover:bg-$c-gray-100',
'btn-ghost-gray': 'text-$c-gray-600 btn-focus hover:bg-$c-gray-100',
'btn-soft-gray': 'text-$c-gray-600 bg-$c-gray-50 btn-focus hover:bg-$c-gray-100',
'btn-outline-gray': 'text-muted hover:text-$c-gray-600 ring-1 ring-base ring-inset btn-focus hover:bg-$c-gray-50',
'btn-link-gray': 'text-muted btn-focus hover:text-base hover:underline underline-offset-4',
'btn-text-gray': 'text-$c-gray-600 btn-focus hover:text-$c-gray-900',
'btn-solid-black': 'bg-inverted text-inverted shadow-sm btn-focus',
'btn-link-black': 'text-base btn-focus hover:underline underline-offset-4',
'btn-text-black': 'text-base btn-focus',
'btn-soft-black': 'text-base bg-base btn-focus shadow-sm',
'btn-text-muted': 'text-muted btn-focus hover:text-accent',
'btn-link-muted': 'text-muted btn-focus hover:underline underline-offset-4',
'btn-ghost-muted': 'text-accent hover:text-muted btn-focus hover:bg-muted',
'btn-soft-accent': 'text-accent bg-accent btn-focus',
'btn-text-accent': 'text-accent btn-focus',
'btn-link-accent': 'text-accent btn-focus hover:underline underline-offset-4',
}
export const dynamicBtn: [RegExp, (params: RegExpExecArray) => string][] = [
// base
[/^btn-focus(-(\S+))?$/, ([, , c = 'primary']) => `focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-${c}-600 dark:focus-visible:ring-${c}-500`],
// variants
[/^btn-solid(-(\S+))?$/, ([, , c = 'primary']) => `btn-focus-${c} text-inverted shadow-sm bg-${c}-600 hover:bg-${c}-500 dark:bg-${c}-500 dark:hover:bg-${c}-400`],
[/^btn-text(-(\S+))?$/, ([, , c = 'primary']) => `btn-focus-${c} text-${c}-600 dark:text-${c}-500 hover:text-${c}-500 dark:hover:text-${c}-400`],
[/^btn-outline(-(\S+))?$/, ([, , c = 'primary']) => `btn-focus-${c} text-${c}-500 dark:text-${c}-400 ring-1 ring-inset ring-${c}-500 dark:ring-${c}-400 hover:bg-${c}-50 dark:hover:bg-${c}-950`],
[/^btn-soft(-(\S+))?$/, ([, , c = 'primary']) => `btn-focus-${c} text-${c}-600 dark:text-${c}-400 bg-${c}-50 dark:bg-${c}-950 hover:bg-${c}-100 dark:hover:bg-${c}-900`],
[/^btn-ghost(-(\S+))?$/, ([, , c = 'primary']) => `btn-focus-${c} text-${c}-600 dark:text-${c}-400 hover:bg-${c}-100 dark:hover:bg-${c}-900`],
[/^btn-link(-(\S+))?$/, ([, , c = 'primary']) => `btn-focus-${c} text-${c}-600 dark:text-${c}-500 hover:underline underline-offset-4`],
]
export const btn = [
...dynamicBtn,
staticBtn,
]
Props
types/button.ts
import type { HTMLAttributes } from 'vue'
import type { RouteLocationRaw } from 'vue-router'
interface BaseExtensionProps {
square?: HTMLAttributes['class']
rounded?: HTMLAttributes['class']
class?: HTMLAttributes['class']
breadcrumbActive?: string
breadcrumbInactive?: string
paginationSelected?: string
paginationUnselected?: string
dropdownMenu?: string
toggleOn?: string
toggleOff?: string
tabsActive?: string
tabsInactive?: string
navigationMenu?: string
navigationMenuLink?: string
ariaLabel?: string
}
export interface NButtonProps extends BaseExtensionProps {
/**
* Change the button type.
*
* @default 'button'
*/
type?: 'button' | 'submit' | 'reset'
/**
* Change the loading placement of the button.
*
* @default 'leading'
*/
loadingPlacement?: 'leading' | 'trailing' | 'label'
/**
* Convert `label` prop to icon component.
*
* @default false
* @example
* icon
* label="i-heroicons-information-circle"
*/
icon?: boolean
/**
* Disable the button.
*
* @default false
*/
disabled?: boolean
/**
* Swap the position of the leading and trailing icons.
*
* @default false
*/
reverse?: boolean
/**
* Show loading state on button
* @default false
*/
loading?: boolean
/**
* Make the button full width.
*
* @default false
*/
block?: boolean
/**
* Change the button tag to `NuxtLink` component,
* This allows you to use `NuxtLink` available props.
*
* @see https://nuxt.com/docs/api/components/nuxt-link#props
* @example
* to="/"
*/
to?: RouteLocationRaw
/**
* Add a label to the button.
*
* @example
* label="Click me"
*/
label?: string
/**
* Allows you to add `UnaUI` button preset properties,
* Think of it as a shortcut for adding options or variants to the preset if available.
*
* @see https://github.com/una-ui/una-ui/blob/main/packages/preset/src/_shortcuts/button.ts
* @example
* btn="solid-green block square"
*/
btn?: string
/**
* Add leading icon the button,
* This also allows you to add utility classes to the icon.
*
* @example
* leading="i-heroicons-information-circle text-green-500 dark:text-green-400 text-2xl"
*/
leading?: string
/**
* Add trailing icon the button.
* This also allows you to add utility classes to the icon.
*
* @example
* trailing="i-heroicons-information-circle text-green-500 dark:text-green-400 text-2xl"
*/
trailing?: string
/**
* Allows you to change the size of the input.
*
* @default sm
*
* @example
* size="sm" | size="2cm" | size="2rem" | size="2px"
*/
size?: string
/**
* `UnaUI` preset configuration
*
* @see https://github.com/una-ui/una-ui/blob/main/packages/preset/src/_shortcuts/button.ts
*/
una?: {
// base
btnDefaultVariant?: string
btn?: string
btnLabel?: string
btnIconLabel?: string
btnLoading?: string
btnTrailing?: string
btnLeading?: string
// icon
btnLoadingIcon?: string
}
}
Components
Button.vue
<script setup lang="ts">
import type { NButtonProps } from '../../types'
import { createReusableTemplate } from '@vueuse/core'
import { computed } from 'vue'
import { cn } from '../../utils'
import NIcon from '../elements/Icon.vue'
import NLink from '../elements/Link.vue'
const props = withDefaults(defineProps<NButtonProps>(), {
type: 'button',
size: 'sm',
rounded: 'md',
loadingPlacement: 'leading',
una: () => ({
btnDefaultVariant: 'btn-default-variant',
}),
})
const mergeVariants = computed(() => {
return {
'btn': props.btn,
'breadcrumb-active': props.breadcrumbActive,
'breadcrumb-inactive': props.breadcrumbInactive,
'pagination-selected': props.paginationSelected,
'pagination-unselected': props.paginationUnselected,
'dropdown-menu': props.dropdownMenu,
'toggle-on': props.toggleOn,
'toggle-off': props.toggleOff,
'tabs-active': props.tabsActive,
'tabs-inactive': props.tabsInactive,
'navigation-menu': props.navigationMenu,
'navigation-menu-link': props.navigationMenuLink,
}
})
const loadingPlacement = computed(() => props.loadingPlacement === 'leading' && props.icon ? 'label' : props.loadingPlacement)
const btnVariants = ['solid', 'outline', 'soft', 'ghost', 'link', 'text'] as const
const hasVariant = computed(() =>
Object.values(mergeVariants.value).some(variantList =>
btnVariants.some(variant => variantList?.includes(variant)),
),
)
const isBaseVariant = computed(() =>
Object.values(mergeVariants.value).some(variantList =>
variantList?.includes('~'),
),
)
const square = computed(() => props.square ?? !!props.icon)
const [DefineTemplate, ReuseTemplate] = createReusableTemplate()
</script>
<template>
<Component
:is="to ? NLink : 'button'"
:to="to"
:type="to ? null : type"
:class="cn(
(square === '' || square) && 'btn-square',
block && 'btn-block',
!hasVariant && !isBaseVariant ? una?.btnDefaultVariant : null,
reverse && 'btn-reverse',
'btn',
una?.btn,
props.class,
)"
:disabled="disabled || loading"
:aria-label="props.ariaLabel ? props.ariaLabel : props.icon ? props.label : undefined"
:rounded
:size
:square
v-bind="mergeVariants"
>
<DefineTemplate v-if="loading">
<slot name="loading">
<NIcon
:name="una?.btnLoadingIcon ?? 'btn-loading-icon'"
:class="una?.btnLoading"
btn="loading"
/>
</slot>
</DefineTemplate>
<ReuseTemplate v-if="loading && loadingPlacement === 'leading'" />
<slot
v-else
name="leading"
>
<NIcon
v-if="leading"
:name="leading"
:class="cn(
'btn-leading',
una?.btnLeading,
)"
/>
</slot>
<ReuseTemplate v-if="loading && loadingPlacement === 'label'" />
<slot v-else>
<NIcon
v-if="label && icon"
:name="label"
btn="icon-label"
:class="una?.btnIconLabel"
/>
<span
v-if="!icon"
btn="label"
:class="una?.btnLabel"
>
{{ label }}
</span>
</slot>
<ReuseTemplate v-if="loading && loadingPlacement === 'trailing'" />
<slot
v-else
name="trailing"
>
<NIcon
v-if="trailing"
:name="trailing"
btn="trailing"
:class="una?.btnTrailing"
/>
</slot>
</Component>
</template>