Input
Un campo de texto con tres tamaños, estados inválido y de solo lectura, estilos de validación nativos y una fuente táctil de 16px para que los móviles nunca hagan zoom.
pnpm dlx shadcn@latest add https://hextaui.com/r/input.jsonAñade el componente, los tokens del tema de HextaUI y los componentes de HextaUI de los que depende.
Añade los tokens del tema a tu CSS global, si aún no lo has hecho.
Instala las dependencias.
pnpm add @base-ui/react class-variance-authority cnCopia y pega el siguiente código en tu proyecto.
components/ui/input.tsx components/ui/number-flow.tsx lib/motion.ts Actualiza las rutas de importación para que coincidan con la configuración de tu proyecto.
Tamaños
sm, default y lg coinciden con las alturas de los botones, así que un input y un botón del mismo tamaño se alinean en una fila.
Con una descripción
Apunta aria-describedby al texto de ayuda para que los lectores de pantalla lo lean después de la etiqueta.
Inválido
aria-invalid pone el borde y el anillo de foco en rojo. Vincula el mensaje con aria-describedby para que se anuncie, no solo se coloree.
Validación nativa
Los campos con required, type="email" o pattern solo se ponen rojos después de que alguien haya escrito en ellos o intentado enviar, nunca en el primer renderizado. Un envío que encuentra un campo no válido lo sacude una vez, para que la vista se dirija a lo que hay que corregir. Nunca se sacude mientras escribes o tabulas. Envía el formulario vacío para verlo.
Deshabilitado
Un input deshabilitado no puede recibir foco, editarse ni enviarse con el formulario.
Solo lectura
readOnly mantiene el valor enfocable, seleccionable y enviado, con una superficie atenuada para que no parezca editable. Prefiérelo a disabled para valores que la gente necesita copiar.
Archivo
type="file" recibe el mismo marco, con el botón del navegador rediseñado como texto simple.
Tipos de input
Password, number, search, date y time comparten una misma altura y marco. En modo oscuro, los selectores y spinners del navegador también pasan a oscuro.
Controlado
onValueChange te entrega la cadena directamente, así que no hay un event.target.value que desenvolver. onChange también sigue funcionando.
Con un botón
Lado a lado con un hueco, o unidos en un solo control dentro de un <ButtonGroup />, donde el input ocupa el ancho restante.
Cuadrícula
Los inputs llenan su contenedor, así que colócalos en una cuadrícula. Dale a las celdas de la cuadrícula min-w-0 para que los valores largos no puedan estirar una columna.
Contenido largo
Los valores largos se desplazan dentro del campo y los placeholders largos se cortan, sin ensanchar el diseño.
De derecha a izquierda
El texto, el cursor y el relleno siguen la dirección. Usa dir="auto" en campos que contienen valores de izquierda a derecha, como una dirección de correo en un formulario en árabe.
- Cada input necesita un nombre. Usa un
<label>conhtmlFor, oaria-labelcuando no hay una etiqueta visible. Un placeholder no es una etiqueta. - Conecta el texto de ayuda y de error con
aria-describedby, y definearia-invalidsolo cuando haya un error que mostrar. - En pantallas táctiles el texto es de al menos 16px, para que iOS Safari no haga zoom en la página cuando el input recibe foco.
- Dentro de un
Fieldde Base UI, la etiqueta, la descripción, el error y la validez se conectan por ti.
Construido sobre el input de Base UI. Acepta todos los atributos nativos de input.
| Prop | Tipo | Predeterminado |
|---|---|---|
sizeAltura y relleno, a juego con los botones. | "sm" | "default" | "lg" | "default" |
htmlSizeEl atributo size nativo, renombrado porque size es la variante. | number | – |
value | string | number | string[] | – |
defaultValue | string | number | string[] | – |
onValueChangeSe llama con el nuevo valor en cada cambio. | (value: string, details) => void | – |
type | string | "text" |
disabled | boolean | false |
readOnly | boolean | false |
aria-invalidMuestra el borde de no válido y el anillo de foco. | boolean | – |
className | string | (state) => string | – |
shakeSe sacude una vez cuando el envío de un formulario encuentra este input no válido. Funciona con la validación nativa, Field de Base UI y librerías que definen aria-invalid. Se omite con movimiento reducido. | boolean | true |
render | ReactElement | (props, state) => ReactElement | <input> |
| Atributo | Descripción |
|---|---|
data-slot="input" | Selecciona el input en CSS. |
data-size | El tamaño actual. |
data-shake | Presente mientras el input se sacude tras un envío fallido. |
data-disabled | Presente cuando el input está deshabilitado. |
data-invalid | Presente cuando el Field circundante no es válido. Con el mismo estilo que aria-invalid. |
data-valid | Presente cuando el Field circundante es válido. |
data-touched | Presente después de que el input perdió el foco una vez, dentro de un Field. |
data-dirty | Presente una vez que el valor cambió, dentro de un Field. |
data-filled | Presente cuando el input tiene un valor, dentro de un Field. |
data-focused | Presente mientras tiene foco, dentro de un Field. |
Los nombres de clase detrás del input, para dar estilo a otro elemento a juego, como un <select> o <textarea> nativo. Llámalo con { size }.
El recuento de caracteres detrás de <InputGroupCount /> y <FieldCounter />. Usa esas partes, que leen el campo por ti. Recurre a este solo cuando lleves tú mismo la cuenta de la longitud.
| Prop | Tipo | Predeterminado |
|---|---|---|
lengthObligatorio. | number | – |
maxLength | number | null | – |
threshold | number | 10% of maxLength, at most 20 |
announcement | (remaining: number) => string | – |
| Atributo | Descripción |
|---|---|
data-slot="input-count" | Apunta al contador en CSS. |
data-state="near" | "limit" | Presente dentro del umbral y en el límite. |
- MotionLas curvas de easing, duraciones y la comprobación de movimiento reducido con las que se anima cada componente, además de hooks para transformaciones de tamaño y resaltados deslizantes.
- Number flowNúmeros animados donde solo giran los dígitos que cambian, con cualquier formato Intl y configuración regional.
- useAutosizeHace crecer un textarea según lo que escribes entre su altura mínima y máxima, animando cada cambio sin tocar nunca el texto.
- useComposedRefMantiene una ref a tu propio elemento y sigue reenviándola a la ref que haya pasado el padre.
- useInvalidShakeSacude un control de formulario cuando un intento de envío lo encuentra inválido, y nunca mientras alguien aún está escribiendo.
- useMergedRefCombina cualquier cantidad de refs de callback y de objeto en una sola, con la limpieza de refs de React 19 para cada una.
Usado en bloques
Bloques que se construyen sobre Input.
- API keysLa página de claves de API de un producto de IA, como las consolas de OpenAI y Anthropic. Crea claves con permisos acotados y caducidad, ve el secreto una sola vez con una copia que lo confirma, revoca con deshacer, renombra en el sitio, rota con un periodo de gracia y consulta el uso por clave.
- BillingPlan y uso para un producto de IA, al estilo de Cursor, Claude y Vercel. Un medidor de uso dividido por modelo que proyecta el final del ciclo y avisa antes de que se agoten los créditos, un gráfico diario por el que puedes desplazarte, un límite de gasto con alertas que puedes previsualizar en el medidor, cambios de plan con prorrateo exacto, un formulario de tarjeta con validación real y facturas descargables en PDF.
- ModelsLa página Modelos de los ajustes de un producto de IA. Un modelo predeterminado con su contexto, velocidad y coste de un vistazo, un esfuerzo predeterminado que sabe qué admite cada modelo, una lista de modelos con búsqueda agrupada por proveedor con filtros, fijados e interruptores masivos, servidores compatibles con OpenAI con una prueba de conexión real y una actualización que te dice qué hay de nuevo.
- NotificationsLa sección Notificaciones de los ajustes de un producto de IA. Una cuadrícula de canal por evento con toggles por fila, por columna y para todo, horas de silencio con una línea en vivo del próximo silencio, un resumen por correo, envíos de prueba reales para escritorio, correo, push y Slack, gestión de permisos del navegador y un flujo para conectar Slack. Se integra en cualquier sección de Ajustes.