shadcn.io is not affiliated with official shadcn/ui
Pagination Blog Block for Radix UI
A transit-planning blog's archive as rows, four to a page over three pages, with the catalog pagination in a band at the foot, a polite 'Showing 5 to 8 of 12' line and a height that never changes between pages.
Installation
Overview
A paginated post list for React with Radix UI, written for Fareplot, a transit-planning blog. A start-aligned header sits over twelve posts shown four to a page as rows that run from rail to rail, and the catalog Pagination sits in a band at the foot that ends the block: Previous, the page numbers with the current one outlined, and Next. Each row has a square line-pattern thumbnail (one pattern per category), the category as an outline badge, the title as the row's one link, a one-line dek and a byline. Choosing a page swaps the four rows in place and a polite line says "Showing 5–8 of 12". Every page is drawn once more, unseen, in the same grid cell, so the list keeps the height of the tallest page and the pager never moves under your pointer. On a phone the byline sits under the dek and the Previous and Next labels fold to arrows. It's built from Pagination, Badge, Avatar and Guides, with CSS for the entrance and the hover. For archives, search results and any blog that has more posts than one screen.
FAQ
How do I change the posts and the page size?
Edit POSTS at the top of the file, newest first, and PER_PAGE. The page numbers, the "Showing 5–8 of 12" line and the last page are derived from the array, so twelve posts at four a page give three numbers and thirteen would give four, the last with one row. Each post is a title, a dek, an author, a category, a date as an ISO string, minutes and an href.
Are the page numbers real links?
They are links to ?page=2 and so on, and the click is handled in place: the rows swap without a reload. To page on the server, drop the handlers and read page from the address in your route, or swap the state for your router's search params.
Each number is an a with an href and an onClick that stops the navigation and sets the page.
Why does the pager not move when I change page?
The list is drawn twice in one grid cell: the current page on top, and an unseen copy of all three pages underneath, hidden from assistive technology and the keyboard. The cell is as tall as the tallest page, so the pager under it stays where you clicked, even when one page has shorter rows. With a thirteenth post, the last page has one row and still takes the full height.
How does it work with a keyboard and a screen reader?
The pager is a labelled navigation ("Archive pages") with a list of links; the current page is marked with aria-current="page". Tab moves through Previous, the numbers and Next, and Enter changes the page. At the first page Previous, and at the last page Next, is dimmed and leaves the tab order. The line under the rows is a polite status, so a screen reader hears "Showing 5–8 of 12" after a change. Each row is one link, its title.
How do the thumbnails work?
Each thumbnail is the line pattern its post's category owns (contours, dots, rings, stripes), drawn in two weights of the foreground colour, so the category reads before the badge does. All colours are your theme's tokens, and thumbnails are decoration, hidden from assistive technology. To use photos, put an img with size-full object-cover in Thumb.