From a6bdbbaa25247c35686b5c9b17b14a02b9f497ba Mon Sep 17 00:00:00 2001 From: TomasSlama Date: Mon, 16 Sep 2024 10:20:50 +0200 Subject: [PATCH] Remove OverridableComponent from Button --- packages/base/Button/src/Button/Button.tsx | 9 +- .../Button/src/ButtonAction/ButtonAction.tsx | 85 +++++----- .../base/Button/src/ButtonBase/ButtonBase.tsx | 157 +++++++++--------- .../src/ButtonCircular/ButtonCircular.tsx | 89 +++++----- .../base/Button/src/ButtonCompound/index.ts | 11 +- .../ButtonControlLabel/ButtonControlLabel.tsx | 42 +++-- 6 files changed, 201 insertions(+), 192 deletions(-) diff --git a/packages/base/Button/src/Button/Button.tsx b/packages/base/Button/src/Button/Button.tsx index 9cd1236f4f..22c2247848 100644 --- a/packages/base/Button/src/Button/Button.tsx +++ b/packages/base/Button/src/Button/Button.tsx @@ -6,7 +6,6 @@ import type { StandardProps, SizeType, ButtonOrAnchorProps, - OverridableComponent, TextLabelProps, } from '@toptal/picasso-shared' import { noop } from '@toptal/picasso-utils' @@ -95,10 +94,10 @@ const getIcon = ({ }) } -export const Button: OverridableComponent = forwardRef< - HTMLButtonElement, - Props ->(function Button(props, ref) { +export const Button = forwardRef(function Button( + props, + ref +) { const { icon, iconPosition, diff --git a/packages/base/Button/src/ButtonAction/ButtonAction.tsx b/packages/base/Button/src/ButtonAction/ButtonAction.tsx index 97b1aaec89..4f1af692ff 100644 --- a/packages/base/Button/src/ButtonAction/ButtonAction.tsx +++ b/packages/base/Button/src/ButtonAction/ButtonAction.tsx @@ -1,11 +1,7 @@ import type { ReactElement, MouseEvent, ElementType, ReactNode } from 'react' import React, { forwardRef } from 'react' import cx from 'classnames' -import type { - BaseProps, - ButtonOrAnchorProps, - OverridableComponent, -} from '@toptal/picasso-shared' +import type { BaseProps, ButtonOrAnchorProps } from '@toptal/picasso-shared' import { Loader } from '@toptal/picasso-loader' import type { IconPositionType } from '../Button' @@ -59,49 +55,48 @@ export interface Props extends BaseProps, ButtonOrAnchorProps { const loaderIcon = -export const ButtonAction: OverridableComponent = forwardRef< - HTMLButtonElement, - Props ->(function ButtonAction(props, ref) { - const { - /* 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, - iconPosition, - onClick, - ...rest - } = props +export const ButtonAction = forwardRef( + function ButtonAction(props, ref) { + const { + /* 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, + iconPosition, + onClick, + ...rest + } = props - const usedIcon = loading ? loaderIcon : icon - const usedIconPosition = icon ? iconPosition : 'right' + const usedIcon = loading ? loaderIcon : icon + const usedIconPosition = icon ? iconPosition : 'right' - const finalClassName = cx(createRootClassNames(props), className) - const finalIcon = getIcon({ - children: rest.children, - icon: usedIcon, - iconPosition: usedIconPosition, - }) + const finalClassName = cx(createRootClassNames(props), className) + const finalIcon = getIcon({ + children: rest.children, + icon: usedIcon, + iconPosition: usedIconPosition, + }) - return ( - - ) -}) + return ( + + ) + } +) ButtonAction.defaultProps = { iconPosition: 'left', diff --git a/packages/base/Button/src/ButtonBase/ButtonBase.tsx b/packages/base/Button/src/ButtonBase/ButtonBase.tsx index a5107f877a..dc681c9f28 100644 --- a/packages/base/Button/src/ButtonBase/ButtonBase.tsx +++ b/packages/base/Button/src/ButtonBase/ButtonBase.tsx @@ -5,7 +5,6 @@ import { twMerge } from '@toptal/picasso-tailwind-merge' import type { StandardProps, ButtonOrAnchorProps, - OverridableComponent, TextLabelProps, } from '@toptal/picasso-shared' import { useTitleCase } from '@toptal/picasso-shared' @@ -31,7 +30,7 @@ export interface Props /** ClassName for the content */ contentClassName?: string /** Add an `` along Button's children */ - icon?: ReactElement + icon?: ReactElement | null /** Icon can be positioned on the left or right */ iconPosition?: IconPositionType /** Shows a loading indicator and disables click events */ @@ -69,86 +68,88 @@ const RootElement = forwardRef( } ) -export const ButtonBase: OverridableComponent = forwardRef< - HTMLButtonElement, - Props ->(function ButtonBase(props, ref) { - const { - icon, - iconPosition, - loading, - children, - className, - contentClassName, - style, - disabled, - onClick, - title, - value, - type, - as = 'button', - titleCase: propsTitleCase, - ...rest - } = props - - const titleCase = useTitleCase(propsTitleCase) - const finalChildren = [titleCase ? toTitleCase(children) : children] - const finalRootElementName = typeof as === 'string' ? as : 'a' - - if (icon) { - const iconComponent = getIcon({ icon }) - - if (iconPosition === 'left') { - finalChildren.unshift(iconComponent) - } else { - finalChildren.push(iconComponent) +export const ButtonBase = forwardRef( + function ButtonBase(props, ref) { + const { + icon, + iconPosition, + loading, + children, + className, + contentClassName, + style, + disabled, + onClick, + title, + value, + type, + as = 'button', + titleCase: propsTitleCase, + ...rest + } = props + + const titleCase = useTitleCase(propsTitleCase) + const finalChildren = [titleCase ? toTitleCase(children) : children] + const finalRootElementName = typeof as === 'string' ? as : 'a' + + if (icon) { + const iconComponent = getIcon({ icon }) + + if (iconPosition === 'left') { + finalChildren.unshift(iconComponent) + } else { + finalChildren.push(iconComponent) + } } - } - const finalClassName = twMerge(createCoreClassNames({ disabled }), className) - - return ( - - - {finalChildren} - - - {loading && ( - - )} - - ) -}) + flex + direction='row' + alignItems='center' + className={contentClassName} + > + {finalChildren} + + + {loading && ( + + )} + + ) + } +) ButtonBase.defaultProps = { as: 'button', diff --git a/packages/base/Button/src/ButtonCircular/ButtonCircular.tsx b/packages/base/Button/src/ButtonCircular/ButtonCircular.tsx index a7bc7c6160..05cbd13b98 100644 --- a/packages/base/Button/src/ButtonCircular/ButtonCircular.tsx +++ b/packages/base/Button/src/ButtonCircular/ButtonCircular.tsx @@ -1,11 +1,7 @@ import type { ReactElement, MouseEvent, ElementType } from 'react' import React, { forwardRef } from 'react' import cx from 'classnames' -import type { - BaseProps, - ButtonOrAnchorProps, - OverridableComponent, -} from '@toptal/picasso-shared' +import type { BaseProps, ButtonOrAnchorProps } from '@toptal/picasso-shared' import { ButtonBase } from '../ButtonBase' import { createRootClassNames, createVariantClassNames } from './styles' @@ -37,51 +33,50 @@ export interface Props extends BaseProps, ButtonOrAnchorProps { responsive?: boolean } -export const ButtonCircular: OverridableComponent = forwardRef< - HTMLButtonElement, - Props ->(function ButtonCircular(props, ref) { - const { - className, - variant = 'primary', - active, - focused, - hovered, - disabled, - responsive, - loading, - ...rest - } = props - const variantClassNames = createVariantClassNames(variant, { - disabled, - focused, - hovered, - active, - }) +export const ButtonCircular = forwardRef( + function ButtonCircular(props, ref) { + const { + className, + variant = 'primary', + active, + focused, + hovered, + disabled, + responsive, + loading, + ...rest + } = props + const variantClassNames = createVariantClassNames(variant, { + disabled, + focused, + hovered, + active, + }) - const finalClassName = cx( - createRootClassNames({ responsive, active, disabled, focused, hovered }), - variantClassNames, - className - ) + const finalClassName = cx( + createRootClassNames({ responsive, active, disabled, focused, hovered }), + variantClassNames, + className + ) - const contentClassName = cx( - 'font-semibold whitespace-nowrap', - 'text-button-small', - loading ? 'opacity-0' : '' - ) + const contentClassName = cx( + 'font-semibold whitespace-nowrap', + 'text-button-small', + loading ? 'opacity-0' : '' + ) - return ( - - ) -}) + return ( + + ) + } +) ButtonCircular.defaultProps = { variant: 'primary', diff --git a/packages/base/Button/src/ButtonCompound/index.ts b/packages/base/Button/src/ButtonCompound/index.ts index 1ccf1ac7af..d868e7b3bf 100644 --- a/packages/base/Button/src/ButtonCompound/index.ts +++ b/packages/base/Button/src/ButtonCompound/index.ts @@ -6,7 +6,16 @@ import { ButtonSplit } from '../ButtonSplit' import { ButtonCheckbox } from '../ButtonCheckbox' import { ButtonRadio } from '../ButtonRadio' -export const ButtonCompound = Object.assign(Button, { +type ButtonCompoundType = typeof Button & { + Group: typeof ButtonGroup + Circular: typeof ButtonCircular + Action: typeof ButtonAction + Split: typeof ButtonSplit + Checkbox: typeof ButtonCheckbox + Radio: typeof ButtonRadio +} + +export const ButtonCompound: ButtonCompoundType = Object.assign(Button, { Group: ButtonGroup, Circular: ButtonCircular, Action: ButtonAction, diff --git a/packages/base/Button/src/ButtonControlLabel/ButtonControlLabel.tsx b/packages/base/Button/src/ButtonControlLabel/ButtonControlLabel.tsx index 49b107c77e..cf56ca1f8a 100644 --- a/packages/base/Button/src/ButtonControlLabel/ButtonControlLabel.tsx +++ b/packages/base/Button/src/ButtonControlLabel/ButtonControlLabel.tsx @@ -50,23 +50,33 @@ const ButtonControlLabel = ({ const contentLeftSpacing = size === 'large' ? 1 : 0.5 return ( - + {React.cloneElement(control, { + id, + checked, + value, + onChange, + disabled, + })} + + {children} + + + ) }