A button is an UI element which signals key actions to take an action throughout an app. It is important a button is identifiable, consistent, communicates its actions clearly, and is appropriately sized to its action.

Preview

Usage

  • <button> and link (<a>) HTML elements each describe a specific intent. Understanding the distinction is important: if it goes somewhere, it's a link (<a>). If an action occurs, use a Button (<button>). When you need button styling with navigation behavior (CTAs, toolbar actions that navigate), use DtButton's href or to props — see Navigation.
  • Avoid using too many buttons on a page.
  • Set the type attribute to define its purpose: submit, button, or reset. Browsers default to submit if it isn't defined, and that cannot be assumed as the preferred behavior.

Do

  • Conveying that an action that will occur when invoked.
  • To trigger an action or behavior, such as submitting a form or spawning a Modal.

Don’t

  • Avoid using to navigate between destinations, deferring to a DtLink instead. Exception: use DtButton with href or to when button styling is intentional (e.g. CTAs, toolbar actions).

Writing Guidelines

Button labels should be clear and predictable so users have confidence in their actions.

  • Lead with a strong verb and use verb + noun structure except for common actions like "Done," "Close," "Cancel," or "OK"
  • Should be sentence case
  • Do not use punctuation
  • Avoid unnecessary articles such as "the," "an," and "a."

Do

  • Add number
  • Create menu

Don’t

  • Add Number
  • Create a menu

Variants

Dialtone provides five options for kind, with three levels of importance. Use kind="primary" for the main call to action, kind="danger" for destructive actions, kind="muted" for secondary actions, kind="clear" for low-emphasis actions, and kind="link" for navigation-style buttons. The DtButton kind prop controls the visual hierarchy and semantic meaning of the action.

clear
Default level of importance. Typically used for secondary or minimally important actions.
outlined
Slightly more important than clear, presenting a contrasting border and transparent background.
primary
Highest level of importance, presenting a solid background color.
default Default button colors.
muted For non-primary actions and contexts where base style may not work. N/A
critical Potentially destructive or otherwise critical actions.
positive Used to communicate positive, confirmatory, or success-related actions.
inverted Use for placement on non-white, dark backgrounds.
unstyled Raw button devoid of any style. N/AN/AN/A

Default

The base button should be the go-to button for most of your needs. When in doubt, use this style. To help provide clarity to users, it is generally recommended to use only one primary button style within a section or page.

Critical

The critical button style is used to communicate critical or destructive actions such as deleting content, accounts, or canceling services.

Positive

The positive button style is used to communicate positive, confirmatory, or success-related actions.

Muted

The muted button style is used to communicate non-primary actions for contexts in which the base style may not work (e.g. colored backgrounds, validation components, etc). This style's use should be rare. When in doubt, use the default button style.

Disabled

Buttons can be disabled using the disabled attribute or the Dialtone class, d-btn--disabled. Use the attribute when a button should appear disabled and not receive focus; use the class when a button should appear disabled but still receive focus (i.e. a disabled button with a tooltip).

Using the class also requires aria-disabled, and additional javascript implementation is required to prevent events.

Active

Buttons can be set to active state using the active prop or .d-btn--active Dialtone class.

Buttons can be styled to match the appearance of a DtLink in situations for which you need the appearance of a link but require the behavior of a button. Using the button element provides a better accessibility experience.

This inverts the underline behavior. With underline="false", the link will not have an underline by default, but will show one on hover.

Unstyled

The unstyled button removes all default Dialtone styling while preserving the semantic HTML <button> element and maintaining proper button behavior and accessibility.

Inverted

Use the v-dt-mode directive in place of kind="inverted" on the component element. The previous inverted variant of DtButton was limited to a single presentation style. The directive now makes every combination available as an inverted style.

DtButton can render as an <a> or <router-link> for cases where you need button styling with navigation behavior.

  • Navigating within the app? Use to. Renders <router-link> for client-side navigation without page reloads.
  • Linking to an external site? Use href. Renders <a> for standard browser navigation.
  • Triggering an action? Use neither. Renders <button> (default).

href

Pass href to render as an <a> element. Use target="_blank" and rel="noopener noreferrer" for external links.

to

Pass to to render as <router-link> for internal client-side SPA navigation. Use replace to navigate without adding a history entry.

Migration

If you have existing <a class="d-btn"> or <router-link class="d-btn"> workarounds, replace them with DtButton props:

Sizes

The default button size is 300, but does not need to be explicitly specified.

Icon Support

Start and End

Place icons before and/or after inline of the label with startIcon and endIcon slots.

Top and Bottom

Place icons above or below the label with blockStartIcon and blockEndIcon slots.

Icon Only

Icon-only buttons are commonly used for toggling actions, navigation, or closing UI elements.

Circle

The following styles are available as a circle shape.

Loading

Loading buttons are useful for communicating a delay between the button interaction and its action taking place. Every button style can accept the loading button class, though we only provide a few possible examples. When loading is true, DtButton replaces the label with a spinner animation, indicating an async operation (such as form submit) is in progress. The spinner is centered within the button and the button remains disabled until loading is false.

Replace button label

The width of the button remains determined by the length of the label, which is visually hidden in this state.

With label

Leading & Trailing

Use the #leading and #trailing slots to render freeform content at the start or end of a button — outside the label area but inside the button's border. Common use cases include badges, count indicators, or keyboard shortcut hints. Use leading-class and trailing-class to add padding or styling to the slot containers.

Leading

Trailing

Split Button

Branded

We provide the following branded buttons for log-in and sign-up workflows.

Vue API

import { DtButton } from '@dialpad/dialtone-vue';

Slots

Name
Type
blockEndIcon

Icon displayed below the button label (block-end)

blockStartIcon

Icon displayed above the button label (block-start)

default

Content within button

endIcon

Icon displayed at the end (aka right) of the button

icon

Button icon

leading

Optional leading content at the start of the button, such as badges or indicators

startIcon

Icon displayed at the start (aka left) of the button

trailing

Optional trailing content at the end of the button, such as badges or indicators

Props

Name
Default
Type
active
false
"true" | "false"

Determines whether the button should have active styling default is false.

assertiveOnFocus
false
"true" | "false"

Determines whether a screenreader reads live updates of the button content to the user while the button is in focus. default is to not.

blockEndIconClass
''
string|array|object

Used to customize the block-end (aka bottom) icon container

blockStartIconClass
''
string|array|object

Used to customize the block-start (aka top) icon container

circle
false
"true" | "false"

Whether the button is a circle or not. Use only with icon-only buttons.

disabled
false
"true" | "false"

HTML button disabled attribute (Reference)

endIconClass
''
string|array|object

Used to customize the end icon container

href
null
string

When provided, renders an <a> element for standard browser navigation.

importance
'primary'
"clear" | "outlined" | "primary"

The fill and outline of the button associated with its visual importance.

kind
'default'
"default" | "unstyled" | "muted" | "critical" | "positive"

The color of the button.

labelClass
''
string|array|object

Used to customize the label container

leadingClass
''
string|array|object

Used to customize the leading container

link
false
"true" | "false"

Whether the button should be styled as a link or not.

linkKind
'default'
"default" | "critical" | "warning" | "positive" | "muted"

The color of the link and button if the button is styled as a link.

linkUnderline
true
"true" | "false"

Determines whether the link-styled button should display an underline. Only applies when the link prop is true.

loading
false
"true" | "false"

Whether the button should display a loading animation or not.

rel
null
string

HTML anchor rel attribute. Only applied when using the href prop.

replace
false
"true" | "false"

vue-router replace prop. When true, navigation will not leave a history entry. Only applied when using the to prop.

size
300
"100" | "200" | "300" | "400" | "500"

The size of the button.

startIconClass
''
string|array|object

Used to customize the start icon container

target
null
"_self" | "_blank" | "_parent" | "_top"

HTML anchor target attribute. Only applied when using the href prop.

to
null
string|object

vue-router to prop. When provided, renders a <router -link> for client-side SPA navigation.

trailingClass
''
string|array|object

Used to customize the trailing container

type
'button'
"button" | "submit" | "reset"

HTML button type attribute (Reference)

width
null
string

Button width, accepts CSS width attribute values

iconClass Deprecated
''
string|array|object

Used to customize the legacy icon container

Use startIconClass or endIconClass

iconPosition Deprecated
'start'
"start" | "end" | "blockStart" | "blockEnd" | "left" | "right" | "top" | "bottom"

The position of the icon slot within the button.

Use startIcon / endIcon / blockStartIcon / blockEndIcon slots instead.

linkInverted Deprecated
false
"true" | "false"

Determines whether the link should have inverted styling if the button is styled as a link.

Use v-dt-mode instead.

underline Deprecated
null
"true" | "false"

Use linkUnderline instead.

Events

Name
Type
focusin
FocusEvent

Native button focus in event

focusout
FocusEvent

Native button focus out event

Accessibility

  • Choosing between Link and Button elements is paramount for screenreaders to inform the user what will occur. For example: will it go somewhere (Link) or will something happen (Button)?
  • Do not rely on color alone to convey the intent of the button. Defer to the button text as primary way to convey the buttons intent.
  • Display a visible focus state when users tab to them.
  • Use standard semantic usage of HTML elements.
  • Be aware of how screenreaders handle buttons and links differently. For example, both the Enter and Space keys triggers a button, while links are triggered only by the Enter key.
  • If it is a button type while focused:
    • Pressing the Enter or Space key should trigger the action.
    • Pressing the Tab key moves focus to the next focusable element.
    • Pressing the Shift+Tab key moves focus to the previous focusable element.
  • When using DtButton with href or to, the component automatically handles Spacebar activation and disabled state (aria-disabled, tabindex="-1"). Navigating elements keep their native link role — role="button" is not added because the element navigates rather than performing an in-page action.

Classes

Class
Applies to
Description

Button documentation last updated Thursday, June 18, 2026