LoadingButton
LoadingButton is a full-featured button that accepts an external isLoading boolean. When loading, the label and icons are replaced with a centered spinner and the button is disabled. Unlike ActionButton, it does not manage HTTP requests — you control the loading state from outside, making it ideal for form submissions handled by hooks or stores.
The component renders centered inside a div with 20px vertical padding, making it well-suited for form footers.
Props
| Prop | Type | Required | Default | Description |
|------|------|----------|---------|-------------|
| title | string | Yes | — | Label text displayed inside the button when not loading. |
| onClick | () => void | Yes | — | Callback fired when the button is pressed. |
| isLoading | boolean | No | false | When true, replaces the button content with a spinner and disables interaction. |
| 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 independently of isLoading. |
| startIcon | string | No | — | Icon identifier rendered before the label (hidden while loading). |
| startIconPaths | string[] | No | — | SVG path data for a custom start icon. |
| 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 (hidden while loading). |
| 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, icon size, and spinner size. |
| className | string | No | "loading-button" | CSS class name applied to the wrapper. |
| spinnerColor | string | No | — | Color of the loading spinner. |
Usage
Basic form submission
import LoadingButton from '@/components/buttons/LoadingButton';
import { useState } from 'react';
export default function LoginForm() {
const [loading, setLoading] = useState(false);
const handleSubmit = async () => {
setLoading(true);
await new Promise((r) => setTimeout(r, 2000)); // simulate API call
setLoading(false);
};
return (
<LoadingButton
title="Sign In"
isLoading={loading}
onClick={handleSubmit}
/>
);
}
With icons and custom spinner color
import LoadingButton from '@/components/buttons/LoadingButton';
export default function Example({ loading }: { loading: boolean }) {
return (
<LoadingButton
title="Save Changes"
isLoading={loading}
onClick={() => {}}
startIcon="save"
spinnerColor="white"
size="lg"
/>
);
}