forked from Creditra/Creditra-Frontend
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathPendingButton.tsx
More file actions
69 lines (67 loc) · 1.85 KB
/
Copy pathPendingButton.tsx
File metadata and controls
69 lines (67 loc) · 1.85 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
import React from 'react';
interface PendingButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
/**
* True while the parent's async action is in flight. Disables the
* button, sets `aria-busy="true"`, and swaps the label.
*/
pending: boolean;
/**
* Label shown while `pending` is true. Choose a verb form that names
* what is happening (e.g. `Submitting`, `Confirming`) so screen
* readers announce a meaningful state change.
*/
pendingLabel: string;
/** Idle-state label (i.e. the normal button label). */
children: React.ReactNode;
}
/**
* PendingButton — standardized submit/async action button.
*
* Rules:
* - Shows an inline spinner (left of label) while pending; no layout shift.
* - Sets disabled + aria-busy=true while pending to prevent double-submission.
* - Spinner is aria-hidden; the visible label change communicates state to screen readers.
* - Caller controls all styling via className; this component adds no visual opinions.
*/
export function PendingButton({
pending,
pendingLabel,
children,
disabled,
className = '',
...rest
}: PendingButtonProps) {
return (
<button
{...rest}
disabled={pending || disabled}
aria-busy={pending}
className={`pending-btn ${className}`}
>
{pending && (
<svg
className="pending-btn__spinner"
aria-hidden="true"
viewBox="0 0 16 16"
fill="none"
>
<circle
cx="8"
cy="8"
r="6"
stroke="currentColor"
strokeOpacity="0.3"
strokeWidth="2"
/>
<path
d="M14 8a6 6 0 0 0-6-6"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
/>
</svg>
)}
{pending ? pendingLabel : children}
</button>
);
}