shadcn.io is not affiliated with official shadcn/ui
Next Appointment Navbar Block for Ark UI
A booking navbar for salon software: links to the schedule, a next-appointment chip with a live countdown, and a New booking action.
Installation
Overview
A booking navbar for React with Ark UI, the bar across Tidebook, salon booking software. Dashboard, Availability, Bookings and Clients follow the wordmark, Bookings marked as the current page. A chip shows the next appointment as a live "in 42 min", filled in after the page loads, and opens a popover with the client, the service, Join and Reschedule. New booking is the one primary action. On a phone the chip folds down to a status dot and the links move into a sheet from the top, where New booking sits when the bar is too narrow for it. The popover and the sheet open over the page, so the block stays one bar high (56 pixels). The page's rails and top rule come from the Guides spine and the bar draws no bottom border: the next block's top rule is its bottom edge. It's built from Relative Time Text, Popover, Data List, Status, Shine Button, Button, Sheet and Guides, with your theme's tokens for every colour. For booking products whose header should show the next client without opening the calendar.
FAQ
How do I change the links and the appointment?
Edit PAGES for the links. Mark the page you're on with current: true: that link gets aria-current="page" and a stroke on the bar. The appointment is Lena Ortiz, Cut and colour, starting 42 minutes after the page loads (LEAD_MS). Change those three in the popover and the constant. Until the browser knows the clock, the chip holds the words "in 42 min." in the same width, so the bar does not jump. Every link points at #.
What do Join and Reschedule do?
Join is a link. Point it at the visit. Reschedule writes a polite line ("Reschedule stays in this demo. Nothing was sent.") and does not submit anything: replace that handler with your reschedule flow.
Join takes asChild with the link inside, so it can be your router's link. New booking does the same.
Why is the time different on the server and in the browser?
The server does not know the visitor's clock, so the first render prints "in 42 min." as plain text. After mount, the same spot becomes a relative time counted from that moment plus 42 minutes. The placeholder is the full phrase, in a reserved width, so swapping it does not move the chip.
How does it work with a keyboard and a screen reader?
The wordmark is a link home. The links sit in a nav landmark named Main. The chip is a button whose name is its own words, "Next appointment in 42 min." (the word "appointment" is visually hidden); below md all of it is visually hidden except the dot, and the name stays the same. The popover repeats the client, the service and the start in a description list.
The popover is not modal: Tab can leave it, and Escape closes it.
How does it work on a phone?
Below md the links hide, the chip keeps the status dot and hides its words, and a menu button opens a sheet from the top with the four links. Below sm New booking leaves the bar and sits at the bottom of that sheet. Choosing a link closes the sheet. At 320 pixels the bar is the wordmark, the dot and the menu button.
What moves, and what happens with reduced motion?
Nothing moves on load. The relative time updates on its own schedule. The popover uses its own open transition, the sheet slides down from the top, and a band of light sweeps across New booking once on hover and keyboard focus. With reduced motion the sheet appears without sliding and the light fades in where it stands.