shadcn.io is not affiliated with official shadcn/ui
Error Validation Checkout Block for Svelte
A pay form that tells field errors from a service error: five checked fields, a demo group that pretends the response is fine, field errors or the bank being down, an alert that lists the fields as buttons that focus them, and a Retry that keeps every typed value.
Installation
Overview
Show shoppers exactly what went wrong, with this error validation checkout for Svelte with Ark UI. A compact header from Wildwick, a kids' scooter shop, carries a Toggle Group that says what the demo's response will be: fine, field errors or service down. Inside a hairline frame with a plus mark on each corner the order is one line, a slot for the alert, and a form of five Fields (email, name, street, ZIP and card) that are pre-filled so you can press Pay at once. The client checks come first, each with its own reason; a clean press waits a moment and the response comes back. Field errors are keyed by field and put on those fields with a reason each, and one alert names the count and lists the fields as buttons that move focus to them, landing on the first. A service error is a different alert, "We could not reach the bank", that says nothing was charged and has a Retry; everything you typed is still there. The alert slot keeps its height, so the form below never moves. Pay is the only Shine Button, and a polite status line says what happened. It's built from Toggle Group, Field, Input, Button and Guides. For any form that talks to a server.
FAQ
What is the difference between the two alerts?
A field error is the user's to fix and belongs to a field, so it appears on the field and in the alert's list of buttons; a service error is nobody's field, so it gets its own alert with Retry and a promise that nothing was charged. The alert is a live region, so each one is announced when it appears, and focus goes to the first wrong field or to Retry.
How do server errors get onto fields?
The demo's response is a typed list of { id, text }, the shape an API returns for a validation failure. serverOf builds it from what was typed (the email already has an account; the ZIP does not match the city), and the form puts each text on the field with that id. Replace it with your API's response and keep the mapping by field id. Typing in a field clears that field's error and updates the count.
What does Retry keep?
Everything. Values live in the block's state; a failed response only turns on the service alert. Retry runs the same pay step again with the current values and the group's current choice. Only a successful pay wipes the card number.
Is the card number really checked?
In memory, in the tab: 13 to 19 digits and the Luhn sum. The pre-filled number is a test number. A real page never lets card digits reach its own code: use the fields your payment provider hosts inside this layout. Autocomplete is off so a browser never offers a real card to the demo.
Why does the alert have a reserved slot?
An alert that pushes the form down moves the field you were about to correct. The slot is sized for the longest case (a wrapped list of five fields on a phone), and its idle sentence sits in the same cell, so the page stays still on every state.
What stays local in the demo, and how do I wire it up?
Everything. The response is picked with the group, a timer stands in for the network, and nothing is sent or charged. In your app post the form to your API, map its field errors by id, show the service alert for network and 5xx failures only, and send the card through your payment provider's fields. The Pay button is a submit button inside the form, so Enter works from any field.