LoadingButton
LoadingButton es un botón completo que acepta un booleano isLoading externo. Cuando está cargando, la etiqueta y los íconos son reemplazados por un spinner centrado y el botón se deshabilita. A diferencia de ActionButton, no gestiona peticiones HTTP — tú controlas el estado de carga desde afuera, lo que lo hace ideal para envíos de formularios manejados por hooks o stores.
El componente se renderiza centrado dentro de un div con 20px de padding vertical, lo que lo hace adecuado para pies de formulario.
Props
| Prop | Tipo | Requerido | Por defecto | Descripción |
|------|------|-----------|-------------|-------------|
| title | string | Sí | — | Texto de la etiqueta que se muestra dentro del botón cuando no está cargando. |
| onClick | () => void | Sí | — | Callback que se dispara cuando se presiona el botón. |
| isLoading | boolean | No | false | Cuando es true, reemplaza el contenido del botón con un spinner y deshabilita la interacción. |
| color | string | No | "primary" | Clave de color del tema o cualquier color CSS (hex o nombre). |
| borderRadius | number | No | 4 | Radio del borde en píxeles. |
| type | "clear" \| "outline" \| "solid" | No | "solid" | Variante visual del botón. |
| disabled | boolean | No | false | Deshabilita la interacción independientemente de isLoading. |
| startIcon | string | No | — | Identificador del ícono renderizado antes de la etiqueta (oculto mientras carga). |
| startIconPaths | string[] | No | — | Datos de path SVG para un ícono de inicio personalizado. |
| startIconSize | number | No | — | Tamaño en píxeles para sobreescribir el ícono de inicio. |
| startIconStyle | React.CSSProperties | No | — | Estilos en línea aplicados al ícono de inicio. |
| startIconColor | string | No | — | Color del ícono de inicio. |
| endIcon | string | No | — | Identificador del ícono renderizado después de la etiqueta (oculto mientras carga). |
| endIconPaths | string[] | No | — | Datos de path SVG para un ícono final personalizado. |
| endIconSize | number | No | — | Tamaño en píxeles para sobreescribir el ícono final. |
| endIconStyle | React.CSSProperties | No | — | Estilos en línea aplicados al ícono final. |
| endIconColor | string | No | — | Color del ícono final. |
| hasShadow | boolean | No | true | Si se aplica sombra al botón. |
| style | React.CSSProperties | No | — | Estilos en línea aplicados al contenedor del botón. |
| titleStyle | React.CSSProperties | No | — | Estilos en línea aplicados al texto de la etiqueta. |
| size | "xs" \| "sm" \| "md" \| "lg" \| "xl" | No | "md" | Controla el padding, tamaño de fuente, tamaño del ícono y del spinner. |
| className | string | No | "loading-button" | Nombre de clase CSS aplicado al contenedor. |
| spinnerColor | string | No | — | Color del spinner de carga. |
Uso
Envío de formulario básico
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)); // simular llamada API
setLoading(false);
};
return (
<LoadingButton
title="Iniciar sesión"
isLoading={loading}
onClick={handleSubmit}
/>
);
}
Con íconos y color de spinner personalizado
import LoadingButton from '@/components/buttons/LoadingButton';
export default function Example({ loading }: { loading: boolean }) {
return (
<LoadingButton
title="Guardar cambios"
isLoading={loading}
onClick={() => {}}
startIcon="save"
spinnerColor="white"
size="lg"
/>
);
}