Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updated typings #852

Merged
merged 4 commits into from
Sep 23, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions .changeset/giant-rules-vanish.md
Original file line number Diff line number Diff line change
@@ -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
21 changes: 21 additions & 0 deletions packages/ActionMenu/src/ActionMenu.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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();
});
});
12 changes: 5 additions & 7 deletions packages/ActionMenu/src/ActionMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export interface ActionMenuOption extends Omit<Option, "type"> {
/** 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?: (e?: React.SyntheticEvent) => void;
}

export interface ActionMenuProps extends React.ComponentProps<"div"> {
Expand Down Expand Up @@ -119,14 +119,12 @@ const ActionMenu: React.FunctionComponent<ActionMenuProps> = ({
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) {
onOptionSelect();
}

actionMenuOption?.onClick?.(e);

if (closeMenuOnSelect(option)) {
toggleMenu(false);
Expand Down Expand Up @@ -187,7 +185,7 @@ const ActionMenu: React.FunctionComponent<ActionMenuProps> = ({
keyboardEvent.preventDefault();
keyboardEvent.stopPropagation();
if (currentFocusedOption) {
selectOption(currentFocusedOption);
selectOption(currentFocusedOption, keyboardEvent);
}
if ((!currentFocusedOption && showMenu) || !showMenu) {
toggleMenu(!showMenu);
Expand Down
2 changes: 1 addition & 1 deletion packages/Alert/src/Alert.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export type Appearance = "card" | "inline" | "horizontal";

export interface AlertButton {
label: React.ReactNode;
onClick: () => void;
onClick?: (e?: React.SyntheticEvent) => void;
fraincs marked this conversation as resolved.
Show resolved Hide resolved
}

export interface AlertProps extends Omit<React.ComponentProps<"div">, "title"> {
Expand Down
2 changes: 1 addition & 1 deletion packages/Button/src/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export interface ButtonOwnProps {
/** Display only the icon in mobile */
showOnlyIconOnMobile?: boolean;
/** Callback when clicked */
onClick?: () => void;
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
Expand Down
58 changes: 46 additions & 12 deletions packages/Combobox/src/Combobox.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,23 @@ const smallOptionList: ComboboxOption[] = [
},
];

const NodeLabelOptionList: ComboboxOption[] = [
{
label: <span>Text option</span>,
value: 'text',
},
{
label: <span>Disabled option</span>,
value: 'disabled',
disabled: true,
},
{
label: <span>Text option with icon</span>,
value: 'icon',
icon: <Happiness size="small" />,
},
];

const largeOptionList: ComboboxOption[] = [
{
label: 'Text 1',
Expand Down Expand Up @@ -154,21 +171,38 @@ const listWithAction: ComboboxOption[] = [
type Story = StoryObj<typeof Combobox>;

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: () => (
Expand Down
15 changes: 15 additions & 0 deletions packages/Combobox/src/Combobox.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,21 @@ describe('Combobox', () => {
expect(comboboxOptions.length).toBe(options.length);
});

test('It should support react nodes', () => {
const options: ComboboxOption[] = [
{ label: <span>1</span>, value: 1 },
{ label: <span>2</span>, value: 2 },
{ label: <span>3</span>, value: 3 },
{ label: <span>4</span>, 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 }];

Expand Down
2 changes: 1 addition & 1 deletion packages/Combobox/src/Combobox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ const Combobox: React.FunctionComponent<ComboboxProps> = ({
}
}, [comboboxOptions]);

const optionText = (option: OptionType | undefined): string | undefined => {
const optionText = (option: OptionType | undefined): React.ReactNode | undefined => {
if (option?.type === "member") {
return option?.member;
}
Expand Down
2 changes: 1 addition & 1 deletion packages/Filter/src/Filter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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?: (e?: React.SyntheticEvent) => void;
/** True if the tag is selected */
selected?: boolean;
}
Expand Down
3 changes: 2 additions & 1 deletion packages/IconButton/src/IconButton.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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(
<IconButton
icon={<Plus size="small" />}
dataTest="ids-icon-btn"
Expand Down
2 changes: 1 addition & 1 deletion packages/IconButton/src/IconButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export interface IconButtonProps extends Omit<ButtonOwnProps, "size"> {
icon: React.ReactNode;
/** Callback function that will be called
* when the user clicks on the button */
onClick?: () => void;
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;
Expand Down
4 changes: 2 additions & 2 deletions packages/List/src/List.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand All @@ -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;
Expand Down
12 changes: 6 additions & 6 deletions packages/List/src/ListItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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";
}
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -127,9 +127,9 @@ const ListItem: React.FunctionComponent<ListItemProps> = ({
}
};

const handleOptionChange = (item: OptionType): void => {
const handleOptionChange = (item: OptionType, e?: React.SyntheticEvent): void => {
if (!isOptionDisabled() && onOptionChange) {
onOptionChange(item);
onOptionChange(item, e);
}
};

Expand Down Expand Up @@ -195,7 +195,7 @@ const ListItem: React.FunctionComponent<ListItemProps> = ({
<span className="ids-list-item__text-member">
{option?.member}
{option?.manager && (
isWorkleap ?
isWorkleap ?
<UserIcon size="sm" className="ids-list-item__manager" /> :
<UserSolid size="small" className="ids-list-item__manager" />
)}
Expand All @@ -218,7 +218,7 @@ const ListItem: React.FunctionComponent<ListItemProps> = ({
!(target as HTMLElement).closest("button")
) {
if (option) {
handleOptionChange(option);
handleOptionChange(option, e);
}
}
}}
Expand Down
2 changes: 1 addition & 1 deletion packages/Select/src/Select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ const Select: React.FunctionComponent<SelectProps> = ({
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;
}
Expand Down
19 changes: 9 additions & 10 deletions packages/Stepper/src/Stepper.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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', () => {
Expand All @@ -76,13 +77,11 @@ describe('Stepper', () => {

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();
}
});


});
7 changes: 5 additions & 2 deletions packages/Stepper/src/Stepper.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import * as React from "react";
import cx from "classnames";
import type { PressEvent } from "react-aria";

import Step from "./Step";

import "./stepper.scss";

export interface Step {
/** The callback function that is called when the step is clicked */
onClick?: (index: number) => void;
onClick?: ((index: number, e?: PressEvent) => void);
/** The title for the step */
title: string;
}
Expand Down Expand Up @@ -54,7 +55,9 @@ const Stepper: React.FunctionComponent<StepperProps> = ({
isComplete={isComplete}
isCurrent={isCurrent}
disabled={disabled}
onPress={() => step.onClick?.(index)}
onPress={(e: PressEvent) => {
step.onClick?.(index, e);
}}
/>
{index < steps.length - 1 && (
<div
Expand Down
Loading
Loading