# Input

> El campo de texto. Tres alturas y el mismo cuerpo que Select, Combobox y Textarea.

```tsx
import { Input } from "sebs7n-ui/input"
```

## Ejemplos

### Con etiqueta

```tsx
import { Input } from "sebs7n-ui/input"
import { Label } from "sebs7n-ui/label"
import { useId } from "react"

function ConEtiqueta() {
  const id = useId()
  return (
    <div className="flex w-full max-w-sm flex-col gap-2">
      <Label htmlFor={id} required>
        Razón social
      </Label>
      <Input id={id} placeholder="Acme S.A." />
    </div>
  )
}
```

### Tamaños

```tsx
import { Input } from "sebs7n-ui/input"

function Tamanos() {
  return (
    <div className="flex w-full max-w-sm flex-col gap-3">
      <Input size="sm" placeholder="sm · 32px" />
      <Input size="md" placeholder="md · 40px" />
      <Input size="lg" placeholder="lg · 48px" />
    </div>
  )
}
```

### Error

`aria-invalid` es todo: el borde rojo y el anillo salen de ahí.

```tsx
import { Input } from "sebs7n-ui/input"
import { Label } from "sebs7n-ui/label"
import { useId, useState } from "react"

function Error() {
  const id = useId()
  const [valor, setValor] = useState("acme@")
  const invalido = !/^[^@\s]+@[^@\s.]+\.[^@\s]+$/.test(valor)
  return (
    <div className="flex w-full max-w-sm flex-col gap-2">
      <Label htmlFor={id}>Email</Label>
      <Input
        aria-describedby={invalido ? `${id}-error` : undefined}
        aria-invalid={invalido || undefined}
        id={id}
        onChange={(event) => setValor(event.target.value)}
        type="email"
        value={valor}
      />
      {invalido && (
        <p className="text-copy-13 text-red-900" id={`${id}-error`}>
          Escribí un email válido, con dominio.
        </p>
      )}
    </div>
  )
}
```

### Deshabilitado y solo lectura

```tsx
import { Input } from "sebs7n-ui/input"

function Estados() {
  return (
    <div className="flex w-full max-w-sm flex-col gap-3">
      <Input defaultValue="No se puede editar" disabled />
      <Input defaultValue="30-71234567-9" readOnly />
    </div>
  )
}
```

## Props

### Input

Hereda las props de `Input`.

| Prop | Tipo | Por defecto | Descripción |
|---|---|---|---|
| `size` | `"sm" \| "md" \| "lg"` | `"md"` | `sm` 32px · `md` 40px · `lg` 48px, con el texto un paso más grande. |
| `className` | `string` | — | — |

## Teclado

| Tecla | Qué hace |
|---|---|
| Tab | Entra y sale del campo. |
| Escape | No hace nada por defecto: si limpia el campo, lo implementa la app. |

## Accesibilidad

- **`aria-invalid` es todo lo que hace falta para el error**: el borde rojo y el anillo salen de ahí, no de una clase aparte.
- Siempre con `Label` asociado por `htmlFor`/`id`. Un `placeholder` no es una etiqueta: desaparece al escribir.
- El mensaje de error va en un `<p id="…-error">` referenciado con `aria-describedby`, para que se lea al enfocar.
- `focus:focus-border` en vez del anillo: en un campo el borde teñido molesta menos y se ve igual.

## Reglas de uso

- **El tamaño se elige una vez por formulario**, no por campo. `md` (40px) es el de una app; `lg` para un formulario de una sola pregunta.
- `type` importa más que el estilo: `email`, `tel`, `url` y `numeric` cambian el teclado del celular.
- Un campo obligatorio se marca en el `Label` (`required`), no con un asterisco pegado al placeholder.
- Para un buscador con sugerencias no uses `Input` a mano: `Combobox` o `Autocomplete`.

## Relacionados

[label](/docs/components/label.md) · [textarea](/docs/components/textarea.md) · [select](/docs/components/select.md) · [combobox](/docs/components/combobox.md)
