shadcn.io is not affiliated with official shadcn/ui
Emergency Contact Dialog Block for Svelte
A hiking-safety app's Safety page with its emergency contacts shown open: a ranked list of up to three people called in order, Remove that asks first, and an Add contact form with a checked phone number, trip plan access and a medical note.
Installation
Overview
Say who gets the call when a trip goes quiet, with this emergency contact dialog for Svelte with Ark UI. It opens from the Safety page of Cairnwatch, a hiking-safety app: the page's header holds an outline Emergency contacts Button that carries the count, "Emergency contacts (2)", and the page, a list of settings rows with one for the contacts, is drawn under a soft scrim inside a hairline frame with a plus mark on each corner. The Dialog lists up to three contacts as a numbered list headed "Called in this order", each with a name, a relationship, a phone number and whether they see the trip plan, and a Remove that asks "Remove Soraya Ellwood?" in the same row. A Collapsible folds open a form for a new contact: a name, a Select for the relationship, a phone number, a Switch for "Can see my trip plan" and a Textarea for a medical note that is shown only to responders after an alert. Adding puts the person third, folds the form away and updates the count on the page; at three the dialog says "Maximum of 3 contacts". Add contact is the one Shine Button. For preview the dialog is drawn open in place when the page loads.
FAQ
Why is the dialog already open?
So you can see it without a click. On load the dialog is a copy drawn in place over the page: a native dialog element that isn't modal, so nothing is trapped, hidden or focused, and the page around the preview keeps working. The Emergency contacts button in the header opens the real Dialog, modal, with its focus trap, Escape and focus return, and the copy stays closed until a reload. Both show the same ContactsBody component and share the block's state, so a contact added in place is in the real one. In your app keep the Dialog and drop the copy: the "in-place" state, the scrim and the dialog element inside the frame.
How does the order work, and can I change it?
The list is the order of the calls: number one is called first, and a new contact joins at the end. There is no reordering here on purpose; to change the order, remove a contact and add them again, or build a drag handle on your own list. The numbers are drawn text and the list is a real ordered list, so a screen reader hears the position of each person.
How does Remove ask?
Pressing Remove swaps that row's buttons for Keep and Remove in the same row height, with focus on Keep, so the safe answer is the one under your keyboard. Keep puts the row back and returns focus to its Remove. Removing takes the person off the list, renumbers the rest, says so in the polite status and moves focus to the first Remove that is left, or to the Add contact fold if the list is now empty.
How is the new contact checked?
Add contact opens the form the first time you press it, and adds the contact the next time. The name needs two characters or more, and the phone needs 7 to 15 digits with only digits, spaces, brackets, dots, dashes and an optional plus. A problem is shown under its field, focuses the first field to fix and clears as you correct it. The phone field uses autoComplete="tel" and reads left to right in any page direction. The medical note is capped at 160 characters.
What stays local, and how do I wire it for real?
Everything. The two contacts are typed into the file with reserved fictional numbers, nothing is stored, and nobody is called, which the status line says after an add. In your app save the contacts through your API in the submit handler, keep the medical note on the server with access limited to the responder role, and send a verification message to a number before you trust it.
Where does focus go?
The real dialog is named by its title and described by its sentence. Unfolding the form moves focus to the name field, and the scroll area holding the list and the form is itself reachable by keyboard. Escape and Done return focus to the Emergency contacts button. The trigger is wrapped in DialogTrigger with asChild, and the dialog is controlled with open and onOpenChange.
How does it look on a phone?
The copy shown on load docks to the foot of the frame as a bottom sheet with its actions pinned and the content scrolling above them; Remove shows only its icon, still named for the person. The list and the form scroll inside a fixed-height area, so the dialog never grows. The real dialog keeps the Dialog's own phone layout, a sheet from the bottom.