shadcn.io is not affiliated with official shadcn/ui
Treatment Menu Tabs Contact Block for React
A day spa treatment menu: pill tabs over radio cells for massage, facial and body treatments, add-ons as checkbox cells, a running total and a form that checks itself and confirms in place.
Installation
Overview
A treatment menu section for React with Base UI, laid out in bands under a start-aligned header. A band of pill tabs (Massage, Facial, Body) sits over three treatments in cells that share their hairlines, rail to rail: each cell is a radio with the treatment's name, what it is, its length and its price. The panels share one height, so switching tabs never moves the page, and a choice made in one tab stays chosen while another is open; a status line names the current choice. Below, four add-ons as checkbox cells, then a band with the running total (the treatment plus every ticked add-on, with the names written out), a name and an email. Submitting checks every field, shows each problem under its field, marks the control invalid and moves focus to the first one; a valid request turns into a confirmation in the same space that repeats the treatment, the add-ons and the total, takes focus, and offers "Plan another visit". The rails and top rule come from the Guides spine, so the block lines up with its neighbours in a stack. It's built from Tabs, Radio Group, Checkbox, Field, Input, Guides, Shine Button and Button, with CSS transitions for the entrances and your theme's tokens for every colour. For spas, salons, studios and any business with a priced menu.
FAQ
Where does the form send its data?
Nowhere yet. The submit handler waits 800 milliseconds, as a stand-in for a request, then shows the confirmation. Replace that timer in submit with a call to your booking system or inbox: treatmentId, addons, name and email hold what the visitor chose. Show the confirmation when the request succeeds, and an error line in the form when it doesn't.
How do I change the menu and the prices?
Edit MENUS (three tabs of three treatments, each with a name, a line about it, its minutes and its price) and ADDONS. Prices are plain numbers formatted with a fixed en-US currency formatter, and each figure is wrapped so it keeps its order in a right-to-left layout. The total is the chosen treatment's price plus the ticked add-ons.
Why doesn't the page jump when I switch tabs?
Every panel is also drawn once, unseen, in the same grid cell (Sizer), so the cell takes the tallest panel's height whichever tab is open. The unseen copies hold no controls, are hidden from assistive technology and can't take focus. A treatment chosen in one tab is remembered: its radio shows as chosen only while its own tab is open, and the status line names it from any tab.
How does the keyboard work?
Arrow keys move between the tabs; Tab then moves into the open panel. Within a menu the three treatments are one radio group: arrow keys move between them and choose. Each add-on is a checkbox, toggled with Space. Whole cells are labels, so clicking anywhere in a cell chooses it.
Are the phone number and email real?
No. +1 (415) 555-0126 is in the 555-0100 to 555-0199 range set aside for fiction, and stay@salthouse.example uses the .example domain, which is reserved for examples. Replace PHONE, PHONE_HREF and EMAIL at the top of the file with yours.
How does it fit on a phone?
The pill tabs scroll sideways inside their band if they don't fit. The treatment cells stack one per row, the add-ons stack one per row, and the name and email go one per row, with the total above them. The submit button goes full width, so nothing scrolls sideways at 320 pixels.
Related
- Pro
Stylist Booking Contact
Visits and servicesA salon booking that starts with the person: three stylists in hairline cells, each with their next three openings as chips, a live appointment line, and a form that checks itself and confirms in place.
- Pro
Coverage Timeline Contact
Events and datesA photography coverage planner on a card in card: a shoot type, a start time and a length slider that draw a bar on a 6 am to 10 pm timeline with a hatched golden hour, and a form that confirms in place.
- Pro
Table Reservation Contact
Events and datesA restaurant reservation in a card in card: a party size stepper, a date picker that closes Mondays and past days, five sittings as choices and a form that checks itself and confirms in place.
- Pro
Month Calendar Scheduler Contact
Calls and meetingsA scheduling split: a host panel at the start; a month calendar that closes weekends and past days, the open times of the chosen day and a name and email at the end, with Confirm unavailable until a day and time are chosen.
- Pro
Talk to Sales Contact
Contact formsA talk-to-sales split for a scheduling platform: what happens next as three numbered steps and a band of contact details beside a form that checks itself, shows each problem under its field and confirms in place.
- Pro
Birthday Room Childcare Contact
Visits and servicesA place request for a day nursery in a card in card: a birthday in a segmented date field names the room the child belongs in, and five day toggles price the week at example rates.