shadcn.io is not affiliated with official shadcn/ui
Blog Posts Carousel Block for React
Eight river-history posts on a hairline track, three to a page, each with tag chips, a dek, a byline and a read time, that read Seen once whole in view, with a Seen count and a Reset in the foot.
Installation
Overview
Show which posts a reader has already passed, with this blog posts carousel for React with Base UI. Millrace Notes, a river-towns history blog, lists eight recent posts on a ruled track. Each cell leads with two tag chips, then the title, a dek, an initials byline, a fixed date and a read time. A post reads "Seen", with a check and the word, once it was whole in view when the track settled, never while you drag. The foot band, ruled by Guides, holds the count ("Seen 5 of 8"), a dot for each step, a ghost Reset and Previous and Next Buttons that stay in the tab order at the ends. Three posts show from the large breakpoint, two from medium and one with the next peeking on a phone. It's built from Carousel, Badge, Button and Guides, with CSS transitions only. The blog, the posts and the dates are made up for the example.
FAQ
How do I use my own posts?
Edit POSTS. Each has an id, a title, a dek, two tags, an author, an ISO iso date and minutes to read. The byline initials come from the author's name, the date is formatted by one helper with no clock and no locale, and the count and the dots are derived from the length of the list.
When does a post count as seen?
A post is seen once it was whole in view when the track stopped, so a card that only flashes past during a drag is not marked. The count is derived from that list, and the foot reads "Seen all 8 posts" when every post has been in view. Reset clears the marks, but the posts in view right now stay seen, because they are whole and settled.
The marks follow Embla's select event, which fires when the track settles.
How does it work with a keyboard?
Tab reaches the controls and Previous and Next. With focus inside the track's panel, the arrow keys move the track (mirrored in a right-to-left layout) and Home and End jump to the first and last page. Previous and Next stay in the tab order at the ends and are marked as unavailable instead of disabled, so focus never disappears. Cells that are out of view are hidden from the tab order and from screen readers.
What is announced when it moves?
The seen count in the foot is the block's one polite live region: after a move a screen reader hears, for example, "Seen 6 of 8". The track itself is silent, so the same posts are not read twice. The "Seen" word on a card is hidden from assistive tech, because the count already says it.
What stays local in the demo?
Everything. The posts are typed example data and the seen marks live in this tab: reload and they are gone. To wire it for real, load the posts from your CMS and the read history from your own API or local storage, and set the initial seen list from it. Keep the marking on the page change so a drag never counts.