"use client"; import React, { forwardRef } from "react"; import { getLabelSizeBasedOnButtonSize, sizeToClassNames } from "./helpers"; import { AnimationWrapper, DEFAULT_BUTTON_ANIMATION_TYPE, } from "@shared/components/animation-wrapper"; import { ButtonProps, ButtonVariantsT, } from "@shared/components/brand-button/types"; import { MaterialIcon } from "@shared/components/material-icon"; import { cx } from "@shared/utils"; // BrandButton is intentionally limited to prevent over-configuration, restricting className and children props. export const BrandButton = forwardRef< HTMLButtonElement | HTMLAnchorElement, ButtonProps >( ( { variant = "primary_brand", isLoading = false, text, label, disabled, fullWidth, buttonClassName, size = { base: "medium" }, iconName, iconSize = 24, iconFill = 0, // `disableAnimation` is intentionally NOT defaulted to `false` here. // Animations are opt-in by design: when this prop is left undefined, // AnimationWrapper falls back to its own default of `true` (animation // disabled). This keeps behavior consistent with the CMS contract where // an unset value means "no animation". Animation runs only when a caller // (or Contentful) explicitly passes `disableAnimation={false}`. disableAnimation, animationType = DEFAULT_BUTTON_ANIMATION_TYPE, as = "button", ...props }, ref ) => { const getVariantClasses = () => { const baseClasses = cx( sizeToClassNames(size), "rounded-button pl-15 pr-15 inline-flex gap-2 items-center justify-center outline-none focus:outline focus:outline-2 focus:outline-offset-2 cursor-pointer transition-colors duration-200 align-top sm:whitespace-nowrap", fullWidth ? "w-full" : "w-auto" ); const variantClasses: Record = { primary_brand: "bg-bg-fill-brand text-text-brand-on-bg-fill [&:not(:disabled)]:hover:bg-bg-fill-brand-hover focus:outline-bg-fill-brand disabled:bg-bg-fill-brand-disabled", primary_inverse: "bg-bg-fill-inverse text-text-inverse [&:not(:disabled)]:hover:bg-bg-fill-inverse-hover focus:outline-bg-fill-inverse disabled:bg-bg-fill-inverse-disabled", secondary: "border border-border-secondary-on-bg-fill bg-bg-fill-secondary text-text [&:not(:disabled)]:hover:bg-bg-fill-secondary-hover focus:bg-bg-fill-secondary focus:outline-input-border-hover disabled:bg-bg-fill-secondary", }; const stateClasses = cx( (disabled || isLoading) && "cursor-not-allowed", isLoading && "pl-7" ); return cx( baseClasses, variantClasses[variant] || "", stateClasses, buttonClassName ); }; const variantClasses = getVariantClasses(); let infoClassNames = `button--${variant}`; if (isLoading) infoClassNames += " button--loading"; if (disabled) infoClassNames += " button--disabled"; const combinedClassName = `${infoClassNames} ${variantClasses}`; const contentEl = ( <> {isLoading ? ( ) : null} {label ? ( {label} {text} ) : ( text )} {iconName ? ( ) : null} ); if (as === "a") { return ( } className={cx(combinedClassName)} {...(props as React.AnchorHTMLAttributes)} data-component="BrandButton" data-variant={"anchor"} > {contentEl} ); } return ( ); } ); BrandButton.displayName = "BrandButton"; export type { ButtonProps, ButtonVariantsT, ButtonSizeT, ResponsiveSize, } from "./types";