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')}
/>
);
}