From 5b55cea1177cc89c0ec6f0b2b60d73e7c79d0838 Mon Sep 17 00:00:00 2001 From: Gert Hengeveld Date: Fri, 24 Mar 2023 10:14:41 +0100 Subject: [PATCH] Avoid React.FC, improve types and fix lint errors --- src/components/AvatarList.tsx | 8 +- src/components/ButtonAction.tsx | 12 +-- src/components/CodeSnippets.tsx | 5 +- src/components/Input.tsx | 63 ++++++------ src/components/Link.tsx | 47 ++++----- src/components/LinkTabs.tsx | 8 +- src/components/OutlineCTA.tsx | 2 +- src/components/Select.tsx | 4 +- src/components/ShadowBoxCTA.tsx | 8 +- src/components/StoryLinkWrapper.tsx | 20 ++-- src/components/Textarea.tsx | 12 ++- src/components/modal/Modal.tsx | 24 ++--- src/components/tooltip/ListItem.tsx | 34 +++---- src/components/tooltip/Tooltip.tsx | 31 +++--- src/components/tooltip/TooltipLinkList.tsx | 22 ++--- src/components/tooltip/TooltipMessage.tsx | 2 +- src/components/tooltip/TooltipNote.tsx | 15 ++- src/components/tooltip/WithTooltip.tsx | 109 +++++++++++---------- 18 files changed, 214 insertions(+), 212 deletions(-) diff --git a/src/components/AvatarList.tsx b/src/components/AvatarList.tsx index 2e5fc70a..a7c31451 100644 --- a/src/components/AvatarList.tsx +++ b/src/components/AvatarList.tsx @@ -1,4 +1,4 @@ -import React, { ComponentProps, FunctionComponent } from 'react'; +import React, { ComponentProps } from 'react'; import { styled } from '@storybook/theming'; import { Avatar, sizes } from './Avatar'; @@ -52,7 +52,7 @@ const Users = styled.ul` } `; -export interface AvatarListProps { +interface AvatarListProps { isLoading: boolean; users: { id: string; @@ -64,7 +64,7 @@ export interface AvatarListProps { } // Either pass the full list of users, or a userCount if known -export const AvatarList: FunctionComponent> = ({ +export const AvatarList = ({ isLoading = false, users = [ { id: 'loading', avatarUrl: null, name: 'loading' }, @@ -74,7 +74,7 @@ export const AvatarList: FunctionComponent { +}: AvatarListProps & ComponentProps) => { const count = userCount || users.length; return ( diff --git a/src/components/ButtonAction.tsx b/src/components/ButtonAction.tsx index 56338d9e..972d2f87 100644 --- a/src/components/ButtonAction.tsx +++ b/src/components/ButtonAction.tsx @@ -1,4 +1,4 @@ -import React, { ComponentProps, FC } from 'react'; +import React, { ComponentProps, ReactNode } from 'react'; import { styled } from '@storybook/theming'; import { transparentize } from 'polished'; import { typography, color } from './shared/styles'; @@ -9,7 +9,7 @@ import WithTooltip from './tooltip/WithTooltip'; interface ButtonActionProps { icon: IconType; - children?: string; + children?: ReactNode; isActive?: boolean; isLoading?: boolean; loadingText?: string | null; @@ -58,7 +58,7 @@ const StyledButton = styled.button` } `; -export const ButtonAction: FC> = ({ +export const ButtonAction = ({ children, icon, isActive = false, @@ -66,7 +66,7 @@ export const ButtonAction: FC { +}: ButtonActionProps & ComponentProps) => { if (tooltip) return ( } hasChrome={false} tagName="span"> @@ -94,7 +94,7 @@ export const ButtonAction: FC> = ({ +const InsideButtonAction = ({ children, icon, isActive = false, @@ -102,7 +102,7 @@ const InsideButtonAction: FC ( +}: ButtonActionProps & ComponentProps) => ( {icon && !isLoading && } {isLoading && ( diff --git a/src/components/CodeSnippets.tsx b/src/components/CodeSnippets.tsx index 1a9e2a52..b33610b2 100644 --- a/src/components/CodeSnippets.tsx +++ b/src/components/CodeSnippets.tsx @@ -115,10 +115,7 @@ function SnippetList({ snippets }: { snippets: SnippetType[] }) { ); } -export function CodeSnippets({ - snippets, - ...rest -}: Props & ComponentProps & { children?: never }) { +export function CodeSnippets({ snippets, ...rest }: Props & ComponentProps) { return ( diff --git a/src/components/Input.tsx b/src/components/Input.tsx index 6dfa362f..14782caa 100644 --- a/src/components/Input.tsx +++ b/src/components/Input.tsx @@ -5,7 +5,6 @@ import React, { useState, forwardRef, ReactNode, - FC, ComponentProps, MutableRefObject, } from 'react'; @@ -18,7 +17,7 @@ import WithTooltip from './tooltip/WithTooltip'; import { TooltipMessage } from './tooltip/TooltipMessage'; // prettier-ignore -const Label = styled.label>` +const Label = styled.label>` font-weight: ${props => props.appearance !== 'code' && typography.weight.bold}; font-family: ${props => props.appearance === 'code' && typography.type.code }; font-size: ${props => props.appearance === 'code' ? typography.size.s1 - 1 : typography.size.s2 }px; @@ -26,7 +25,7 @@ const Label = styled.label>` `; // prettier-ignore -const LabelWrapper = styled.div>` +const LabelWrapper = styled.div>` margin-bottom: 8px; ${props => props.hideLabel && css` @@ -64,7 +63,7 @@ const InputEl = styled.input` &:-webkit-autofill { -webkit-box-shadow: 0 0 0 3em ${color.lightest} inset; } `; -const getStackLevelStyling = (props: Pick) => { +const getStackLevelStyling = (props: Pick) => { const radius = 4; const stackLevelDefinedStyling = css` position: relative; @@ -107,7 +106,7 @@ const getStackLevelStyling = (props: Pick) => { // prettier-ignore const InputWrapper = styled.div< - Pick + Pick >` display: inline-block; position: relative; @@ -228,7 +227,7 @@ const InputWrapper = styled.div< `} `; // prettier-ignore -const InputContainer = styled.div>` +const InputContainer = styled.div>` ${props => props.orientation === 'horizontal' && css` display: table-row; @@ -272,7 +271,7 @@ const getErrorMessage = ({ error, value, lastErrorValue, -}: Pick) => { +}: Pick) => { let errorMessage = typeof error === 'function' ? error(value) : error; if (lastErrorValue) { if (value !== lastErrorValue) { @@ -282,8 +281,30 @@ const getErrorMessage = ({ return errorMessage; }; -// FC> -export const PureInput = forwardRef>( +interface PureInputProps { + id: string; + value?: string; + appearance?: 'default' | 'pill' | 'code' | 'tertiary'; + errorTooltipPlacement?: ComponentProps['placement']; + stackLevel?: 'top' | 'middle' | 'bottom'; + label: string; + hideLabel?: boolean; + orientation?: 'vertical' | 'horizontal'; + icon?: ComponentProps['icon']; + error?: ReactNode | ((value: PureInputProps['value']) => ReactNode); + suppressErrorMessage?: boolean; + className?: string; + lastErrorValue?: string; + startingType?: string; + type?: string; + onActionClick?: (ev: React.MouseEvent) => void; + startFocused?: boolean; +} + +export const PureInput = forwardRef< + HTMLInputElement, + PureInputProps & ComponentProps +>( ( { id, @@ -379,26 +400,7 @@ export const PureInput = forwardRef['placement']; - stackLevel?: 'top' | 'middle' | 'bottom'; - label: string; - hideLabel?: boolean; - orientation?: 'vertical' | 'horizontal'; - icon?: ComponentProps['icon']; - error?: ReactNode | Function; - suppressErrorMessage?: boolean; - className?: string; - lastErrorValue?: string; - startingType?: string; - type?: string; - onActionClick?: (ev: React.MouseEvent) => void; - startFocused?: boolean; -} +PureInput.displayName = 'PureInput'; export const Input = forwardRef>( ({ type: startingType, startFocused, ...rest }, ref) => { @@ -427,7 +429,7 @@ export const Input = forwardRef( - ({ children, withArrow, ...rest }, ref) => { - const content = ( - <> - - {children} - {withArrow && } - - - ); - - return ( - } - {...rest} - > - {content} - - ); - } -); +export const Link = forwardRef< + HTMLAnchorElement | HTMLButtonElement, + LinkProps & ComponentProps +>(({ children, withArrow, ...rest }, ref) => { + const content = ( + <> + + {children} + {withArrow && } + + + ); + + return ( + } + {...rest} + > + {content} + + ); +}); Link.displayName = 'Link'; Link.defaultProps = { diff --git a/src/components/LinkTabs.tsx b/src/components/LinkTabs.tsx index 8a291c35..c53b02fd 100644 --- a/src/components/LinkTabs.tsx +++ b/src/components/LinkTabs.tsx @@ -1,4 +1,4 @@ -import React, { ComponentProps, FC } from 'react'; +import React, { ComponentProps } from 'react'; import { styled, css } from '@storybook/theming'; import type { StyledComponent } from '@storybook/theming'; @@ -59,16 +59,16 @@ type ItemProps = { label: string; } & ComponentProps; -interface Props { +interface LinkTabsProps { isLoading?: boolean; items: ItemProps[]; } -export const LinkTabs: FC> = ({ +export const LinkTabs = ({ isLoading = false, items = [], ...props -}) => ( +}: LinkTabsProps & ComponentProps) => ( {items.map(({ key, label, ...item }) => (
  • diff --git a/src/components/OutlineCTA.tsx b/src/components/OutlineCTA.tsx index b22f6d8b..d74a7e11 100644 --- a/src/components/OutlineCTA.tsx +++ b/src/components/OutlineCTA.tsx @@ -1,4 +1,4 @@ -import React, { ComponentProps, FC, ReactNode } from 'react'; +import React, { ReactNode } from 'react'; import { styled } from '@storybook/theming'; import { breakpoint, color, spacing, typography } from './shared/styles'; diff --git a/src/components/Select.tsx b/src/components/Select.tsx index 1da661cc..bbb0abea 100644 --- a/src/components/Select.tsx +++ b/src/components/Select.tsx @@ -1,6 +1,6 @@ -import React, { ComponentProps, FC, FunctionComponent, ReactNode } from 'react'; +import React, { ComponentProps, FunctionComponent, ReactNode } from 'react'; import { styled, css } from '@storybook/theming'; -import { color, typography, spacing } from './shared/styles'; +import { color, typography } from './shared/styles'; import { jiggle } from './shared/animation'; import { Icon } from './Icon'; import { Spinner } from './Spinner'; diff --git a/src/components/ShadowBoxCTA.tsx b/src/components/ShadowBoxCTA.tsx index 2ac51f5f..076d44dc 100644 --- a/src/components/ShadowBoxCTA.tsx +++ b/src/components/ShadowBoxCTA.tsx @@ -1,4 +1,4 @@ -import React, { ComponentProps, FC, ReactNode } from 'react'; +import React, { ComponentProps, ReactNode } from 'react'; import { styled } from '@storybook/theming'; import { breakpoint, spacing, typography } from './shared/styles'; @@ -55,18 +55,18 @@ const Action = styled.div` } `; -interface Props { +interface ShadowBoxCTAProps { headingText: ReactNode; messageText?: ReactNode; action: ReactNode; } -export const ShadowBoxCTA: FC> = ({ +export const ShadowBoxCTA = ({ action, headingText, messageText, ...rest -}) => ( +}: ShadowBoxCTAProps & ComponentProps) => ( {headingText} diff --git a/src/components/StoryLinkWrapper.tsx b/src/components/StoryLinkWrapper.tsx index d0f2114e..9068824f 100644 --- a/src/components/StoryLinkWrapper.tsx +++ b/src/components/StoryLinkWrapper.tsx @@ -1,17 +1,21 @@ -/* eslint-disable import/no-extraneous-dependencies */ -// This is allows us to test whether the link works via the actions addon -import React, { ComponentProps, FC } from 'react'; +// eslint-disable-next-line import/no-extraneous-dependencies import { action } from '@storybook/addon-actions'; +import React, { ComponentProps } from 'react'; +// This is allows us to test whether the link works via the actions addon const fireClickAction = action('onLinkClick'); -export const StoryLinkWrapper: FC> = ({ +interface StoryLinkWrapperProps { + to: string; +} + +export const StoryLinkWrapper = ({ children, href, onClick, to, ...rest -}) => { +}: StoryLinkWrapperProps & ComponentProps<'a'>) => { const modifiedOnClick: React.DOMAttributes['onClick'] = (event) => { event.preventDefault(); onClick(event); @@ -19,12 +23,8 @@ export const StoryLinkWrapper: FC> = ({ }; return ( - + {children} ); }; - -interface Props { - to: string; -} diff --git a/src/components/Textarea.tsx b/src/components/Textarea.tsx index ce0d4aac..1bcb8322 100644 --- a/src/components/Textarea.tsx +++ b/src/components/Textarea.tsx @@ -1,7 +1,6 @@ import React, { ComponentProps, ComponentType, - FC, forwardRef, MutableRefObject, ReactNode, @@ -114,7 +113,7 @@ const TextareaWrapper = styled.div<{ error: ReactNode }>` `}; `; -const TextareaContainer = styled.div<{ orientation: Props['orientation'] }>` +const TextareaContainer = styled.div<{ orientation: TextareaProps['orientation'] }>` ${(props) => props.orientation === 'horizontal' && css` @@ -138,7 +137,7 @@ const TextareaContainer = styled.div<{ orientation: Props['orientation'] }>` const getErrorMessage = ({ error, value }: any): ReactNode => typeof error === 'function' ? error(value) : error; -interface Props { +interface TextareaProps { id: string; value: string; label: string; @@ -152,7 +151,10 @@ interface Props { subtextSentiment?: 'default' | 'negative' | 'warning'; } -export const Textarea: FC> = forwardRef( +export const Textarea = forwardRef< + HTMLTextAreaElement, + TextareaProps & ComponentProps +>( ( { id, @@ -181,7 +183,7 @@ export const Textarea: FC> = forward textareaRef.current.focus(); didFocusOnStart.current = true; } - }, [textareaRef, textareaRef.current, didFocusOnStart, didFocusOnStart.current]); + }, [textareaRef, startFocused]); const [errorMessage, setErrorMessage] = useState(getErrorMessage({ error, value })); diff --git a/src/components/modal/Modal.tsx b/src/components/modal/Modal.tsx index 2228f7a3..c740751d 100644 --- a/src/components/modal/Modal.tsx +++ b/src/components/modal/Modal.tsx @@ -1,4 +1,4 @@ -import React, { Children, ComponentProps, FC, ReactNode, CSSProperties } from 'react'; +import React, { Children, ComponentProps, ReactNode, CSSProperties } from 'react'; import { styled } from '@storybook/theming'; import ReactModal from 'react-modal'; @@ -44,14 +44,23 @@ const CenteredWrapper = styled.div` left: 0; `; -export const Modal: FC = ({ +interface ModalProps { + isOpen: boolean; + isBlank?: boolean; + onClose: ComponentProps['onRequestClose']; + children: (obj: { onClose: ModalProps['onClose'] }) => ReactNode; + overlayStyles?: CSSProperties; + contentStyles?: CSSProperties; +} + +export const Modal = ({ isBlank = false, isOpen, onClose, children, overlayStyles = {}, contentStyles = {}, -}) => { +}: ModalProps) => { const actions = { onClose, }; @@ -105,12 +114,3 @@ export const Modal: FC = ({ ); }; - -interface Props { - isOpen: boolean; - isBlank?: boolean; - onClose: ComponentProps['onRequestClose']; - children: (obj: { onClose: Props['onClose'] }) => ReactNode; - overlayStyles?: CSSProperties; - contentStyles?: CSSProperties; -} diff --git a/src/components/tooltip/ListItem.tsx b/src/components/tooltip/ListItem.tsx index b12aefc6..6f999032 100644 --- a/src/components/tooltip/ListItem.tsx +++ b/src/components/tooltip/ListItem.tsx @@ -1,4 +1,4 @@ -import React, { ComponentProps, FC, ReactNode } from 'react'; +import React, { ComponentProps, ReactNode } from 'react'; import { styled, css } from '@storybook/theming'; import weakMemoize from '@emotion/weak-memoize'; import { background, color, typography } from '../shared/styles'; @@ -169,7 +169,20 @@ const buildStyledLinkWrapper = weakMemoize( type StyledLinkWrapperProps = ComponentProps>; -export const ListItem: FC> = ({ +interface ListItemProps { + appearance?: 'primary' | 'secondary'; + isLoading?: boolean; + left?: ReactNode; + title?: ReactNode; + center?: ReactNode; + right?: ReactNode; + active?: boolean; + disabled?: boolean; + LinkWrapper?: LinkWrapperType | null; + onClick?: ComponentProps['onClick']; +} + +export const ListItem = ({ appearance = 'primary', left, title = Loading, @@ -178,10 +191,10 @@ export const ListItem: FC> = onClick, LinkWrapper, ...rest -}) => { +}: ListItemProps & Omit) => { const listItemActiveColor = color[appearance]; const linkInner = ( - + {left && {left}} {title && {title}} {center &&
    {center}
    } @@ -212,16 +225,3 @@ export const ListItem: FC> = type AnyProps = Record; type LinkWrapperType = (props: AnyProps) => React.ReactElement; - -interface Props { - appearance?: 'primary' | 'secondary'; - isLoading?: boolean; - left?: ReactNode; - title?: ReactNode; - center?: ReactNode; - right?: ReactNode; - active?: boolean; - disabled?: boolean; - LinkWrapper?: LinkWrapperType | null; - onClick?: Function; -} diff --git a/src/components/tooltip/Tooltip.tsx b/src/components/tooltip/Tooltip.tsx index 0d1d8d24..eea9de1e 100644 --- a/src/components/tooltip/Tooltip.tsx +++ b/src/components/tooltip/Tooltip.tsx @@ -1,6 +1,6 @@ // Our wrapper around react-popper that does common stuff. -import React, { ComponentProps, FC } from 'react'; +import React, { ComponentProps } from 'react'; import { styled, css } from '@storybook/theming'; import { TooltipArg } from 'react-popper-tooltip'; import { typography, spacing, zIndex as sharedZIndex } from '../shared/styles'; @@ -93,10 +93,16 @@ const TooltipWrapper = styled.div` `}; `; -export const Tooltip: FC< - Props & - Omit, keyof Props | 'data-placement' | 'ref' | 'zIndex'> -> = ({ +interface TooltipProps { + hasChrome?: boolean; + arrowProps?: ComponentProps; + placement?: Placement; + arrowRef?: any; + tooltipRef?: any; + zIndex?: number; +} + +export const Tooltip = ({ placement = 'top', hasChrome = true, children, @@ -105,7 +111,11 @@ export const Tooltip: FC< arrowRef, zIndex = sharedZIndex.tooltip, ...props -}) => { +}: TooltipProps & + Omit< + ComponentProps, + keyof TooltipProps | 'data-placement' | 'ref' | 'zIndex' + >) => { return ( ); }; - -interface Props { - hasChrome?: boolean; - arrowProps?: ComponentProps; - placement?: Placement; - arrowRef?: any; - tooltipRef?: any; - zIndex?: number; -} diff --git a/src/components/tooltip/TooltipLinkList.tsx b/src/components/tooltip/TooltipLinkList.tsx index e750c861..fa7c1247 100644 --- a/src/components/tooltip/TooltipLinkList.tsx +++ b/src/components/tooltip/TooltipLinkList.tsx @@ -1,4 +1,4 @@ -import React, { ComponentProps, FC } from 'react'; +import React, { ComponentProps } from 'react'; import { styled } from '@storybook/theming'; import { ListItem } from './ListItem'; import { spacing } from '../shared/styles'; @@ -12,12 +12,20 @@ const List = styled.ul` list-style: none; `; -export const TooltipLinkList: FC = ({ links, LinkWrapper, ...rest }) => { +type AnyProps = Record; +type LinkWrapperType = (props: AnyProps) => React.ReactElement; + +interface TooltipLinkListProps { + links: Omit, 'LinkWrapper'>[]; + LinkWrapper?: LinkWrapperType; +} + +export const TooltipLinkList = ({ links, LinkWrapper, ...rest }: TooltipLinkListProps) => { return ( {links.map((data, index) => ( = ({ links, LinkWrapper, ...rest }) => { ); }; - -type AnyProps = Record; -type LinkWrapperType = (props: AnyProps) => React.ReactElement; - -interface Props { - links: Omit, 'LinkWrapper'>[]; - LinkWrapper?: LinkWrapperType; -} diff --git a/src/components/tooltip/TooltipMessage.tsx b/src/components/tooltip/TooltipMessage.tsx index a2a6bb29..f6a2a361 100644 --- a/src/components/tooltip/TooltipMessage.tsx +++ b/src/components/tooltip/TooltipMessage.tsx @@ -36,7 +36,7 @@ export function TooltipMessage({ desc, links, ...rest -}: Props & ComponentProps & { children?: never }) { +}: Props & ComponentProps) { return ( diff --git a/src/components/tooltip/TooltipNote.tsx b/src/components/tooltip/TooltipNote.tsx index f7145ed0..b0dfc8e9 100644 --- a/src/components/tooltip/TooltipNote.tsx +++ b/src/components/tooltip/TooltipNote.tsx @@ -1,4 +1,4 @@ -import React, { ComponentProps, FC } from 'react'; +import React, { ComponentProps } from 'react'; import { styled } from '@storybook/theming'; import { color, typography, spacing } from '../shared/styles'; @@ -18,13 +18,10 @@ const Note = styled.div` margin: 6px; `; -export const TooltipNote = ({ - note, - ...rest -}: Props & Omit, 'children'> & { children?: never }) => { - return {note}; -}; - -interface Props { +interface TooltipNoteProps { note: string; } + +export const TooltipNote = ({ note, ...rest }: TooltipNoteProps & ComponentProps) => { + return {note}; +}; diff --git a/src/components/tooltip/WithTooltip.tsx b/src/components/tooltip/WithTooltip.tsx index 64c26e3b..80649164 100644 --- a/src/components/tooltip/WithTooltip.tsx +++ b/src/components/tooltip/WithTooltip.tsx @@ -1,4 +1,4 @@ -import React, { useState, useMemo, FC, ReactNode, ComponentProps } from 'react'; +import React, { useState, useMemo, ReactNode, ComponentProps } from 'react'; import { styled } from '@storybook/theming'; import TooltipTrigger from 'react-popper-tooltip'; import uuid from 'uuid'; @@ -6,7 +6,7 @@ import uuid from 'uuid'; import { Tooltip } from './Tooltip'; // A target that doesn't speak popper -const ButtonContainer = styled.button>` +const ButtonContainer = styled.button>` background: transparent; border: 0; cursor: ${(props) => (props.trigger === 'hover' ? 'default' : 'pointer')}; @@ -39,44 +39,63 @@ const isDescendantOfAction = (element: HTMLElement): boolean => { return isDescendantOfAction(parentElement); }; -const AsComponent = React.forwardRef & Record>( - ({ tabIndex, tagName, onClick, onMouseEnter, onMouseLeave, ...props }, ref) => { - const Component = tagName || ButtonContainer; - const asProps = { - ref, - onClick, - onMouseEnter, - onMouseLeave, - onFocus: onMouseEnter, - onBlur: onMouseLeave, - role: 'button', - ...props, - } as any; +const AsComponent = React.forwardRef< + unknown, + Pick & Record +>(({ tabIndex, tagName, onClick, onMouseEnter, onMouseLeave, ...props }, ref) => { + const Component = tagName || ButtonContainer; + const asProps = { + ref, + onClick, + onMouseEnter, + onMouseLeave, + onFocus: onMouseEnter, + onBlur: onMouseLeave, + role: 'button', + ...props, + } as any; - const onKeyDown = useMemo( - () => (event: any) => { - if (!onClick) { - return; - } - if (event.key === 'Enter' || event.key === ' ') { - event.preventDefault(); - onClick(event); - } - }, - [onClick] - ); + const onKeyDown = useMemo( + () => (event: any) => { + if (!onClick) { + return; + } + if (event.key === 'Enter' || event.key === ' ') { + event.preventDefault(); + onClick(event); + } + }, + [onClick] + ); - // for non button component, we need to simulate the same behavior as a button - if (tagName) { - asProps.tabIndex = tabIndex || 0; - asProps.onKeyDown = onKeyDown; - } - return ; + // for non button component, we need to simulate the same behavior as a button + if (tagName) { + asProps.tabIndex = tabIndex || 0; + asProps.onKeyDown = onKeyDown; } -); + return ; +}); AsComponent.displayName = 'AsComponent'; -const WithTooltip: FC> = ({ +interface WithTooltipProps { + tagName?: keyof JSX.IntrinsicElements; + trigger?: ComponentProps['trigger']; + closeOnClick?: boolean; + placement?: ComponentProps['placement']; + modifiers?: any; + hasChrome?: boolean; + // eslint-disable-next-line @typescript-eslint/ban-types + tooltip?: ReactNode | Function; + children: ReactNode; + startOpen?: boolean; + delayHide?: number; + // eslint-disable-next-line @typescript-eslint/ban-types + onVisibilityChange?: Function; + portalContainer?: ComponentProps['portalContainer']; + tooltipZIndex?: number; +} + +const WithTooltip = ({ children, closeOnClick = false, delayHide = 100, @@ -91,7 +110,7 @@ const WithTooltip: FC> = ({ tooltipZIndex = undefined, trigger = 'hover', ...props -}) => { +}: WithTooltipProps & ComponentProps) => { const id = React.useMemo(() => uuid.v4(), []); const [isTooltipShown, setTooltipShown] = useState(startOpen); const closeTooltip = useMemo(() => () => setTooltipShown(false), [setTooltipShown]); @@ -168,22 +187,4 @@ const WithTooltip: FC> = ({ ); }; -interface Props { - tagName?: keyof JSX.IntrinsicElements; - trigger?: ComponentProps['trigger']; - closeOnClick?: boolean; - placement?: ComponentProps['placement']; - modifiers?: any; - hasChrome?: boolean; - // eslint-disable-next-line @typescript-eslint/ban-types - tooltip?: ReactNode | Function; - children: ReactNode; - startOpen?: boolean; - delayHide?: number; - // eslint-disable-next-line @typescript-eslint/ban-types - onVisibilityChange?: Function; - portalContainer?: ComponentProps['portalContainer']; - tooltipZIndex?: number; -} - export default WithTooltip;