shadcn.io is not affiliated with official shadcn/ui
City Tabs Locations Contact Block for Radix UI
A contact section for a coffee roaster with four cafes: city tabs over a panel with address, hours and a street map, and a form addressed to the cafe you picked.
Installation
Overview
A contact section for React with Radix UI. A compact header, then a band of city tabs (they scroll sideways on a phone) above a panel for the chosen cafe: its address, phone, email and opening hours in one cell, and a street-map drawing in the cell beside it, the two sharing a hairline. Below, a band with the form, whose first line reads "To: Portland cafe" and follows the tab. Name, email, what it's about in a select and a message; submitting checks every field, shows each problem under its field and moves focus to the first one, and a valid note turns into a confirmation that names the cafe it went to. The panels share one height, so switching tabs moves nothing. It's built from Tabs, Field, Input, Select, Textarea, Guides, Shine Button and Button.
FAQ
Are the tabs real, and how do they work with the keyboard?
Yes: each city is a tab with a real panel, in a tab list named "Cafes". The arrow keys move between the tabs, Home and End jump to the first and last, and the selected tab's panel is the one a screen reader reads. The selected tab also decides who the form is addressed to: its heading follows the tab, and so does the confirmation.
Why doesn't the page move when I switch tabs?
Every cafe's panel is also drawn once, unseen, in the same grid cell as the live panel (hidden from assistive technology and the keyboard), so the cell is always as tall as the tallest panel. Add a cafe by adding an entry to CAFES: the tabs, the panels and the sizer all read the same list.
How is the select labelled?
The label above it names the select's button for screen readers, and focus can land on that button when nothing is chosen.
The select's trigger takes the id, and the label points to it with htmlFor.
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 your own call: details holds the name, email, topic and message, and cafeId says which cafe it is for (each cafe's own address is in CAFES).
Are the addresses, emails and phone numbers real?
No. The emails use the .example domain, which is reserved for examples, the phone numbers are in the 555-0100 to 555-0199 range set aside for fiction, and the streets are made up. Replace them in CAFES. Phone numbers keep their order in a right-to-left layout.
Are the maps real?
No: each is a small SVG drawing of made-up streets (a main street with the pin on it, a cross street, a diagonal and a park), laid out differently per cafe from the numbers in CAFES. They are decorative and hidden from assistive technology, and never flip in a right-to-left layout; the address beside each is the real information.