CardElement with styled container

The following example uses TailwindCSS to style containers wrapping OpenPay Elements.

import {
  ElementsForm,
  FieldName,
  CardElement,
} 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>

          <StyledWrapper>
            <CardElement />
          </StyledWrapper>

          {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>
  );
}