๐ŸŸข Button


Basic

NButton - use to trigger an action or event, such as submitting a form, opening a dialog, canceling an action, or performing a delete operation.

You can use label prop or default slot to set the button text.

<template>
  <NButton label="Button" />
</template>

Variants

btn="{variant}" - change the variant of the button.

VariantDescription
solidThe default variant.
outlineThe outline variant.
ghostThe ghost variant.
linkThe link variant.
softThe soft variant.
textThe text variant.
~The unstyle or base variant
<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

btn="{variant}-{color}" - change the color of the button.

You can use any color provided by the Tailwind CSS color palette, the default is primary. You can also add your own colors to the palette through the Configuration section.
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="ghost-gray"
          btn="ghost-gray"
        />
        <NButton
          label="link-gray"
          btn="link-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"
        />
      </div>

      <div class="flex flex-col gap-2 md:flex-row">
        <NButton
          label="solid-black"
          btn="solid-black"
        />
        <NButton
          label="link-black"
          btn="link-black"
        />
      </div>

      <div class="flex flex-col gap-2 md:flex-row">
        <NButton
          label="text-black"
          btn="text-black"
        />
        <NButton
          label="text-gray"
          btn="text-gray"
        />
      </div>
    </div>
  </div>
</template>

Size

size="{size}" - change the size of the button.

๐Ÿš€ You can freely adjust the size of the button using any size imaginable. No limits exist, and you can use breakpoints such as sm:sm, xs:lg to change size based on screen size or states such as hover:lg, focus:3xl to change size based on input state and more.

The padding and font-size of the button scale depends on the size. If you want to change the font-size and padding simultaneously, you can always customize it using utility classes.
<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

rounded="{size}" - change the border-radius of the button.

๐Ÿš€ You can freely adjust the size of the rounded using any size imaginable. No limits exist, and you can use breakpoints such as sm:sm, xs:lg to change size based on screen size or states such as hover:lg, focus:3xl to change size based on input state and more.

You can use any size provided by the Tailwind CSS border-radius scale, the default is md. You can also add your own sizes to the scale through the Configuration section.
<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

square - to force width and height to have the same size, usefull for icon buttons.

๐Ÿš€ You can freely adjust the square of the button using any size imaginable. No limits exist, and you can use breakpoints such as sm:sm, xs:lg to change size based on screen size or states such as hover:lg, focus:3xl to change size based on input state and more.

PropsTypeDefaultDescription
squarestring boolean2.5emSet the button to have the same width and height. If you provide empty value or true, it will use the default value.
You can use any value provided by the Tailwind CSS. You can also add your own sizes to the scale through the Configuration section.
<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

icon - change label text to icon.

leading="{icon}" - add a leading icon to the button.

trailing="{icon}" - add a trailing icon to the button.

By default we use heroicons and tabler for the icons, you can use any icon provided by Iconify through icones, refer to configuration for more information.
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
        label="i-heroicons-arrow-down-tray-20-solid"
        icon
      />

      <NButton
        label="i-heroicons-arrow-down-tray-20-solid"
        icon
        btn="soft"
        square
      />
    </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="square 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 square 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
        leading="i-logos-google-icon"
        btn="solid-gray"
        label="Sign in with Google"
      />
      <NButton
        leading="i-logos-facebook text-lg"
        btn="solid-white"
        label="Sign in with Facebook"
      />
      <NButton
        leading="i-bi-github text-lg"
        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>

to - add a link to the button.

Since we use NuxtLink for the link, you can use any NuxtLink props such as prefetch, target, activeClass, etc. Refer to NuxtLink for more information.
<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="#button"
    />
  </div>
</template>

Block

btn="block" - add block style to the button.

<template>
  <div class="flex gap-4">
    <NButton
      label="Normal"
    />

    <NButton
      btn="block"
      label="Block"
    />
  </div>
</template>

Disabled

disabled - add a disabled state to the button.

<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

By default we trigger the disabled state when the button is loading.

loading - add a loading state to the button.

loading-placement - change the loading icon placement, default is leading. options are leading, trailing and label.

You can use loading with icon and label at the same time.
<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

#default - set the button label, refer to label for the example.

Leading

#leading - add a leading icon to the button.

<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

#tailing - add a trailing icon to the button.

<template>
  <NButton label="Login">
    <template #trailing>
      <NIcon name="i-heroicons-arrow-right-on-rectangle-20-solid" />
    </template>
  </NButton>
</template>

Loading

#loading - add a loading icon to the button.

<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>

Props

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
}

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

  /**
   * 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

    // icons
    btnTrailing?: string
    btnLeading?: string
    btnLoadingIcon?: string
  }
}

Presets

type BtnPrefix = 'btn'

export const staticBtn: Record<`${BtnPrefix}-${string}` | BtnPrefix, string> = {
  // config
  'btn-default-variant': 'btn-solid',
  'btn-loading-icon': 'i-loading',
  'btn-default-radius': 'rounded-md',

  // base
  'btn': 'btn-rectangle px-1em py-0.5em bg-transparent transition-colors text-0.875em leading-5 gap-x-0.5em rounded-md whitespace-nowrap inline-flex justify-center items-center btn-disabled font-medium cursor-pointer',
  'btn-disabled': 'disabled:n-disabled',
  'btn-label': '',
  'btn-icon-label': 'text-1.191em',
  'btn-leading': '-ml-0.14285714285714285em text-1.191em',
  'btn-trailing': '-mr-0.14285714285714285em text-1.191em',
  'btn-loading': 'animate-spin text-1.191em',
  'btn-rectangle': 'h-2.5em',
  'btn-square': 'w-2.5em h-2.5em',

  // 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',

  '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 ring-1 ring-base ring-inset btn-focus',
  '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',
}

export const dynamicBtn: [RegExp, (params: RegExpExecArray) => string][] = [
  // base
  [/^btn-focus(-(\S+))?$/, ([, , c = 'primary']) => `focus-visible:outline-${c}-600 dark:focus-visible:outline-${c}-500 focus-visible:outline-2 focus-visible:outline-offset-2`],

  // 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}-500 dark:text-${c}-400 hover:underline underline-offset-4`],
]

export const btn = [
  ...dynamicBtn,
  staticBtn,
]

Component

<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',
  loadingPlacement: 'leading',
  square: false,
  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,
  }
})

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 [DefineTemplate, ReuseTemplate] = createReusableTemplate()
</script>

<template>
  <Component
    :is="to ? NLink : 'button'"
    :to="to"
    :type="to ? null : type"
    :class="cn(
      (square === '' || square === true) && 'btn-square',
      !rounded && 'btn-default-radius',
      !hasVariant && !isBaseVariant ? una?.btnDefaultVariant : null,
      reverse && 'btn-reverse',
      'btn',
      una?.btn,
      props.class,
    )"
    :disabled="to ? null : disabled || loading"
    :aria-label="icon ? label : null"
    :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="una?.btnLeading"
        btn="leading"
      />
    </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>