# TextField

Campo de texto em pílula (HTML copy-first) e Input compatível com shadcn.

> Documentação do Sinapse DS. Snippets shadcn usam os componentes do seu projeto (`@/components/ui/*`); snippets HTML usam as classes `itps-*` do CSS Sinapse (`/css/<versão>/`, veja `/comecar.md`). Componentes do site de documentação não fazem parte do DS.

- Categoria: Forms
- Status: stable
- Relacionados: /componentes/field.md, /componentes/search.md, /componentes/select.md

## Em cada stack

- HTML e Astro: Classes `itps-*` do CSS Sinapse, com todas as variantes desta página.
- React e Vue: Componentes padrão do shadcn (`input`) com o tema Sinapse: cores, fonte e raio vêm do tema, e as variantes `itps-*` desta página existem só no HTML.

**React/Next (shadcn/ui)**

```tsx
import { Input } from '@/components/ui/input'

export function TextFieldExample() {
  return <Input type="email" placeholder="nome@example.com" />
}
```

**Vue 3/Nuxt 4 (shadcn-vue)**

```vue
<script setup lang="ts">
import { Input } from '@/components/ui/input'
</script>

<template>
  <Input type="email" placeholder="nome@example.com" />
</template>
```

**HTML (copy-first)**

```html
<div class="itps-textfield">
  <i class="itps-textfield__icon ti ti-mail" aria-hidden="true"></i>
  <input class="itps-textfield__input" type="email" placeholder="nome@example.com" />
</div>
```

## Instalação

O comando instala o Input da sua stack com o tema Sinapse. Configure o registry uma vez por projeto em [Comece por aqui](/comecar).

**terminal · React/Next**

```sh
pnpm dlx shadcn@latest add @sinapse/textfield
```

**terminal · Vue 3/Nuxt 4**

```sh
pnpm dlx shadcn-vue@latest add https://dsystem.sinapse.org.br/r/vue/textfield.json
```

Sem shadcn, não há instalação por componente: use o CSS Sinapse e as classes da API copy-first desta página.

## Uso

Em React/Next com shadcn/ui e Vue 3/Nuxt 4 com shadcn-vue, use o `Input` instalado pela stack. O tema Sinapse vem dos tokens instalados pelo CLI do shadcn ou do shadcn-vue.

Use `itps-textfield` quando precisar do contrato copy-first em pílula, ícones internos ou composição direta em HTML.

## Exemplos

### Tamanhos

| Uso | React/Next e Vue 3/Nuxt 4 | HTML |
|-----|--------------------------|------|
| Pequeno | defina no componente instalado, quando existir | `itps-textfield--sm` |
| Padrão | padrão do `Input` | sem modificador |
| Grande | defina no componente instalado, quando existir | `itps-textfield--lg` |

Nas classes `itps-textfield`, os tamanhos seguem o token `form-height`: 40, 48 e 56px.

### Estados

| Estado | React/Next e Vue 3/Nuxt 4 | HTML |
|--------|--------------------------|------|
| Desabilitado | `disabled` | `is-disabled` no wrapper e `disabled` no input |
| Inválido | `aria-invalid="true"` | `is-invalid` no wrapper e `aria-invalid="true"` no input |
| Preenchido | valor controlado ou `defaultValue` | valor no input |

Associe mensagens de ajuda ou erro com `aria-describedby`.

### Ícones

Ícones internos do `itps-textfield` são decorativos ou indicadores e devem usar `aria-hidden="true"`. Para ações, como revelar senha ou limpar busca, use um botão nomeado com `aria-label`.

### Com Field

Use `Field` como composição visual: label, ajuda e mensagens ficam fora do `TextField`.

**HTML (copy-first)**

```html
<div class="itps-field">
  <label for="phone" class="itps-field__label">
    Telefone <span class="itps-field__required" aria-hidden="true">*</span>
  </label>
  <div class="itps-textfield">
    <input
      id="phone"
      name="phone"
      type="tel"
      class="itps-textfield__input"
      placeholder="(11) 99999-9999"
      required
      aria-describedby="phone-help"
    />
  </div>
  <p id="phone-help" class="itps-field__hint">Use DDD + número.</p>
</div>
```

## API copy-first

| Classe/atributo | Uso |
|-----------------|-----|
| `itps-textfield` | Wrapper visual do campo em pílula. |
| `itps-textfield__input` | Input interno sem borda própria. |
| `itps-textfield__icon` | Ícone interno decorativo ou indicador. |
| `itps-textfield__icon--danger` | Ícone de erro em estado inválido. |
| `itps-textfield--sm` | Altura 40px. |
| `itps-textfield--lg` | Altura 56px. |
| `is-disabled` | Estado desabilitado no wrapper. |
| `is-invalid` | Estado inválido no wrapper. |
| `disabled` | Desabilita o input nativo. |
| `aria-invalid="true"` | Comunica estado inválido. |
| `aria-describedby` | Liga o controle ao texto de apoio ou erro. |
| `aria-hidden="true"` | Esconde ícones decorativos de tecnologias assistivas. |

## Acessibilidade

Associe labels externos com `for`/`id`. Use `aria-describedby` para texto de apoio ou erro. Ícones decorativos devem usar `aria-hidden="true"`; ações dentro do campo precisam ser botões nomeados.
