# AiButton

> Lo que hace la IA: el botón, el ícono, el lanzador flotante del asistente, el borde que se enciende mientras trabaja y el placeholder. Con su propio color, que no es el de marca.

```tsx
import { AiButton, AiGlow, AiIcon, AiLauncher, … } from "sebs7n-ui/ai-button"
```

## Ejemplos

### El botón

`outline` para una acción de IA entre otras; `solid` para la principal. Uno sólido por pantalla.

```tsx
import { AiButton, AiIcon } from "sebs7n-ui/ai-button"

function Basico() {
  return (
    <div className="flex flex-wrap items-center gap-3">
      <AiButton variant="solid">
        <AiIcon />
        Generar resumen
      </AiButton>
      <AiButton>
        <AiIcon />
        Completar con IA
      </AiButton>
      <AiButton size="sm">
        <AiIcon />
        Mejorar
      </AiButton>
      <AiButton aria-label="Preguntarle a la IA" size="icon-md">
        <AiIcon />
      </AiButton>
      <AiButton loading variant="solid">
        Generando…
      </AiButton>
      <AiButton disabled>
        <AiIcon />
        Sin conexión
      </AiButton>
    </div>
  )
}
```

### El lanzador

El botón redondo que abre el asistente. Con `active`, el canto gira: hay una respuesta en camino. Acá va adentro de una caja para que se vea en la página; en una app flota con `className="fixed right-6 bottom-6"`.

```tsx
import { AiLauncher } from "sebs7n-ui/ai-button"

function Lanzador() {
  return (
    <div className="relative flex h-40 w-full max-w-md items-end justify-end gap-6 p-4">
      <AiLauncher labelVisible />
      {/* Con una respuesta en camino, el canto gira. */}
      <AiLauncher active label="Respondiendo" labelSide="right" />
    </div>
  )
}
```

### La IA está trabajando

El borde se enciende en cualquier contenedor mientras la IA trabaja, y el placeholder ocupa el lugar de lo que está escribiendo. Apretá el botón: dura tres segundos.

```tsx
import { AiButton, AiGlow, AiIcon, AiShimmer } from "sebs7n-ui/ai-button"
import { Card, CardContent } from "sebs7n-ui/card"
import { useState } from "react"

function Trabajando() {
  const [leyendo, setLeyendo] = useState(false)
  return (
    // `relative` es lo que ancla el borde a la tarjeta; `aria-busy` es lo que anuncia la espera.
    <Card aria-busy={leyendo} className="relative w-full max-w-sm" size="sm">
      <AiGlow active={leyendo} />
      <CardContent className="flex flex-col gap-4">
        {leyendo ? (
          <div className="flex flex-col gap-2">
            <AiShimmer className="w-2/3" />
            <AiShimmer />
            <AiShimmer className="w-1/2" />
          </div>
        ) : (
          <p className="text-callout text-label-secondary">Subí el comprobante y la IA completa los datos de la factura.</p>
        )}
        <AiButton
          disabled={leyendo}
          onClick={() => {
            setLeyendo(true)
            setTimeout(() => setLeyendo(false), 3000)
          }}
          variant="solid"
        >
          <AiIcon />
          {leyendo ? "Leyendo el comprobante…" : "Leer el comprobante"}
        </AiButton>
      </CardContent>
    </Card>
  )
}
```

## Props

### AiButton

| Prop | Tipo | Por defecto | Descripción |
|---|---|---|---|
| `loading` | `boolean` | — | Muestra el spinner y frena el click. Se anuncia con `aria-busy`, como en `Button`. |
| `size` | `S` | — | Los mismos seis tamaños de `Button`. Con uno de ícono (`icon-sm`, `icon-md`, `icon-lg`) el tipo exige `aria-label`. |
| `variant` | `"outline" \| "solid"` | `"outline"` | `outline` es una acción de IA entre otras: «Resumir», «Completar con IA». `solid` es la acción principal de un flujo de IA: enviar la pregunta, generar. |
| `className` | `string` | — | Se fusiona con las clases del componente vía `cn()` (tailwind-merge): lo que pongas gana. |
| `disabled` | `boolean` | — | **Heredada de Base UI.** Apaga la interacción y lo marca con `data-disabled`, que es el atributo del que cuelgan los estilos de apagado. |

### AiGlow

Hereda las props de `<div>`.

| Prop | Tipo | Por defecto | Descripción |
|---|---|---|---|
| `active` | `boolean` | `false` | La IA está trabajando. Sin esto el borde está apagado. |
| `className` | `string` | — | Se fusiona con las clases del componente vía `cn()` (tailwind-merge): lo que pongas gana. |

### AiIcon

| Prop | Tipo | Por defecto | Descripción |
|---|---|---|---|
| `className` | `string` | — | Se fusiona con las clases del componente vía `cn()` (tailwind-merge): lo que pongas gana. |

### AiLauncher

Hereda las props de `<button>`.

| Prop | Tipo | Por defecto | Descripción |
|---|---|---|---|
| `active` | `boolean` | `false` | La IA está trabajando: el canto gira. Es lo que avisa, con el panel cerrado, que hay una respuesta en camino. En reposo el canto está quieto. |
| `label` | `string` | — | El nombre del lanzador. Es su nombre accesible y también la etiqueta que aparece al lado al pasar el puntero o al enfocarlo. Por defecto, «Asistente». |
| `labels` | `Partial<AiLabels>` | — | Textos de la interfaz, para traducir o ajustar el tono. |
| `labelSide` | `"left" \| "right"` | `"left"` | De qué lado del botón va la etiqueta. Por defecto a la izquierda: el lanzador vive abajo a la derecha. |
| `labelVisible` | `boolean` | `false` | Deja la etiqueta a la vista siempre, no solo con el puntero encima. |
| `className` | `string` | — | Se fusiona con las clases del componente vía `cn()` (tailwind-merge): lo que pongas gana. |

### AiShimmer

Hereda las props de `<div>`.

| Prop | Tipo | Por defecto | Descripción |
|---|---|---|---|
| `className` | `string` | — | Se fusiona con las clases del componente vía `cn()` (tailwind-merge): lo que pongas gana. |

## Teclado

| Tecla | Qué hace |
|---|---|
| Enter · Espacio | Activa el botón. |
| Tab | El lanzador es una parada de tabulación más; al enfocarlo muestra su etiqueta. |

## Accesibilidad

- `AiButton` es el `Button` del sistema: mismo foco, mismo apagado, misma espera (`aria-busy`).
- `AiLauncher` no tiene texto adentro: su nombre accesible es `label` (por defecto, «Asistente»). La etiqueta que aparece al lado es el mismo texto y está fuera del árbol de accesibilidad, para que no se lea dos veces.
- `AiIcon` y `AiShimmer` son decoración (`aria-hidden`). La espera la anuncia el contenedor: `aria-busy`, o el `role="status"` de `ChatTyping`.
- El texto en color IA llega a 4,5:1 sobre la superficie en los dos temas, y el blanco sobre el sólido también. Lo verifica un test.

## Reglas de uso

- `outline` para una acción de IA entre otras («Resumir», «Completar con IA»). `solid` para la principal de un flujo de IA. **Uno sólido por pantalla.**
- El color de la IA es propio y no el de marca, a propósito: lo que hace la IA tiene que distinguirse de lo que hace la app, con cualquier brand.
- `AiLauncher` no se posiciona solo: `className="fixed right-6 bottom-6"`. Depende de qué más flote ahí.
- Como trigger de un `Popover` o un `Sheet`: `render={<AiLauncher />}`.
- `AiShimmer` va donde iría un `Skeleton`, en un flujo de IA: dice «alguien lo está escribiendo», no «esto está cargando».
- `AiGlow` es el borde de la IA para cualquier contenedor: se suelta adentro de un `Dialog`, un `Popover` o una `Card` con `relative`, y se enciende con `active`. **Siempre que la IA esté trabajando, y solo entonces**: es lo que hace que signifique algo. El contenedor anuncia la espera con `aria-busy`.
- `active` en el lanzador hace girar el canto. Es una señal de estado —hay una respuesta en camino—, no un adorno: encendido siempre, deja de significar algo.

## Relacionados

[chat](/docs/components/chat.md) · [button](/docs/components/button.md) · [skeleton](/docs/components/skeleton.md) · [popover](/docs/components/popover.md)
