Campos de texto
Cada campo va en un .form-field, que ordena y separa el form-label, el control y los textos de ayuda o validación. form-input sirve para <input> y <textarea>.
form-helper agrega un texto de ayuda. Conéctalo al campo con aria-describedby.
<div class="form-field"> <label class="form-label" for="nombre">Nombre</label> <input class="form-input" type="text" id="nombre" name="nombre" placeholder="Ej.: Ana Pérez" autocomplete="name" aria-describedby="nombre-ayuda"> <p class="form-helper" id="nombre-ayuda">Como quieres que te llamemos.</p></div>export default function CamposBasico() { return ( <div className="form-field"> <label className="form-label" htmlFor="nombre">Nombre</label> <input className="form-input" type="text" id="nombre" name="nombre" placeholder="Ej.: Ana Pérez" autoComplete="name" aria-describedby="nombre-ayuda" /> <p className="form-helper" id="nombre-ayuda">Como quieres que te llamemos.</p> </div> );}Obligatorio
Sección titulada «Obligatorio»Agrega el atributo required al campo y marca el label con form-label__required. El asterisco va con aria-hidden="true": el lector de pantalla ya anuncia el campo como obligatorio por required.
<div class="form-field"> <label class="form-label" for="email">Email <span class="form-label__required" aria-hidden="true">*</span></label> <input class="form-input" type="email" id="email" name="email" autocomplete="email" required></div>export default function CamposObligatorio() { return ( <div className="form-field"> <label className="form-label" htmlFor="email">Email <span className="form-label__required" aria-hidden="true">*</span></label> <input className="form-input" type="email" id="email" name="email" autoComplete="email" required /> </div> );}Textarea
Sección titulada «Textarea»Usa la misma clase form-input. El textarea tiene esquinas menos redondeadas, un alto mínimo de 120 px y solo cambia de tamaño en vertical.
<div class="form-field"> <label class="form-label" for="comentario">Comentario</label> <textarea class="form-input" id="comentario" name="comentario" rows="4" placeholder="Cuéntanos qué necesitas"></textarea></div>export default function CamposTextarea() { return ( <div className="form-field"> <label className="form-label" htmlFor="comentario">Comentario</label> <textarea className="form-input" id="comentario" name="comentario" rows="4" placeholder="Cuéntanos qué necesitas" /> </div> );}Tamaños
Sección titulada «Tamaños»form-input--sm y form-input--lg tienen el mismo alto que btn--sm y btn--lg, así quedan alineados en una fila.
<input class="form-input form-input--sm" type="text" placeholder="Pequeño" aria-label="Ejemplo pequeño"><input class="form-input" type="text" placeholder="Normal" aria-label="Ejemplo normal"><input class="form-input form-input--lg" type="text" placeholder="Grande" aria-label="Ejemplo grande">export default function CamposTamanos() { return ( <> <input className="form-input form-input--sm" type="text" placeholder="Pequeño" aria-label="Ejemplo pequeño" /> <input className="form-input" type="text" placeholder="Normal" aria-label="Ejemplo normal" /> <input className="form-input form-input--lg" type="text" placeholder="Grande" aria-label="Ejemplo grande" /> </> );}Deshabilitado y solo lectura
Sección titulada «Deshabilitado y solo lectura»disabled: el campo se ve atenuado, no recibe foco y no se envía con el formulario.readonly: se ve igual que un campo normal, recibe foco y se envía, pero no se puede editar.
<div class="form-field"> <label class="form-label" for="plan">Plan</label> <input class="form-input" type="text" id="plan" value="Básico" disabled></div><div class="form-field"> <label class="form-label" for="cliente">Código de cliente</label> <input class="form-input" type="text" id="cliente" value="DS-0042" readonly></div>export default function CamposEstados() { return ( <> <div className="form-field"> <label className="form-label" htmlFor="plan">Plan</label> <input className="form-input" type="text" id="plan" defaultValue="Básico" disabled /> </div> <div className="form-field"> <label className="form-label" htmlFor="cliente">Código de cliente</label> <input className="form-input" type="text" id="cliente" defaultValue="DS-0042" readOnly /> </div> </> );}Para los estados de error y de campo válido, revisa Validación.
Accesibilidad
Sección titulada «Accesibilidad»- Todo campo necesita un label:
<label for="…">con el mismo valor deliddel campo. Si no se muestra un label, usaaria-label. El placeholder no reemplaza al label. - Usa el
typeadecuado (email,tel,url,number) yautocomplete(name,email,tel…): en móvil se abre el teclado correcto y el navegador puede autocompletar. - El foco muestra el borde primary y un anillo de 4 px.
- En iOS, un campo con letra menor a 16 px hace zoom al enfocarlo. Evita
form-input--smen formularios para móvil. - Con los colores por defecto, el borde del campo (
--ds-color-border) tiene un contraste de 1,2:1, bajo el 3:1 que pide WCAG para los bordes de un control.
| Clase | Uso |
|---|---|
form-field |
Agrupa label, control y textos. También sirve en <fieldset>. |
form-label |
Label del campo (o <legend> de un grupo). |
form-label__required |
Asterisco de campo obligatorio. |
form-input |
Campo de texto en <input> y <textarea>. |
form-input--sm, form-input--lg |
Tamaños. |
form-helper |
Texto de ayuda. |
Variables
Sección titulada «Variables»form-input y form-select comparten estas variables:
| Variable | Valor por defecto | Uso |
|---|---|---|
--ds-form-input-bg | var(--ds-color-surface) | Fondo. |
--ds-form-input-color | var(--ds-color-text) | Color del texto. |
--ds-form-input-border-color | var(--ds-color-border) | Color del borde. |
--ds-form-input-placeholder-color | var(--ds-color-text-muted) | Color del texto de ejemplo (placeholder). |
--ds-form-input-padding-y | 0.375rem | Espacio vertical interno. |
--ds-form-input-padding-x | 0.75rem | Espacio horizontal interno. |
--ds-form-input-font-size | var(--ds-font-size-base) | |
--ds-form-input-line-height | var(--ds-line-height-base) | |
--ds-form-input-radius | var(--ds-radius-full) | Radio de las esquinas (píldora). |
--ds-form-input-multiline-radius | var(--ds-radius-lg) | Radio del textarea y del select múltiple. |
--ds-form-input-textarea-min-height | 7.5rem | Alto mínimo del textarea. |
--ds-form-input-focus-border-color | var(--ds-color-primary) | Borde con foco. |
--ds-form-input-focus-ring-color | color-mix(in srgb, var(--ds-color-primary) 15%, transparent) | Anillo de foco. |
--ds-form-input-focus-ring-width | 4px | Grosor del anillo de foco. |
--ds-form-input-invalid-color | var(--ds-color-danger) | Borde y anillo con error (is-invalid o aria-invalid). |
--ds-form-input-valid-color | var(--ds-color-success) | Borde y anillo de un campo válido (is-valid). |
--ds-form-input-disabled-opacity | 0.6 | Opacidad cuando está deshabilitado. |
| Variable | Valor por defecto | Uso |
|---|---|---|
--ds-form-field-gap | var(--ds-space-2) | Separación entre label, control y mensajes. |
--ds-form-field-margin-bottom | var(--ds-space-4) | Margen inferior (separa campos seguidos). |
| Variable | Valor por defecto | Uso |
|---|---|---|
--ds-form-label-color | var(--ds-color-text) | Color del texto. |
--ds-form-label-font-size | var(--ds-font-size-sm) | |
--ds-form-label-font-weight | var(--ds-font-weight-regular) | |
--ds-form-label-required-color | var(--ds-color-danger) | Color del asterisco de campo obligatorio. |
Texto de ayuda
Sección titulada «Texto de ayuda»| Variable | Valor por defecto | Uso |
|---|---|---|
--ds-form-helper-color | var(--ds-color-text-muted) | Color del texto. |
--ds-form-helper-font-size | var(--ds-font-size-sm) |