-
Notifications
You must be signed in to change notification settings - Fork 99
feat: update Icon to be ts and remove all stuff #4136
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
base: release-23.x
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,9 +1,7 @@ | ||
| import React from 'react'; | ||
| import PropTypes from 'prop-types'; | ||
| import classNames from 'classnames'; | ||
|
|
||
| import newId from '../utils/newId'; | ||
| import withDeprecatedProps, { DeprTypes } from '../withDeprecatedProps'; | ||
|
|
||
| /** | ||
| * An svg with an "img" role must satisfy the following a11y requirements | ||
|
|
@@ -12,16 +10,53 @@ import withDeprecatedProps, { DeprTypes } from '../withDeprecatedProps'; | |
| * - focusable is set to false on the svg in all cases as a workaround for an ie11 bug | ||
| */ | ||
|
|
||
| interface SvgAttrs extends React.SVGAttributes<SVGElement> { | ||
| 'aria-label'?: string; | ||
| 'aria-labelledby'?: string; | ||
| 'aria-hidden'?: boolean; | ||
| } | ||
|
|
||
| export interface IconProps extends Omit<React.ComponentPropsWithoutRef<'span'>, 'id' | 'className'> { | ||
| /** | ||
| * An icon component to render. | ||
| * Example import of a Paragon icon component: `import { Check } from '@openedx/paragon/icons';` | ||
| */ | ||
| src?: React.ComponentType<React.SVGAttributes<SVGElement>>; | ||
| /** HTML element attributes to pass through to the underlying svg element */ | ||
| svgAttrs?: SvgAttrs; | ||
| /** | ||
| * the `id` property of the Icon element, by default this value is generated | ||
| * with the `newId` function with the `prefix` of `Icon`. | ||
| */ | ||
| id?: string | null; | ||
| /** The size of the icon. */ | ||
| size?: 'xs' | 'sm' | 'md' | 'lg' | 'inline'; | ||
| /** A class name that will define what the Icon looks like. */ | ||
| className?: string | string[]; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think our Paragon components generally just accept Fine to do that in a separate PR if you'd like, but I think it's better for |
||
| /** | ||
| * a boolean that determines the value of `aria-hidden` attribute on the Icon span, | ||
| * this value is `true` by default. | ||
| */ | ||
| hidden?: boolean; | ||
| /** | ||
| * a string or an element that will be used on a secondary span leveraging the `sr-only` style | ||
| * for screenreader only text, this value is `undefined` by default. This value is recommended for use unless | ||
| * the Icon is being used in a way that is purely decorative or provides no additional context for screen | ||
| * reader users. This field should be thought of the same way an `alt` attribute would be used for `image` tags. | ||
| */ | ||
| screenReaderText?: React.ReactNode; | ||
| } | ||
|
|
||
| function Icon({ | ||
| src: Component, | ||
| id, | ||
| className, | ||
| hidden, | ||
| hidden = true, | ||
| screenReaderText, | ||
| svgAttrs, | ||
| svgAttrs = {}, | ||
| size, | ||
| ...attrs | ||
| }) { | ||
| }: IconProps) { | ||
| if (Component) { | ||
| // If no aria label is specified, hide this icon from screenreaders | ||
| const hasAriaLabel = svgAttrs['aria-label'] || svgAttrs['aria-labelledby']; | ||
|
|
@@ -35,8 +70,8 @@ function Icon({ | |
|
|
||
| return ( | ||
| <span | ||
| className={classNames('pgn__icon', { [`pgn__icon__${size}`]: !!size }, className)} | ||
| id={id} | ||
| className={classNames('pgn__icon', { [`pgn__icon__${size}`]: !!size }, Array.isArray(className) ? className.join(' ') : className)} | ||
| id={id || undefined} | ||
| {...attrs} | ||
| > | ||
| <Component | ||
|
|
@@ -57,7 +92,7 @@ function Icon({ | |
| <> | ||
| <span | ||
| id={id || newId('Icon')} | ||
| className={className} | ||
| className={Array.isArray(className) ? className.join(' ') : className} | ||
| aria-hidden={hidden} | ||
| /> | ||
| {screenReaderText && ( | ||
|
|
@@ -69,55 +104,4 @@ function Icon({ | |
| ); | ||
| } | ||
|
|
||
| Icon.propTypes = { | ||
| /** | ||
| * An icon component to render. | ||
| * Example import of a Paragon icon component: `import { Check } from '@openedx/paragon/icons';` | ||
| */ | ||
| src: PropTypes.elementType, | ||
| /** HTML element attributes to pass through to the underlying svg element */ | ||
| svgAttrs: PropTypes.shape({ | ||
| 'aria-label': PropTypes.string, | ||
| 'aria-labelledby': PropTypes.string, | ||
| }), | ||
| /** | ||
| * the `id` property of the Icon element, by default this value is generated | ||
| * with the `newId` function with the `prefix` of `Icon`. | ||
| */ | ||
| id: PropTypes.string, | ||
| /** The size of the icon. */ | ||
| size: PropTypes.oneOf(['xs', 'sm', 'md', 'lg']), | ||
| /** A class name that will define what the Icon looks like. */ | ||
| className: PropTypes.string, | ||
| /** | ||
| * a boolean that determines the value of `aria-hidden` attribute on the Icon span, | ||
| * this value is `true` by default. | ||
| */ | ||
| hidden: PropTypes.bool, | ||
| /** | ||
| * a string or an element that will be used on a secondary span leveraging the `sr-only` style | ||
| * for screenreader only text, this value is `undefined` by default. This value is recommended for use unless | ||
| * the Icon is being used in a way that is purely decorative or provides no additional context for screen | ||
| * reader users. This field should be thought of the same way an `alt` attribute would be used for `image` tags. | ||
| */ | ||
| screenReaderText: PropTypes.oneOfType([PropTypes.string, PropTypes.element]), | ||
| }; | ||
|
|
||
| Icon.defaultProps = { | ||
| src: null, | ||
| svgAttrs: {}, | ||
| id: undefined, | ||
| hidden: true, | ||
| screenReaderText: undefined, | ||
| size: undefined, | ||
| className: undefined, | ||
| }; | ||
|
|
||
| export default withDeprecatedProps(Icon, 'Icon', { | ||
| className: { | ||
| deprType: DeprTypes.FORMAT, | ||
| expect: value => typeof value === 'string', | ||
| transform: value => (Array.isArray(value) ? value.join(' ') : value), | ||
| message: 'It should be a string.', | ||
| }, | ||
| }); | ||
| export default Icon; | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where did
nullcome from? It seems likeidjust acceptedstring | undefinedbefore, so can we leave it at that?