Commerce & auth
Payment Status
Refined transaction status card with self-drawing checkmark and receipt actions
detent-payment-status
Port status
- Catalog status
- implemented
- Origin
- upstream
- Phase
- 3
- Wave
- phase-3-data
- Group
- Commerce & auth
8.0 KB gzip for the class module
Variants
Sample data; nothing is fetched or sent. The success card reveals the transaction metadata, the itemized receipt and
the copy button; the failed card shows the non-aggressive recovery actions. View Receipt emits one
composed event per toggle and Download only emits detent-download-receipt — the
component never starts a download, so the demo logs receiptText instead. Both cards announce the status
change through a visually hidden live region, so success and failure are readable without colour.
Recorded states
errorrecorded state; no setterreduced motionrecorded state; no setterprocessingrecorded state; no setterverifyingrecorded state; no settersuccessrecorded state; no setterfailedrecorded state; no setterrefundedrecorded state; no setter
Usage
Import
import '/components/payment-status/define.js';
// or register it yourself
import { DetentPaymentStatus } from '/components/payment-status/payment-status.js';
Attributes
amountcurrencydateerror-messagelast4merchant-namepayment-methodrefund-reasonstatustransaction-id
Properties
itemsonChangePaymentMethodonDownloadReceiptonRetryonViewReceipt
Slots
No slots are recorded for this component.
Events
detent-retry— {}detent-change-payment-method— {}detent-download-receipt— {}detent-view-receipt— {}
Example
Runnable example: site/examples/payment-status.ts. The snippet below is generated from the catalogued attributes.
<detent-payment-status
amount="$149.00"
currency="{{MAIN}}quot;
date="Today at 3:42 PM"
error-message
last4="4242"
merchant-name="Detent Cloud"
payment-method="Apple Pay"
refund-reason
status="processing"
transaction-id="tx_9842a8d11c7f"
></detent-payment-status>
Property-only values
const element = document.querySelector('detent-payment-status');
if (element !== null) {
// items: PaymentReceiptItem[]
element.items = [];
// onRetry: () => void
element.onRetry = () => {};
// onChangePaymentMethod: () => void
element.onChangePaymentMethod = () => {};
}
Source
The pinned upstream source for this row:
src/components/ui/PaymentStatus.tsxsha256 e8284c0343ad…
Native files
The native module and its artifacts:
src/components/payment-status/payment-status.tssrc/components/payment-status/styles.csssrc/components/payment-status/define.tsdocs/components/payment-status.mdsite/examples/payment-status.tstests/browser/payment-status.spec.tsevidence/components/payment-status.md
API
Boolean attributes follow HTML presence semantics: present means true, absent means false, and disabled="false" still means disabled.
Attributes
| Attribute | Property | Type | Default | Notes |
|---|---|---|---|---|
amount | amount | string | number | '$149.00' | Kebab-case attribute; camelCase property. |
currency | currency | string | '{{MAIN}}#39; | Kebab-case attribute; camelCase property. |
date | date | string | Date | 'Today at 3:42 PM' | Kebab-case attribute; camelCase property. |
error-message | — | — | — | Recorded in the catalog as an attribute. |
last4 | last4 | string | '4242' | Kebab-case attribute; camelCase property. |
merchant-name | merchantName | string | 'Detent Cloud' | Kebab-case attribute; camelCase property. |
payment-method | paymentMethod | string | 'Apple Pay' | Kebab-case attribute; camelCase property. |
refund-reason | — | — | — | Recorded in the catalog as an attribute. |
status | status | 'processing' | 'verifying' | 'success' | 'failed' | 'refunded' | 'processing' | Kebab-case attribute; camelCase property. |
transaction-id | transactionId | string | 'tx_9842a8d11c7f' | Kebab-case attribute; camelCase property. |
Properties
| Property | Type | Default | Notes |
|---|---|---|---|
items | PaymentReceiptItem[] | [...] | Property-only: assign from script; not accepted as an attribute. |
onChangePaymentMethod | () => void | undefined | Property-only: assign from script; not accepted as an attribute. |
onDownloadReceipt | — | — | Recorded in the catalog without a top-level type; pinned from source when the row is ported. |
onRetry | () => void | undefined | Property-only: assign from script; not accepted as an attribute. |
onViewReceipt | — | — | Recorded in the catalog without a top-level type; pinned from source when the row is ported. |
Events
| Event | Upstream prop | Payload type | Notes |
|---|---|---|---|
detent-retry | onRetry | () => void | Composed, bubbles; fires only for a user action. |
detent-change-payment-method | onChangePaymentMethod | () => void | Composed, bubbles; fires only for a user action. |
detent-download-receipt | onDownloadReceipt | () => void | Composed, bubbles; fires only for a user action. |
detent-view-receipt | onViewReceipt | () => void | Composed, bubbles; fires only for a user action. |
Slots
No slots are recorded for this component.
CSS customisation
- React callback props become typed composed CustomEvents; programmatic state assignment emits none.
- Framer Motion springs/AnimatePresence ported to CSS transitions, WAAPI or the shared rAF spring helper.
- React state/hooks replaced by element-owned state with pre-upgrade property preservation.
- The receipt download is consumer-owned: upstream builds a Blob and clicks a synthetic <a download>; the native row exposes a read-only receiptText and emits detent-download-receipt, with zero network requests.
- Framer Motion springs and AnimatePresence become CSS transitions plus hidden toggling so the live region stays mounted; the checkmark pathLength becomes stroke-dashoffset whose reduced-motion form is the fully drawn stroke.
- Action boundaries use #6b6b6b instead of the upstream #1f1f1f to reach the WCAG 1.4.11 3:1 non-text ratio; dividers keep the hairline.
- The pinned card was one fixed dark surface because the source has no dark: variants; this port follows the theme tokens in both colour schemes, and the --detent-payment-status-* custom properties still override every value.
- errorMessage and refundReason are exposed as the error-message and refund-reason attributes pinned from source (the upstream meta omitted them), and the transaction-ID copy uses the async Clipboard API with the upstream execCommand fallback: a blocked clipboard never throws and never suppresses the confirmation.
- Default demo copy and labels use Detent branding instead of EasyUI (pre-release rebrand).
What it does
A transaction status card: one of five lifecycle states with its own heading, subtext and indicator, a live announcement, the amount, the transaction metadata, an unfolding itemized receipt, a one-click transaction-ID copy and the failure recovery actions.
Upstream behaviour
- 5 clear lifecycle states: Processing, Verifying, Success, Failed, and Refunded
- Self-drawing SVG stroke checkmark animation upon payment confirmation
- Staggered metadata reveal for amount, transaction hash, timestamp, and card info
- Unfolding itemized receipt accordion with instant text-file receipt download
- One-click transaction ID copying with instant checkmark feedback
- Non-aggressive error state with instant retry and payment method alternatives
Differences from upstream
- React callback props become typed composed CustomEvents; programmatic state assignment emits none.
- Framer Motion springs/AnimatePresence ported to CSS transitions, WAAPI or the shared rAF spring helper.
- React state/hooks replaced by element-owned state with pre-upgrade property preservation.
- The receipt download is consumer-owned: upstream builds a Blob and clicks a synthetic <a download>; the native row exposes a read-only receiptText and emits detent-download-receipt, with zero network requests.
- Framer Motion springs and AnimatePresence become CSS transitions plus hidden toggling so the live region stays mounted; the checkmark pathLength becomes stroke-dashoffset whose reduced-motion form is the fully drawn stroke.
- Action boundaries use #6b6b6b instead of the upstream #1f1f1f to reach the WCAG 1.4.11 3:1 non-text ratio; dividers keep the hairline.
- The pinned card was one fixed dark surface because the source has no dark: variants; this port follows the theme tokens in both colour schemes, and the --detent-payment-status-* custom properties still override every value.
- errorMessage and refundReason are exposed as the error-message and refund-reason attributes pinned from source (the upstream meta omitted them), and the transaction-ID copy uses the async Clipboard API with the upstream execCommand fallback: a blocked clipboard never throws and never suppresses the confirmation.
- Default demo copy and labels use Detent branding instead of EasyUI (pre-release rebrand).