From f90c47d04f870e60806052e446fa1417c565e8d5 Mon Sep 17 00:00:00 2001 From: Hugo Leote Date: Tue, 23 Jun 2020 11:06:56 +0200 Subject: [PATCH] feat(components): Migrate Badge component to typescript (#624) * Initial refactor to ts of the Badge component * Conclude refactoring of Badge component * Fix lint issues * Update Badge snapshot --- scripts/static-styles/config.js | 18 ++-- src/__snapshots__/storyshots.spec.js.snap | 52 +++++----- .../Badge/{Badge.spec.js => Badge.spec.tsx} | 13 ++- .../Badge/{Badge.story.js => Badge.story.tsx} | 24 +++-- src/components/Badge/{Badge.js => Badge.tsx} | 95 +++++++++---------- ...Badge.spec.js.snap => Badge.spec.tsx.snap} | 16 ++-- src/components/Badge/{index.js => index.ts} | 0 7 files changed, 111 insertions(+), 107 deletions(-) rename src/components/Badge/{Badge.spec.js => Badge.spec.tsx} (92%) rename src/components/Badge/{Badge.story.js => Badge.story.tsx} (74%) rename src/components/Badge/{Badge.js => Badge.tsx} (70%) rename src/components/Badge/__snapshots__/{Badge.spec.js.snap => Badge.spec.tsx.snap} (94%) rename src/components/Badge/{index.js => index.ts} (100%) diff --git a/scripts/static-styles/config.js b/scripts/static-styles/config.js index 93781e0f6b..f471112da4 100644 --- a/scripts/static-styles/config.js +++ b/scripts/static-styles/config.js @@ -18,7 +18,7 @@ import { entries, isFunction, kebabCase } from 'lodash/fp'; import { light } from '@sumup/design-tokens'; import { - Badge, + // Badge, ButtonGroup, Card, Checkbox, @@ -115,14 +115,14 @@ export function getComponentInfo(component, propOverrides = {}) { export default { themes: { light }, components: [ - { - name: 'badge', - component: Badge, - props: { - color: ['neutral', 'primary', 'success', 'warning', 'danger'], - circle: PropTypes.bool - } - }, + // { + // name: 'badge', + // component: Badge, + // props: { + // color: ['neutral', 'primary', 'success', 'warning', 'danger'], + // circle: PropTypes.bool + // } + // }, // getComponentInfo(Button, { size: [KILO, MEGA] }), // getComponentInfo(Blockquote, { // size: [Blockquote.KILO, Blockquote.MEGA, Blockquote.GIGA] diff --git a/src/__snapshots__/storyshots.spec.js.snap b/src/__snapshots__/storyshots.spec.js.snap index a4d04aac07..8494907969 100644 --- a/src/__snapshots__/storyshots.spec.js.snap +++ b/src/__snapshots__/storyshots.spec.js.snap @@ -62,7 +62,7 @@ exports[`Storyshots Components/Badge Base 1`] = ` }
Badge
@@ -101,7 +101,7 @@ exports[`Storyshots Components/Badge Circular 1`] = ` }
42
@@ -146,7 +146,7 @@ exports[`Storyshots Components/Badge Clickable 1`] = ` } @@ -172,7 +172,7 @@ HTMLCollection [ }
Neutral
, @@ -194,7 +194,7 @@ HTMLCollection [ }
Primary
, @@ -216,7 +216,7 @@ HTMLCollection [ }
Success
, @@ -238,7 +238,7 @@ HTMLCollection [ }
Warning
, @@ -260,7 +260,7 @@ HTMLCollection [ }
Danger
, @@ -12468,7 +12468,7 @@ tbody .circuit-18:last-child td { `; exports[`Storyshots Components/Table With Component Rows 1`] = ` -.circuit-24 { +.circuit-23 { border-radius: 999999px; color: #FFFFFF; display: inline-block; @@ -12485,7 +12485,7 @@ exports[`Storyshots Components/Table With Component Rows 1`] = ` background-color: #8CC13F; } -.circuit-34 { +.circuit-32 { border-radius: 999999px; color: #FFFFFF; display: inline-block; @@ -12519,36 +12519,36 @@ exports[`Storyshots Components/Table With Component Rows 1`] = ` background-color: #DB4D4D; } -.circuit-44 { +.circuit-41 { position: relative; box-shadow: 0 0 0 1px rgba(12,15,20,0.07), 0 0 1px 0 rgba(12,15,20,0.07),0 2px 2px 0 rgba(12,15,20,0.07); } -.circuit-42 { +.circuit-39 { border-radius: 4px; } @media (max-width:767px) { - .circuit-42 { + .circuit-39 { height: unset; margin-left: 145px; overflow-x: auto; } } -.circuit-40 { +.circuit-37 { background-color: #FFFFFF; border-collapse: separate; width: 100%; } @media (max-width:767px) { - .circuit-40 { + .circuit-37 { margin-left: -145px; width: calc(100% + 145px); } - .circuit-40:after { + .circuit-37:after { content: ''; background-image: linear-gradient( 90deg,rgba(0,0,0,0.12),transparent ); height: 100%; @@ -12648,7 +12648,7 @@ tbody .circuit-6:last-child td { } } -.circuit-16 { +.circuit-15 { background-color: #FFFFFF; border-bottom: 1px solid #D8DDE1; padding: 24px; @@ -12685,13 +12685,13 @@ tbody .circuit-6:last-child td { }
Fruit
@@ -12770,11 +12770,11 @@ tbody .circuit-6:last-child td { Broccoli
Vegetable
@@ -12799,11 +12799,11 @@ tbody .circuit-6:last-child td { Chickpeas
Legume
diff --git a/src/components/Badge/Badge.spec.js b/src/components/Badge/Badge.spec.tsx similarity index 92% rename from src/components/Badge/Badge.spec.js rename to src/components/Badge/Badge.spec.tsx index 05423fc7b3..7496114173 100644 --- a/src/components/Badge/Badge.spec.js +++ b/src/components/Badge/Badge.spec.tsx @@ -15,6 +15,15 @@ import React from 'react'; +import { + create, + render, + renderToHtml, + axe, + act, + userEvent +} from '../../util/test-utils'; + import Badge from '.'; describe('Badge', () => { @@ -63,7 +72,7 @@ describe('Badge', () => { * Should accept a working ref */ it('should accept a working ref', () => { - const tref = React.createRef(); + const tref = React.createRef(); const { container } = render(); const div = container.querySelector('div'); expect(tref.current).toBe(div); @@ -89,7 +98,7 @@ describe('Badge', () => { ); act(() => { - fireEvent.click(getByTestId('badge')); + userEvent.click(getByTestId('badge')); }); expect(onClick).toHaveBeenCalledTimes(1); diff --git a/src/components/Badge/Badge.story.js b/src/components/Badge/Badge.story.tsx similarity index 74% rename from src/components/Badge/Badge.story.js rename to src/components/Badge/Badge.story.tsx index 449194cde6..166a3e447b 100644 --- a/src/components/Badge/Badge.story.js +++ b/src/components/Badge/Badge.story.tsx @@ -13,8 +13,8 @@ * limitations under the License. */ -import React, { Fragment } from 'react'; -import { select, boolean } from '@storybook/addon-knobs/react'; +import React, { FunctionComponent, Fragment } from 'react'; +import { select, boolean } from '@storybook/addon-knobs'; import { action } from '@storybook/addon-actions'; import docs from './Badge.docs.mdx'; @@ -28,21 +28,19 @@ export default { } }; -export const base = () => ( +export const base: FunctionComponent = () => ( Badge ); -export const colors = () => ( +export const colors: FunctionComponent = () => ( Neutral Primary @@ -52,13 +50,13 @@ export const colors = () => ( ); -export const circular = () => ( +export const circular: FunctionComponent = () => ( 42 ); -export const clickable = () => ( +export const clickable: FunctionComponent = () => ( Click me diff --git a/src/components/Badge/Badge.js b/src/components/Badge/Badge.tsx similarity index 70% rename from src/components/Badge/Badge.js rename to src/components/Badge/Badge.tsx index 6c64371714..ba82c0d4d3 100644 --- a/src/components/Badge/Badge.js +++ b/src/components/Badge/Badge.tsx @@ -13,14 +13,41 @@ * limitations under the License. */ -import React from 'react'; -import PropTypes from 'prop-types'; -import styled from '@emotion/styled'; +import React, { + forwardRef, + MouseEvent, + KeyboardEvent, + Ref, + HTMLProps +} from 'react'; import { css } from '@emotion/core'; import isPropValid from '@emotion/is-prop-valid'; +import styled, { StyleProps } from '../../styles/styled'; import { subHeadingKilo, focusOutline } from '../../styles/style-helpers'; +type OnClick = ( + event: MouseEvent | KeyboardEvent +) => void; +type RefType = Ref; + +export interface BadgeProps extends HTMLProps { + /** + * Callback for the click event. + */ + onClick?: OnClick; + /** + * Ensures text is centered and the badge looks like a circle. + */ + circle?: boolean; + color?: 'neutral' | 'primary' | 'success' | 'warning' | 'danger'; + /** + * The ref to the html div DOM element + */ + ref?: RefType; + as?: string; +} + const COLOR_MAP = { success: { default: 'g500', @@ -47,8 +74,8 @@ const COLOR_MAP = { hover: 'n700', active: 'n900' } -}; -const baseStyles = ({ theme }) => css` +} as const; +const baseStyles = ({ theme }: StyleProps) => css` label: badge; border-radius: ${theme.borderRadius.pill}; color: ${theme.colors.white}; @@ -61,7 +88,7 @@ const baseStyles = ({ theme }) => css` text-align: center; `; -const colorStyles = ({ theme, color }) => { +const colorStyles = ({ theme, color = 'neutral' }: StyleProps & BadgeProps) => { const currentColor = COLOR_MAP[color]; if (!currentColor) { return null; @@ -72,7 +99,7 @@ const colorStyles = ({ theme, color }) => { `; }; -const circleStyles = ({ circle }) => +const circleStyles = ({ circle }: BadgeProps) => circle && css` label: badge--circle; @@ -83,7 +110,11 @@ const circleStyles = ({ circle }) => width: 24px; `; -const clickableStyles = ({ theme, onClick, color }) => { +const clickableStyles = ({ + theme, + onClick, + color = 'neutral' +}: StyleProps & BadgeProps) => { const currentColor = COLOR_MAP[color]; if (!onClick || !currentColor) { return null; @@ -108,51 +139,17 @@ const clickableStyles = ({ theme, onClick, color }) => { `; }; -const StyledBadge = styled('div', { - shouldForwardProp: prop => isPropValid(prop) && prop !== 'color' -})(baseStyles, colorStyles, circleStyles, clickableStyles); - /** * A badge for displaying update notifications etc. */ -const Badge = React.forwardRef((props, ref) => ( - -)); - -Badge.displayName = 'Badge'; - -Badge.propTypes = { - /** - * Callback for the click event. - */ - onClick: PropTypes.func, - /** - * Ensures text is centered and the badge looks like a circle. - */ - circle: PropTypes.bool, - color: PropTypes.oneOf([ - 'neutral', - 'primary', - 'success', - 'warning', - 'danger' - ]), - /** - * The ref to the html button dom element - */ - ref: PropTypes.oneOfType([ - PropTypes.func, - PropTypes.shape({ - current: PropTypes.oneOf([PropTypes.instanceOf(HTMLDivElement)]) - }) - ]) -}; +const StyledBadge = styled('div', { + shouldForwardProp: prop => isPropValid(prop) && prop !== 'color' +})(baseStyles, colorStyles, circleStyles, clickableStyles); -Badge.defaultProps = { - circle: false, - color: 'neutral', - ref: undefined -}; +/* eslint-disable react/display-name */ +const Badge = forwardRef((props: BadgeProps, ref: BadgeProps['ref']) => ( + +)); /** * @component diff --git a/src/components/Badge/__snapshots__/Badge.spec.js.snap b/src/components/Badge/__snapshots__/Badge.spec.tsx.snap similarity index 94% rename from src/components/Badge/__snapshots__/Badge.spec.js.snap rename to src/components/Badge/__snapshots__/Badge.spec.tsx.snap index ad83cf5220..2720f3996a 100644 --- a/src/components/Badge/__snapshots__/Badge.spec.js.snap +++ b/src/components/Badge/__snapshots__/Badge.spec.tsx.snap @@ -19,7 +19,7 @@ exports[`Badge rendering color variations should render with danger colors 1`] = }
`; @@ -42,7 +42,7 @@ exports[`Badge rendering color variations should render with primary colors 1`] }
`; @@ -65,7 +65,7 @@ exports[`Badge rendering color variations should render with success colors 1`] }
`; @@ -88,7 +88,7 @@ exports[`Badge rendering color variations should render with warning colors 1`] }
`; @@ -130,8 +130,8 @@ exports[`Badge should have hover/active styles only when the onClick handler is border: 0; } -
`; @@ -168,7 +168,7 @@ exports[`Badge should have the correct circle styles 1`] = ` }
`; @@ -191,6 +191,6 @@ exports[`Badge should render with default styles 1`] = ` }
`; diff --git a/src/components/Badge/index.js b/src/components/Badge/index.ts similarity index 100% rename from src/components/Badge/index.js rename to src/components/Badge/index.ts