Skip to content

NbButton is the library's action control. Its job on any given screen is to make one action obvious and keep the rest available without competing.

Action hierarchy ​

Three variants carry the hierarchy. Reach for these first; the status colours below are a different tool for a different job.

vue
<NbButton variant="ghost">Cancel</NbButton>
<NbButton variant="secondary">Save draft</NbButton>
<NbButton variant="primary">Publish</NbButton>
VariantUse it for
primaryThe one action the screen exists for. At most one per view.
secondaryA real alternative the user might reasonably take instead.
ghostEverything else: Cancel, Back, and toolbar actions.

One primary per view. Two filled buttons side by side is two screens' worth of emphasis on one, and the eye picks neither.

Cancel is never danger. Cancel does not destroy anything; the button it sits next to might.

When a status colour is right ​

success, info, warning and danger say what a press means, not how loud it should be. Use one only when the semantics match:

vue
<NbButton variant="ghost">Cancel</NbButton>
<NbButton variant="danger">Delete environment</NbButton>

danger belongs on a control that destroys something. It is not a way to make a button louder, and a screen with three red buttons has told the user nothing. success on a Save button is the common mistake: saving is the primary action, not a positive outcome, so it takes primary.

For a destructive action, the dialog does the guarding: see NbConfirm and Dialogs.

Basic Usage ​

Icon Button ​

An icon-only button has no text for a screen reader to announce, so give it a name. aria-label is the usual way. v-nb-tooltip also works, because it writes the tooltip text to aria-label when the button has no other name.

vue
<NbButton icon="trash" aria-label="Delete" />
<NbButton v-nb-tooltip="{ body: 'Delete' }" icon="trash" />

In development, an icon-only button that renders without aria-label, aria-labelledby, title or text logs a warning naming the icon, once per icon. Production builds stay silent.

Features ​

  • Color Tints: Six distinct color variants (primary, secondary, success, info, warning, danger)
  • CSS Custom Properties: Uses design system variables for theming

Examples ​

Form Integration ​

Realistic groups ​

Every group above has exactly one filled button, and the exit is always ghost. See the whole pattern working on a real screen in Team management.

Button Sizes ​

Button Variants ​

The button component supports distinct color variant, each designed for specific use cases:

Outlined Variants ​

Add :outlined="true" (or just outlined) to any variant to remove the background and show a colored border and text instead. Ghost is excluded since it already has no background.

vue
<NbButton variant="danger" outlined>Delete</NbButton>
<NbButton variant="success" outlined>Save</NbButton>
<NbButton variant="primary" outlined>Cancel</NbButton>

Styling ​

The button uses CSS custom properties from the design system:

css
.nb-button {
  background: var(--nb-c-contrast);
  color: var(--nb-c-surface);
}
  • Proper button semantics with <button> element
  • Keyboard navigation support (Enter and Space keys)
  • Focus indicators for keyboard users
  • Screen reader friendly
  • Disabled state support

Best Practices ​

  1. Use descriptive button text that clearly indicates the action
  2. Provide loading states for async operations
  3. Use appropriate button types (submit, button, reset)
  4. Consider button hierarchy (primary vs secondary actions)
  5. Test with keyboard navigation to ensure accessibility

Props ​

PropTypeDefaultDescription
variant'primary' | 'secondary' | 'ghost' | 'danger' | 'success' | 'warning' | 'info'—Visual role. Omitted, the button renders the high-contrast base treatment.
outlinedbooleanfalseTransparent bg with colored border/text
size'xxs' | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'xxl''md'Button size. The full scale, all seven backed by CSS (since 1.55.0)
disabledbooleanfalseDisables the button
loadingbooleanfalseShows a spinner and prevents interaction
type'button' | 'submit' | 'reset''button'Native <button> type. Ignored when href is set
hrefstring-When provided, renders as <a> instead of <button>
targetstring-Forwarded to <a>. Only used when href is set (e.g. _blank)
relstring-Forwarded to <a>. Only used when href is set (e.g. noopener)
tostring | object-When provided, renders as a <RouterLink> for Vue Router navigation

Use href for external links and to for internal Vue Router navigation.

When href is provided the component renders a semantic <a> element, preserving native browser link behaviors (right-click, middle-click, ctrl+click, target="_blank").

When to is provided the component renders as a <RouterLink>, enabling client-side navigation with active-link tracking.

Disabled state is communicated via aria-disabled instead of the disabled attribute for both <a> and <RouterLink>.

vue
<!-- External link: renders <a href="..." target="_blank" rel="noopener"> -->
<NbButton
  variant="primary"
  href="https://github.com/nubisco/verba"
  target="_blank"
  rel="noopener"
>
  View on GitHub
</NbButton>

<!-- Internal Vue Router link: renders <RouterLink to="..."> -->
<NbButton variant="ghost" to="/products">
  Explore products
</NbButton>

Events ​

EventPayloadDescription
clickMouseEventFired on button click

Which token each variant paints ​

Every variant reads a semantic token, never a ramp name. That is what lets a white-label product retheme the library without the accent leaking through:

VariantTokenMeans
primary--nb-c-primaryThe screen's action
secondary--nb-c-secondaryAn alternative
ghost--nb-c-contrastText only, no fill
success--nb-c-successA positive outcome
info--nb-c-infoInformational
warning--nb-c-warningProceed with care
danger--nb-c-dangerDestroys something

Each also uses the matching -hover, -active and -a11y tokens, so a retheme moves the whole state set together. Override the semantic token, not the button.