diff --git a/.eslintrc.js b/.eslintrc.js index 916fd5dd..ebd98d0a 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -5,4 +5,12 @@ const ignore = 0; module.exports = { root: true, extends: ['@storybook/eslint-config-storybook'], + overrides: [ + { + files: ['**/*.tsx'], + rules: { + 'react/prop-types': 'off', + }, + }, + ], }; diff --git a/.storybook/main.js b/.storybook/main.js index 53ebee5c..76d23d74 100644 --- a/.storybook/main.js +++ b/.storybook/main.js @@ -1,8 +1,4 @@ module.exports = { - stories: ['../src/**/*.stories.mdx', '../src/**/*.stories.js'], - addons: [ - '@storybook/addon-essentials', - '@storybook/addon-storysource', - '@storybook/addon-a11y', - ], + stories: ['../src/**/*.stories.mdx', '../src/**/*.stories.js', '../src/**/*.stories.tsx'], + addons: ['@storybook/addon-essentials', '@storybook/addon-storysource', '@storybook/addon-a11y'], }; diff --git a/src/components/Avatar.tsx b/src/components/Avatar.tsx index 731f90f8..6baad71c 100644 --- a/src/components/Avatar.tsx +++ b/src/components/Avatar.tsx @@ -1,4 +1,3 @@ -/* eslint-disable react/prop-types */ import React, { FunctionComponent, ComponentProps } from 'react'; import styled, { css } from 'styled-components'; import { color, typography } from './shared/styles'; diff --git a/src/components/AvatarList.tsx b/src/components/AvatarList.tsx index 6cc171ef..93cec799 100644 --- a/src/components/AvatarList.tsx +++ b/src/components/AvatarList.tsx @@ -1,4 +1,3 @@ -/* eslint-disable react/prop-types */ import React, { ComponentProps, FunctionComponent } from 'react'; import styled from 'styled-components'; diff --git a/src/components/Icon.tsx b/src/components/Icon.tsx index 5c555519..f2ae9c4d 100644 --- a/src/components/Icon.tsx +++ b/src/components/Icon.tsx @@ -1,4 +1,3 @@ -/* eslint-disable react/prop-types */ import React, { FunctionComponent } from 'react'; import styled from 'styled-components'; import { icons } from './shared/icons'; diff --git a/src/components/Link.stories.js b/src/components/Link.stories.tsx similarity index 91% rename from src/components/Link.stories.js rename to src/components/Link.stories.tsx index aab84399..177429e0 100644 --- a/src/components/Link.stories.js +++ b/src/components/Link.stories.tsx @@ -4,6 +4,7 @@ import { action } from '@storybook/addon-actions'; import { Icon } from './Icon'; import { Link } from './Link'; +// @ts-ignore import { StoryLinkWrapper } from './StoryLinkWrapper'; const CustomLink = styled(Link)` @@ -19,8 +20,11 @@ export default { component: Link, }; -export const Basic = (args) => ; -Basic.args = { children: 'link text', inverse: false }; +export const Basic: React.FunctionComponent> = () => ( + + link text + +); export const All = () => ( <> diff --git a/src/components/Link.js b/src/components/Link.tsx similarity index 70% rename from src/components/Link.js rename to src/components/Link.tsx index 21ba774d..68f9ec57 100644 --- a/src/components/Link.js +++ b/src/components/Link.tsx @@ -1,12 +1,11 @@ import React, { forwardRef } from 'react'; -import PropTypes from 'prop-types'; import styled, { css } from 'styled-components'; import { darken } from 'polished'; import { Icon } from './Icon'; import { color } from './shared/styles'; -const LinkInner = styled.span` +const LinkInner = styled.span<{ withArrow: boolean }>` ${(props) => props.withArrow && css` @@ -21,7 +20,15 @@ const LinkInner = styled.span` `}; `; -const StyledLink = styled.a` +interface StyledLinkProps { + containsIcon?: boolean; + secondary?: boolean; + tertiary?: boolean; + nochrome?: boolean; + inverse?: boolean; +} + +const StyledLink = styled.a` display: inline-block; transition: transform 150ms ease-out, color 150ms ease-out; text-decoration: none; @@ -127,78 +134,71 @@ const LinkButton = styled.button` outline: inherit; `; +/** + * Links can contains text and/or icons. Be careful using only icons, you must provide a text alternative via aria-label for accessibility. + */ +export type LinkProps = React.ComponentProps & { + withArrow?: boolean; + isButton?: boolean; + LinkWrapper?: React.ComponentType; +}; + // The main purpose of this component is to strip certain props that get passed // down to the styled component, so that we don't end up passing them to a // tag which would throw warnings for non-standard props. const LinkComponentPicker = forwardRef( ( - { containsIcon, inverse, isButton, LinkWrapper, nochrome, secondary, tertiary, ...rest }, + { + containsIcon, + inverse, + isButton, + LinkWrapper, + nochrome, + secondary, + tertiary, + ...rest + }: LinkProps, ref ) => { // Use the UnstyledLink here to avoid duplicating styles and creating // specificity conflicts by first rendering the StyledLink higher up the chain // and then re-rendering it through the 'as' prop. - const LinkComponent = isButton ? LinkButton : LinkWrapper || UnstyledLink; - return ; + /* eslint no-else-return: ["error", { allowElseIf: true }] */ + if (isButton) { + return ; + } else if (LinkWrapper) { + return ; + } + + return ; } ); -const linkStyleProps = { - containsIcon: PropTypes.bool, - inverse: PropTypes.bool, - isButton: PropTypes.bool, - LinkWrapper: PropTypes.oneOfType([PropTypes.func, PropTypes.object]), - nochrome: PropTypes.bool, - secondary: PropTypes.bool, - tertiary: PropTypes.bool, -}; +export const Link = forwardRef( + ({ children, withArrow, ...rest }, ref) => { + const content = ( + <> + + {children} + {withArrow && } + + + ); + + return ( + + {content} + + ); + } +); -const linkStyleDefaultProps = { +Link.defaultProps = { + withArrow: false, isButton: false, containsIcon: false, - LinkWrapper: undefined, - inverse: false, - nochrome: false, secondary: false, tertiary: false, -}; - -LinkComponentPicker.propTypes = { - ...linkStyleProps, -}; - -LinkComponentPicker.defaultProps = { - ...linkStyleDefaultProps, -}; - -/** - * Links can contains text and/or icons. Be careful using only icons, you must provide a text alternative via aria-label for accessibility. - */ -export const Link = forwardRef(({ children, withArrow, ...rest }, ref) => { - const content = ( - <> - - {children} - {withArrow && } - - - ); - - return ( - - {content} - - ); -}); - -Link.propTypes = { - children: PropTypes.node, - withArrow: PropTypes.bool, - ...linkStyleProps, -}; - -Link.defaultProps = { - children: null, - withArrow: false, - ...linkStyleDefaultProps, + nochrome: false, + inverse: false, };