From 3f4a07500d3780d37b16be8de93df8c2a2fab352 Mon Sep 17 00:00:00 2001 From: Francis Thibault Date: Thu, 19 Sep 2024 17:29:27 -0400 Subject: [PATCH 1/4] Updated typings --- .changeset/giant-rules-vanish.md | 22 ++++++++ packages/ActionMenu/src/ActionMenu.test.tsx | 21 ++++++++ packages/ActionMenu/src/ActionMenu.tsx | 11 +++- packages/Alert/src/Alert.tsx | 2 +- packages/Button/src/Button.tsx | 2 +- packages/Combobox/src/Combobox.stories.tsx | 58 ++++++++++++++++----- packages/Combobox/src/Combobox.test.tsx | 15 ++++++ packages/Combobox/src/Combobox.tsx | 2 +- packages/Filter/src/Filter.tsx | 2 +- packages/IconButton/src/IconButton.test.tsx | 3 +- packages/IconButton/src/IconButton.tsx | 2 +- packages/List/src/ListItem.tsx | 4 +- packages/Select/src/Select.tsx | 2 +- packages/Stepper/src/Stepper.test.tsx | 29 +++++++++-- packages/Stepper/src/Stepper.tsx | 12 ++++- packages/Toaster/src/Toaster.stories.tsx | 15 +++++- packages/Toaster/src/Toaster.tsx | 8 +-- 17 files changed, 177 insertions(+), 33 deletions(-) create mode 100644 .changeset/giant-rules-vanish.md diff --git a/.changeset/giant-rules-vanish.md b/.changeset/giant-rules-vanish.md new file mode 100644 index 00000000..6574f3fc --- /dev/null +++ b/.changeset/giant-rules-vanish.md @@ -0,0 +1,22 @@ +--- +"@igloo-ui/action-menu": minor +"@igloo-ui/alert": minor +"@igloo-ui/button": minor +"@igloo-ui/combobox": minor +"@igloo-ui/filter": minor +"@igloo-ui/icon-button": minor +"@igloo-ui/list": minor +"@igloo-ui/select": minor +"@igloo-ui/stepper": minor +"@igloo-ui/toaster": minor +"@igloo-ui/datepicker": minor +"@igloo-ui/dialog": minor +"@igloo-ui/modal": minor +"@igloo-ui/popover": minor +"@igloo-ui/stacked-bar": minor +"@igloo-ui/tag": minor +"@igloo-ui/tag-picker": minor +"@igloo-ui/text-editor": minor +--- + +Updated typings diff --git a/packages/ActionMenu/src/ActionMenu.test.tsx b/packages/ActionMenu/src/ActionMenu.test.tsx index 9a4d0095..f34c6d87 100644 --- a/packages/ActionMenu/src/ActionMenu.test.tsx +++ b/packages/ActionMenu/src/ActionMenu.test.tsx @@ -78,4 +78,25 @@ describe('ActionMenu', () => { } expect(selected).toBeTruthy(); }); + + test('It calls the onClick of the option even with an eventHandler', () => { + let selected = false; + setup({ + ...actionMenuProps, options: [ + { + label: 'Add Item', + value: 'add', + onClick: (e) => { + e.preventDefault(); + selected = true; + } + }, + ] + }); + const listItem = screen.getByText('Add Item'); + if (listItem) { + fireEvent.click(listItem); + } + expect(selected).toBeTruthy(); + }); }); diff --git a/packages/ActionMenu/src/ActionMenu.tsx b/packages/ActionMenu/src/ActionMenu.tsx index 6e9c9d34..a18ff94d 100644 --- a/packages/ActionMenu/src/ActionMenu.tsx +++ b/packages/ActionMenu/src/ActionMenu.tsx @@ -23,7 +23,7 @@ export interface ActionMenuOption extends Omit { /** Whether or not the action menu should close when an option is selected */ closeOnSelect?: boolean | ((option: OptionType) => boolean); /** Callback when an option is selected */ - onClick?: () => void; + onClick?: (() => void) | React.MouseEventHandler; } export interface ActionMenuProps extends React.ComponentProps<"div"> { @@ -125,7 +125,14 @@ const ActionMenu: React.FunctionComponent = ({ ); const onOptionSelect = actionMenuOption?.onClick; if (onOptionSelect) { - onOptionSelect(); + if (onOptionSelect.length > 0) { + // eslint-disable-next-line max-len + const syntheticEvent = new MouseEvent("click") as unknown as React.MouseEvent; + onOptionSelect(syntheticEvent); + } else { + // Call the function without arguments if it doesn't expect any + (onOptionSelect as () => void)(); + } } if (closeMenuOnSelect(option)) { diff --git a/packages/Alert/src/Alert.tsx b/packages/Alert/src/Alert.tsx index a961a782..7ee804bb 100644 --- a/packages/Alert/src/Alert.tsx +++ b/packages/Alert/src/Alert.tsx @@ -30,7 +30,7 @@ export type Appearance = "card" | "inline" | "horizontal"; export interface AlertButton { label: React.ReactNode; - onClick: () => void; + onClick: (() => void) | React.MouseEventHandler; } export interface AlertProps extends Omit, "title"> { diff --git a/packages/Button/src/Button.tsx b/packages/Button/src/Button.tsx index a82a39cb..93619da8 100644 --- a/packages/Button/src/Button.tsx +++ b/packages/Button/src/Button.tsx @@ -56,7 +56,7 @@ export interface ButtonOwnProps { /** Display only the icon in mobile */ showOnlyIconOnMobile?: boolean; /** Callback when clicked */ - onClick?: () => void; + onClick?: (() => void) | React.MouseEventHandler; /** Optional prop to specify the type of the Button */ type?: "button" | "reset" | "submit"; /** Add a data-intercom-target with unique id to link a diff --git a/packages/Combobox/src/Combobox.stories.tsx b/packages/Combobox/src/Combobox.stories.tsx index b22ff1a0..fc1585a2 100644 --- a/packages/Combobox/src/Combobox.stories.tsx +++ b/packages/Combobox/src/Combobox.stories.tsx @@ -61,6 +61,23 @@ const smallOptionList: ComboboxOption[] = [ }, ]; +const NodeLabelOptionList: ComboboxOption[] = [ + { + label: Text option, + value: 'text', + }, + { + label: Disabled option, + value: 'disabled', + disabled: true, + }, + { + label: Text option with icon, + value: 'icon', + icon: , + }, + ]; + const largeOptionList: ComboboxOption[] = [ { label: 'Text 1', @@ -154,21 +171,38 @@ const listWithAction: ComboboxOption[] = [ type Story = StoryObj; export const Overview: Story = { - args: { - children: comboboxPlaceholder, - options: smallOptionList, - }, + args: { + children: comboboxPlaceholder, + options: smallOptionList, + }, - play: async ({ canvasElement }) => { - const body = canvasElement.ownerDocument.body; - const canvas = within(body); + play: async ({ canvasElement }) => { + const body = canvasElement.ownerDocument.body; + const canvas = within(body); - await userEvent.click(canvas.getByRole('button')); - const firstOption = await canvas.findByText('Text option'); + await userEvent.click(canvas.getByRole('button')); + const firstOption = await canvas.findByText('Text option'); - await expect(firstOption).toBeInTheDocument(); - }, -}; + await expect(firstOption).toBeInTheDocument(); + }, + }; + + export const Nodes: Story = { + args: { + children: comboboxPlaceholder, + options: NodeLabelOptionList, + }, + + play: async ({ canvasElement }) => { + const body = canvasElement.ownerDocument.body; + const canvas = within(body); + + await userEvent.click(canvas.getByRole('button')); + const firstOption = await canvas.findByText('Text option'); + + await expect(firstOption).toBeInTheDocument(); + }, + }; export const Sizes: Story = { render: () => ( diff --git a/packages/Combobox/src/Combobox.test.tsx b/packages/Combobox/src/Combobox.test.tsx index 79f53563..195a9f23 100644 --- a/packages/Combobox/src/Combobox.test.tsx +++ b/packages/Combobox/src/Combobox.test.tsx @@ -155,6 +155,21 @@ describe('Combobox', () => { expect(comboboxOptions.length).toBe(options.length); }); + test('It should support react nodes', () => { + const options: ComboboxOption[] = [ + { label: 1, value: 1 }, + { label: 2, value: 2 }, + { label: 3, value: 3 }, + { label: 4, value: 4 }, + ]; + + setup({ isOpen: true }, options); + const combobox = screen.getByTestId('combobox1'); + const comboboxOptions = combobox.querySelectorAll('.ids-list-item'); + + expect(comboboxOptions.length).toBe(options.length); + }); + test("It should put the option label in the header after it's clicked", () => { const options = [{ label: '1', value: 1 }]; diff --git a/packages/Combobox/src/Combobox.tsx b/packages/Combobox/src/Combobox.tsx index 87154c95..0ec48f44 100644 --- a/packages/Combobox/src/Combobox.tsx +++ b/packages/Combobox/src/Combobox.tsx @@ -167,7 +167,7 @@ const Combobox: React.FunctionComponent = ({ } }, [comboboxOptions]); - const optionText = (option: OptionType | undefined): string | undefined => { + const optionText = (option: OptionType | undefined): React.ReactNode | undefined => { if (option?.type === "member") { return option?.member; } diff --git a/packages/Filter/src/Filter.tsx b/packages/Filter/src/Filter.tsx index b13e24de..d5954993 100644 --- a/packages/Filter/src/Filter.tsx +++ b/packages/Filter/src/Filter.tsx @@ -13,7 +13,7 @@ export interface FilterProps extends React.ComponentProps<"button"> { /** True if the filter should be disabled */ disabled?: boolean; /** Add an event for when the filter is clicked */ - onClick?: () => void; + onClick?: (() => void) | React.MouseEventHandler; /** True if the tag is selected */ selected?: boolean; } diff --git a/packages/IconButton/src/IconButton.test.tsx b/packages/IconButton/src/IconButton.test.tsx index e45077a7..292b02c1 100644 --- a/packages/IconButton/src/IconButton.test.tsx +++ b/packages/IconButton/src/IconButton.test.tsx @@ -2,13 +2,14 @@ * @jest-environment jsdom */ import React from 'react'; + import { render, screen } from '@testing-library/react'; import Plus from '@igloo-ui/icons/dist/Plus'; import IconButton from './IconButton'; const setUp = (props = {}) => { - return render( + return render( } dataTest="ids-icon-btn" diff --git a/packages/IconButton/src/IconButton.tsx b/packages/IconButton/src/IconButton.tsx index a75845d0..90786ee3 100644 --- a/packages/IconButton/src/IconButton.tsx +++ b/packages/IconButton/src/IconButton.tsx @@ -15,7 +15,7 @@ export interface IconButtonProps extends Omit { icon: React.ReactNode; /** Callback function that will be called * when the user clicks on the button */ - onClick?: () => void; + onClick?: (() => void) | React.MouseEventHandler; /** True if the control is disabled and shows a disabled state. * The user cannot click on the button */ disabled?: boolean; diff --git a/packages/List/src/ListItem.tsx b/packages/List/src/ListItem.tsx index 7c895bb9..10f1716d 100644 --- a/packages/List/src/ListItem.tsx +++ b/packages/List/src/ListItem.tsx @@ -30,7 +30,7 @@ export interface Option extends ListItem { /** Whether or not the option is disabled */ disabled?: boolean; /** The option label */ - label: string; + label: React.ReactNode; /** The option type */ type: "list"; } @@ -195,7 +195,7 @@ const ListItem: React.FunctionComponent = ({ {option?.member} {option?.manager && ( - isWorkleap ? + isWorkleap ? : )} diff --git a/packages/Select/src/Select.tsx b/packages/Select/src/Select.tsx index e59db986..8d22a2ac 100644 --- a/packages/Select/src/Select.tsx +++ b/packages/Select/src/Select.tsx @@ -92,7 +92,7 @@ const Select: React.FunctionComponent = ({ React.useState(selectedOption); const [showMenu, setShowMenu] = React.useState(isOpen); - const optionText = (option: OptionType | undefined): string | undefined => { + const optionText = (option: OptionType | undefined): React.ReactNode | undefined => { if (option?.type === "member") { return option?.member; } diff --git a/packages/Stepper/src/Stepper.test.tsx b/packages/Stepper/src/Stepper.test.tsx index 98935c91..39e52c39 100644 --- a/packages/Stepper/src/Stepper.test.tsx +++ b/packages/Stepper/src/Stepper.test.tsx @@ -74,15 +74,38 @@ describe('Stepper', () => { } }); + test('It should accept React.MouseEventHandler as onClick prop', () => { + const mockOnClick: React.MouseEventHandler = jest.fn(); + + const steps = [ + { title: 'Step 1', onClick: mockOnClick }, + { title: 'Step 2' }, + { title: 'Step 3' }, + ]; + + const currentStep = 1; + const {container} = setup({steps: steps, currentStep: currentStep, clickableNextSteps: false}); + + const props: StepperProps = { + steps: steps, + currentStep: 0, + }; + + render(); + + const stepElements = container.querySelectorAll('.ids-step'); + fireEvent.click(stepElements[0]); + + expect(mockOnClick).toHaveBeenCalled(); + }); + test('Enables steps after the current step if clickableNextSteps is true', () => { const currentStep = 1; - + const {container} = setup({steps: steps, currentStep: currentStep, clickableNextSteps: true}); const stepElements = container.querySelectorAll('.ids-step'); for (let i = currentStep + 1; i < stepElements.length; i++) { expect(stepElements[i]).not.toBeDisabled(); } }); - - }); diff --git a/packages/Stepper/src/Stepper.tsx b/packages/Stepper/src/Stepper.tsx index 555ad3ad..66194814 100644 --- a/packages/Stepper/src/Stepper.tsx +++ b/packages/Stepper/src/Stepper.tsx @@ -1,5 +1,6 @@ import * as React from "react"; import cx from "classnames"; +import type { PressEvent } from "react-aria"; import Step from "./Step"; @@ -7,7 +8,7 @@ import "./stepper.scss"; export interface Step { /** The callback function that is called when the step is clicked */ - onClick?: (index: number) => void; + onClick?: ((index: number) => void) | React.MouseEventHandler; /** The title for the step */ title: string; } @@ -54,7 +55,14 @@ const Stepper: React.FunctionComponent = ({ isComplete={isComplete} isCurrent={isCurrent} disabled={disabled} - onPress={() => step.onClick?.(index)} + onPress={(event: PressEvent) => { + if (typeof step.onClick === "function") { + (step.onClick as (index: number) => void)(index); + } else if (step.onClick) { + // eslint-disable-next-line max-len + (step.onClick as React.MouseEventHandler)(event as unknown as React.MouseEvent); + } + }} /> {index < steps.length - 1 && (
{ ); -}; \ No newline at end of file +}; + + +export const NodeMessageSuccessToast = () => { + + return ( + + + + + ); + }; diff --git a/packages/Toaster/src/Toaster.tsx b/packages/Toaster/src/Toaster.tsx index 12d91fa0..86c1d054 100644 --- a/packages/Toaster/src/Toaster.tsx +++ b/packages/Toaster/src/Toaster.tsx @@ -11,7 +11,7 @@ import "./toaster.scss"; export interface ToastArgs { isClosable?: boolean; status?: "success" | "error"; - message: string; + message: React.ReactNode; } export interface ToastQueueOptionsProps { @@ -20,8 +20,8 @@ export interface ToastQueueOptionsProps { } export interface ToastQueueProps { - success: (message: string, options?: ToastQueueOptionsProps) => void; - error: (message: string, options?: ToastQueueOptionsProps) => void; + success: (message: React.ReactNode, options?: ToastQueueOptionsProps) => void; + error: (message: React.ReactNode, options?: ToastQueueOptionsProps) => void; } const TOAST_DURATION = 4000 as const; @@ -66,7 +66,7 @@ const useActiveToastContainer = (): unknown => { }; const addToast = ( - message: string, + message: React.ReactNode, status: "success" | "error", duration: number | "infinite", isClosable: boolean From 6901b5ebe0c9fd6992c98e2ae6afaa6dd957bd6d Mon Sep 17 00:00:00 2001 From: Francis Thibault Date: Fri, 20 Sep 2024 15:27:59 -0400 Subject: [PATCH 2/4] PR fixes --- packages/ActionMenu/src/ActionMenu.test.tsx | 2 +- packages/ActionMenu/src/ActionMenu.tsx | 19 +++++----------- packages/Alert/src/Alert.tsx | 2 +- packages/Button/src/Button.tsx | 2 +- packages/Filter/src/Filter.tsx | 2 +- packages/IconButton/src/IconButton.tsx | 2 +- packages/List/src/List.tsx | 4 ++-- packages/List/src/ListItem.tsx | 8 +++---- packages/Stepper/src/Stepper.test.tsx | 25 --------------------- packages/Stepper/src/Stepper.tsx | 11 +++------ 10 files changed, 19 insertions(+), 58 deletions(-) diff --git a/packages/ActionMenu/src/ActionMenu.test.tsx b/packages/ActionMenu/src/ActionMenu.test.tsx index f34c6d87..4f498cc2 100644 --- a/packages/ActionMenu/src/ActionMenu.test.tsx +++ b/packages/ActionMenu/src/ActionMenu.test.tsx @@ -87,7 +87,7 @@ describe('ActionMenu', () => { label: 'Add Item', value: 'add', onClick: (e) => { - e.preventDefault(); + e?.preventDefault(); selected = true; } }, diff --git a/packages/ActionMenu/src/ActionMenu.tsx b/packages/ActionMenu/src/ActionMenu.tsx index a18ff94d..f3c666e5 100644 --- a/packages/ActionMenu/src/ActionMenu.tsx +++ b/packages/ActionMenu/src/ActionMenu.tsx @@ -23,7 +23,7 @@ export interface ActionMenuOption extends Omit { /** Whether or not the action menu should close when an option is selected */ closeOnSelect?: boolean | ((option: OptionType) => boolean); /** Callback when an option is selected */ - onClick?: (() => void) | React.MouseEventHandler; + onClick?: (e?: React.SyntheticEvent) => void; } export interface ActionMenuProps extends React.ComponentProps<"div"> { @@ -119,21 +119,12 @@ const ActionMenu: React.FunctionComponent = ({ return closeOnSelect; }; - const selectOption = (option: OptionType): void => { + const selectOption = (option: OptionType, e?: React.SyntheticEvent): void => { const actionMenuOption = options.find( actionMenuOption => actionMenuOption.value === option.value ); - const onOptionSelect = actionMenuOption?.onClick; - if (onOptionSelect) { - if (onOptionSelect.length > 0) { - // eslint-disable-next-line max-len - const syntheticEvent = new MouseEvent("click") as unknown as React.MouseEvent; - onOptionSelect(syntheticEvent); - } else { - // Call the function without arguments if it doesn't expect any - (onOptionSelect as () => void)(); - } - } + + actionMenuOption?.onClick?.(e); if (closeMenuOnSelect(option)) { toggleMenu(false); @@ -194,7 +185,7 @@ const ActionMenu: React.FunctionComponent = ({ keyboardEvent.preventDefault(); keyboardEvent.stopPropagation(); if (currentFocusedOption) { - selectOption(currentFocusedOption); + selectOption(currentFocusedOption, keyboardEvent); } if ((!currentFocusedOption && showMenu) || !showMenu) { toggleMenu(!showMenu); diff --git a/packages/Alert/src/Alert.tsx b/packages/Alert/src/Alert.tsx index 7ee804bb..f189fe90 100644 --- a/packages/Alert/src/Alert.tsx +++ b/packages/Alert/src/Alert.tsx @@ -30,7 +30,7 @@ export type Appearance = "card" | "inline" | "horizontal"; export interface AlertButton { label: React.ReactNode; - onClick: (() => void) | React.MouseEventHandler; + onClick?: (e?: React.SyntheticEvent) => void; } export interface AlertProps extends Omit, "title"> { diff --git a/packages/Button/src/Button.tsx b/packages/Button/src/Button.tsx index 93619da8..d9908074 100644 --- a/packages/Button/src/Button.tsx +++ b/packages/Button/src/Button.tsx @@ -56,7 +56,7 @@ export interface ButtonOwnProps { /** Display only the icon in mobile */ showOnlyIconOnMobile?: boolean; /** Callback when clicked */ - onClick?: (() => void) | React.MouseEventHandler; + onClick?: (e?: React.SyntheticEvent) => void; /** Optional prop to specify the type of the Button */ type?: "button" | "reset" | "submit"; /** Add a data-intercom-target with unique id to link a diff --git a/packages/Filter/src/Filter.tsx b/packages/Filter/src/Filter.tsx index d5954993..1e6e2f43 100644 --- a/packages/Filter/src/Filter.tsx +++ b/packages/Filter/src/Filter.tsx @@ -13,7 +13,7 @@ export interface FilterProps extends React.ComponentProps<"button"> { /** True if the filter should be disabled */ disabled?: boolean; /** Add an event for when the filter is clicked */ - onClick?: (() => void) | React.MouseEventHandler; + onClick?: (e?: React.SyntheticEvent) => void; /** True if the tag is selected */ selected?: boolean; } diff --git a/packages/IconButton/src/IconButton.tsx b/packages/IconButton/src/IconButton.tsx index 90786ee3..e0ae2736 100644 --- a/packages/IconButton/src/IconButton.tsx +++ b/packages/IconButton/src/IconButton.tsx @@ -15,7 +15,7 @@ export interface IconButtonProps extends Omit { icon: React.ReactNode; /** Callback function that will be called * when the user clicks on the button */ - onClick?: (() => void) | React.MouseEventHandler; + onClick?: (e?: React.SyntheticEvent) => void; /** True if the control is disabled and shows a disabled state. * The user cannot click on the button */ disabled?: boolean; diff --git a/packages/List/src/List.tsx b/packages/List/src/List.tsx index 57908445..18f4aeac 100644 --- a/packages/List/src/List.tsx +++ b/packages/List/src/List.tsx @@ -14,7 +14,7 @@ export interface ListProps extends React.ComponentPropsWithRef<"ul"> { disableTabbing?: boolean; /** The option that is currently being focused or hovered */ focusedOption?: OptionType | null; - /** True for a compact appearance + /** True for a compact appearance * (Corresponds to "small" in Figma for compact, and "medium" for non-compact) */ isCompact?: boolean; /** Whether or not the list is loading */ @@ -25,7 +25,7 @@ export interface ListProps extends React.ComponentPropsWithRef<"ul"> { /** Called when an option becomes focused or hovered */ onOptionFocus?: (option: OptionType) => void; /** Called when an option is selected */ - onOptionChange?: (option: OptionType) => void; + onOptionChange?: (option: OptionType, e?: React.SyntheticEvent) => void; /** Called when the mouse moves outside of the option * or the option loses focus */ onOptionBlur?: (option: OptionType) => void; diff --git a/packages/List/src/ListItem.tsx b/packages/List/src/ListItem.tsx index 10f1716d..58769146 100644 --- a/packages/List/src/ListItem.tsx +++ b/packages/List/src/ListItem.tsx @@ -64,7 +64,7 @@ export interface ListItemProps extends React.ComponentProps<"li"> { /** Called when an option becomes focused or hovered */ onOptionFocus?: (option: OptionType) => void; /** Called when an option is selected */ - onOptionChange?: (option: OptionType) => void; + onOptionChange?: (option: OptionType, e?: React.SyntheticEvent) => void; /** Called when the mouse moves outside of the option * or the option loses focus */ onOptionBlur?: (option: OptionType) => void; @@ -127,9 +127,9 @@ const ListItem: React.FunctionComponent = ({ } }; - const handleOptionChange = (item: OptionType): void => { + const handleOptionChange = (item: OptionType, e?: React.SyntheticEvent): void => { if (!isOptionDisabled() && onOptionChange) { - onOptionChange(item); + onOptionChange(item, e); } }; @@ -218,7 +218,7 @@ const ListItem: React.FunctionComponent = ({ !(target as HTMLElement).closest("button") ) { if (option) { - handleOptionChange(option); + handleOptionChange(option, e); } } }} diff --git a/packages/Stepper/src/Stepper.test.tsx b/packages/Stepper/src/Stepper.test.tsx index 39e52c39..9a3d1dbf 100644 --- a/packages/Stepper/src/Stepper.test.tsx +++ b/packages/Stepper/src/Stepper.test.tsx @@ -74,31 +74,6 @@ describe('Stepper', () => { } }); - test('It should accept React.MouseEventHandler as onClick prop', () => { - const mockOnClick: React.MouseEventHandler = jest.fn(); - - const steps = [ - { title: 'Step 1', onClick: mockOnClick }, - { title: 'Step 2' }, - { title: 'Step 3' }, - ]; - - const currentStep = 1; - const {container} = setup({steps: steps, currentStep: currentStep, clickableNextSteps: false}); - - const props: StepperProps = { - steps: steps, - currentStep: 0, - }; - - render(); - - const stepElements = container.querySelectorAll('.ids-step'); - fireEvent.click(stepElements[0]); - - expect(mockOnClick).toHaveBeenCalled(); - }); - test('Enables steps after the current step if clickableNextSteps is true', () => { const currentStep = 1; diff --git a/packages/Stepper/src/Stepper.tsx b/packages/Stepper/src/Stepper.tsx index 66194814..2c61c358 100644 --- a/packages/Stepper/src/Stepper.tsx +++ b/packages/Stepper/src/Stepper.tsx @@ -8,7 +8,7 @@ import "./stepper.scss"; export interface Step { /** The callback function that is called when the step is clicked */ - onClick?: ((index: number) => void) | React.MouseEventHandler; + onClick?: ((index: number, e?: PressEvent) => void); /** The title for the step */ title: string; } @@ -55,13 +55,8 @@ const Stepper: React.FunctionComponent = ({ isComplete={isComplete} isCurrent={isCurrent} disabled={disabled} - onPress={(event: PressEvent) => { - if (typeof step.onClick === "function") { - (step.onClick as (index: number) => void)(index); - } else if (step.onClick) { - // eslint-disable-next-line max-len - (step.onClick as React.MouseEventHandler)(event as unknown as React.MouseEvent); - } + onPress={(e: PressEvent) => { + step.onClick?.(index, e); }} /> {index < steps.length - 1 && ( From 5c9469fba80391c10d5e372c32a99fcb0a4c578e Mon Sep 17 00:00:00 2001 From: Francis Thibault Date: Fri, 20 Sep 2024 16:10:41 -0400 Subject: [PATCH 3/4] Stepper test fix --- packages/Stepper/src/Stepper.test.tsx | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/packages/Stepper/src/Stepper.test.tsx b/packages/Stepper/src/Stepper.test.tsx index 9a3d1dbf..98fe6afd 100644 --- a/packages/Stepper/src/Stepper.test.tsx +++ b/packages/Stepper/src/Stepper.test.tsx @@ -53,16 +53,17 @@ describe('Stepper', () => { }); test('Calls the step onClick callback when a step is clicked', () => { - const onStepChange = jest.fn(); + let currentStep = 0; + const onStepChange = jest.fn((step: number) => currentStep = step); const stepsWithClicks = [ - { title: 'Step 1', onClick: onStepChange }, - { title: 'Step 2', onClick: onStepChange }, - { title: 'Step 3', onClick: onStepChange }, + { title: 'Step 1', onClick: () => onStepChange(1) }, + { title: 'Step 2', onClick: () => onStepChange(2) }, + { title: 'Step 3', onClick: () => onStepChange(3) }, ]; const {container} = setup({steps: stepsWithClicks, currentStep: 2}); - const stepElements = container.querySelectorAll('.ids-step'); - fireEvent.click(stepElements[0]); - expect(onStepChange).toHaveBeenCalledWith(0); + const [firstStep] = container.querySelectorAll('.ids-step'); + fireEvent.click(firstStep); + expect(onStepChange).toHaveBeenCalledWith(1); }); test('Disables steps after the current step if clickableNextSteps is false', () => { From 4bb1e89a3722fcfbb2aaa235c8d448dbb05835d0 Mon Sep 17 00:00:00 2001 From: Francis Thibault Date: Mon, 23 Sep 2024 10:48:04 -0400 Subject: [PATCH 4/4] pr fixes --- packages/Alert/src/Alert.tsx | 2 +- packages/Toaster/src/Toaster.stories.tsx | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/Alert/src/Alert.tsx b/packages/Alert/src/Alert.tsx index f189fe90..86bff7e2 100644 --- a/packages/Alert/src/Alert.tsx +++ b/packages/Alert/src/Alert.tsx @@ -30,7 +30,7 @@ export type Appearance = "card" | "inline" | "horizontal"; export interface AlertButton { label: React.ReactNode; - onClick?: (e?: React.SyntheticEvent) => void; + onClick: (e?: React.SyntheticEvent) => void; } export interface AlertProps extends Omit, "title"> { diff --git a/packages/Toaster/src/Toaster.stories.tsx b/packages/Toaster/src/Toaster.stories.tsx index e6cf6bdd..73ebb7ac 100644 --- a/packages/Toaster/src/Toaster.stories.tsx +++ b/packages/Toaster/src/Toaster.stories.tsx @@ -117,9 +117,7 @@ export const ErrorToast = () => { ); }; - export const NodeMessageSuccessToast = () => { - return (