/v1.0

ActionButton

ActionButton is a versatile button component that handles both local click actions and remote HTTP requests. It supports icons on both sides, multiple visual styles, size variants, a typing animation for its label, and a built-in loading spinner while a request is in flight.

Use it when you need a button that can directly call an API endpoint without writing request logic in the parent component.

Props

| Prop | Type | Required | Default | Description | |------|------|----------|---------|-------------| | title | string | Yes | — | Label text displayed inside the button. | | onClick | () => void | Yes | — | Callback fired when the button is pressed. | | color | string | No | "primary" | Theme color key or any CSS hex/named color. | | borderRadius | number | No | 4 | Border radius in pixels. | | type | "clear" \| "outline" \| "solid" | No | "solid" | Visual variant of the button. | | disabled | boolean | No | false | Disables interaction and reduces opacity. | | startIcon | string | No | — | Icon identifier rendered before the label. | | startIconPaths | string[] | No | — | SVG path data for a custom start icon (alternative to startIcon). | | startIconSize | number | No | — | Override size for the start icon in pixels. | | startIconStyle | React.CSSProperties | No | — | Inline styles applied to the start icon. | | startIconColor | string | No | — | Color override for the start icon. | | endIcon | string | No | — | Icon identifier rendered after the label. | | endIconPaths | string[] | No | — | SVG path data for a custom end icon. | | endIconSize | number | No | — | Override size for the end icon in pixels. | | endIconStyle | React.CSSProperties | No | — | Inline styles applied to the end icon. | | endIconColor | string | No | — | Color override for the end icon. | | hasShadow | boolean | No | true | Whether to apply a drop shadow. | | style | React.CSSProperties | No | — | Inline styles applied to the button container. | | titleStyle | React.CSSProperties | No | — | Inline styles applied to the label text. | | size | "xs" \| "sm" \| "md" \| "lg" \| "xl" | No | "md" | Controls padding, font size, and icon size. | | className | string | No | "button" | CSS class name applied to the wrapper. | | animateTitle | boolean | No | false | When true, the label appears with a typing animation. | | animationSpeed | number | No | 50 | Speed of the typing animation in milliseconds per character. | | onAnimationComplete | () => void | No | — | Callback fired when the typing animation finishes. | | apiBaseUrl | string | No | — | Base URL for the HTTP request. Overrides the default client base URL. | | path | string | No | — | API endpoint path. When provided, a request is made on click. | | useAuthToken | boolean | No | — | When true, uses the authenticated HTTP client (includes Bearer token). | | method | "GET" \| "POST" \| "PUT" \| "DELETE" | No | "POST" | HTTP method for the request. | | data | Record<string, any> | No | — | Request body payload sent with the HTTP request. | | spinnerPosition | "start" \| "end" | No | "end" | Where the loading spinner appears relative to the label. | | spinnerColor | string | No | — | Color of the loading spinner. | | onSuccess | (response: any) => void | No | — | Callback fired when the HTTP request succeeds. | | onError | (error: any) => void | No | — | Callback fired when the HTTP request fails. | | isExport | boolean | No | false | When true and method is "GET", uses getBlob() to download binary data. |

Usage

Basic

import ActionButton from '@/components/buttons/ActionButton';

export default function Example() {
  return (
    <ActionButton
      title="Save Changes"
      onClick={() => console.log('clicked')}
    />
  );
}

With icons and outline style

import ActionButton from '@/components/buttons/ActionButton';

export default function Example() {
  return (
    <ActionButton
      title="Export Report"
      onClick={() => {}}
      type="outline"
      color="primary"
      startIcon="download"
      size="sm"
    />
  );
}

Remote API call with loading state

import ActionButton from '@/components/buttons/ActionButton';

export default function Example() {
  return (
    <ActionButton
      title="Submit Order"
      onClick={() => {}}
      path="/v1/orders"
      method="POST"
      useAuthToken
      data={{ productId: 42, quantity: 1 }}
      onSuccess={(res) => console.log('Order created', res)}
      onError={(err) => console.error('Failed', err)}
      spinnerPosition="start"
    />
  );
}

Typing animation

import ActionButton from '@/components/buttons/ActionButton';

export default function Example() {
  return (
    <ActionButton
      title="Welcome to Snapping!"
      onClick={() => {}}
      animateTitle
      animationSpeed={40}
      onAnimationComplete={() => console.log('Animation done')}
    />
  );
}