Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Chat Sidebar Skeleton Block for Svelte

A team chat window that loads in place: a list of six conversations beside the open chat, bars becoming avatars, names, previews and messages, list first, then the chat.

Framework
UI library

Preview

Preview width

Installation

Part of Pro
Pro unlocks the code and one-line install of every Pro button and text effect, plus the MCP for your AI editor.
Have Pro already? Sign in to open it.Opens here as soon as you're Pro.

Overview

Show a messenger while its chats load, then swap them in without moving anything, with this chat sidebar skeleton for Svelte with Ark UI. A fixed-height window from Voile, a workplace messenger, holds a list of six conversations at the start and the open chat beside it. The search field, the composer and the Load control are real from the first paint; every conversation's avatar, name, time and preview line, and the chat's avatar, name, status and five messages, are Skeleton bars that become the data in the same boxes, the list first and the chat a moment after it. Opening another conversation, searching and sending say they are not wired in this demo. On a phone the list becomes a row of six avatar buttons above the chat. It's built from Skeleton, Message, Bubble, Input, Textarea, Avatar and Guides, with a CSS entrance only. For team chats, support inboxes and any two-pane messenger.

FAQ

What stays local, and how do I wire it to a real messenger?

Nothing is fetched. The six conversations and the open chat's five messages are typed in CONVERSATIONS and THREAD, Load starts a 700 millisecond timer, and when it ends the phase becomes ready and the data swaps in; Reload goes back to the bars and in again. To wire it for real, delete the timer, the Load button and the polite line, and set data-state (loading or ready) and aria-busy on the region from your query's pending state, or use the bars as a Suspense fallback and render the real chats when they arrive. The bars are derived from the same data as the content, so keep one component for both.

Does the window keep its height while it loads?

Each bar and its content sit in one grid cell, so the larger of the two sets the cell's box and the swap changes nothing around it. The window is a fixed height; only the list and the log scroll, and every row of the list is the same height. The chrome is real in both phases and the polite line reserves two lines, so the window is exactly as tall before, during and after loading at every width.

Why do the list and the chat load one after the other?

Each cell's delay is its position times 35 milliseconds, and the chat's cells start after the list's six, so the list arrives first and the messages follow. Under reduced motion the delay is zero and everything swaps at once.

What happens to the list on a phone?

It becomes a row of six round avatar buttons above the chat, each named for its conversation. Both layouts are in the page and CSS hides one, so the height holds at every width.

What do the search field, the list and Send do?

The field and the composer hold what you type. Pressing a conversation, submitting the search or pressing Send says it isn't wired in this demo. Wire them to your own state: the list row calls onOpen and the composer's form has an onSubmit.

Is it accessible?

The window is marked busy while it loads and carries a screen-reader-only "Loading chats…". The bars are hidden from assistive technology and the layer that isn't showing is invisible, so it is neither read nor focusable. The message log is a named, focusable region so the keyboard can scroll it, the composer has a label, and the one polite line under it announces what loaded and what you did, once. Under reduced motion there is no pulse, no spinner and no stagger: the swap is instant.