Separate elements with styled containers
The following example uses TailwindCSS to style containers wrapping OpenPay Elements.
import {
ElementsForm,
FieldName,
CardNumberElement,
CardExpiryElement,
CardCvcElement,
} from '@getopenpay/openpay-js-react';
import { FC, PropsWithChildren, useState } from 'react';
interface InputProps {
type?: string;
placeholder: string;
openPayId?: FieldName;
}
const Input: FC<InputProps> = ({ type, placeholder, openPayId }) => (
<input
type={type ?? 'text'}
placeholder={placeholder}
className="w-full text-sm bg-transparent outline-none py-2"
data-opid={openPayId}
/>
);
const StyledWrapper: FC<PropsWithChildren> = (props) => {
const { children } = props;
return <div className="bg-emerald-50 dark:bg-emerald-800 shadow-md px-4 py-2 rounded-md mb-2">{children}</div>;
};
const HorizontalRule: FC = () => <hr className="border-emerald-200 dark:border-emerald-700" />;
function CheckoutForm() {
const [error, setError] = useState<string | undefined>(undefined);
const [amount, setAmount] = useState<string | undefined>(undefined);
const onLoad = (totalAmountAtoms: number) => {
setAmount(`$${totalAmountAtoms / 100}`);
};
const onCheckoutError = (message: string) => {
setError(message);
};
const onCheckoutSuccess = (invoiceUrls: string[]) => {
// Invoice URLs are returned here
console.log('invoiceUrls', invoiceUrls);
};
return (
<ElementsForm
checkoutSecureToken={`checkout-secure-token-uuid`}
onChange={() => setError(undefined)}
onLoad={onLoad}
onValidationError={(message) => setError(message)}
onCheckoutSuccess={onCheckoutSuccess}
onCheckoutError={onCheckoutError}
>
{({ submit }) => (
<>
<StyledWrapper>
<div className="flex gap-2 items-center justify-between">
<Input placeholder="Given name" openPayId={FieldName.FIRST_NAME} />
<Input placeholder="Family name" openPayId={FieldName.LAST_NAME} />
</div>
<HorizontalRule />
<Input placeholder="Email" type="email" openPayId={FieldName.EMAIL} />
<HorizontalRule />
<div className="flex gap-2 items-center justify-between">
<Input placeholder="Country" openPayId={FieldName.COUNTRY} />
<Input placeholder="ZIP" openPayId={FieldName.ZIP_CODE} />
</div>
</StyledWrapper>
<div>
<StyledWrapper>
<CardNumberElement />
</StyledWrapper>
<div className="flex gap-2 items-center justify-between">
<StyledWrapper>
<CardExpiryElement />
</StyledWrapper>
<StyledWrapper>
<CardCvcElement />
</StyledWrapper>
</div>
</div>
{error && <small className="font-bold text-xs mt-2 text-red-500">{error}</small>}
<button
onClick={submit}
className="px-4 py-2 mt-2 w-full font-bold rounded-lg bg-emerald-500 text-white hover:bg-emerald-400 active:bg-emerald-600"
>
Pay {amount}
</button>
</>
)}
</ElementsForm>
);
}