diff --git a/src/components/StripeForm/StripeForm.tsx b/src/components/StripeForm/StripeForm.tsx
index d18c0fbf..f4858343 100644
--- a/src/components/StripeForm/StripeForm.tsx
+++ b/src/components/StripeForm/StripeForm.tsx
@@ -1,17 +1,72 @@
import { Elements } from "@stripe/react-stripe-js";
-import { loadStripe } from "@stripe/stripe-js";
-import { ENV } from "@app/env";
-import { StripeFormElements, type StripeFormElementsProps } from "./StripeFormElements";
+import { loadStripe, type StripeElementsOptionsMode } from "@stripe/stripe-js";
+import { useTheme, rgbToHex } from "@mui/material/styles";
+import { ENV } from "@/app/env";
+import { StripeFormContent, type StripeFormContentProps } from "./StripeFormContent";
+import type { Simplify, Except } from "type-fest";
+
+if (!ENV.STRIPE_PUBLISHABLE_KEY) {
+ throw new Error("Unable to load Stripe.");
+}
const stripePromise = loadStripe(ENV.STRIPE_PUBLISHABLE_KEY);
/**
- * A form wrapped in the Stripe Elements provider.
+ * A form wrapped in the Stripe {@link Elements} provider.
+ *
+ * Relevant Stripe Docs:
+ *
+ * - [Stripe Elements](https://stripe.com/docs/stripe-js/react#elements-provider)
+ * - [Stripe Appearance API](https://stripe.com/docs/elements/appearance-api?platform=web)
+ * - [Stripe Appearance API: Variables](https://stripe.com/docs/elements/appearance-api?platform=web#variables)
+ */
+export const StripeForm = ({ stripeElementsOptions = {}, ...props }: StripeFormProps) => {
+ const { palette } = useTheme();
+
+ const { mode, secondary, text, success, warning, error } = palette;
+
+ const elementsOptions: StripeElementsOptionsMode = {
+ // CALLER-PROVIDED OPTIONS:
+ ...stripeElementsOptions,
+ paymentMethodCreation: "manual",
+ // https://stripe.com/docs/elements/appearance-api?platform=web
+ appearance: {
+ theme: mode === "dark" ? "night" : "stripe",
+ labels: "floating",
+ // https://stripe.com/docs/elements/appearance-api?platform=web#variables
+ variables: {
+ // font
+ fontFamily: "Roboto, sans-serif",
+ fontSizeBase: "16px",
+ fontSmooth: "always", // enables anti-aliasing
+ // colors
+ colorPrimary: secondary.main, // the PaymentInput doesn't look good with orange
+ colorText: text.primary,
+ colorTextPlaceholder: text.disabled,
+ colorSuccess: success.main,
+ colorSuccessText: success.main,
+ colorWarning: warning.main,
+ colorWarningText: warning.main,
+ colorDanger: rgbToHex(error.main), // <-- Stripe logs warning if provided rgba here
+ colorDangerText: error.main,
+ colorIconCardError: error.main,
+ colorIconCardCvcError: error.main,
+ },
+ },
+ };
+
+ return (
+
+
+
+ );
+};
+
+/**
+ * Options for the {@link Elements|Stripe Elements context provider} (uses "mode").
*/
-export const StripeForm = (props: StripeFormElementsProps) => (
-
-
-
-);
+export type StripeFormElementsOptions = Simplify;
-export type StripeFormProps = StripeFormElementsProps;
+export type StripeFormProps = {
+ stripeElementsOptions?: Except;
+} & StripeFormContentProps;