Standardized rules for submit/async action buttons across all forms.
src/components/PendingButton.tsx — use this instead of a raw <button> for any form submission or async action.
<PendingButton
type="submit"
pending={loading}
pendingLabel="Saving..."
className="..."
>
Save
</PendingButton>| Prop | Type | Description |
|---|---|---|
pending |
boolean |
Whether the async action is in progress |
pendingLabel |
string |
Label shown while pending (e.g. "Signing in...") |
children |
ReactNode |
Idle label |
disabled |
boolean |
Additional disabled condition (e.g. form invalid) |
...rest |
ButtonHTMLAttributes |
All standard button attributes |
- Spinner placement — inline, left of label. SVG-based, sized
1emso it scales with font size. - No layout shift —
min-width: max-contenton.pending-btnkeeps the button width stable between idle and pending states. - Disabled while pending —
disabledandaria-busy="true"are set automatically whenpending={true}. This prevents double-submission. - Label change — the visible label changes to
pendingLabelduring submission. Screen readers announce the change via the button's accessible name. - Reduced motion — the spinner animation is disabled via
@media (prefers-reduced-motion: reduce).
| Flow | File | Pending label |
|---|---|---|
| Login | LoginPage.tsx |
"Signing in..." |
| Register | RegisterPage.tsx |
"Creating Account..." |
| Forgot password | ForgotPasswordPage.tsx |
"Sending..." |
| Reset password | ResetPasswordPage.tsx |
"Resetting..." |
| Draw credit confirm | ConfirmationStep.tsx |
"Processing..." |
| Repay confirm | RepayModal.tsx |
"Processing..." |
| Request evaluation | RequestEvaluation.tsx |
"Starting..." |