From 336026b6c1c6235a2bfacb0867a81f538ac37e29 Mon Sep 17 00:00:00 2001 From: Alex Carpenter Date: Fri, 14 Mar 2025 16:20:19 -0400 Subject: [PATCH 01/13] Update CheckoutPage.tsx --- .../ui/components/Checkout/CheckoutPage.tsx | 111 ++++++++++-------- 1 file changed, 62 insertions(+), 49 deletions(-) diff --git a/packages/clerk-js/src/ui/components/Checkout/CheckoutPage.tsx b/packages/clerk-js/src/ui/components/Checkout/CheckoutPage.tsx index f44fb7666f6..6cc3ccdab86 100644 --- a/packages/clerk-js/src/ui/components/Checkout/CheckoutPage.tsx +++ b/packages/clerk-js/src/ui/components/Checkout/CheckoutPage.tsx @@ -9,7 +9,7 @@ import { loadStripe } from '@stripe/stripe-js'; import { useEffect, useRef, useState } from 'react'; import { useEnvironment } from '../../contexts'; -import { Alert, Col, Flex, Spinner } from '../../customizables'; +import { Alert, Box, Flex, Spinner } from '../../customizables'; import { LineItems } from '../../elements'; import { useCheckout } from '../../hooks'; import { CheckoutComplete } from './CheckoutComplete'; @@ -41,57 +41,70 @@ export const CheckoutPage = (props: __experimental_CheckoutProps) => { } }, [checkout?.externalGatewayId, __experimental_commerceSettings]); + if (isLoading) { + return ( + + + + ); + } + + if (!checkout) { + return ( + + {/* TODO(@COMMERCE): needs localization */} + There was a problem, please try again later. + + ); + } + + if (checkout?.status === 'completed') { + return ; + } + return ( <> - {isLoading ? ( - - - - ) : !checkout ? ( - - {/* TODO(@COMMERCE): needs localization */} - There was a problem, please try again later. - - ) : checkout.status === 'completed' ? ( - - ) : ( - <> - ({ - padding: t.space.$4, - borderBottomWidth: t.borderWidths.$normal, - borderBottomStyle: t.borderStyles.$solid, - borderBottomColor: t.colors.$neutralAlpha100, - })} - > - - + ({ + padding: t.space.$4, + borderBottomWidth: t.borderWidths.$normal, + borderBottomStyle: t.borderStyles.$solid, + borderBottomColor: t.colors.$neutralAlpha100, + })} + > + + - {stripe && ( - - - - )} - + {stripe && ( + + + )} ); From 88494923f013b2b4ded044dcb4684e8d4d8f17ae Mon Sep 17 00:00:00 2001 From: Alex Carpenter Date: Fri, 14 Mar 2025 17:17:23 -0400 Subject: [PATCH 02/13] wip --- .../components/Checkout/CheckoutComplete.tsx | 215 +++++++----------- .../ui/components/Checkout/CheckoutPage.tsx | 35 ++- 2 files changed, 96 insertions(+), 154 deletions(-) diff --git a/packages/clerk-js/src/ui/components/Checkout/CheckoutComplete.tsx b/packages/clerk-js/src/ui/components/Checkout/CheckoutComplete.tsx index 00b9d5cb7ab..e35f5bea86e 100644 --- a/packages/clerk-js/src/ui/components/Checkout/CheckoutComplete.tsx +++ b/packages/clerk-js/src/ui/components/Checkout/CheckoutComplete.tsx @@ -1,7 +1,7 @@ import type { __experimental_CommerceCheckoutResource } from '@clerk/types'; import { useCheckoutContext } from '../../contexts'; -import { Box, Button, Col, Flex, Icon, Text } from '../../customizables'; +import { Button, Col, Icon, Span, Text } from '../../customizables'; import { LineItems } from '../../elements'; import { Check } from '../../icons'; @@ -15,34 +15,72 @@ export const CheckoutComplete = ({ checkout }: { checkout: __experimental_Commer }; return ( - + <> ({ + sx={{ flex: 1, - paddingBlock: t.space.$4, - })} + }} > - - - ({ + position: 'relative', + aspectRatio: '1/1', + display: 'grid', + width: '100%', + padding: t.space.$4, + flexShrink: 0, + })} > - {/* TODO(@COMMERCE): needs localization */} - Payment was successful! - ({ textAlign: 'center', paddingInline: t.space.$8 })}> - {/* TODO(@COMMERCE): needs localization */} - Minim adipisicing enim fugiat enim est ad nisi exercitation nisi exercitation quis culpa. - - + + + + ({ + margin: 'auto', + gridArea: '1/1', + position: 'relative', + display: 'flex', + width: t.sizes.$16, + height: t.sizes.$16, + borderRadius: t.radii.$circle, + backgroundImage: + 'linear-gradient(180deg, rgba(255, 255, 255, 0.30) 0%, rgba(0, 0, 0, 0.12) 50%, rgba(0, 0, 0, 0.30) 95.31%)', + '&:before': { + content: '""', + position: 'absolute', + inset: t.space.$1, + backgroundColor: t.colors.$colorBackground, + borderRadius: t.radii.$circle, + }, + })} + > + + + ({ + margin: 'auto', + gridArea: '1/1', + position: 'relative', + textAlign: 'center', + transform: `translateY(${t.space.$20})`, + })} + > + Payment was successful! + ({ textAlign: 'center', paddingInline: t.space.$8 })}> + {/* TODO(@COMMERCE): needs localization */} + Minim adipisicing enim fugiat enim est ad nisi exercitation nisi exercitation quis culpa. + + + - + ); }; -const SuccessCircle = () => { +function Circle({ + scale, +}: { + /** + * Number between 0-1 + */ + scale: number; +}) { return ( - ({ - position: 'relative', - width: '100%', - height: t.sizes.$16, + margin: 'auto', + gridArea: '1/1', + width: `${scale * 100}%`, + height: `${scale * 100}%`, + borderWidth: 1, + borderStyle: 'solid', + borderColor: t.colors.$neutralAlpha200, + borderRadius: t.radii.$circle, + maskImage: `linear-gradient(to bottom, transparent 15%, black, transparent 85%)`, })} - > - {/* rings */} - - ({ - position: 'absolute', - top: `-${t.sizes.$8}`, - bottom: `-${t.sizes.$8}`, - left: '50%', - translate: '-50% 0', - aspectRatio: '1/1', - borderWidth: 1, - borderStyle: 'solid', - borderColor: t.colors.$neutralAlpha150, - borderRadius: t.radii.$circle, - })} - /> - ({ - position: 'absolute', - top: `-${t.sizes.$24}`, - bottom: `-${t.sizes.$24}`, - left: '50%', - translate: '-50% 0', - aspectRatio: '1/1', - borderWidth: 1, - borderStyle: 'solid', - borderColor: t.colors.$neutralAlpha200, - borderRadius: t.radii.$circle, - })} - /> - ({ - position: 'absolute', - top: `-${t.sizes.$40}`, - bottom: `-${t.sizes.$40}`, - left: '50%', - translate: '-50% 0', - aspectRatio: '1/1', - borderWidth: 1, - borderStyle: 'solid', - borderColor: t.colors.$neutralAlpha200, - borderRadius: t.radii.$circle, - })} - /> - - - {/* fade overlays */} - ({ - position: 'absolute', - width: '120%', - aspectRatio: '1/1', - top: '50%', - translate: '0 -50%', - backgroundImage: `linear-gradient(to bottom, ${t.colors.$colorBackground} 35%, transparent 48%, transparent 52%, ${t.colors.$colorBackground} 65%)`, - })} - /> - - {/* coin */} - ({ - position: 'relative', - width: t.sizes.$16, - height: t.sizes.$16, - borderRadius: t.radii.$circle, - backgroundImage: - 'linear-gradient(180deg, rgba(255, 255, 255, 0.30) 0%, rgba(0, 0, 0, 0.12) 50%, rgba(0, 0, 0, 0.30) 95.31%)', - })} - > - ({ - position: 'relative', - width: t.sizes.$16, - height: t.sizes.$16, - borderRadius: t.radii.$circle, - backgroundImage: 'linear-gradient(180deg, rgba(255, 255, 255, 0.06) 0%, rgba(255, 255, 255, 0.00) 60.94%)', - backgroundBlendMode: 'plus-lighter, normal', - boxShadow: '0px 4px 12px 0px rgba(0, 0, 0, 0.35), 0px 1px 0px 0px rgba(255, 255, 255, 0.05) inset', - })} - > - ({ - position: 'absolute', - inset: t.space.$1, - borderRadius: t.radii.$circle, - backgroundColor: t.colors.$colorBackground, - })} - > - - - - - + /> ); -}; +} diff --git a/packages/clerk-js/src/ui/components/Checkout/CheckoutPage.tsx b/packages/clerk-js/src/ui/components/Checkout/CheckoutPage.tsx index 6cc3ccdab86..de9eb9465f6 100644 --- a/packages/clerk-js/src/ui/components/Checkout/CheckoutPage.tsx +++ b/packages/clerk-js/src/ui/components/Checkout/CheckoutPage.tsx @@ -9,7 +9,7 @@ import { loadStripe } from '@stripe/stripe-js'; import { useEffect, useRef, useState } from 'react'; import { useEnvironment } from '../../contexts'; -import { Alert, Box, Flex, Spinner } from '../../customizables'; +import { Alert, Box, Spinner } from '../../customizables'; import { LineItems } from '../../elements'; import { useCheckout } from '../../hooks'; import { CheckoutComplete } from './CheckoutComplete'; @@ -43,34 +43,27 @@ export const CheckoutPage = (props: __experimental_CheckoutProps) => { if (isLoading) { return ( - - - + /> ); } if (!checkout) { return ( - + <> {/* TODO(@COMMERCE): needs localization */} - There was a problem, please try again later. - + + There was a problem, please try again later. + + ); } From eb668674d4361b281bfb234be60d5c135f6b796c Mon Sep 17 00:00:00 2001 From: Alex Carpenter Date: Mon, 17 Mar 2025 10:48:15 -0400 Subject: [PATCH 03/13] WIP --- .../components/Checkout/CheckoutComplete.tsx | 37 ++++++++++++------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/packages/clerk-js/src/ui/components/Checkout/CheckoutComplete.tsx b/packages/clerk-js/src/ui/components/Checkout/CheckoutComplete.tsx index e35f5bea86e..68bca6afb71 100644 --- a/packages/clerk-js/src/ui/components/Checkout/CheckoutComplete.tsx +++ b/packages/clerk-js/src/ui/components/Checkout/CheckoutComplete.tsx @@ -1,7 +1,7 @@ import type { __experimental_CommerceCheckoutResource } from '@clerk/types'; import { useCheckoutContext } from '../../contexts'; -import { Button, Col, Icon, Span, Text } from '../../customizables'; +import { Box, Button, Col, Heading, Icon, Span, Text } from '../../customizables'; import { LineItems } from '../../elements'; import { Check } from '../../icons'; @@ -33,26 +33,26 @@ export const CheckoutComplete = ({ checkout }: { checkout: __experimental_Commer flexShrink: 0, })} > - - - - + + + ({ margin: 'auto', gridArea: '1/1', - position: 'relative', display: 'flex', + position: 'relative', width: t.sizes.$16, height: t.sizes.$16, borderRadius: t.radii.$circle, - backgroundImage: - 'linear-gradient(180deg, rgba(255, 255, 255, 0.30) 0%, rgba(0, 0, 0, 0.12) 50%, rgba(0, 0, 0, 0.30) 95.31%)', - '&:before': { + backgroundImage: `linear-gradient(180deg, rgba(255, 255, 255, 0.30) 0%, rgba(0, 0, 0, 0.12) 50%, rgba(0, 0, 0, 0.30) 95.31%)`, + boxShadow: '0px 4px 12px 0px rgba(0, 0, 0, 0.35), 0px 1px 0px 0px rgba(255, 255, 255, 0.05) inset', + ':before': { content: '""', position: 'absolute', inset: t.space.$1, - backgroundColor: t.colors.$colorBackground, borderRadius: t.radii.$circle, + backgroundColor: t.colors.$colorBackground, }, })} > @@ -63,8 +63,9 @@ export const CheckoutComplete = ({ checkout }: { checkout: __experimental_Commer position: 'relative', margin: 'auto', }} + aria-hidden /> - + ({ margin: 'auto', @@ -74,8 +75,16 @@ export const CheckoutComplete = ({ checkout }: { checkout: __experimental_Commer transform: `translateY(${t.space.$20})`, })} > - Payment was successful! - ({ textAlign: 'center', paddingInline: t.space.$8 })}> + + Payment was successful! + + ({ textAlign: 'center', paddingInline: t.space.$8, marginBlockStart: t.space.$2 })} + > {/* TODO(@COMMERCE): needs localization */} Minim adipisicing enim fugiat enim est ad nisi exercitation nisi exercitation quis culpa. @@ -130,7 +139,7 @@ export const CheckoutComplete = ({ checkout }: { checkout: __experimental_Commer ); }; -function Circle({ +function Ring({ scale, }: { /** From c8b8f361fe067398fdab18701b9624a378bd0dc0 Mon Sep 17 00:00:00 2001 From: Alex Carpenter Date: Mon, 17 Mar 2025 11:07:34 -0400 Subject: [PATCH 04/13] WIP --- .../ui/components/Checkout/CheckoutForm.tsx | 78 +++++++++++++++- .../ui/components/Checkout/CheckoutPage.tsx | 91 ++----------------- 2 files changed, 82 insertions(+), 87 deletions(-) diff --git a/packages/clerk-js/src/ui/components/Checkout/CheckoutForm.tsx b/packages/clerk-js/src/ui/components/Checkout/CheckoutForm.tsx index 2d6cb7e122d..88d0a12a4b2 100644 --- a/packages/clerk-js/src/ui/components/Checkout/CheckoutForm.tsx +++ b/packages/clerk-js/src/ui/components/Checkout/CheckoutForm.tsx @@ -6,17 +6,89 @@ import type { ClerkAPIError, ClerkRuntimeError, } from '@clerk/types'; -import { PaymentElement, useElements, useStripe } from '@stripe/react-stripe-js'; +import { Elements, PaymentElement, useElements, useStripe } from '@stripe/react-stripe-js'; +import type { Stripe } from '@stripe/stripe-js'; import { useCallback, useEffect, useMemo, useState } from 'react'; -import { Button, Col, Flex, Form, Icon, Text } from '../../customizables'; -import { Alert, Disclosure, Divider, Select, SelectButton, SelectOptionList } from '../../elements'; +import { Box, Button, Col, Flex, Form, Icon, Text } from '../../customizables'; +import { Alert, Disclosure, Divider, LineItems, Select, SelectButton, SelectOptionList } from '../../elements'; import { useFetch } from '../../hooks'; import { ArrowUpDown, CreditCard } from '../../icons'; import { animations } from '../../styledSystem'; import { handleError } from '../../utils'; export const CheckoutForm = ({ + stripe, + checkout, + onCheckoutComplete, +}: { + stripe: Stripe | null; + checkout: __experimental_CommerceCheckoutResource; + onCheckoutComplete: (checkout: __experimental_CommerceCheckoutResource) => void; +}) => { + const { plan, planPeriod, totals } = checkout; + return ( + <> + ({ + padding: t.space.$4, + borderBottomWidth: t.borderWidths.$normal, + borderBottomStyle: t.borderStyles.$solid, + borderBottomColor: t.colors.$neutralAlpha100, + })} + > + + + {plan.name} + + {plan.currencySymbol} + {planPeriod === 'month' ? plan.amountFormatted : plan.annualMonthlyAmountFormatted} + + + + Subtotal + + {totals.subtotal.currencySymbol} + {totals.subtotal.amountFormatted} + + + + Tax + + {totals.taxTotal.currencySymbol} + {totals.taxTotal.amountFormatted} + + + + Total{totals.totalDueNow ? ' Due Today' : ''} + + {totals.totalDueNow + ? `${totals.totalDueNow.currencySymbol}${totals.totalDueNow.amountFormatted}` + : `${totals.grandTotal.currencySymbol}${totals.grandTotal.amountFormatted}`} + + + + + + {stripe && ( + + + + )} + + ); +}; + +const CheckoutFormElements = ({ checkout, onCheckoutComplete, }: { diff --git a/packages/clerk-js/src/ui/components/Checkout/CheckoutPage.tsx b/packages/clerk-js/src/ui/components/Checkout/CheckoutPage.tsx index de9eb9465f6..cc6f48f174d 100644 --- a/packages/clerk-js/src/ui/components/Checkout/CheckoutPage.tsx +++ b/packages/clerk-js/src/ui/components/Checkout/CheckoutPage.tsx @@ -1,16 +1,10 @@ -import type { - __experimental_CheckoutProps, - __experimental_CommercePlanResource, - __experimental_CommerceTotals, -} from '@clerk/types'; -import { Elements } from '@stripe/react-stripe-js'; +import type { __experimental_CheckoutProps } from '@clerk/types'; import type { Stripe } from '@stripe/stripe-js'; import { loadStripe } from '@stripe/stripe-js'; import { useEffect, useRef, useState } from 'react'; import { useEnvironment } from '../../contexts'; -import { Alert, Box, Spinner } from '../../customizables'; -import { LineItems } from '../../elements'; +import { Alert, Spinner } from '../../customizables'; import { useCheckout } from '../../hooks'; import { CheckoutComplete } from './CheckoutComplete'; import { CheckoutForm } from './CheckoutForm'; @@ -72,81 +66,10 @@ export const CheckoutPage = (props: __experimental_CheckoutProps) => { } return ( - <> - ({ - padding: t.space.$4, - borderBottomWidth: t.borderWidths.$normal, - borderBottomStyle: t.borderStyles.$solid, - borderBottomColor: t.colors.$neutralAlpha100, - })} - > - - - - {stripe && ( - - - - )} - - ); -}; - -// TODO(@COMMERCE): needs localization -const CheckoutPlanRows = ({ - plan, - planPeriod, - totals, -}: { - plan: __experimental_CommercePlanResource; - planPeriod: string; - totals: __experimental_CommerceTotals; -}) => { - return ( - - - {plan.name} - - {plan.currencySymbol} - {planPeriod === 'month' ? plan.amountFormatted : plan.annualMonthlyAmountFormatted} - - - - Subtotal - - {totals.subtotal.currencySymbol} - {totals.subtotal.amountFormatted} - - - - Tax - - {totals.taxTotal.currencySymbol} - {totals.taxTotal.amountFormatted} - - - - Total{totals.totalDueNow ? ' Due Today' : ''} - - {totals.totalDueNow - ? `${totals.totalDueNow.currencySymbol}${totals.totalDueNow.amountFormatted}` - : `${totals.grandTotal.currencySymbol}${totals.grandTotal.amountFormatted}`} - - - + ); }; From a6dbd8019ff124febec19e22aa7ee3c710703969 Mon Sep 17 00:00:00 2001 From: Alex Carpenter Date: Mon, 17 Mar 2025 11:20:13 -0400 Subject: [PATCH 05/13] WIP --- .../components/Checkout/CheckoutComplete.tsx | 148 ++++++++---------- 1 file changed, 68 insertions(+), 80 deletions(-) diff --git a/packages/clerk-js/src/ui/components/Checkout/CheckoutComplete.tsx b/packages/clerk-js/src/ui/components/Checkout/CheckoutComplete.tsx index 68bca6afb71..1cacf776d65 100644 --- a/packages/clerk-js/src/ui/components/Checkout/CheckoutComplete.tsx +++ b/packages/clerk-js/src/ui/components/Checkout/CheckoutComplete.tsx @@ -1,7 +1,7 @@ import type { __experimental_CommerceCheckoutResource } from '@clerk/types'; import { useCheckoutContext } from '../../contexts'; -import { Box, Button, Col, Heading, Icon, Span, Text } from '../../customizables'; +import { Box, Button, Flex, Heading, Icon, Span, Text } from '../../customizables'; import { LineItems } from '../../elements'; import { Check } from '../../icons'; @@ -16,85 +16,79 @@ export const CheckoutComplete = ({ checkout }: { checkout: __experimental_Commer return ( <> - ({ + position: 'relative', + aspectRatio: '1/1', + display: 'grid', + width: '100%', + padding: t.space.$4, + flexShrink: 0, + })} > - + + + ({ + margin: 'auto', + gridArea: '1/1', + display: 'flex', position: 'relative', - aspectRatio: '1/1', - display: 'grid', - width: '100%', - padding: t.space.$4, - flexShrink: 0, + width: t.sizes.$16, + height: t.sizes.$16, + borderRadius: t.radii.$circle, + backgroundImage: `linear-gradient(180deg, rgba(255, 255, 255, 0.30) 0%, rgba(0, 0, 0, 0.12) 50%, rgba(0, 0, 0, 0.30) 95.31%)`, + boxShadow: '0px 4px 12px 0px rgba(0, 0, 0, 0.35), 0px 1px 0px 0px rgba(255, 255, 255, 0.05) inset', + ':before': { + content: '""', + position: 'absolute', + inset: t.space.$1, + borderRadius: t.radii.$circle, + backgroundColor: t.colors.$colorBackground, + }, })} > - - - - ({ - margin: 'auto', - gridArea: '1/1', - display: 'flex', + - - - ({ margin: 'auto', - gridArea: '1/1', - position: 'relative', - textAlign: 'center', - transform: `translateY(${t.space.$20})`, - })} + }} + aria-hidden + /> + + ({ + margin: 'auto', + gridArea: '1/1', + position: 'relative', + textAlign: 'center', + transform: `translateY(${t.space.$20})`, + })} + > + - - Payment was successful! - - ({ textAlign: 'center', paddingInline: t.space.$8, marginBlockStart: t.space.$2 })} - > - {/* TODO(@COMMERCE): needs localization */} - Minim adipisicing enim fugiat enim est ad nisi exercitation nisi exercitation quis culpa. - - + Payment was successful! + + ({ textAlign: 'center', paddingInline: t.space.$8, marginBlockStart: t.space.$2 })} + > + {/* TODO(@COMMERCE): needs localization */} + Minim adipisicing enim fugiat enim est ad nisi exercitation nisi exercitation quis culpa. + - + - ({ + marginBlockStart: 'auto', padding: t.space.$4, borderTopWidth: t.borderWidths.$normal, borderTopStyle: t.borderStyles.$solid, @@ -106,7 +100,7 @@ export const CheckoutComplete = ({ checkout }: { checkout: __experimental_Commer Total paid - {checkout.invoice + {checkout?.invoice ? `${checkout.invoice.totals.grandTotal.currencySymbol}${checkout.invoice.totals.grandTotal.amountFormatted}` : '–'} @@ -115,26 +109,20 @@ export const CheckoutComplete = ({ checkout }: { checkout: __experimental_Commer {/* TODO(@COMMERCE): needs localization */} Payment method - {checkout.paymentSource ? `${checkout.paymentSource.cardType} ⋯ ${checkout.paymentSource.last4}` : '–'} + {checkout?.paymentSource ? `${checkout.paymentSource.cardType} ⋯ ${checkout.paymentSource.last4}` : '–'} {/* TODO(@COMMERCE): needs localization */} Invoice ID - {checkout.invoice ? checkout.invoice.id : '–'} + {checkout?.invoice ? checkout.invoice.id : '–'} - - + ); }; From cdc4e7bcd25a812a49d3feff8a7dfd120fc6d7b6 Mon Sep 17 00:00:00 2001 From: Alex Carpenter Date: Mon, 17 Mar 2025 12:51:57 -0400 Subject: [PATCH 06/13] wip --- .../src/ui/components/Checkout/Checkout.tsx | 4 +- .../components/Checkout/CheckoutComplete.tsx | 137 +++++++++--------- .../ui/components/Checkout/CheckoutForm.tsx | 6 +- packages/clerk-js/src/ui/elements/Drawer.tsx | 35 +++-- 4 files changed, 90 insertions(+), 92 deletions(-) diff --git a/packages/clerk-js/src/ui/components/Checkout/Checkout.tsx b/packages/clerk-js/src/ui/components/Checkout/Checkout.tsx index 848a2edc0da..7d4e4bcb933 100644 --- a/packages/clerk-js/src/ui/components/Checkout/Checkout.tsx +++ b/packages/clerk-js/src/ui/components/Checkout/Checkout.tsx @@ -36,9 +36,7 @@ const AuthenticatedRoutes = withCoreUserGuard((props: __experimental_CheckoutPro - - - + ); diff --git a/packages/clerk-js/src/ui/components/Checkout/CheckoutComplete.tsx b/packages/clerk-js/src/ui/components/Checkout/CheckoutComplete.tsx index 1cacf776d65..9a966c1df9d 100644 --- a/packages/clerk-js/src/ui/components/Checkout/CheckoutComplete.tsx +++ b/packages/clerk-js/src/ui/components/Checkout/CheckoutComplete.tsx @@ -1,8 +1,8 @@ import type { __experimental_CommerceCheckoutResource } from '@clerk/types'; import { useCheckoutContext } from '../../contexts'; -import { Box, Button, Flex, Heading, Icon, Span, Text } from '../../customizables'; -import { LineItems } from '../../elements'; +import { Box, Button, Heading, Icon, Span, Text } from '../../customizables'; +import { Drawer, LineItems } from '../../elements'; import { Check } from '../../icons'; export const CheckoutComplete = ({ checkout }: { checkout: __experimental_CommerceCheckoutResource }) => { @@ -16,84 +16,79 @@ export const CheckoutComplete = ({ checkout }: { checkout: __experimental_Commer return ( <> - ({ - position: 'relative', - aspectRatio: '1/1', - display: 'grid', - width: '100%', - padding: t.space.$4, - flexShrink: 0, - })} - > - - - - ({ - margin: 'auto', - gridArea: '1/1', - display: 'flex', - position: 'relative', - width: t.sizes.$16, - height: t.sizes.$16, - borderRadius: t.radii.$circle, - backgroundImage: `linear-gradient(180deg, rgba(255, 255, 255, 0.30) 0%, rgba(0, 0, 0, 0.12) 50%, rgba(0, 0, 0, 0.30) 95.31%)`, - boxShadow: '0px 4px 12px 0px rgba(0, 0, 0, 0.35), 0px 1px 0px 0px rgba(255, 255, 255, 0.05) inset', - ':before': { - content: '""', - position: 'absolute', - inset: t.space.$1, - borderRadius: t.radii.$circle, - backgroundColor: t.colors.$colorBackground, - }, - })} - > - - + ({ margin: 'auto', - gridArea: '1/1', position: 'relative', - textAlign: 'center', - transform: `translateY(${t.space.$20})`, + aspectRatio: '1/1', + display: 'grid', + width: '100%', + padding: t.space.$4, + flexShrink: 0, })} > - + + + ({ + margin: 'auto', + gridArea: '1/1', + display: 'flex', + position: 'relative', + width: t.sizes.$16, + height: t.sizes.$16, + borderRadius: t.radii.$circle, + backgroundImage: `linear-gradient(180deg, rgba(255, 255, 255, 0.30) 0%, rgba(0, 0, 0, 0.12) 50%, rgba(0, 0, 0, 0.30) 95.31%)`, + boxShadow: '0px 4px 12px 0px rgba(0, 0, 0, 0.35), 0px 1px 0px 0px rgba(255, 255, 255, 0.05) inset', + ':before': { + content: '""', + position: 'absolute', + inset: t.space.$1, + borderRadius: t.radii.$circle, + backgroundColor: t.colors.$colorBackground, + }, + })} > - Payment was successful! - - ({ textAlign: 'center', paddingInline: t.space.$8, marginBlockStart: t.space.$2 })} + + + ({ + margin: 'auto', + gridArea: '1/1', + position: 'relative', + textAlign: 'center', + transform: `translateY(${t.space.$20})`, + })} > - {/* TODO(@COMMERCE): needs localization */} - Minim adipisicing enim fugiat enim est ad nisi exercitation nisi exercitation quis culpa. - + + Payment was successful! + + ({ textAlign: 'center', paddingInline: t.space.$8, marginBlockStart: t.space.$2 })} + > + {/* TODO(@COMMERCE): needs localization */} + Minim adipisicing enim fugiat enim est ad nisi exercitation nisi exercitation quis culpa. + + - - - + ({ - marginBlockStart: 'auto', - padding: t.space.$4, - borderTopWidth: t.borderWidths.$normal, - borderTopStyle: t.borderStyles.$solid, - borderTopColor: t.colors.$neutralAlpha100, - position: 'relative', + rowGap: t.space.$4, })} > @@ -122,7 +117,7 @@ export const CheckoutComplete = ({ checkout }: { checkout: __experimental_Commer {/* TODO(@COMMERCE): needs localization */} Continue - + ); }; diff --git a/packages/clerk-js/src/ui/components/Checkout/CheckoutForm.tsx b/packages/clerk-js/src/ui/components/Checkout/CheckoutForm.tsx index 88d0a12a4b2..38edca81dd3 100644 --- a/packages/clerk-js/src/ui/components/Checkout/CheckoutForm.tsx +++ b/packages/clerk-js/src/ui/components/Checkout/CheckoutForm.tsx @@ -11,7 +11,7 @@ import type { Stripe } from '@stripe/stripe-js'; import { useCallback, useEffect, useMemo, useState } from 'react'; import { Box, Button, Col, Flex, Form, Icon, Text } from '../../customizables'; -import { Alert, Disclosure, Divider, LineItems, Select, SelectButton, SelectOptionList } from '../../elements'; +import { Alert, Disclosure, Divider, Drawer, LineItems, Select, SelectButton, SelectOptionList } from '../../elements'; import { useFetch } from '../../hooks'; import { ArrowUpDown, CreditCard } from '../../icons'; import { animations } from '../../styledSystem'; @@ -28,7 +28,7 @@ export const CheckoutForm = ({ }) => { const { plan, planPeriod, totals } = checkout; return ( - <> + ({ padding: t.space.$4, @@ -84,7 +84,7 @@ export const CheckoutForm = ({ /> )} - + ); }; diff --git a/packages/clerk-js/src/ui/elements/Drawer.tsx b/packages/clerk-js/src/ui/elements/Drawer.tsx index d65ebc68991..4cb743ccc0a 100644 --- a/packages/clerk-js/src/ui/elements/Drawer.tsx +++ b/packages/clerk-js/src/ui/elements/Drawer.tsx @@ -348,27 +348,32 @@ const Body = React.forwardRef(({ children }, ref) => interface FooterProps { children?: React.ReactNode; + sx?: ThemableCssProp; } -const Footer = React.forwardRef(({ children }, ref) => { +const Footer = React.forwardRef(({ children, sx }, ref) => { return ( ({ - display: 'flex', - background: common.mergedColorsBackground( - colors.setAlpha(t.colors.$colorBackground, 1), - t.colors.$neutralAlpha50, - ), - borderBlockStartWidth: t.borderWidths.$normal, - borderBlockStartStyle: t.borderStyles.$solid, - borderBlockStartColor: t.colors.$neutralAlpha100, - borderEndStartRadius: t.radii.$xl, - borderEndEndRadius: t.radii.$xl, - paddingBlock: t.space.$3, - paddingInline: t.space.$4, - })} + sx={[ + t => ({ + display: 'flex', + flexDirection: 'column', + background: common.mergedColorsBackground( + colors.setAlpha(t.colors.$colorBackground, 1), + t.colors.$neutralAlpha50, + ), + borderBlockStartWidth: t.borderWidths.$normal, + borderBlockStartStyle: t.borderStyles.$solid, + borderBlockStartColor: t.colors.$neutralAlpha100, + borderEndStartRadius: t.radii.$xl, + borderEndEndRadius: t.radii.$xl, + paddingBlock: t.space.$3, + paddingInline: t.space.$4, + }), + sx, + ]} > {children} From 69bc15fbacc6de8ea55f22c362f6b17590bedfc9 Mon Sep 17 00:00:00 2001 From: Alex Carpenter Date: Mon, 17 Mar 2025 13:23:43 -0400 Subject: [PATCH 07/13] WIP --- .../src/ui/components/Checkout/CheckoutComplete.tsx | 8 +++++++- .../clerk-js/src/ui/customizables/elementDescriptors.ts | 6 ++++++ packages/types/src/appearance.ts | 6 ++++++ 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/packages/clerk-js/src/ui/components/Checkout/CheckoutComplete.tsx b/packages/clerk-js/src/ui/components/Checkout/CheckoutComplete.tsx index 9a966c1df9d..cadfdc4da21 100644 --- a/packages/clerk-js/src/ui/components/Checkout/CheckoutComplete.tsx +++ b/packages/clerk-js/src/ui/components/Checkout/CheckoutComplete.tsx @@ -1,7 +1,7 @@ import type { __experimental_CommerceCheckoutResource } from '@clerk/types'; import { useCheckoutContext } from '../../contexts'; -import { Box, Button, Heading, Icon, Span, Text } from '../../customizables'; +import { Box, Button, descriptors, Heading, Icon, Span, Text } from '../../customizables'; import { Drawer, LineItems } from '../../elements'; import { Check } from '../../icons'; @@ -18,6 +18,7 @@ export const CheckoutComplete = ({ checkout }: { checkout: __experimental_Commer <> ({ margin: 'auto', position: 'relative', @@ -32,6 +33,7 @@ export const CheckoutComplete = ({ checkout }: { checkout: __experimental_Commer ({ margin: 'auto', gridArea: '1/1', @@ -71,12 +73,14 @@ export const CheckoutComplete = ({ checkout }: { checkout: __experimental_Commer })} > Payment was successful! ({ textAlign: 'center', paddingInline: t.space.$8, marginBlockStart: t.space.$2 })} > @@ -86,6 +90,7 @@ export const CheckoutComplete = ({ checkout }: { checkout: __experimental_Commer + ({ rowGap: t.space.$4, @@ -132,6 +137,7 @@ function Ring({ }) { return ( ({ margin: 'auto', gridArea: '1/1', diff --git a/packages/clerk-js/src/ui/customizables/elementDescriptors.ts b/packages/clerk-js/src/ui/customizables/elementDescriptors.ts index c6ac9d01884..051549c42ba 100644 --- a/packages/clerk-js/src/ui/customizables/elementDescriptors.ts +++ b/packages/clerk-js/src/ui/customizables/elementDescriptors.ts @@ -82,6 +82,12 @@ export const APPEARANCE_KEYS = containsAllElementsConfigKeys([ 'alternativeMethodsBlockButtonText', 'alternativeMethodsBlockButtonArrow', + 'checkoutSuccessRoot', + 'checkoutSuccessRing', + 'checkoutSuccessBadge', + 'checkoutSuccessTitle', + 'checkoutSuccessDescription', + 'otpCodeField', 'otpCodeFieldInputs', 'otpCodeFieldInput', diff --git a/packages/types/src/appearance.ts b/packages/types/src/appearance.ts index 49bfe60287f..08e860b4573 100644 --- a/packages/types/src/appearance.ts +++ b/packages/types/src/appearance.ts @@ -201,6 +201,12 @@ export type ElementsConfig = { alternativeMethodsBlockButtonText: WithOptions; alternativeMethodsBlockButtonArrow: WithOptions; + checkoutSuccessRoot: WithOptions; + checkoutSuccessRing: WithOptions; + checkoutSuccessBadge: WithOptions; + checkoutSuccessTitle: WithOptions; + checkoutSuccessDescription: WithOptions; + otpCodeField: WithOptions; otpCodeFieldInputs: WithOptions; otpCodeFieldInput: WithOptions; From 851cd3ac4748e5b284b9403b1d15763c011bd8d8 Mon Sep 17 00:00:00 2001 From: Alex Carpenter Date: Mon, 17 Mar 2025 13:38:12 -0400 Subject: [PATCH 08/13] wip --- .../ui/components/Checkout/CheckoutForm.tsx | 282 +++++++++--------- packages/types/src/appearance.ts | 2 +- 2 files changed, 148 insertions(+), 136 deletions(-) diff --git a/packages/clerk-js/src/ui/components/Checkout/CheckoutForm.tsx b/packages/clerk-js/src/ui/components/Checkout/CheckoutForm.tsx index bd043a734a4..f36146f3fbd 100644 --- a/packages/clerk-js/src/ui/components/Checkout/CheckoutForm.tsx +++ b/packages/clerk-js/src/ui/components/Checkout/CheckoutForm.tsx @@ -10,7 +10,7 @@ import { Elements, PaymentElement, useElements, useStripe } from '@stripe/react- import type { Stripe } from '@stripe/stripe-js'; import { useCallback, useEffect, useMemo, useState } from 'react'; -import { Box, Button, Col, Flex, Form, Icon, Text } from '../../customizables'; +import { Box, Button, Col, descriptors, Flex, Form, Icon, Text } from '../../customizables'; import { Alert, Disclosure, Divider, Drawer, LineItems, Select, SelectButton, SelectOptionList } from '../../elements'; import { useFetch } from '../../hooks'; import { ArrowUpDown, CreditCard } from '../../icons'; @@ -253,65 +253,73 @@ const PaymentSourceMethods = ({ }, [paymentSources]); return ( -
- - { + const paymentSource = paymentSources.find(source => source.id === option.value); + setSelectedPaymentSource(paymentSource); + }} + portal + > + {/*Store value inside an input in order to be accessible as form data*/} + + ({ + justifyContent: 'space-between', + backgroundColor: t.colors.$colorBackground, + })} > - {/*Store value inside an input in order to be accessible as form data*/} - - ({ - justifyContent: 'space-between', - backgroundColor: t.colors.$colorBackground, - })} - > - {selectedPaymentSource && ( - + + - - - {selectedPaymentSource.cardType} ⋯ {selectedPaymentSource.last4} - - - )} - - ({ - paddingBlock: t.space.$1, - color: t.colors.$colorText, - })} - /> - - - + {selectedPaymentSource.cardType} ⋯ {selectedPaymentSource.last4} + + + )} + + ({ + paddingBlock: t.space.$1, + color: t.colors.$colorText, + })} + /> + + ); }; @@ -336,83 +344,87 @@ const StripePaymentMethods = ({ }, [collapsed, onExpand]); return ( -
- - - {collapsed ? ( - <> - - - - - ) : ( - <> - - - - )} - + ({ + display: 'flex', + flexDirection: 'column', + rowGap: t.space.$3, + })} + > + + {collapsed ? ( + <> + + + + + ) : ( + <> + + + + )} ); }; diff --git a/packages/types/src/appearance.ts b/packages/types/src/appearance.ts index 08e860b4573..1e5041fc7f1 100644 --- a/packages/types/src/appearance.ts +++ b/packages/types/src/appearance.ts @@ -134,7 +134,7 @@ export type ElementObjectKey = K extends `${infer Parent}-${in * Kebab-case is used to differentiate between the container and child elements */ export type ElementsConfig = { - button: WithOptions; + button: WithOptions; input: WithOptions; checkbox: WithOptions; radio: WithOptions; From 6e613f9240210c46578e56b15be7dc5ae7f7cfaa Mon Sep 17 00:00:00 2001 From: Alex Carpenter Date: Mon, 17 Mar 2025 13:40:16 -0400 Subject: [PATCH 09/13] add changeset --- .changeset/twenty-ducks-pump.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .changeset/twenty-ducks-pump.md diff --git a/.changeset/twenty-ducks-pump.md b/.changeset/twenty-ducks-pump.md new file mode 100644 index 00000000000..1e44d431a29 --- /dev/null +++ b/.changeset/twenty-ducks-pump.md @@ -0,0 +1,6 @@ +--- +'@clerk/clerk-js': patch +'@clerk/types': patch +--- + +Refactor `` components. From 6bdd2acc33822ce3c0509c17007e9f15615b9e10 Mon Sep 17 00:00:00 2001 From: Alex Carpenter Date: Mon, 17 Mar 2025 13:52:27 -0400 Subject: [PATCH 10/13] wip --- packages/clerk-js/src/ui/components/Checkout/CheckoutForm.tsx | 2 ++ packages/clerk-js/src/ui/customizables/elementDescriptors.ts | 3 +++ packages/types/src/appearance.ts | 3 +++ 3 files changed, 8 insertions(+) diff --git a/packages/clerk-js/src/ui/components/Checkout/CheckoutForm.tsx b/packages/clerk-js/src/ui/components/Checkout/CheckoutForm.tsx index f36146f3fbd..fa5f4af55df 100644 --- a/packages/clerk-js/src/ui/components/Checkout/CheckoutForm.tsx +++ b/packages/clerk-js/src/ui/components/Checkout/CheckoutForm.tsx @@ -30,6 +30,7 @@ export const CheckoutForm = ({ return ( ({ padding: t.space.$4, borderBottomWidth: t.borderWidths.$normal, @@ -175,6 +176,7 @@ const CheckoutFormElements = ({ return ( ({ padding: t.space.$4 })} > diff --git a/packages/clerk-js/src/ui/customizables/elementDescriptors.ts b/packages/clerk-js/src/ui/customizables/elementDescriptors.ts index 051549c42ba..8d05f7d4b95 100644 --- a/packages/clerk-js/src/ui/customizables/elementDescriptors.ts +++ b/packages/clerk-js/src/ui/customizables/elementDescriptors.ts @@ -82,6 +82,9 @@ export const APPEARANCE_KEYS = containsAllElementsConfigKeys([ 'alternativeMethodsBlockButtonText', 'alternativeMethodsBlockButtonArrow', + 'checkoutFormLineItemsRoot', + 'checkoutFormElementsRoot', + 'checkoutSuccessRoot', 'checkoutSuccessRing', 'checkoutSuccessBadge', diff --git a/packages/types/src/appearance.ts b/packages/types/src/appearance.ts index 1e5041fc7f1..fd06952c063 100644 --- a/packages/types/src/appearance.ts +++ b/packages/types/src/appearance.ts @@ -201,6 +201,9 @@ export type ElementsConfig = { alternativeMethodsBlockButtonText: WithOptions; alternativeMethodsBlockButtonArrow: WithOptions; + checkoutFormLineItemsRoot: WithOptions; + checkoutFormElementsRoot: WithOptions; + checkoutSuccessRoot: WithOptions; checkoutSuccessRing: WithOptions; checkoutSuccessBadge: WithOptions; From d5a9b1471285c2919d31c044271c96d82ecaa358 Mon Sep 17 00:00:00 2001 From: Alex Carpenter Date: Mon, 17 Mar 2025 13:58:07 -0400 Subject: [PATCH 11/13] wip --- .../src/ui/components/Checkout/CheckoutComplete.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/clerk-js/src/ui/components/Checkout/CheckoutComplete.tsx b/packages/clerk-js/src/ui/components/Checkout/CheckoutComplete.tsx index cadfdc4da21..c44ff51e7ba 100644 --- a/packages/clerk-js/src/ui/components/Checkout/CheckoutComplete.tsx +++ b/packages/clerk-js/src/ui/components/Checkout/CheckoutComplete.tsx @@ -100,7 +100,7 @@ export const CheckoutComplete = ({ checkout }: { checkout: __experimental_Commer Total paid - {checkout?.invoice + {checkout.invoice ? `${checkout.invoice.totals.grandTotal.currencySymbol}${checkout.invoice.totals.grandTotal.amountFormatted}` : '–'} @@ -109,13 +109,13 @@ export const CheckoutComplete = ({ checkout }: { checkout: __experimental_Commer {/* TODO(@COMMERCE): needs localization */} Payment method - {checkout?.paymentSource ? `${checkout.paymentSource.cardType} ⋯ ${checkout.paymentSource.last4}` : '–'} + {checkout.paymentSource ? `${checkout.paymentSource.cardType} ⋯ ${checkout.paymentSource.last4}` : '–'} {/* TODO(@COMMERCE): needs localization */} Invoice ID - {checkout?.invoice ? checkout.invoice.id : '–'} + {checkout.invoice ? checkout.invoice.id : '–'}