diff --git a/.changeset/angry-colts-scream.md b/.changeset/angry-colts-scream.md new file mode 100644 index 0000000000..cbf25fdb18 --- /dev/null +++ b/.changeset/angry-colts-scream.md @@ -0,0 +1,5 @@ +--- +'@toptal/picasso-button': patch +--- + +- fix "Maximum update depth exceeded" issue diff --git a/packages/base/Button/src/ButtonAction/ButtonAction.tsx b/packages/base/Button/src/ButtonAction/ButtonAction.tsx index 5d125a8d91..97b1aaec89 100644 --- a/packages/base/Button/src/ButtonAction/ButtonAction.tsx +++ b/packages/base/Button/src/ButtonAction/ButtonAction.tsx @@ -64,10 +64,13 @@ export const ButtonAction: OverridableComponent = forwardRef< Props >(function ButtonAction(props, ref) { const { - className, + /* eslint-disable @typescript-eslint/no-unused-vars */ + // We use these props only to determine styles active, focused, hovered, + /* eslint-enable @typescript-eslint/no-unused-vars */ + className, disabled, loading, icon, @@ -95,9 +98,6 @@ export const ButtonAction: OverridableComponent = forwardRef< onClick={loading ? undefined : onClick} className={finalClassName} contentClassName='font-semibold text-blue-500 text-md' - active={active} - hovered={hovered} - focused={focused} disabled={disabled} /> ) diff --git a/packages/base/Button/src/ButtonBase/ButtonBase.tsx b/packages/base/Button/src/ButtonBase/ButtonBase.tsx index 18f7920b8b..8ed80d1b4d 100644 --- a/packages/base/Button/src/ButtonBase/ButtonBase.tsx +++ b/packages/base/Button/src/ButtonBase/ButtonBase.tsx @@ -1,10 +1,4 @@ -import type { - ReactNode, - ReactElement, - MouseEvent, - ElementType, - FC, -} from 'react' +import type { ReactNode, ReactElement, MouseEvent, ElementType } from 'react' import React, { forwardRef } from 'react' import { twMerge } from 'tailwind-merge' import type { @@ -15,6 +9,7 @@ import type { } from '@toptal/picasso-shared' import { useTitleCase } from '@toptal/picasso-shared' import { Button as MUIButtonBase } from '@mui/base/Button' +import type { ButtonRootSlotProps } from '@mui/base/Button' import { Loader } from '@toptal/picasso-loader' import { Container } from '@toptal/picasso-container' import { noop, toTitleCase } from '@toptal/picasso-utils' @@ -48,6 +43,8 @@ export interface Props title?: string /** HTML type of Button component */ type?: 'button' | 'reset' | 'submit' + /** The HTML element that is ultimately rendered, for example 'button', 'a' or 'label */ + rootElementName?: keyof HTMLElementTagNameMap } const getClickHandler = (loading?: boolean, handler?: Props['onClick']) => @@ -64,14 +61,14 @@ const getIcon = ({ icon }: { icon?: ReactElement }) => { }) } -// eslint-disable-next-line @typescript-eslint/no-explicit-any -const isReactComponent = (component: any) => { - return ( - component && - (component.$$typeof === Symbol.for('react.forward_ref') || - typeof component === 'function') - ) -} +const RootElement = forwardRef( + (props: ButtonRootSlotProps & { as: ElementType }, ref) => { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const { ownerState, as: Root, ...rest } = props + + return + } +) export const ButtonBase: OverridableComponent = forwardRef< HTMLButtonElement, @@ -91,32 +88,20 @@ export const ButtonBase: OverridableComponent = forwardRef< value, type, as = 'button', + rootElementName, titleCase: propsTitleCase, ...rest } = props - let RootElement: ElementType | FC = as - - if (isReactComponent(RootElement)) { - RootElement = forwardRef( - // We don't need to pass ownerState to the root component - // eslint-disable-next-line @typescript-eslint/no-unused-vars - ({ ownerState, ...restProps }: { ownerState: object }, rootRef) => { - const Root = as - - return - } - ) - } - const titleCase = useTitleCase(propsTitleCase) const finalChildren = [titleCase ? toTitleCase(children) : children] /* Workaround for the case: