shadcn.io is not affiliated with official shadcn/ui
API Error Dialog Block for React
A deploy platform's overview with its failed card and the error alert shown open: the 502 status, the code and request id, a retry ladder of three attempts, a real copy of the error report and the error body as a JSON tree.
Installation
Overview
Give a failure its facts and a way forward, with this API error alert for React with Base UI. It opens from the Overview page of Keelhurst, a deploy platform: the header holds an outline Error details Button, and the page itself, a rail, three cells over a chart, is drawn under a soft scrim inside a hairline frame with a plus mark on each corner. In the drawing the Deploys cell is the failed one, a dash and the word Unavailable. The Alert Dialog lists the status as a Badge, the error code, the request id in monospace and the time in a Data List, then says how many attempts are used. Try again, the only Shine Button, counts three attempts and then says that support has the request id; Copy Button puts a typed, multi-line error report on the clipboard; Technical details opens a Collapsible with the error body in a JSON Tree View. For preview the alert is drawn open in place when the page loads; the header button opens the real Alert Dialog, with the same facts and the same count. For dashboards, deploy and build tools, and any app that talks to an API it does not own.
FAQ
Why is the alert already open, and what do I keep?
So you can see it without a click. On load the alert is a copy drawn in place over the page: a native dialog element with the alertdialog role that isn't modal, so nothing is trapped, hidden or focused, and the page around the preview keeps working. The Error details button opens the real Alert Dialog, modal, with its focus trap, Escape and focus on Close, and the copy stays closed until a reload. Both show the same ErrorFields component and share the block's state, so what was done in the copy is there in the real one. In your app keep the Alert Dialog and drop the copy: the "in-place" state, the scrim and the dialog element inside the frame.
How does the retry ladder work?
Try again starts an attempt, which takes under a second here and then fails by design, because nothing is requested; the polite line under the facts reads "Attempt 1 of 3 failed: the API answered 502 again", then 2, then 3. After the third the button goes quiet but still answers a press, naming the request id, and the line says that support has it. In your app call the failed request again in retry, stop on a success and close the alert, and keep the count so a person can't hammer an API that is down; for a 429 or a Retry-After header, wait that long before you enable the button.
Is Copy error report real?
Yes. The Copy Button writes reportOf(attempts) to the clipboard: the status and code, the request id, the endpoint, the time and the attempts so far, one fact a line, ready to paste into a ticket. A polite message says the report was copied, or that the clipboard refused it, which happens on a page that is not served over HTTPS. The request id, the endpoint and the time are typed constants here; in your app take them from the response that failed.
What are Technical details for?
They show the error body your API returned as a tree, two levels open, so a developer sees the code, the message, whether it is retryable and the upstream that timed out without leaving the alert. It sits last in the alert, so opening it never moves the facts, the attempt line or the buttons above it; in the copy on the page the alert is aligned to the top of the frame for the same reason. Values are plain foreground text, not the tree's usual colours, and the tree scrolls inside its own box if the body is long.
Where does focus go, and how does it close?
The real alert is named by its title and described by its sentence, and it opens with focus on Close, never on Try again, so a stray Enter backs out. Escape and Close return focus to Error details; clicking outside does not close it, since an alert has to be answered. Close is the focus target through initialFocus. The copy shown on load moves no focus; Escape inside it and Close shut it the same way.
What stays local in the demo, and how do I wire it up?
Everything. No request goes out: the 502, the request id, the time and the error body are typed constants, and Try again only counts. Closing says in a polite message how many attempts were made, and the drawn Deploys card shows "Tried 2 of 3". In your app replace the constants with the failed response, make retry call your API, and send the same report to your error tracker when someone copies it.
Related
- Pro
Loading Dialog
Status and errorsA release tool's page with its publish alert shown open: a four-step run that starts when you press the button, never moves the dialog while it waits, shows skeleton boxes where the file sizes will be, and can be stopped.
- Pro
Rate Limit Dialog
Status and errorsAn API console with its 429 notice shown open: a dialog with the quota used, the plan's limit, a clock to the reset and a Countdown Button that turns into Retry request when the wait ends.
- Pro
Session Timeout Dialog
Status and errorsA bank's accounts page with an alert dialog shown open that warns before an idle session ends: a one-minute clock with a draining bar, Stay signed in and Sign out now, and a signed-out view at zero.
- Pro
API Uptime Strips Error
Server and outagesA full-screen outage page for an API host: the display 503, a notify-me form that saves in the page, and four APIs as rows of thirty day-cells with a shape and a word for today and an uptime counted from the minutes.
- Pro
Confirm Action Dialog
Confirm and consentA newsletter editor with its publish confirmation shown open: an alert dialog that lists what happens to the issue, a box that remembers the answer, and a foot that gives the question back.
- Pro
Contact Support Dialog
Feedback and reportsA shipments table with a support dialog shown open: a ticket form with a category, a priority and attached file names, and beside it up to three help articles picked by the category and the subject's words, each opening in place.