Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Pagination Skeleton Block for Vue

An order list that is already there while its total and pager load: the count and the page buttons come in over bars, and pressing a page shows its six orders at once and sends the pager back to the bars.

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 list whose pager arrives later, with this pagination skeleton for Vue with Ark UI. A hairline frame with a plus mark on each corner holds a list of six recent orders from Quatrain, an order desk for small shops, over a foot. Unlike the other skeleton blocks the list is real from the first paint, as it is when a first request returns the rows and a second one is still counting; what loads is the foot. The "Showing 1-6 of 248" line and the page buttons (Previous, 1 2 3, a gap, 42, Next) are Skeleton bars that become the real count and the real Pagination in the same place, next to a rows-per-page Native Select. Press Load and only the foot changes. Press a page and its six orders show at once while the pager goes back to the bars until the total returns. On a phone the pager keeps Previous, "Page 1 of 42" and Next. For order histories, inboxes and any list whose total is slower than its rows.

FAQ

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

Nothing is fetched. Eighteen orders are typed in ORDERS, three pages of six, and the total of 248 is a constant. 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 card from your query's pending state, or use the bars as a Suspense fallback and render the real content when it arrives. Keep one component for the bars and the data so they can't drift apart.

What happens when I press a page?

The list shows that page's six orders straight away, because the rows are the part that is already there, and the pager goes back to the bars for 700 milliseconds before the real Pagination returns with the new page current. Focus moves to the list's heading before the pressed button is hidden, so it is never lost. Only pages 1 to 3 are typed: Next past page 3 and the last page, 42, say so in the polite line.

Why doesn't the foot jump when the pager arrives?

The pager's bars and the real Pagination share one grid cell, so the wider of the two sets the box, and the count's bar shares a cell with its text. The six rows are a fixed height and every page has six, so the list never changes height either, and the polite line reserves two lines.

What does the rows-per-page select do?

Nothing here: choosing a size sets the polite line to "Rows per page isn't wired in this demo." and the select stays on 6. In your app, hold the size in state, request that many rows and recompute the number of pages from the total.

Is it accessible?

The panel is marked busy while it loads and carries a screen-reader-only "Loading pager…", and the polite line announces what loaded once. The bars are hidden from assistive technology and the layer that isn't showing is invisible, so it is neither read nor focusable. Pagination is a navigation landmark named "Order pages", the current page is marked with aria-current, and the ends are aria-disabled when they have nowhere to go. The pulse stops when the data is in, and under reduced motion there is no pulse, no spinner and no stagger: the swap is instant.