Skip to content

Commit

Permalink
feat: Add TypeScript types for <Overlay>, <OverlayTrigger>, <Tooltip>…
Browse files Browse the repository at this point in the history
…, <IconButton> (#3100)

* feat: add typings for <Overlay> and <OverlayTrigger>

* feat: add typings for <Tooltip>

* feat: add typings for <IconButton>

* chore: typing cleanups for <Chip> code

* feat: slightly more detailed types for <Chip/ChipIcon> - per review
  • Loading branch information
bradenmacdonald authored and PKulkoRaccoonGang committed Jul 7, 2024
1 parent a3372a9 commit b1a9712
Show file tree
Hide file tree
Showing 20 changed files with 228 additions and 96 deletions.
12 changes: 5 additions & 7 deletions src/Chip/Chip.test.jsx → src/Chip/Chip.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { Close } from '../../icons';
import { STYLE_VARIANTS } from './constants';
import Chip from '.';

function TestChip(props) {
function TestChip(props: Omit<React.ComponentProps<typeof Chip>, 'children'>) {
return (
<Chip {...props}>
Test
Expand Down Expand Up @@ -42,15 +42,13 @@ describe('<Chip />', () => {
iconBeforeAlt="close icon"
iconAfter={Close}
iconAfterAlt="close icon"
>
Chip
</TestChip>
/>
)).toJSON();
expect(tree).toMatchSnapshot();
});
it('renders div with "button" role when onClick is provided', () => {
const tree = renderer.create((
<TestChip onClick={jest.fn}>Chip</TestChip>
<TestChip onClick={jest.fn} />
)).toJSON();
expect(tree).toMatchSnapshot();
});
Expand Down Expand Up @@ -104,7 +102,7 @@ describe('<Chip />', () => {
/>,
);
const iconAfter = screen.getByLabelText('icon-after');
await userEvent.click(iconAfter, '{enter}', { skipClick: true });
await userEvent.click(iconAfter);
expect(func).toHaveBeenCalledTimes(1);
});
it('onIconBeforeClick is triggered', async () => {
Expand All @@ -130,7 +128,7 @@ describe('<Chip />', () => {
/>,
);
const iconBefore = screen.getByLabelText('icon-before');
await userEvent.click(iconBefore, '{enter}', { skipClick: true });
await userEvent.click(iconBefore);
expect(func).toHaveBeenCalledTimes(1);
});
it('checks the absence of the `selected` class in the chip', async () => {
Expand Down
14 changes: 7 additions & 7 deletions src/Chip/ChipIcon.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
import React, { KeyboardEventHandler, MouseEventHandler } from 'react';
import PropTypes from 'prop-types';
import Icon from '../Icon';
// @ts-ignore
import IconButton from '../IconButton';
// @ts-ignore
import { STYLE_VARIANTS } from './constants';

export interface ChipIconProps {
export type ChipIconProps = {
className: string,
src: React.ComponentType,
onClick?: KeyboardEventHandler & MouseEventHandler,
alt?: string,
variant: string,
variant: typeof STYLE_VARIANTS[keyof typeof STYLE_VARIANTS],
disabled?: boolean,
}
} & (
// Either _both_ onClick and alt are provided, or neither is:
| { onClick: KeyboardEventHandler<HTMLButtonElement> & MouseEventHandler<HTMLButtonElement>, alt: string }
| { onClick?: undefined, alt?: undefined }
);

function ChipIcon({
className, src, onClick, alt, variant, disabled,
Expand Down
File renamed without changes.
2 changes: 1 addition & 1 deletion src/Chip/constants.js → src/Chip/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
export const STYLE_VARIANTS = {
DARK: 'dark',
LIGHT: 'light',
};
} as const;
4 changes: 1 addition & 3 deletions src/Chip/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@ import PropTypes, { type Requireable } from 'prop-types';
import classNames from 'classnames';
// @ts-ignore
import { requiredWhen } from '../utils/propTypes';
// @ts-ignore
import { STYLE_VARIANTS } from './constants';
// @ts-ignore
import ChipIcon from './ChipIcon';

export const CHIP_PGN_CLASS = 'pgn__chip';
Expand All @@ -14,7 +12,7 @@ export interface IChip {
children: React.ReactNode,
onClick?: KeyboardEventHandler & MouseEventHandler,
className?: string,
variant?: string,
variant?: typeof STYLE_VARIANTS[keyof typeof STYLE_VARIANTS],
iconBefore?: React.ComponentType,
iconBeforeAlt?: string,
iconAfter?: React.ComponentType,
Expand Down
2 changes: 0 additions & 2 deletions src/ChipCarousel/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@ import { useIntl } from 'react-intl';
import classNames from 'classnames';
// @ts-ignore
import { OverflowScroll, OverflowScrollContext } from '../OverflowScroll';
// @ts-ignore
import IconButton from '../IconButton';
// @ts-ignore
import Icon from '../Icon';
// @ts-ignore
import { ArrowForward, ArrowBack } from '../../icons';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,27 @@ describe('<IconButton />', () => {
const alt = 'alternative';
const iconAs = Icon;
const src = InfoOutline;
const variant = 'secondary';
const variant = 'secondary' as const;
const props = {
alt,
src,
iconAs,
variant,
};
const iconParams = {
const deprecatedFontAwesomeExample = {
prefix: 'pgn',
iconName: 'InfoOutlineIcon',
icon: [InfoOutline],
};
it('renders with required props', () => {
const tree = renderer.create((
<IconButton icon={iconParams} alt={alt} />
<IconButton iconAs={Icon} src={InfoOutline} alt={alt} />
)).toJSON();
expect(tree).toMatchSnapshot();
});
it('renders with deprecated props', () => {
const tree = renderer.create((
<IconButton icon={deprecatedFontAwesomeExample} alt={alt} />
)).toJSON();
expect(tree).toMatchSnapshot();
});
Expand Down Expand Up @@ -94,4 +100,19 @@ describe('<IconButton />', () => {
expect(spy2).toHaveBeenCalledTimes(1);
});
});

describe('<IconButton.IconButtonWithTooltip>', () => {
it('renders with required props', () => {
const tree = renderer.create((
<IconButton.IconButtonWithTooltip
iconAs={Icon}
src={InfoOutline}
alt={alt}
tooltipContent="Hello"
tooltipPlacement="left-end"
/>
)).toJSON();
expect(tree).toMatchSnapshot();
});
});
});
20 changes: 0 additions & 20 deletions src/IconButton/__snapshots__/IconButton.test.jsx.snap

This file was deleted.

90 changes: 90 additions & 0 deletions src/IconButton/__snapshots__/IconButton.test.tsx.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`<IconButton /> <IconButton.IconButtonWithTooltip> renders with required props 1`] = `
<button
aria-label="alternative"
className="btn-icon btn-icon-primary btn-icon-md"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
onMouseOut={[Function]}
onMouseOver={[Function]}
type="button"
>
<span
className="btn-icon__icon-container"
>
<span
className="pgn__icon btn-icon__icon"
>
<svg
aria-hidden={true}
fill="none"
focusable={false}
height={24}
role="img"
viewBox="0 0 24 24"
width={24}
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M11 7h2v2h-2V7Zm0 4h2v6h-2v-6Zm1-9C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2Zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8Z"
fill="currentColor"
/>
</svg>
</span>
</span>
</button>
`;
exports[`<IconButton /> renders with deprecated props 1`] = `
<button
aria-label="alternative"
className="btn-icon btn-icon-primary btn-icon-md"
onClick={[Function]}
type="button"
>
<span
className="btn-icon__icon-container"
>
<span
aria-hidden={true}
className="btn-icon__icon"
id="Icon1"
/>
</span>
</button>
`;
exports[`<IconButton /> renders with required props 1`] = `
<button
aria-label="alternative"
className="btn-icon btn-icon-primary btn-icon-md"
onClick={[Function]}
type="button"
>
<span
className="btn-icon__icon-container"
>
<span
className="pgn__icon btn-icon__icon"
>
<svg
aria-hidden={true}
fill="none"
focusable={false}
height={24}
role="img"
viewBox="0 0 24 24"
width={24}
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M11 7h2v2h-2V7Zm0 4h2v6h-2v-6Zm1-9C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2Zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8Z"
fill="currentColor"
/>
</svg>
</span>
</span>
</button>
`;
Loading

0 comments on commit b1a9712

Please sign in to comment.