d5596afe10
Modal owns the overlay, header, close button and footer for the balance, planned-day and QR modals, and closes on Escape (held off while the QR fetch runs). InlineConfirm replaces the hand-built delete and remove-member confirmations. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
98 lines
2.7 KiB
TypeScript
98 lines
2.7 KiB
TypeScript
import { ReactNode } from 'react'
|
|
|
|
export interface InlineConfirmProps {
|
|
prompt: ReactNode
|
|
confirmLabel: ReactNode
|
|
cancelLabel: ReactNode
|
|
onConfirm: () => void
|
|
onCancel: () => void
|
|
isBusy?: boolean
|
|
confirmTestId?: string
|
|
cancelTestId?: string
|
|
/** Class for the outer wrapper — the two callers use different elements
|
|
* for this (`.modal__delete-confirm`, `.settings-panel__remove-confirm`),
|
|
* so the wrapper's look stays theirs rather than being unified here. */
|
|
className?: string
|
|
/** Class for the span wrapping `prompt` — only `PlannedDayModal` needs
|
|
* one (`.modal__delete-confirm-text`, which pushes the buttons right via
|
|
* `margin-right: auto`); `Settings`' row has no such class. */
|
|
promptClassName?: string
|
|
/** `Settings`' remove-member row shows the danger confirm before cancel;
|
|
* `PlannedDayModal`'s delete row shows cancel first. Defaults to cancel
|
|
* first. */
|
|
confirmFirst?: boolean
|
|
/** Appends `btn--sm` to both buttons — `Settings`' compact row uses it,
|
|
* `PlannedDayModal`'s footer-sized row doesn't. */
|
|
small?: boolean
|
|
/** `data-testid` on the outer wrapper — `PlannedDayModal`'s row has one
|
|
* (`delete-confirm`); `Settings`' row doesn't. */
|
|
testId?: string
|
|
}
|
|
|
|
/**
|
|
* The shared "are you sure" row — a prompt plus a danger confirm and a
|
|
* secondary cancel, both disabled while busy. Replaces the hand-copied
|
|
* versions in `PlannedDayModal` (delete confirm) and `Settings` (remove-
|
|
* member confirm), which differ only in wrapper class, prompt wrapping,
|
|
* button order and button size — all exposed as props here so neither
|
|
* caller's DOM has to change.
|
|
*/
|
|
export function InlineConfirm({
|
|
prompt,
|
|
confirmLabel,
|
|
cancelLabel,
|
|
onConfirm,
|
|
onCancel,
|
|
isBusy = false,
|
|
confirmTestId,
|
|
cancelTestId,
|
|
className,
|
|
promptClassName,
|
|
confirmFirst = false,
|
|
small = false,
|
|
testId,
|
|
}: InlineConfirmProps): ReactNode {
|
|
const sizeClass = small ? ' btn--sm' : ''
|
|
|
|
const confirmButton = (
|
|
<button
|
|
type="button"
|
|
className={`btn btn--danger${sizeClass}`}
|
|
onClick={onConfirm}
|
|
disabled={isBusy}
|
|
data-testid={confirmTestId}
|
|
>
|
|
{confirmLabel}
|
|
</button>
|
|
)
|
|
|
|
const cancelButton = (
|
|
<button
|
|
type="button"
|
|
className={`btn btn--secondary${sizeClass}`}
|
|
onClick={onCancel}
|
|
disabled={isBusy}
|
|
data-testid={cancelTestId}
|
|
>
|
|
{cancelLabel}
|
|
</button>
|
|
)
|
|
|
|
return (
|
|
<div className={className} data-testid={testId}>
|
|
<span className={promptClassName}>{prompt}</span>
|
|
{confirmFirst ? (
|
|
<>
|
|
{confirmButton}
|
|
{cancelButton}
|
|
</>
|
|
) : (
|
|
<>
|
|
{cancelButton}
|
|
{confirmButton}
|
|
</>
|
|
)}
|
|
</div>
|
|
)
|
|
}
|