shadcn.io is not affiliated with official shadcn/ui
Loading Skeleton Chat Block for Vue
A direct message thread that is still loading: the top bar is real, eight messages are Skeleton bars in the boxes the text will fill, and Reload replays the wait and the swap without moving a pixel.
Installation
Overview
Show a conversation while its history loads, then swap the messages in without moving the window, with this loading skeleton chat for Vue with Ark UI. A hairline frame with a plus mark on each corner holds a window of fixed height for Fathomline, a team messaging app. The top bar is real from the first paint: Rosalba Keane's name is known from the route, her initials sit in the avatar and the status line says "Loading messages…". The composer is there but quiet ("Messages are loading"), and the log holds eight messages drawn as Skeleton bars, each in the same grid cell as the text, name, avatar and time that will replace it, so a two-line message is two lines tall in both phases. Reload in the top bar plays the cycle again: the bars come back, and 900 milliseconds later the typed thread swaps in, message by message, and the composer opens without taking focus. Once the thread is in, a line you type is added to the log in this tab only. It's built from Message, Bubble, Avatar, Textarea, the Shine Button and Guides, with CSS only. For any chat that waits for its history.
FAQ
What stays local, and how do I wire it to a real conversation?
Nothing is fetched. The eight messages are typed in SEED, Reload starts a 900 millisecond timer, and when it ends the phase becomes ready and the data swaps in. To wire it for real, delete the timer and the polite line, and set data-state (loading or ready) and aria-busy on the window from your query's pending state; the bars and the messages come from one component, so keep it that way. Your own lines are only added to the log: send them to your backend in post and append the saved message when it returns.
Does the window move while the messages load?
No. Each bar and the content it stands for share one grid cell, so the larger of the two sets the box and the swap changes nothing around it; the bar follows the text's width and lines instead of a guessed percentage. The window has a fixed height, the top bar and the composer are real in both phases, and only the log scrolls.
Can I send a message before the history arrives?
The composer is real but read only while the bars show: the field says "Messages are loading", Send stays quiet, and pressing it explains why in the status line. When the thread is in, the field opens and focus is left where it was. Enter sends, Shift and Enter add a line, and focus stays in the field after you send.
What happens under reduced motion?
The bars don't pulse, the spinner on Reload stays still and the swap is instant: there is no stagger and no fade. The state is still readable, because the status line says "Loading messages…" and the busy window is announced.
Is it accessible?
The window is marked aria-busy while it loads and carries a screen-reader-only "Loading messages…". The bars are hidden from assistive technology and the layer that isn't showing is invisible, so it is neither read nor focusable. The log is a named, focusable region, the composer has a label and a hint, and the one polite line under it says what loaded and what you did, once.