Chat Thread
Toute la conversation autour du champ de saisie. Votre question reste épinglée en haut pendant que la réponse arrive en streaming, des points de repère sur le côté permettent de sauter d’un message à l’autre, et chaque réponse peut être copiée, modifiée, relancée, notée et basculée entre versions. Les réponses affichent du Markdown avec blocs de code, tableaux et citations, et la réflexion, les appels d’outils et Prompt Input s’y insèrent directement.
Chat Thread est la conversation autour du champ de saisie : vos messages, les réponses du modèle et ce que vous pouvez en faire. Il démarre avec votre état vide et le champ de saisie centré, puis ancre ce champ en bas dès qu’il y a des messages, sans le remonter, si bien que le focus et le brouillon restent en place.
Le message que vous venez d’envoyer remonte en haut pendant que sa réponse arrive en dessous, et la vue suit le nouveau texte jusqu’à ce que vous défiliez ailleurs. Un rail de points de repère à droite permet de sauter d’un de vos messages à l’autre, avec un aperçu au survol. L’historique plus ancien se charge par le haut sans que la vue bouge.
Survolez un message pour le copier, le modifier ou réessayer. Les modifications et nouveaux essais deviennent des versions entre lesquelles vous pouvez basculer, et rien n’est perdu. Les réponses en échec proposent Try again, les réponses interrompues le disent, et le pouce levé ou baissé se donne en un clic. Dans chaque réponse, Reasoning, ToolCalls et Markdown des autres blocks s’insèrent directement.
Ajouter le registre Pro à components.json
components.json Ajouter votre token
Créez un token sur votre page de compte et placez-le dans
.env.localsous le nomHEXTAUI_PRO_TOKEN.Ajouter le block
pnpm dlx shadcn@latest add @hextaui-pro/chat-thread
Avec AI SDK
Associez les messages de useChat au fil. Les parts de raisonnement vont à Reasoning, les parts d’outil à ToolCalls et le texte à Markdown. Épinglez le dernier message de l’utilisateur, utilisez regenerate pour Try again, et renvoyez une modification à partir de ce point.
Anatomie
Les parties à composer, de l’extérieur vers l’intérieur.
| Partie | Description |
|---|---|
ChatThread | Le cadre : scroller, points de repère, état vide et emplacement du champ de saisie. |
ChatUserMessage | Votre message : pièces jointes, bulle, heure, versions, copie et modification. |
ChatAssistantMessage | Une réponse. Placez-y Reasoning, ToolCalls et Markdown ; elle ajoute les actions et les états d’erreur et d’arrêt. |
ChatDivider | Une ligne libellée entre des groupes de messages. |
ChatAttachments, ChatAction, ChatCopy, ChatBranchSwitch, ChatEditor | Les éléments utilisés par les messages, exportés pour des mises en page personnalisées. |
| Prop | Type | Par défaut |
|---|---|---|
childrenMessages et séparateurs, dans l’ordre. | ReactNode | – |
composerGénéralement Prompt Input. Centré quand c’est vide, ancré en bas sinon. | ReactNode | – |
emptyAffiché au-dessus du champ de saisie quand il n’y a aucun message. | ReactNode | – |
busyMarque la conversation comme occupée pour les technologies d’assistance pendant qu’une réponse arrive en streaming. | boolean | false |
hasOlderAffiche « Load earlier messages » en haut. | boolean | false |
loadingOlderAffiche un spinner sur ce bouton. La position de défilement est restaurée quand la valeur repasse à false. | boolean | false |
onLoadOlderAjoutez ici les messages plus anciens en tête. | () => void | – |
| Prop | Type | Par défaut |
|---|---|---|
idId stable. Gardez-le identique d’une version à l’autre pour que la vue ne saute pas. | string | – |
textLe message. Également utilisé pour l’aperçu du point de repère. | string | – |
pinFait défiler ce message jusqu’en haut quand il apparaît. À définir sur le message qui vient d’être envoyé. | boolean | false |
files{ id, name, size?, type?, url? }. Les images avec une url s’affichent en miniatures. | ChatFile[] | – |
timeAffiché au survol, dans la locale du lecteur. | Date | – |
branch{ index, count, onChange } pour les flèches de version. | ChatBranch | – |
onEditAffiche Edit. Appelé avec le nouveau texte lorsqu’il a changé. | (text: string) => void | – |
attachmentsContenu personnalisé au-dessus de la bulle. | ReactNode | – |
| Prop | Type | Par défaut |
|---|---|---|
idId stable. | string | – |
childrenReasoning, ToolCalls, Markdown ou tout autre contenu. | ReactNode | – |
textTexte brut pour Copy. | string | – |
streamingMasque les actions jusqu’à la fin de la réponse. | boolean | false |
lastGarde les actions visibles au lieu de les afficher au survol. | boolean | false |
metaCôté droit de la rangée d’actions, comme le modèle et l’effort. | ReactNode | – |
branchFlèches de version pour les nouveaux essais. | ChatBranch | – |
feedbackLa notation actuelle. | "up" | "down" | null | null |
onFeedbackAffiche les pouces. Appelé avec null quand une notation est annulée. | (feedback) => void | – |
onRetryAffiche Try again. | () => void | – |
errorAffiche le message avec Try again à la place des actions. | string | null | – |
stoppedMarque une réponse interrompue prématurément. | boolean | false |
| Prop | Type | Par défaut |
|---|---|---|
childrenLe libellé, comme Today ou « Switched to Nova 3 Max ». | ReactNode | – |
| Touche | Action |
|---|---|
| Tab | Parcourt les actions des messages. Elles apparaissent au focus, pas seulement au survol. |
| Enter | Envoie un message modifié. |
| ShiftEnter | Ajoute une ligne pendant la modification. |
| Esc | Annule une modification. |
| ↑↓PgUpPgDn | Fait défiler la conversation quand elle a le focus. |
- La conversation est une région libellée contenant un log, donc les nouveaux messages sont annoncés à leur arrivée et la région est marquée comme occupée pendant qu’une réponse arrive en streaming.
- Chaque action d’icône a un libellé et une infobulle. Les pouces utilisent aria-pressed, Copy et le retour de notation confirment via une région live polie, et les erreurs utilisent role=alert.
- Les points de repère forment une zone de navigation de boutons nommés « Message 2: … », et le point courant a aria-current.
- Les flèches de version forment un groupe nommé « Version 1 of 2 ».
- L’éditeur prend lui-même le focus avec le curseur à la fin et revient au message sur Cancel. Enter attend tant qu’une méthode de saisie est en cours de composition.
- Les anneaux de focus ne sont jamais coupés par le scroller, et les actions restent visibles sur les écrans tactiles.
Construit avec
Les composants HextaUI gratuits dont Chat Thread est constitué. Chacun s’installe séparément.
Code
2 fichiers, ajoutés à components/blocks/chat-thread.