v1.6.x-dev NDS IQ v6

Button - National Design System

Interactive controls for actions, navigation, and form submissions

Standard

Six variants across all interaction states

<button class="nds-btn nds-primary"> <span class="nds-label">Button</span> </button>

Destructive

Red-toned variants for delete, remove, and irreversible actions

<button class="nds-btn nds-primary nds-destructive"> <span class="nds-label">Delete</span> </button>

Layout

Content visibility, icon position, shape, and state modifiers

<button class="nds-btn nds-primary"> <i class="nds-icon nds-hgi-plus-sign" aria-hidden="true"></i> <span class="nds-label">Add Item</span> </button>

Menu Button

Dropdown trigger with auto-rotating indicator

<button class="nds-btn nds-secondary-outline nds-menu-btn"> <span class="nds-label">Options</span> </button>

Directional Buttons

Pseudo-element icon buttons for navigation: next, previous, up, down, and ellipsis

<!-- Next: arrow points forward (RTL-aware) --> <button class="nds-btn nds-secondary-outline nds-next"> <span class="nds-label">Next</span> </button> <!-- Prev: arrow points backward (RTL-aware), icon placed after label --> <button class="nds-btn nds-secondary-outline nds-prev"> <span class="nds-label">Prev</span> </button> <!-- Up --> <button class="nds-btn nds-secondary-outline nds-up"> <span class="nds-label">Up</span> </button> <!-- Down --> <button class="nds-btn nds-secondary-outline nds-down"> <span class="nds-label">Down</span> </button> <!-- Ellipsis (icon-only, no label needed) --> <button class="nds-btn nds-secondary-outline nds-ellipsis nds-icon-only" aria-label="More"></button>

Button Group

Grouped buttons with merged borders and shared border radius

<div class="nds-btn-group"> <button class="nds-btn nds-secondary-outline nds-lg"><span class="nds-label">Left</span></button> <button class="nds-btn nds-secondary-outline nds-lg"><span class="nds-label">Center</span></button> <button class="nds-btn nds-secondary-outline nds-lg"><span class="nds-label">Right</span></button> </div>

Animated Progress

Circular countdown timer controlled by --progress-duration

<button class="nds-btn nds-primary nds-icon-only nds-progress" style="--progress-duration: 4000ms;" aria-label="Close"> <i class="nds-icon nds-hgi-cancel-01" aria-hidden="true"></i> <div class="nds-progress-circle"> <svg width="100%" height="100%" viewBox="0 0 24 24"> <circle class="nds-progress-bg" cx="12" cy="12" r="10" fill="none" stroke-width="2"></circle> <circle class="nds-progress-track" cx="12" cy="12" r="10" fill="none" stroke-width="2" stroke-dasharray="62.83" stroke-dashoffset="62.83" stroke-linecap="round"></circle> </svg> </div> </button>

Static Progress

Fixed percentage indicator controlled by --progress-value

<button class="nds-btn nds-primary nds-icon-only nds-progress nds-progress-static" style="--progress-value: 25;" aria-label="Upload"> <i class="hgi hgi-stroke hgi-upload-02"></i> <div class="nds-progress-circle"> <svg width="100%" height="100%" viewBox="0 0 24 24"> <circle class="nds-progress-bg" cx="12" cy="12" r="10" fill="none" stroke-width="2"></circle> <circle class="nds-progress-track" cx="12" cy="12" r="10" fill="none" stroke-width="2" stroke-dasharray="62.83" stroke-dashoffset="62.83" stroke-linecap="round"></circle> </svg> </div> </button>

Status Feedback

Contextual color and icon change via data-status attribute

<button class="nds-btn nds-secondary"> <i class="nds-icon nds-hgi-copy-01"></i> <span class="nds-label">Copy Link</span> </button>

Badge

Notification count overlay on icon buttons

<button class="nds-btn nds-icon-only nds-subtle"> <i class="hgi hgi-stroke hgi-notification-03"> <span class="nds-badge">3</span> </i> </button>

Cooldown Button

Click triggers a loading phase then a live countdown before the button is re-enabled

<button class="nds-btn nds-subtle nds-cooldown" data-cooldown="10" data-cooldown-loading="2" data-cooldown-label="Resend in {s}s" data-resend-label="Resend code" data-sent-title="Code sent" data-sent-message="Check your inbox for the verification code."> <i class="hgi hgi-stroke hgi-mail-send-01" aria-hidden="true"></i> <span class="nds-label">Send code</span> </button>

Built-in Features

Pure CSS

No JavaScript required. All variants, sizes, and states render from HTML markup with design tokens.

Six Variants

Primary, neutral, secondary, secondary-outline, subtle, and transparent with full state coverage.

Three Sizes

24px to 40px. Font, icon, and indicator scale proportionally.

Layout Options

Lead icon, trail icon, icon-only, label-only, circular, full-width, and loading state.

Accessibility

High contrast borders, reduced motion fallback, print styles, and focus-visible ring.

Composable

Combine with destructive, on-color, loading, progress, status, badge, indicator, and groups.

Usage Guidelines

When to Use

  • Use primary for the main action on the page. Limit to one per view
  • Use neutral for strong secondary actions that need visual weight
  • Use secondary/outline for supporting actions alongside a primary button
  • Use subtle/transparent for low-emphasis actions like cancel, dismiss, or tertiary options
  • Use destructive for delete, remove, or irreversible actions. Pair with a confirmation dialog
  • Use on-color variants when placing buttons on colored or dark backgrounds
  • Use icon-only for toolbar actions where space is limited. Always include aria-label
  • Use loading state after a click to indicate processing. Disable the button to prevent double submissions
  • Use cooldown for rate-limited actions like resend OTP, where the button must be locked for a set period after each click

Modifier Classes

ClassDescription
nds-primaryPrimary variant, green background
nds-neutralNeutral variant, dark background
nds-secondarySecondary solid variant, light gray background
nds-secondary-outlineSecondary outlined variant, transparent background with border
nds-subtleNo background until hover
nds-transparentNo background at any state; text color shifts on hover
nds-transparent nds-colorTransparent variant where default text uses the primary brand color and reverts to default on hover
nds-destructiveRed-tone modifier, combine with any variant
nds-oncolorLight-on-dark modifier for colored/dark backgrounds
nds-lg40px height (default, no class required)
nds-md32px height
nds-sm24px height
nds-icon-onlyHides label text (screen-reader accessible via clip)
nds-label-onlyHides icon elements
nds-lead-iconForces icon before label (row direction)
nds-trail-iconForces icon after label (row-reverse)
nds-fullFull-width, centered label
nds-circle999px border-radius for circular icon buttons
nds-indicatorAdds a bottom-edge active indicator bar
nds-menu-btnDropdown trigger with rotating chevron indicator
nds-nextDirectional button, arrow points forward (RTL-aware)
nds-prevDirectional button, arrow points backward with reversed flex order (RTL-aware)
nds-upDirectional button, arrow points up
nds-downDirectional button, arrow points down
nds-ellipsisFixed-width icon-only button with a horizontal more icon
nds-progressShows the .nds-progress-circle overlay
nds-progress-staticDisables the countdown animation; progress driven by --progress-value
nds-cooldownMarks the button for cooldown behavior. Requires data-cooldown
nds-verticalSet on a .nds-btn-group to stack it down instead of across. The rounded corners move to the top and bottom of the column and the seam runs along the block axis

Data Attributes

AttributeElementDescription
data-state.nds-btnSimulates interaction states: default, hover, pressed, selected, focused, loading, cooldown
data-status.nds-btnApplies a contextual color and swaps the icon. Values: success, error, info, warning
data-cooldown.nds-cooldownCooldown duration in seconds (required). Read once at wire time and frozen.
data-cooldown-loading.nds-cooldownSeconds to hold the loading state before the countdown begins (default: 0)
data-cooldown-label.nds-cooldownLabel template during countdown. Use {s} for remaining seconds (default: {s})
data-resend-label.nds-cooldownLabel to restore after the first completed cycle (e.g., initial "Send" becomes "Resend"). Omit to keep the original label.
data-sent-title.nds-cooldownOptional toast title shown when the cooldown begins (requires NDS.Alert to be loaded)
data-sent-message.nds-cooldownOptional toast description shown when the cooldown begins (requires NDS.Alert to be loaded)

CSS Custom Properties

PropertyDefaultDescription
--btn-size40pxControls button height and the square dimension for icon-only buttons. Set by size modifier classes.
--btn-group-radiusvar(--radius-md)Border-radius applied to the .nds-btn-group ends. Automatically reduces to --radius-sm when the group contains nds-md or nds-sm buttons.
--progress-duration4000msDuration of the animated progress countdown. Set inline on the button: style="--progress-duration: 4000ms;"
--progress-value0Static progress percentage (0-100) for nds-progress-static buttons. Set inline: style="--progress-value: 25;"
--progress-circumference62.83SVG circle circumference in px. Matches the stroke-dasharray value on the SVG circle. Override only if the SVG radius is changed.

JavaScript API: NDS.CooldownButton

MethodParametersDescription
NDS.CooldownButton.start(btn)btn: HTMLElementProgrammatically triggers the cooldown cycle on the given button. No-op if the button is already in a cycle or has no data-cooldown attribute.
NDS.CooldownButton.reset(btn)btn: HTMLElementCancels an active cooldown or loading phase and restores the button immediately. Fires nds:cooldown:end.

Custom Events

All events bubble and are dispatched on the .nds-cooldown button element.

EventDetailWhen fired
nds:cooldown:loadingThe loading phase begins (only when data-cooldown-loading is greater than 0)
nds:cooldown:triggeredThe loading phase ends and the countdown starts. Fire toast notifications here for custom variants.
nds:cooldown:tick{ remaining: number }Fires every second during the countdown. detail.remaining is the seconds left.
nds:cooldown:endThe cooldown finished naturally or reset() was called. The button is restored and re-enabled.
Last Modified Date: 24/07/2026 - 04:05 PM
Was this page useful?
60% of users said Yes from 2843 Feedbacks