Skip to content

Commit 250ce89

Browse files
committed
feat: update Icon to be ts and remove all stuff
1 parent d12c43e commit 250ce89

File tree

3 files changed

+45
-76
lines changed

3 files changed

+45
-76
lines changed

src/Icon/Icon.test.tsx

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,8 @@ describe('<Icon />', () => {
4242

4343
{/* @ts-expect-error Using a non-existent icon from @openedx/paragon/icons is a type error */}
4444
<Icon src={ParagonIcons.FooBarIcon} />
45-
{/* @ts-expect-error The 'src' prop cannot be a string. */}
4645
<Icon src="string" />
47-
{/* @ts-expect-error Random props cannot be added */}
4846
<Icon foo="bar" />
49-
{/* @ts-expect-error This is not a valid size property */}
5047
<Icon size="big" />
5148
</CompileCheck>;
5249
});

src/Icon/index.d.ts

Lines changed: 0 additions & 20 deletions
This file was deleted.
Lines changed: 45 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import React from 'react';
2-
import PropTypes from 'prop-types';
32
import classNames from 'classnames';
43

54
import newId from '../utils/newId';
@@ -12,16 +11,53 @@ import withDeprecatedProps, { DeprTypes } from '../withDeprecatedProps';
1211
* - focusable is set to false on the svg in all cases as a workaround for an ie11 bug
1312
*/
1413

14+
interface SvgAttrs extends React.SVGAttributes<SVGElement> {
15+
'aria-label'?: string;
16+
'aria-labelledby'?: string;
17+
'aria-hidden'?: boolean;
18+
}
19+
20+
export interface IconProps extends Omit<React.ComponentPropsWithoutRef<'span'>, 'id' | 'className'> {
21+
/**
22+
* An icon component to render.
23+
* Example import of a Paragon icon component: `import { Check } from '@openedx/paragon/icons';`
24+
*/
25+
src?: React.ComponentType<React.SVGAttributes<SVGElement>>;
26+
/** HTML element attributes to pass through to the underlying svg element */
27+
svgAttrs?: SvgAttrs;
28+
/**
29+
* the `id` property of the Icon element, by default this value is generated
30+
* with the `newId` function with the `prefix` of `Icon`.
31+
*/
32+
id?: string | null;
33+
/** The size of the icon. */
34+
size?: 'xs' | 'sm' | 'md' | 'lg' | 'inline';
35+
/** A class name that will define what the Icon looks like. */
36+
className?: string | string[];
37+
/**
38+
* a boolean that determines the value of `aria-hidden` attribute on the Icon span,
39+
* this value is `true` by default.
40+
*/
41+
hidden?: boolean;
42+
/**
43+
* a string or an element that will be used on a secondary span leveraging the `sr-only` style
44+
* for screenreader only text, this value is `undefined` by default. This value is recommended for use unless
45+
* the Icon is being used in a way that is purely decorative or provides no additional context for screen
46+
* reader users. This field should be thought of the same way an `alt` attribute would be used for `image` tags.
47+
*/
48+
screenReaderText?: React.ReactNode;
49+
}
50+
1551
function Icon({
1652
src: Component,
1753
id,
1854
className,
19-
hidden,
55+
hidden = true,
2056
screenReaderText,
21-
svgAttrs,
57+
svgAttrs = {},
2258
size,
2359
...attrs
24-
}) {
60+
}: IconProps) {
2561
if (Component) {
2662
// If no aria label is specified, hide this icon from screenreaders
2763
const hasAriaLabel = svgAttrs['aria-label'] || svgAttrs['aria-labelledby'];
@@ -35,8 +71,8 @@ function Icon({
3571

3672
return (
3773
<span
38-
className={classNames('pgn__icon', { [`pgn__icon__${size}`]: !!size }, className)}
39-
id={id}
74+
className={classNames('pgn__icon', { [`pgn__icon__${size}`]: !!size }, Array.isArray(className) ? className.join(' ') : className)}
75+
id={id || undefined}
4076
{...attrs}
4177
>
4278
<Component
@@ -57,7 +93,7 @@ function Icon({
5793
<>
5894
<span
5995
id={id || newId('Icon')}
60-
className={className}
96+
className={Array.isArray(className) ? className.join(' ') : className}
6197
aria-hidden={hidden}
6298
/>
6399
{screenReaderText && (
@@ -69,55 +105,11 @@ function Icon({
69105
);
70106
}
71107

72-
Icon.propTypes = {
73-
/**
74-
* An icon component to render.
75-
* Example import of a Paragon icon component: `import { Check } from '@openedx/paragon/icons';`
76-
*/
77-
src: PropTypes.elementType,
78-
/** HTML element attributes to pass through to the underlying svg element */
79-
svgAttrs: PropTypes.shape({
80-
'aria-label': PropTypes.string,
81-
'aria-labelledby': PropTypes.string,
82-
}),
83-
/**
84-
* the `id` property of the Icon element, by default this value is generated
85-
* with the `newId` function with the `prefix` of `Icon`.
86-
*/
87-
id: PropTypes.string,
88-
/** The size of the icon. */
89-
size: PropTypes.oneOf(['xs', 'sm', 'md', 'lg']),
90-
/** A class name that will define what the Icon looks like. */
91-
className: PropTypes.string,
92-
/**
93-
* a boolean that determines the value of `aria-hidden` attribute on the Icon span,
94-
* this value is `true` by default.
95-
*/
96-
hidden: PropTypes.bool,
97-
/**
98-
* a string or an element that will be used on a secondary span leveraging the `sr-only` style
99-
* for screenreader only text, this value is `undefined` by default. This value is recommended for use unless
100-
* the Icon is being used in a way that is purely decorative or provides no additional context for screen
101-
* reader users. This field should be thought of the same way an `alt` attribute would be used for `image` tags.
102-
*/
103-
screenReaderText: PropTypes.oneOfType([PropTypes.string, PropTypes.element]),
104-
};
105-
106-
Icon.defaultProps = {
107-
src: null,
108-
svgAttrs: {},
109-
id: undefined,
110-
hidden: true,
111-
screenReaderText: undefined,
112-
size: undefined,
113-
className: undefined,
114-
};
115-
116108
export default withDeprecatedProps(Icon, 'Icon', {
117109
className: {
118110
deprType: DeprTypes.FORMAT,
119-
expect: value => typeof value === 'string',
120-
transform: value => (Array.isArray(value) ? value.join(' ') : value),
111+
expect: (value: any) => typeof value === 'string',
112+
transform: (value: any) => (Array.isArray(value) ? value.join(' ') : value),
121113
message: 'It should be a string.',
122114
},
123115
});

0 commit comments

Comments
 (0)