/v1.0

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