Hecho sobre el UI SDK 0.1.0-beta.1 de Vercel. Su API puede cambiar.
Token input
Un campo de texto sobre el UI SDK de Vercel que mezcla texto con tokens para personas, archivos y comandos, con sugerencias con @ y /.
- Componentes de formulario
- 15 partes
- 10 ejemplos
@tabler/icons-react@ui-sdk/core@ui-sdk/react
pnpm dlx shadcn@latest add https://hextaui.com/r/ui-sdk-token-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 @ui-sdk/react@0.1.0-beta.1 @ui-sdk/core@0.1.0-beta.1 @tabler/icons-react cnCopia y pega el siguiente código en tu proyecto.
components/ui/ui-sdk-token-input.tsx Actualiza las rutas de importación para que coincidan con la configuración de tu proyecto.
UI SDK añade un poco de CSS propio en una capa de cascada llamada ui-sdk. Declara esa capa al principio de tu hoja de estilos global, encima del import de Tailwind, para que tus clases ganen.
Un valor es un array de texto y tokens. Cada token tiene un type, un value para tu app y un label que leen las personas. El editor gestiona su contenido, selección y deshacer, así que deja que renderice y pasa renderToken para cambiar cómo se ve un token. Sin él, cada token muestra su label y un botón de quitar.
Un TriggerMenu dentro del input sugiere tokens cuando alguien escribe un disparador como @ o /. Omítelo cuando tu código aporte los tokens.
Escribe @ para archivos o / al principio para skills. Un archivo queda pendiente mientras carga, y al enviar cada skill se marca como en curso y luego como hecha con updateToken(). Enter envía y Shift+Enter añade una línea.
tokenDeletion define qué hace Retroceso en un token. whole lo quita, select primero lo selecciona y revert lo vuelve texto.
Un controlador de createTokenInputController() inserta, actualiza y quita tokens desde el código. Pasa una promesa como resolve para dejar un token pendiente hasta que se resuelva.
Con un name, el input envía su texto con cada token escrito como [@label](type:value). required bloquea un envío vacío, y reiniciar vuelve a defaultValue.
Con submitShortcut="mod+enter", Enter añade una línea y Command o Control+Enter envía, algo que prefieren muchas personas que escriben en japonés y chino.
Un codec convierte los tokens en texto y viceversa, aquí como <@id>. Con copy="label", copiar escribe lo que se lee, y al pegar de vuelta se restauran los tokens.
Un input deshabilitado no recibe foco ni cambia, oculta los botones de quitar y no envía nada.
Con readOnly, el texto sigue recibiendo foco, se puede seleccionar y se envía, pero escribir, pegar y soltar no lo cambian.
El editor sigue la dirección de la página, y un token sigue siendo una pieza dentro de texto de derecha a izquierda.
| Key | Acción |
|---|---|
| BackspaceDelete | Quita el token antes o después del cursor, según tokenDeletion. |
| ←→ | Mueve el cursor más allá de un token de una pulsación. Nunca se detiene dentro de uno. |
| ↑↓ | Recorre las sugerencias mientras el menú está abierto. |
| Enter | Envía. Con el menú abierto, elige la sugerencia resaltada. |
| Shift + Enter | Inicia una nueva línea. |
| ⌘ + EnterCtrl + Enter | Envía cuando submitShortcut es mod+enter. Enter empieza entonces una línea nueva. |
| ⌘ + ZCtrl + Z | Deshace el último paso. Lo escrito se agrupa, y pegar o cambiar tokens son pasos propios. |
| Esc | Cierra las sugerencias. |
El editor es un cuadro de texto multilínea. Un menú de disparadores dentro añade aria-autocomplete y aria-haspopup, y el foco sigue en el texto mientras las flechas recorren las sugerencias. Cada token se lee como su label y su tipo, como “routes.ts archivo”, y se anuncia al insertarlo o quitarlo. Nombra el editor con aria-label o con una etiqueta alrededor.
Los botones de quitar se ocultan a los lectores de pantalla, ya que Retroceso quita un token desde el teclado. Su área táctil crece en pantallas táctiles, un token pendiente solo pulsa si se permite el movimiento, y un token seleccionado recibe un borde de resaltado del sistema en el modo de colores forzados.
Cada parte envuelve la parte de UI SDK del mismo nombre y acepta todas sus props, incluidas render y un className que puede ser una función del estado de la parte.
| Prop | Tipo | Predeterminado |
|---|---|---|
value | TokenInputValue | – |
defaultValue | TokenInputValue | – |
onValueChangeSe ejecuta al escribir, pegar, usar menús, deshacer y con llamadas del controlador. details indica el motivo y los tokens quitados. | (value, details) => void | – |
onSubmitSe ejecuta con el atajo de envío, salvo que haya un menú abierto o un método de entrada componiendo. | (value, details) => void | – |
submitShortcut | "enter" | "mod+enter" | "enter" |
tokenDeletion | "whole" | "select" | "revert" | "whole" |
renderTokenRenderiza un token. Por defecto, un TokenInputToken con su label y un botón de quitar. | (token: Token) => ReactNode | – |
copy | "codec" | "label" | "codec" |
codec | TokenCodec | – |
getTokenDescriptionLo que un token dice a los lectores de pantalla además de su label. | (token: Token) => string | – |
history | { limit, groupDelay } | – |
name | string | – |
form | string | – |
required | boolean | false |
disabled | boolean | false |
readOnly | boolean | false |
controllerDe createTokenInputController(). | TokenInputController | – |
| Prop | Tipo | Predeterminado |
|---|---|---|
placeholderSe muestra con aria-placeholder mientras el input está vacío. | string | – |
render | ReactElement | (props, state) => ReactElement | – |
| Atributo | Descripción |
|---|---|
data-slot="token-input-editor" | Para apuntar al editor en CSS. |
data-empty | Presente mientras el input está vacío. |
data-disabled | Presente cuando está deshabilitado. |
data-readonly | Presente cuando es de solo lectura. |
| Atributo | Descripción |
|---|---|
data-slot="token-input-token" | Para apuntar a un token en CSS. |
data-token-type | El tipo del token, como file o mention. |
data-selected | Presente mientras el token está en la selección o seleccionado para quitarlo. |
data-pending | Presente mientras el token carga. |
data-unresolved | Presente mientras el token necesita a la persona, como una mención ambigua. |
Quita su token y mantiene el foco en el editor. Renderiza un icono X de Tabler salvo que pases children, y se oculta mientras el input está deshabilitado o es de solo lectura.
| Prop | Tipo | Predeterminado |
|---|---|---|
triggersLos caracteres que abren el menú, el tipo de token que inserta cada uno y sus elementos. | TriggerDefinition[] | – |
onSelectSe ejecuta al elegir un elemento. Devuelve una promesa para insertar el token como pendiente. | (value, details) => void | Promise | – |
autoHighlight | boolean | true |
loop | boolean | true |
| Prop | Tipo | Predeterminado |
|---|---|---|
align | "start" | "center" | "end" | "start" |
sideOffset | number | 6 |
collisionPadding | number | 8 |
| Atributo | Descripción |
|---|---|
data-slot="trigger-menu-content" | Para apuntar al popup en CSS. |
data-trigger | El disparador de la coincidencia actual, como @, para que cada lista pueda verse distinta. |
data-starting-style | Presente mientras el popup se anima al entrar. |
data-ending-style | Presente mientras el popup se anima al salir. |
| Prop | Tipo | Predeterminado |
|---|---|---|
value | T | – |
labelEl texto que se inserta y compara, cuando el contenido no es texto plano. | string | – |
disabled | boolean | false |
| Atributo | Descripción |
|---|---|
data-highlighted | Presente en el elemento resaltado. El foco sigue en el editor. |
data-disabled | Presente cuando el elemento no se puede elegir. |
- CalendarUna cuadrícula de fechas para selección única, de rango y múltiple, con meses deslizantes, vistas previas de rango y días de tamaño táctil.
- CheckboxUna casilla de verificación cuya marca se dibuja, con padres indeterminados, grupos y etiquetas que comparten su hover.
- ComboboxUn select filtrable con chips, grupos y resultados asíncronos, en un popup que cambia de tamaño mientras escribes.
- Date pickerUn botón que abre un calendario en un popover, o en una hoja inferior en móviles, para fechas únicas y rangos.
- FieldEtiquetas, descripciones y errores conectados a su control, con estados de validación y diseños para formularios.
- InputUn 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.