Order Detail
The merchant’s page for one order: shipments, payment, customer and timeline. Handles partial fulfillment, holds, failed payments and cancellations.
Order Detail is the page a merchant opens from the orders table: one order with everything they need to act on it. The header shows the order number, separate payment and fulfillment pills with a progress glyph (empty, half or full circle) so status never depends on color, the date and channel, the order actions and previous and next arrows.
The main column splits items by what happened to them. An Unfulfilled card lists what’s left to ship, worked out as purchased minus fulfilled minus refunded. Each shipment gets its own card with carrier, tracking link, delivery status and items, and refunded items get a Refunded card. The Payment card shows the total and only the lines that matter right now (refunded and net, an authorization with its expiry, or a balance due); subtotal, discounts, shipping, tax and currency conversion sit behind Breakdown. It has Capture payment for authorizations and Send invoice for pending or failed payments.
Fulfill items opens a sheet with a quantity stepper per line, capped at what’s left, a location, a tracking number that detects UPS, USPS, FedEx, DHL, Canada Post and Royal Mail from its pattern, and a Notify customer switch. Submitting closes the sheet and adds the shipment and a timeline event straight away. If onFulfill throws, both roll back and a toast offers Try again with the same choices.
The timeline reads like Shopify, Linear and Stripe activity feeds: a rail with one icon per event type (status color only on the icon), a short title built from the order data (“Payment of $564.41 captured”, “Shipped with UPS” with the tracking number linked), a muted second line and a relative time with the exact date in a tooltip. Day labels stick while you scroll. Customer emails fold into the event that sent them (“Customer emailed”, with Resend in Show details), three or more same-kind events in a row collapse into one line, and older history folds behind “Show N earlier events”. Comments are cards with avatar, author, edit and delete, and attachments as chips. Filter by All, Comments or System. The composer is one line until you focus it, then shows attachments, “Only visible to staff” and Post (⌘↵), and posts optimistically with retry. The right rail keeps to what matters: notes and tags only appear when they have content or can be edited, the customer card drops repeated name and phone lines, and conversion and risk show a one-line summary with details behind Show more. Cancelled, on hold, archived and loading states, and actions a staff member isn’t allowed to take, are all handled with a reason.
HextaUI Pro holen
Eine einmalige Zahlung schaltet jeden Block frei, auch künftige. Preise ansehen.
Die Pro-Registry zu components.json hinzufügen
components.json Token hinzufügen
Erstelle auf deiner Kontoseite einen Token und trage ihn in
.env.localalsHEXTAUI_PRO_TOKENein.Den Block hinzufügen
pnpm dlx shadcn@latest add @hextaui-pro/order-detail
From the Shopify Admin API
Map an Admin API order to Order once, then pass onFulfill to call fulfillmentCreate with the quantities, tracking number and notify flag from the Fulfill items sheet. Throw the first userError and the new shipment rolls back with that message.
Post timeline comments
onComment gets the message and attached files from the one-line composer (it expands on focus, ⌘↵ posts). The comment card shows right away, dimmed, and turns into a failed state with Retry when the request throws. Return the saved OrderEvent so edits and deletes use your id; onResendEmail adds Resend inside an event’s Show details.
A Stripe charge in the payment card
Read a Stripe charge into paymentStatus, the card label, amountPaid and a failed-payment event. When the balance transaction settles in another currency, pass shopCurrency and the card adds the converted total and net payment.
Aufbau
Die Teile, die du zusammensetzt, von außen nach innen.
| Part | Beschreibung |
|---|---|
OrderDetail | The whole page: header, banners, item cards, payment card, timeline and right rail. |
OrderDetailSkeleton | The loading layout, also shown when loading is true. |
FulfillItemsSheet | The sheet that picks quantities, location, tracking and notification for a new shipment. |
OrderTimeline | The one-line composer, the All / Comments / System filter and the day-grouped rail of events and comment cards. |
NotesCard, CustomerCard, ConversionCard, RiskCard, TagsCard | The right rail cards, usable on their own. |
orderActionState, paymentSummary, lineQuantities, detectCarrier, applyFulfillment | Pure helpers for action availability with reasons, payment totals, remaining quantities, carrier detection and optimistic shipments. |
OrderDetail
Also takes div props. Every callback may return a promise; throw to show the message where the action happened.
| Prop | Typ | Standard |
|---|---|---|
orderThe order, from ../order-status/order. Pass a new object when it changes; local optimistic state resets to it. | Order | – |
loadingShows OrderDetailSkeleton. | boolean | false |
localeLocale for dates, money and plurals. | string | "en-US" |
timeZoneThe shop’s time zone for dates and day groups. | string | "UTC" |
nowAn ISO time for Today and Yesterday labels and the authorization countdown. New events are stamped from it. | string | – |
currentUserThe staff member. Their comments can be edited and deleted. | { name: string; avatar?: string } | – |
permissionsfalse or a reason string disables that action with a tooltip, such as { refund: "Only admins can refund orders." }. | Partial<Record<OrderDetailAction, boolean | string>> | – |
archivedShows the archived banner and badge. | boolean | – |
holdReasonText for the on hold banner. Defaults to the latest hold note on the order. | string | – |
riskLevel, headline, indicators with good, bad or neutral tone, IP and provider. Defaults to order.risk. | OrderRiskAnalysis | – |
conversionVisit details for the conversion summary. | { channel?; source?; firstVisit?; sessions?; landingPage? } | – |
shopCurrencyWhen it differs from the order currency, the payment card adds the total and net in the shop currency. | { currencyCode: string; rate: number } | – |
amountPaidWhat the customer has paid, for partially paid orders. | Money | – |
locationsLocations for the Fulfill items sheet. Defaults to the locations of existing shipments. | string[] | – |
backHref, onBackThe back arrow. | string, () => void | – |
customerHrefLink for the customer’s name. | string | – |
previousOrder, nextOrderThe neighbors for the arrows and J/K. | { name: string; href?: string } | null | – |
onNavigateCalled by the arrows and by J and K. | (direction: "previous" | "next") => void | – |
onRefund, onReturn, onEditHeader actions. Wire onRefund to the Refund block’s sheet. | (order: Order) => void | – |
onDuplicate, onPrintPackingSlipMore menu actions. | (order: Order) => Awaitable | – |
onCancelConfirmed in a dialog that explains what happens to the payment. The dialog stays open and shows the error if it throws. | (order, { reason, restock, notifyCustomer }) => Awaitable | – |
onArchiveChangeArchive and unarchive, optimistic with Undo. | (order, archived: boolean) => Awaitable | – |
onFulfillCreates a shipment. Return the saved Fulfillment to replace the optimistic one. | (order, draft: FulfillmentDraft) => Awaitable<Fulfillment | void> | – |
onCapturePayment, onSendInvoice, onReleaseHoldPayment and hold actions. | (order: Order) => Awaitable | – |
onCommentPosts a comment. Return the saved event. | ({ message, attachments }) => Awaitable<OrderEvent | void> | – |
onEditComment, onDeleteCommentEdit and delete your own comments. Delete waits for the Undo toast to close. | (event, message?) => Awaitable | – |
onResendEmailShows Resend on email events. | (event: OrderEvent) => Awaitable | – |
onNoteChange, onTagsChangeSaved optimistically and reverted with a message if they throw. Omit to make them read-only. | (note: string) / (tags: string[]) => Awaitable | – |
labelsWords for the actions and buttons. | Partial<OrderDetailLabels> | – |
OrderTimeline
Usable on its own for customers, drafts or inventory history.
| Prop | Typ | Standard |
|---|---|---|
orderThe order whose events, fulfillments and refunds the titles are built from. | Order | – |
currentUserThe signed-in staff member. Their comments get Edit and Delete. | { name: string; avatar?: string } | – |
defaultFilterThe filter selected on first render. Defaults to "all". | "all" | "comments" | "system" | – |
visibleCountHow many entries show before older history folds behind “Show N earlier events”. Comments-only view never folds. Defaults to 6. | number | – |
nowISO time used for relative times (“2 hr. ago”) and Today / Yesterday labels. Without it, times show as clock times. | string | null | – |
commentStateDisables the composer and explains why. | { available: boolean; reason?: string } | – |
onComment, onEditComment, onDeleteCommentComment posting is optimistic with Retry and Discard on failure; delete has a 5 second Undo toast. | async callbacks | – |
onResendEmailAdds Resend next to each email inside Show details. | (event: OrderEvent) => Awaitable | – |
| Prop | Typ | Standard |
|---|---|---|
linesQuantities to ship, each at most the line’s remaining quantity. | { lineId: string; quantity: number }[] | – |
locationNameThe location it ships from. | string | – |
trackingNumberOptional tracking number. | string | – |
carrierThe chosen carrier, or empty to use the detected one. | string | – |
notifyCustomerSend a shipping confirmation. | boolean | – |
orderActionState
(order, action, { permissions, archived }) => { available, reason }
| Prop | Typ | Standard |
|---|---|---|
actionReturns why an action isn’t available, such as “Items have shipped. Refund or return them instead.” | "refund" | "return" | "edit" | "duplicate" | "cancel" | "archive" | "print" | "fulfill" | "capture" | "invoice" | "releaseHold" | "comment" | – |
| Taste | Aktion |
|---|---|
| J | Opens the next order when focus isn’t in a field. |
| K | Opens the previous order. |
| MetaEnter | Posts the comment, or saves a comment or note you’re editing. |
| Escape | Cancels a comment or note edit and closes sheets, dialogs and menus. |
| ArrowUpArrowDown | Change a quantity in the Fulfill items sheet. |
| Backspace | In an empty tag field, removes the last tag. |
| Escape | In an empty comment composer, leaves it so it folds back to one line. |
- Status pills pair words with a progress glyph, so payment, fulfillment and shipment states never rely on color. The risk meter is a meter with a text value.
- Disabled actions stay focusable, show their reason in a tooltip and link it with aria-describedby. Disabled menu items show the reason under the label.
- A polite live region announces fulfillments, comments, holds released and archive changes, and failures. Comment and note errors use role="alert" next to the item.
- Every card is a labelled section and the page has one h1. The timeline is an ordered list per day; each event reads as one sentence (title, details, then the full date from a time element), icons are hidden from screen readers, Show details buttons name their event and report expanded state, and comments are articles labelled with their author. Copy buttons announce “Copied to clipboard” and tracking and map links say they open a new tab.
Gebaut mit
Die kostenlosen HextaUI-Komponenten, aus denen Order Detail besteht. Jede lässt sich einzeln installieren.
Code
9 Dateien, hinzugefügt zu components/blocks/order-detail.