Skip to main content

Documentation Index

Fetch the complete documentation index at: https://araf.badr.co.id/llms.txt

Use this file to discover all available pages before exploring further.

Overview

The Button component is the primary interactive element in the A’raf Design System. It can render as a <button> or <a> tag automatically depending on whether the href prop is provided.

Installation

npm install @araf-ds/core

Usage

import { Button } from "@araf-ds/core"

export default function Example() {
  return <Button>Click me</Button>
}

Variants

Button has 7 visual hierarchies reflecting the level of action emphasis.

Primary

Used for the primary and most important action on a page. Use sparingly — one per view at most.
<Button color="primary">Save changes</Button>
<Button color="primary" isDisabled>Disabled</Button>

When to use

  • Primary form submission
  • Page-level CTA
  • Irreversible actions

When not to use

  • More than one important action in the same area
  • Secondary or tertiary actions

Secondary

Two variants: secondary with a light blue background and secondary-gray with a gray border. Use alongside Primary for alternative actions.
<Button color="secondary">Secondary</Button>
<Button color="secondary-gray">Secondary Gray</Button>

Tertiary

A borderless button that looks like plain text but retains an interactive hit area. Use for tertiary actions that don’t need visual prominence.
<Button color="tertiary">Tertiary</Button>
<Button color="tertiary-gray">Tertiary Gray</Button>
Appears as a hyperlink. Available in two colors: link-color and link-gray.
<Button color="link-color">View profile</Button>
<Button color="link-gray">Terms of service</Button>
Add the href prop to make this button render as an anchor tag for navigation.

Destructive

Red variant for dangerous or permanent actions. Available across all hierarchies.
<Button color="primary-destructive">Delete account</Button>
<Button color="secondary-destructive">Remove</Button>
<Button color="tertiary-destructive">Discard changes</Button>
Always add a confirmation dialog before triggering a destructive action.

Sizes

5 sizes are available to match different layout contexts.
SizePropHeightUse case
Smallsm36pxTables, dense toolbars
Mediummd40pxDefault — forms, cards, dialogs
Largelg44pxHero sections, landing pages
Extra Largexl48pxMarketing pages
2X Large2xl56pxFull-width CTAs, splash screens
<Button size="sm">Small</Button>
<Button size="md">Medium</Button>
<Button size="lg">Large</Button>
<Button size="xl">Extra Large</Button>
<Button size="2xl">2X Large</Button>
Keep sizes consistent within a single UI context. Do not mix sm and xl in the same toolbar.

States

StatePropDescription
DefaultNormal appearance
HoverBackground becomes #045CA0, handled automatically
FocusedRing 4px #CDE4F5 for keyboard navigation
DisabledisDisabledOpacity 0.4, cursor not-allowed
LoadingisLoadingSpinner scales to match button size and color
<Button>Default</Button>
<Button isDisabled>Disabled</Button>
<Button isLoading>Loading</Button>
<Button isLoading showTextWhileLoading>Saving changes</Button>
Avoid hiding a button when it is unavailable. Use isDisabled so users can still see the action exists.

Icons

Button supports icons on the left, right, or in icon-only mode.
import { Button } from "@araf-ds/core"
import { PlusIcon, ArrowRightIcon } from "@araf-ds/core/icons"

// Leading icon
<Button iconLeading={PlusIcon}>New item</Button>

// Trailing icon
<Button iconTrailing={ArrowRightIcon}>Continue</Button>

// Icon only — aria-label required
<Button iconLeading={PlusIcon} aria-label="Add new item" />
For icon-only mode, always add an aria-label prop so screen readers can identify the button’s action.

Button renders as an <a> tag simply by adding the href prop.
// Internal navigation
<Button href="/dashboard">Go to dashboard</Button>

// External link
<Button href="https://example.com" target="_blank" rel="noopener noreferrer">
  Open docs
</Button>

API Reference

color
string
default:"primary"
Visual hierarchy of the button. Values: primary · secondary · secondary-gray · tertiary · tertiary-gray · link-color · link-gray · primary-destructive · secondary-destructive · tertiary-destructive · link-destructive
size
string
default:"md"
Button size. Values: sm · md · lg · xl · 2xl
isDisabled
boolean
default:"false"
Disables interaction and applies the disabled visual state.
isLoading
boolean
default:"false"
Shows a loading spinner and prevents interaction.
showTextWhileLoading
boolean
default:"false"
When true, the children text remains visible during isLoading.
iconLeading
ComponentType
Icon component rendered to the left of the label. Without children, the button becomes icon-only.
iconTrailing
ComponentType
Icon component rendered to the right of the label.
href
string
When provided, the button renders as an <a> anchor tag.
className
string
Additional Tailwind classes for custom overrides.

Accessibility

  • Uses a semantic <button> element by default
  • The disabled state is handled with the native disabled attribute
  • Keyboard focus is shown with a 4px #CDE4F5 outline ring
  • Icon-only mode requires an aria-label
  • When rendered as a link (href), full anchor semantics apply

Do’s & Don’ts

Do

  • Use Primary for one main action per page
  • Pair Primary + Secondary for confirm/cancel actions
  • Always add aria-label on icon-only buttons
  • Use the Destructive variant for irreversible actions

Don't

  • Don’t use more than one Primary button in the same section
  • Don’t use custom colors outside the design system
  • Don’t hide a disabled button — use the isDisabled prop instead
  • Don’t use the Link variant for actions that modify data