Message scroller
Un área de desplazamiento de chat que sigue los mensajes nuevos, conserva tu posición mientras lees mensajes anteriores y cuenta lo que te perdiste en el botón de salto.
New chat
How can I help you today?
The prompt is read only. Press send to play the next turn.
pnpm dlx shadcn@latest add https://hextaui.com/r/message-scroller.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 @shadcn/react @tabler/icons-react cnCopia y pega el siguiente código en tu proyecto.
components/ui/message-scroller.tsx components/ui/button.tsx lib/motion.ts Actualiza las rutas de importación para que coincidan con la configuración de tu proyecto.
Da a cada elemento un messageId estable. El scroller lo usa para seguir los mensajes nuevos, mantener tu posición y contar lo que no has visto. Combínalo con <Message /> y <Bubble /> para las filas.
Chat de grupo
Los anclajes no tienen por qué ser mensajes. Aquí un <Marker /> de alguien que se une inicia el turno. Haz scroll hacia arriba, recibe mensajes, y el botón de salto cuenta lo que llegó mientras no estabas.
Mantener el contexto
scrollPreviousItemPeek mantiene un trozo del turno anterior sobre uno recién anclado, para que el hilo siga sintiéndose continuo. Prueba cada valor y luego haz la siguiente pregunta.
Abrir hilos guardados
defaultScrollPosition="last-anchor" reabre una conversación en su última pregunta, con la respuesta debajo, en lugar de dejar al lector en mitad de la respuesta, al final.
Cargar mensajes anteriores
Los mensajes antiguos añadidos por encima mantienen en su sitio lo que estás leyendo (preserveScrollOnPrepend, activado por defecto).
Saltar a mensajes
useMessageScroller controla el hilo desde fuera, y useMessageScrollerVisibility informa del turno actual, de modo que el índice resalta dónde estás.
Dentro del provider, estos hooks permiten que tus propios controles desplacen el hilo y reaccionen a lo que hay en pantalla.
| Key | Acción |
|---|---|
| Tab | Enfoca la conversación. El botón de salto entra en el orden de tabulación solo mientras se muestra. |
| ↑↓ | Desplaza la conversación. |
| Page UpPage Down | Se desplaza una pantalla. |
| HomeEnd | Salta al primer mensaje o al más reciente. |
- El viewport es una región enfocable con etiqueta y el contenido es un
role="log", así que los lectores de pantalla anuncian los mensajes nuevos al llegar. Dale al viewport unaria-label. - La etiqueta del botón de salto indica cuántos mensajes son nuevos, de modo que se lee "3 mensajes nuevos" y no solo una flecha.
- Seguir los mensajes nuevos nunca te mueve mientras relees. Solo se reanuda cuando vuelves a estar al final.
| Prop | Tipo | Predeterminado |
|---|---|---|
autoScrollSigue los mensajes nuevos mientras el lector está al final. | boolean | false |
defaultScrollPositionDónde se abre el hilo. | "start" | "end" | "last-anchor" | "end" |
scrollPreviousItemPeekCuánto del elemento anterior permanece visible sobre un anclaje nuevo. | number | 64 |
scrollEdgeThresholdPíxeles desde un borde que aún cuentan como estar en él. | number | – |
scrollMarginEspacio que se mantiene sobre los mensajes desplazados a la vista. | number | – |
| Prop | Tipo | Predeterminado |
|---|---|---|
preserveScrollOnPrependMantiene la posición de lectura cuando se añaden mensajes por encima. | boolean | false |
aria-labelDa nombre a la región de la conversación. | string | – |
| Atributo | Descripción |
|---|---|
data-scrollable="start end" | Qué bordes tienen más contenido por desplazar. Controla los degradados de los bordes. |
data-autoscrolling | Presente mientras se siguen los mensajes nuevos. La barra de scroll se oculta. |
--scroller-fade-start / --scroller-fade-end | Tamaño de los degradados de los bordes. Aparecen y desaparecen con animación. |
| Prop | Tipo | Predeterminado |
|---|---|---|
messageIdId estable para el seguimiento, los anclajes y los recuentos. | string | – |
scrollAnchorDesplaza este elemento a la parte superior cuando llegue, con defaultScrollPosition="last-anchor". | boolean | false |
| Prop | Tipo | Predeterminado |
|---|---|---|
direction | "start" | "end" | "end" |
showUnseenCrece hasta convertirse en una píldora que cuenta los mensajes que llegaron mientras estabas más arriba. | boolean | true |
unseenLabel | (count: number) => ReactNode | "3 new messages" |
variant | Button variant | "outline" |
behavior | ScrollBehavior | "smooth" |
| Atributo | Descripción |
|---|---|
data-slot="message-scroller-button" | Apunta al botón en CSS. |
data-active | "true" mientras hay algún sitio al que saltar. |
data-unseen | El recuento de no vistos, mientras sea mayor que cero. |
- ButtonBotones en todas las variantes y tamaños, con un flujo integrado de carga, éxito y error que omite el spinner en las peticiones rápidas.
- 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.
- MessageUna fila de mensaje de chat con avatar, nombre, burbujas y estado, donde los mensajes nuevos suben desde el lado del remitente.
- AttachmentTarjetas de archivos e imágenes para subidas, con progreso, estados, acciones, un trigger de tarjeta completa y nombres que conservan su extensión.
- BubbleBurbujas de mensajes de chat con variantes, esquinas agrupadas, reacciones y espacio para contenido interactivo.
- MarkerNotas discretas entre el contenido, como separadores de fecha y eventos del sistema, con fechas y horas fijas que se leen como Hoy o Ayer.
Usado en bloques
Bloques que se construyen sobre Message scroller.
- Prompt InputUn compositor de chat que empieza como una línea tranquila, crece hasta convertirse en una tarjeta mientras escribes y baja cuando empieza la conversación. Enter envía, de forma segura con entrada en japonés y chino. Pega, suelta o elige archivos con vistas previas, progreso y reintento. @ añade archivos y / ejecuta comandos desde un menú junto al cursor. Un selector de modelo con teclas numéricas, un control deslizante de esfuerzo que cobra vida en Max, un anillo de contexto, dictado con forma de onda en vivo, chips de herramientas, una cola para los mensajes escritos mientras se transmite una respuesta y borradores que sobreviven a una recarga.
- Agent TodosMuestra el plan de un agente mientras trabaja. Cada paso pasa de pendiente a por hacer, en curso y hecho, con tiempos en vivo, fallos y las llamadas a herramientas detrás. Una píldora de estado para sobre el compositor, cambios del plan que puedes ver y un paso de revisión para editar el plan antes de ejecutarlo.
- Chat ThreadToda la conversación alrededor del compositor. Tu pregunta se fija arriba mientras la respuesta llega en streaming, los puntos de control del lateral saltan entre mensajes, y cada respuesta se puede copiar, editar, reintentar, valorar y cambiar entre versiones. Las respuestas renderizan Markdown con bloques de código, tablas y citas, y el razonamiento, las llamadas a herramientas y Prompt Input encajan directamente.
- Code BlockBloques de código pensados para respuestas de IA. Resaltado de sintaxis que sigue el ritmo del streaming, copiar, descargar y ajustar líneas, números de línea y líneas resaltadas, diffs con aceptar y rechazar, y una terminal para comandos.