Input
Campos de texto permitem que usuários insiram e editem texto. Usa um padrão de wrapper com um elemento de campo interno para estilização consistente.Text inputs allow users to enter and edit text. Uses a wrapper pattern with an inner field element for consistent styling.
Quando usarWhen to use
| SituaçãoSituation | Use em vez dissoUse instead |
|---|---|
| Texto multilinhaMulti-line text | Textarea |
| Escolher de uma listaChoosing from a list | Select |
| Sim/não ou liga/desligaYes/no or on/off | Toggle ou Checkbox |
| Busca com autocompleteSearching with autocomplete | Componente de busca customizado (futuro)Custom search component (future) |
AnatomiaAnatomy
.ds-input) — container com borda, radius, background, padding e gap.2 Ícone (opcional,
.ds-input__icon) — frame 24px; ícone 16/20/24px em sm/md/lg.3 Campo (
.ds-input__field) — o elemento nativo <input>.4 Label (
.ds-field__label) — externo, via Form Field.5 Mensagem de erro (
.ds-field__error) — externa, via Form Field.6 Texto auxiliar (
.ds-field__helper) — externo, via Form Field.
1 Wrapper (.ds-input) — container with border, radius, background, padding and gap.2 Icon (optional,
.ds-input__icon) — 24px frame; 16/20/24px ícone in sm/md/lg.3 Field (
.ds-input__field) — the native <input> element.4 Label (
.ds-field__label) — external, via Form Field.5 Error message (
.ds-field__error) — external, via Form Field.6 Helper text (
.ds-field__helper) — external, via Form Field.
PadrãoDefault
<div class="ds-field">
<div class="ds-field__label-row">
<label class="ds-field__label" for="input-default">Label</label>
</div>
<div class="ds-input">
<input type="text" class="ds-input__field" id="input-default"
placeholder="Enter text..."
aria-describedby="input-default-helper">
</div>
<span class="ds-field__helper" id="input-default-helper">Helper text</span>
</div>
TamanhosSizes
<div class="ds-input ds-input--sm">
<input type="text" class="ds-input__field" placeholder="Small (32px)">
</div>
<div class="ds-input ds-input--md">
<input type="text" class="ds-input__field" placeholder="Medium (40px)">
</div>
<div class="ds-input ds-input--lg">
<input type="text" class="ds-input__field" placeholder="Large (48px)">
</div>
Com íconeWith Icon
<!-- Leading icon -->
<div class="ds-input">
<i data-lucide="search" class="ds-input__icon ds-icon"></i>
<input type="text" class="ds-input__field" placeholder="Leading icon">
</div>
<!-- Trailing icon -->
<div class="ds-input">
<input type="text" class="ds-input__field" placeholder="Trailing icon">
<i data-lucide="eye" class="ds-input__icon ds-icon"></i>
</div>
<!-- Both sides -->
<div class="ds-input">
<i data-lucide="mail" class="ds-input__icon ds-icon"></i>
<input type="text" class="ds-input__field" placeholder="Both sides">
<i data-lucide="x" class="ds-input__icon ds-icon"></i>
</div>
EstadosStates
No Figma, State representa apenas estados visuais exclusivos: Default, Hover, Focus e Disabled. Filled, Error e Read-only são propriedades separadas; Error combina com Default/Hover/Focus, e Read-only combina com Default/Focus.In Figma, State only represents exclusive visual states: Default, Hover, Focus, and Disabled. Filled, Error, and Read-only are separate properties; Error combines with Default/Hover/Focus, and Read-only combines with Default/Focus.
Error
<div class="ds-field ds-field--error">
<label class="ds-field__label" for="email">Email address</label>
<div class="ds-input ds-input--error">
<input type="email" class="ds-input__field" id="email"
value="invalid-email" aria-invalid="true"
aria-describedby="email-error">
</div>
<span class="ds-field__error" id="email-error">Please enter a valid email address.</span>
</div>
Disabled
<div class="ds-input">
<input type="text" class="ds-input__field" value="Disabled input" disabled>
</div>
Readonly
<div class="ds-input">
<input type="text" class="ds-input__field" value="Read-only value" readonly>
</div>
| Figma property | Value / CSS trigger | Visual change | Token |
|---|---|---|---|
| State | Default | Neutral surface and border | component.field.bg.default, component.field.border-color.default |
| State | Hover / :hover | Darker border | component.field.border-color.hover |
| State | Focus / :focus-within | 2px outline ring, component radius | component.field.border-color.focus, component.focus-ring.*, component.input.focus-ring.radius.default |
| State | Disabled / [disabled] or .ds-input--disabled | Muted bg, border and content | component.field.bg.disabled, component.field.value.color.disabled |
| Error | True / .ds-input--error or .ds-field--error .ds-input | Red border and error focus ring | component.field.border-color.error, component.focus-ring.color.error |
| Error + State | True + Hover / .ds-input--error:hover | Darker red border | component.field.border-color.error-hover |
| Read-only | True / [readonly] or .ds-input--readonly | Readonly bg with neutral focus ring | component.field.bg.readonly, component.focus-ring.color.readonly |
Com Form FieldWith Form Field
<div class="ds-field">
<label class="ds-field__label" for="name">Full name</label>
<div class="ds-input">
<input type="text" class="ds-input__field" id="name" placeholder="John Doe">
</div>
<span class="ds-field__helper">Enter your first and last name.</span>
</div>
<div class="ds-field ds-field--error">
<label class="ds-field__label" for="email">Email<span class="ds-field__required">*</span></label>
<div class="ds-input">
<input type="email" class="ds-input__field" id="email" aria-invalid="true" aria-describedby="email-error">
</div>
<span class="ds-field__error" id="email-error">Please enter a valid email address.</span>
<span class="ds-field__helper">We'll never share your email.</span>
</div>
Boas práticasBest practices
ds-input--error E ds-field--error, com aria-invalid="true" e uma mensagem de erro clara.Show error state with ds-input--error AND ds-field--error, with aria-invalid="true" and a clear error message.Diretrizes de conteúdoContent guidelines
| RegraRule | ExemploExample |
|---|---|
| O texto do placeholder deve ser um valor de exemplo, não uma instruçãoPlaceholder text should be an example value, not an instruction | "john@example.com" — não "Enter your email""john@example.com" — not "Enter your email" |
| Labels devem ter 1-3 palavras, substantivo ou frase nominalLabels should be 1-3 words, noun or noun phrase | "Email address", "Phone number" |
| Texto auxiliar é opcional, use para dicas de formatoHelper text is optional, use for format hints | "Deve ter pelo menos 8 caracteres""Must be at least 8 characters" |
| Mensagens de erro devem dizer o que deu errado E como corrigirError messages should say what went wrong AND how to fix it | "Email é obrigatório. Insira um endereço de email válido.""Email is required. Enter a valid email address." |
| Campos obrigatórios: adicione indicador de obrigatório ao labelRequired fields: add required indicator to the label | <span class="ds-field__required">*</span> |
Mapeamento de tokensToken mapping
Tokens consumidos pelo componente Input em seus estados.Tokens consumed by the Input component across its states.
| PropriedadeProperty | Token | Variável CSSCSS variable |
|---|---|---|
| bg (default/disabled/error/filled/focus/readonly) | component.field.bg.* | --ds-field-bg-* |
| border-color (default/hover/focus/error/filled/disabled/readonly) | component.field.border-color.* | --ds-field-border-color-* |
| border-width | component.field.border-width | --ds-field-border-width |
| border-radius | component.field.radius | --ds-field-radius |
| focus ring | component.focus-ring.* + component.input.focus-ring.radius.default | --ds-focus-ring-* + --ds-input-focus-ring-radius-default |
| content color | component.field.value.color.{default,disabled,readonly} | --ds-field-value-color-* |
| placeholder color | component.field.placeholder.color.{default,disabled} | --ds-field-placeholder-color-* |
| icon color | component.input.icon.color.{default,disabled} | --ds-input-icon-color-* |
| height (sm/md/lg) | component.input.height.{sm,md,lg} | --ds-input-height-* |
| padding-x (sm/md/lg) | component.input.padding-x.{sm,md,lg} | --ds-input-padding-x-* |
| padding-y (sm/md/lg) | component.field.padding-y.{sm,md,lg} | --ds-field-padding-y-* |
| gap (sm/md/lg) | component.input.gap.{sm,md,lg} | --ds-input-gap-* |
| text-frame padding-x | component.input.text-frame.padding-x.default | --ds-input-text-frame-padding-x-default |
| icon | component.input.icon.{color,size,stroke-width}.{sm,md,lg} + component.input.icon-frame.padding-x.default | --ds-input-icon-*, --ds-input-icon-frame-padding-x-default |
| text typography | component.input.text.{font-family,font-size,font-weight,letter-spacing,line-height}.* | --ds-input-text-* |
| label typography/color | component.form-field.label.* | --ds-form-field-label-* |
| required typography/color | component.form-field.required.* | --ds-form-field-required-* |
| helper typography/color | component.form-field.helper.* | --ds-form-field-helper-* |
| stack/label-row gap | component.form-field.stack.gap.default, component.form-field.label-row.gap.default | --ds-form-field-stack-gap-default, --ds-form-field-label-row-gap-default |
Classes CSSCSS classes
| ClasseClass | DescriçãoDescription |
|---|---|
ds-input | Elemento wrapper do inputWrapper element for the input |
ds-input__field | O elemento nativo <input>The native <input> element |
ds-input__icon | Ícone à esquerda dentro do wrapperLeading icon inside the wrapper |
ds-input--sm | Tamanho pequeno (altura 32px)Small size (32px height) |
ds-input--md | Tamanho médio (altura 40px, padrão)Medium size (40px height, default) |
ds-input--lg | Tamanho grande (altura 48px)Large size (48px height) |
ds-input--error | Estado de erro com borda vermelhaError state with red border |
ds-input--disabled | Estado desabilitado (ou use o nativo disabled)Disabled state (or use native disabled) |
ds-input--readonly | Estado somente leitura (ou use o nativo readonly)Readonly state (or use native readonly) |
ds-field | Wrapper de campo de formulário com label, auxiliar e erroForm field wrapper with label, helper, and error |
ds-field__label | Label do campoField label |
ds-field__helper | Texto auxiliar abaixo do inputHelper text below the input |
ds-field__error | Linha de erro com ícone automático e mensagem (exibida quando ds-field--error está definido)Error row with automatic icon and message (shown when ds-field--error is set) |
ds-field--error | Estado de erro no wrapper do campoError state on the field wrapper |
ds-field__label-row | Linha horizontal com label e asterisco de obrigatórioHorizontal row with label and required asterisk |
ds-field__required | Asterisco * em feedback/error/content/default (decorativo, aria-hidden)Asterisk * in feedback/error/content/default (decorative, aria-hidden) |
ds-field--no-label | Oculta o label row quando Show Label = falseHides the label row when Show Label = false |
ds-field--no-helper | Oculta o helper text quando Show Helper Text = falseHides helper text when Show Helper Text = false |
Propriedades FigmaFigma properties
| PropriedadeProperty | TipoType | PadrãoDefault | DescriçãoDescription |
|---|---|---|---|
Show Label | Boolean | true | Exibe ou oculta o label row (incluindo asterisco de obrigatório)Shows or hides the label row (including required asterisk) |
Label | Text | "Rótulo" | Texto do label (label/md)Label text (label/md) |
Required | Boolean | false | Exibe o asterisco * em feedback/error/content/default ao lado do labelShows * in feedback/error/content/default next to the label |
Show Helper Text | Boolean | true | Exibe ou oculta o texto auxiliar abaixo do controleShows or hides the helper text below the control |
Helper Text | Text | "Texto auxiliar" | Anotação em caption/sm (content/secondary)Caption/sm annotation (content/secondary) |
Interação por tecladoKeyboard interaction
| TeclaKey | AçãoAction |
|---|---|
Tab | Move o foco para dentro / fora do inputMoves focus into / out of the input |
| Qualquer caractereAny character | Digita no campoTypes into the field |
Escape | Remove o foco (padrão do navegador)Clears focus (browser default) |
AccessibilityAccessibility
| Critério WCAGWCAG criterion | RequisitoRequirement | Status |
|---|---|---|
| 1.3.1 Info and Relationships (A) | Label associado via for/idLabel associated via for/id | ✓ |
| 1.3.5 Identify Input Purpose (AA) | Use o atributo autocomplete para campos de dados pessoaisUse autocomplete attribute for personal data fields | ✓ (when implemented) |
| 2.4.11 Focus Appearance (AA) | Focus ring 2px + offset de 2pxFocus ring 2px + 2px offset | ✓ |
| 3.3.1 Error Identification (A) | Estado de erro + mensagem via aria-invalid + aria-describedbyError state + message via aria-invalid + aria-describedby | ✓ |
| 3.3.2 Labels or Instructions (A) | Label visível sempre presenteVisible label always present | ✓ |
| 4.1.2 Name, Role, Value (A) | O <input> nativo fornece o roleNative <input> provides role | ✓ |
for / id — sempre associe <label> com <input> usando atributos correspondentes.aria-invalid="true" — definido no input nativo quando em estado de erro.aria-describedby — vincule o input ao ID do elemento de mensagem de erro para que leitores de tela anunciem o erro.autocomplete — use valores apropriados (name, email, tel, etc.) para campos de dados pessoais.for / id — always pair <label> with <input> using matching attributes.aria-invalid="true" — set on the native input when in error state.aria-describedby — link the input to the error message element ID so screen readers announce the error.autocomplete — use appropriate values (name, email, tel, etc.) for personal data fields.
Required = true, adicione aria-required="true" no <input> — o asterisco visual (.ds-field__required) é decorativo (aria-hidden="true"). Quando Show Label = false, use aria-label no <input>. O Helper Text deve ser vinculado via aria-describedby.When Required = true, add aria-required="true" to the <input> — the visual asterisk (.ds-field__required) is decorative (aria-hidden="true"). When Show Label = false, use aria-label on the <input>. Helper Text should be linked via aria-describedby.