diff --git a/.changeset/neat-grapes-allow.md b/.changeset/neat-grapes-allow.md new file mode 100644 index 0000000000..c5cf1c63d5 --- /dev/null +++ b/.changeset/neat-grapes-allow.md @@ -0,0 +1,5 @@ +--- +"@bigcommerce/catalyst-core": patch +--- + +Add Button with loading state. diff --git a/core/app/[locale]/(default)/account/[tab]/_components/change-password-form.tsx b/core/app/[locale]/(default)/account/[tab]/_components/change-password-form.tsx index 5d7524f075..fafe2d5a0c 100644 --- a/core/app/[locale]/(default)/account/[tab]/_components/change-password-form.tsx +++ b/core/app/[locale]/(default)/account/[tab]/_components/change-password-form.tsx @@ -1,6 +1,5 @@ 'use client'; -import { Loader2 as Spinner } from 'lucide-react'; import { useTranslations } from 'next-intl'; import { ChangeEvent, useEffect, useRef, useState } from 'react'; import { useFormState, useFormStatus } from 'react-dom'; @@ -74,20 +73,11 @@ const SubmitButton = () => { ); }; diff --git a/core/app/[locale]/(default)/cart/_components/checkout-button.tsx b/core/app/[locale]/(default)/cart/_components/checkout-button.tsx index a702081d12..91b23f213e 100644 --- a/core/app/[locale]/(default)/cart/_components/checkout-button.tsx +++ b/core/app/[locale]/(default)/cart/_components/checkout-button.tsx @@ -1,6 +1,5 @@ 'use client'; -import { Loader2 as Spinner } from 'lucide-react'; import { useTranslations } from 'next-intl'; import { useFormStatus } from 'react-dom'; @@ -13,15 +12,8 @@ const InternalButton = () => { const { pending } = useFormStatus(); return ( - ); }; diff --git a/core/app/[locale]/(default)/cart/_components/coupon-code/index.tsx b/core/app/[locale]/(default)/cart/_components/coupon-code/index.tsx index 1cde87dca4..265e1a8933 100644 --- a/core/app/[locale]/(default)/cart/_components/coupon-code/index.tsx +++ b/core/app/[locale]/(default)/cart/_components/coupon-code/index.tsx @@ -1,6 +1,6 @@ 'use client'; -import { AlertCircle, Loader2 as Spinner } from 'lucide-react'; +import { AlertCircle } from 'lucide-react'; import { useFormatter, useTranslations } from 'next-intl'; import { useEffect, useState } from 'react'; import { useFormStatus } from 'react-dom'; @@ -20,15 +20,13 @@ const SubmitButton = () => { const { pending } = useFormStatus(); return ( - ); }; diff --git a/core/app/[locale]/(default)/cart/_components/remove-from-cart-button.tsx b/core/app/[locale]/(default)/cart/_components/remove-from-cart-button.tsx index 29dee50c90..4e5c1e60f2 100644 --- a/core/app/[locale]/(default)/cart/_components/remove-from-cart-button.tsx +++ b/core/app/[locale]/(default)/cart/_components/remove-from-cart-button.tsx @@ -1,28 +1,23 @@ 'use client'; -import { Loader2 as Spinner } from 'lucide-react'; import { useTranslations } from 'next-intl'; import { useFormStatus } from 'react-dom'; +import { Button } from '~/components/ui/button'; + export const RemoveFromCartButton = () => { const { pending } = useFormStatus(); const t = useTranslations('Cart.SubmitRemoveItem'); return ( - + {t('remove')} + ); }; diff --git a/core/app/[locale]/(default)/cart/_components/shipping-info/index.tsx b/core/app/[locale]/(default)/cart/_components/shipping-info/index.tsx index 9fb1e31c2a..7c50c36be1 100644 --- a/core/app/[locale]/(default)/cart/_components/shipping-info/index.tsx +++ b/core/app/[locale]/(default)/cart/_components/shipping-info/index.tsx @@ -1,4 +1,4 @@ -import { AlertCircle, Loader2 as Spinner } from 'lucide-react'; +import { AlertCircle } from 'lucide-react'; import { useTranslations } from 'next-intl'; import { useEffect, useReducer } from 'react'; import { useFormStatus } from 'react-dom'; @@ -37,15 +37,13 @@ const SubmitButton = () => { const t = useTranslations('Cart.SubmitShippingInfo'); return ( - ); }; diff --git a/core/app/[locale]/(default)/cart/_components/shipping-options/submit-button.tsx b/core/app/[locale]/(default)/cart/_components/shipping-options/submit-button.tsx index 09ebbefa3a..3780b1c656 100644 --- a/core/app/[locale]/(default)/cart/_components/shipping-options/submit-button.tsx +++ b/core/app/[locale]/(default)/cart/_components/shipping-options/submit-button.tsx @@ -1,4 +1,3 @@ -import { Loader2 as Spinner } from 'lucide-react'; import { useTranslations } from 'next-intl'; import { useFormStatus } from 'react-dom'; @@ -9,15 +8,13 @@ export const SubmitButton = () => { const { pending } = useFormStatus(); return ( - ); }; diff --git a/core/app/[locale]/(default)/compare/_components/add-to-cart.tsx b/core/app/[locale]/(default)/compare/_components/add-to-cart.tsx index 5c09e42a5e..5bef42a7d5 100644 --- a/core/app/[locale]/(default)/compare/_components/add-to-cart.tsx +++ b/core/app/[locale]/(default)/compare/_components/add-to-cart.tsx @@ -1,6 +1,5 @@ 'use client'; -import { Loader2 as Spinner } from 'lucide-react'; import { useTranslations } from 'next-intl'; import { useFormStatus } from 'react-dom'; @@ -17,15 +16,14 @@ export const AddToCart = ({ const { pending } = useFormStatus(); return ( - ); }; diff --git a/core/app/[locale]/(default)/login/_components/change-password-form.tsx b/core/app/[locale]/(default)/login/_components/change-password-form.tsx index c005810517..e88a9a2faf 100644 --- a/core/app/[locale]/(default)/login/_components/change-password-form.tsx +++ b/core/app/[locale]/(default)/login/_components/change-password-form.tsx @@ -1,6 +1,5 @@ 'use client'; -import { Loader2 as Spinner } from 'lucide-react'; import { useTranslations } from 'next-intl'; import { ChangeEvent, useRef, useState } from 'react'; import { useFormState, useFormStatus } from 'react-dom'; @@ -33,20 +32,11 @@ const SubmitButton = () => { ); }; diff --git a/core/app/[locale]/(default)/login/_components/login-form.tsx b/core/app/[locale]/(default)/login/_components/login-form.tsx index d2469b9ea9..32a05ba2d7 100644 --- a/core/app/[locale]/(default)/login/_components/login-form.tsx +++ b/core/app/[locale]/(default)/login/_components/login-form.tsx @@ -1,6 +1,5 @@ 'use client'; -import { Loader2 as Spinner } from 'lucide-react'; import { useTranslations } from 'next-intl'; import { ChangeEvent, useState } from 'react'; import { useFormState, useFormStatus } from 'react-dom'; @@ -20,8 +19,23 @@ import { Message } from '~/components/ui/message'; import { submitLoginForm } from '../_actions/submit-login-form'; -export const LoginForm = () => { +const SubmitButton = () => { const { pending } = useFormStatus(); + const t = useTranslations('Account.Login'); + + return ( + + ); +}; + +export const LoginForm = () => { const [isEmailValid, setIsEmailValid] = useState(true); const [isPasswordValid, setIsPasswordValid] = useState(true); const [state, formAction] = useFormState(submitLoginForm, { status: 'idle' }); @@ -101,16 +115,7 @@ export const LoginForm = () => {
- + { ); }; diff --git a/core/app/[locale]/(default)/login/register-customer/_components/register-customer-form/index.tsx b/core/app/[locale]/(default)/login/register-customer/_components/register-customer-form/index.tsx index a8e8c140a8..d84cf3f38c 100644 --- a/core/app/[locale]/(default)/login/register-customer/_components/register-customer-form/index.tsx +++ b/core/app/[locale]/(default)/login/register-customer/_components/register-customer-form/index.tsx @@ -1,6 +1,5 @@ 'use client'; -import { Loader2 as Spinner } from 'lucide-react'; import { useTranslations } from 'next-intl'; import { ChangeEvent, useRef, useState } from 'react'; import { useFormStatus } from 'react-dom'; @@ -101,20 +100,11 @@ const SubmitButton = ({ messages }: SumbitMessages) => { return ( ); }; diff --git a/core/app/[locale]/(default)/webpages/contact/[id]/contact-us/index.tsx b/core/app/[locale]/(default)/webpages/contact/[id]/contact-us/index.tsx index 0fbcf492b8..57d676a13c 100644 --- a/core/app/[locale]/(default)/webpages/contact/[id]/contact-us/index.tsx +++ b/core/app/[locale]/(default)/webpages/contact/[id]/contact-us/index.tsx @@ -1,7 +1,6 @@ 'use client'; import { type FragmentOf } from 'gql.tada'; -import { Loader2 as Spinner } from 'lucide-react'; import { useTranslations } from 'next-intl'; import { ChangeEvent, useRef, useState } from 'react'; import { useFormStatus } from 'react-dom'; @@ -46,20 +45,11 @@ const Submit = () => { ); diff --git a/core/components/product-card/add-to-cart.tsx b/core/components/product-card/add-to-cart.tsx index e6d0ade96d..0978e96f6b 100644 --- a/core/components/product-card/add-to-cart.tsx +++ b/core/components/product-card/add-to-cart.tsx @@ -1,6 +1,5 @@ 'use client'; -import { Loader2 as Spinner } from 'lucide-react'; import { useTranslations } from 'next-intl'; import { useFormStatus } from 'react-dom'; @@ -11,15 +10,14 @@ export const AddToCart = ({ disabled = false }: { disabled?: boolean }) => { const t = useTranslations('Product.ProductSheet'); return ( - ); }; diff --git a/core/components/product-form/add-to-cart.tsx b/core/components/product-form/add-to-cart.tsx index 366e825094..6eb4b59935 100644 --- a/core/components/product-form/add-to-cart.tsx +++ b/core/components/product-form/add-to-cart.tsx @@ -1,6 +1,6 @@ 'use client'; -import { ShoppingCart, Loader2 as Spinner } from 'lucide-react'; +import { ShoppingCart } from 'lucide-react'; import { useTranslations } from 'next-intl'; import { useFormContext } from 'react-hook-form'; @@ -13,18 +13,9 @@ export const AddToCart = ({ disabled = false }: { disabled?: boolean }) => { const t = useTranslations('Product.Form'); return ( - ); }; diff --git a/core/components/search-form/index.tsx b/core/components/search-form/index.tsx index 1ae65bc688..21f00631d2 100644 --- a/core/components/search-form/index.tsx +++ b/core/components/search-form/index.tsx @@ -1,6 +1,5 @@ 'use client'; -import { Loader2 as Spinner } from 'lucide-react'; import { useTranslations } from 'next-intl'; import { useFormStatus } from 'react-dom'; @@ -31,15 +30,8 @@ export const SearchForm = ({ initialTerm = '' }: Props) => { - diff --git a/core/components/ui/button/button.tsx b/core/components/ui/button/button.tsx index 209206cbc9..df61b5a779 100644 --- a/core/components/ui/button/button.tsx +++ b/core/components/ui/button/button.tsx @@ -1,11 +1,12 @@ import { Slot } from '@radix-ui/react-slot'; import { cva } from 'class-variance-authority'; +import { Loader2 as Spinner } from 'lucide-react'; import { ComponentPropsWithRef, ElementRef, forwardRef } from 'react'; import { cn } from '~/lib/utils'; export const buttonVariants = cva( - 'inline-flex w-full justify-center items-center border-2 py-2.5 px-[30px] text-base leading-6 font-semibold border-primary disabled:border-gray-400 focus-visible:outline-none focus-visible:ring-4 focus-visible:ring-primary/20', + 'relative flex w-full justify-center items-center border-2 py-2.5 px-[30px] text-base leading-6 font-semibold border-primary disabled:border-gray-400 focus-visible:outline-none focus-visible:ring-4 focus-visible:ring-primary/20', { variants: { variant: { @@ -26,15 +27,31 @@ export const buttonVariants = cva( export interface ButtonProps extends ComponentPropsWithRef<'button'> { variant?: 'primary' | 'secondary' | 'subtle'; asChild?: boolean; + loading?: boolean; + loadingText?: string; } export const Button = forwardRef, ButtonProps>( - ({ asChild = false, children, className, variant, ...props }, ref) => { + ( + { asChild = false, children, className, variant, loading, loadingText, disabled, ...props }, + ref, + ) => { const Comp = asChild ? Slot : 'button'; return ( - - {children} + + {loading && ( + + + )} + {children} ); }, diff --git a/core/messages/en.json b/core/messages/en.json index fcf7ac459b..864fb64a71 100644 --- a/core/messages/en.json +++ b/core/messages/en.json @@ -164,7 +164,6 @@ "SubmitRemoveItem": { "remove": "Remove", "spinnerText": "Removing...", - "submitText": "Remove item from cart", "errorMessage": "Something went wrong while removing item, please try again." } },