diff --git a/.changeset/cool-snakes-bathe.md b/.changeset/dull-cheetahs-applaud.md similarity index 55% rename from .changeset/cool-snakes-bathe.md rename to .changeset/dull-cheetahs-applaud.md index 83896219e26..5a799c59928 100644 --- a/.changeset/cool-snakes-bathe.md +++ b/.changeset/dull-cheetahs-applaud.md @@ -2,4 +2,4 @@ "@primer/components": patch --- -Migrate `Text` to TypeScript +Migrate `Flash` to TypeScript diff --git a/.changeset/happy-taxis-compare.md b/.changeset/eleven-days-hope.md similarity index 52% rename from .changeset/happy-taxis-compare.md rename to .changeset/eleven-days-hope.md index f7c15c5e33a..56c3ed395d0 100644 --- a/.changeset/happy-taxis-compare.md +++ b/.changeset/eleven-days-hope.md @@ -2,4 +2,4 @@ "@primer/components": patch --- -Migrate `Flex` to TypeScript +Migrate `Truncate` to TypeScript diff --git a/.changeset/flat-moose-guess.md b/.changeset/flat-moose-guess.md deleted file mode 100644 index a63cbd4b1f9..00000000000 --- a/.changeset/flat-moose-guess.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@primer/components": patch ---- - -Migrate `BaseStyles` to TypeScript diff --git a/.changeset/fluffy-peaches-study.md b/.changeset/fluffy-peaches-study.md deleted file mode 100644 index f909526645f..00000000000 --- a/.changeset/fluffy-peaches-study.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@primer/components": patch ---- - -Migrate `Heading` to TypeScript diff --git a/.changeset/funny-kangaroos-worry.md b/.changeset/funny-kangaroos-worry.md deleted file mode 100644 index 4d4dffd7d06..00000000000 --- a/.changeset/funny-kangaroos-worry.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@primer/components": patch ---- - -Migrate `Label` to TypeScript diff --git a/.changeset/funny-pots-explain.md b/.changeset/funny-pots-explain.md new file mode 100644 index 00000000000..4791170c256 --- /dev/null +++ b/.changeset/funny-pots-explain.md @@ -0,0 +1,5 @@ +--- +"@primer/components": patch +--- + +Migrate `StyledOcticon` to TypeScript diff --git a/.changeset/lovely-walls-cover.md b/.changeset/lovely-walls-cover.md deleted file mode 100644 index 813c1f3f7ce..00000000000 --- a/.changeset/lovely-walls-cover.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@primer/components": patch ---- - -Migrate `LabelGroup` to TypeScript diff --git a/.changeset/mighty-pumpkins-behave.md b/.changeset/mighty-pumpkins-behave.md deleted file mode 100644 index fd51936d82f..00000000000 --- a/.changeset/mighty-pumpkins-behave.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@primer/components": patch ---- - -Add supported `htmlFor` prop to `FormGroupLabelProps` type definition diff --git a/.changeset/nice-spies-compete.md b/.changeset/nice-spies-compete.md deleted file mode 100644 index d11560bc33b..00000000000 --- a/.changeset/nice-spies-compete.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@primer/components': patch ---- - -Migrate `BorderBox` to TypeScript diff --git a/.changeset/sharp-pugs-tap.md b/.changeset/sharp-pugs-tap.md deleted file mode 100644 index ec1ae8af2a3..00000000000 --- a/.changeset/sharp-pugs-tap.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@primer/components": patch ---- - -Migrate `BranchName` to TypeScript diff --git a/.changeset/slimy-rats-mix.md b/.changeset/slimy-rats-mix.md deleted file mode 100644 index 81f5d0e0bfd..00000000000 --- a/.changeset/slimy-rats-mix.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@primer/components": patch ---- - -Migrate `Pagehead` to TypeScript diff --git a/.changeset/tricky-gifts-bake.md b/.changeset/tricky-gifts-bake.md deleted file mode 100644 index c6e4fc812da..00000000000 --- a/.changeset/tricky-gifts-bake.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@primer/components": patch ---- - -Migrate `Grid` to TypeScript diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000000..48fb6432522 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,48 @@ +# @primer/components + +## 23.0.2 +### Patch Changes + + + +- [`7128403c`](https://github.com/primer/components/commit/7128403c488a2cfefda3743d7f92be8142071bc8) [#979](https://github.com/primer/components/pull/979) Thanks [@colebemis](https://github.com/colebemis)! - Migrate `Text` to TypeScript + + + +- [`fe16e21c`](https://github.com/primer/components/commit/fe16e21cb3a67d424cdbb663ea2d13e2397eb42c) [#982](https://github.com/primer/components/pull/982) Thanks [@colebemis](https://github.com/colebemis)! - Migrate `BaseStyles` to TypeScript + + + +- [`ee806857`](https://github.com/primer/components/commit/ee8068579106d34309faa1a0c44e1ed25edafb59) [#975](https://github.com/primer/components/pull/975) Thanks [@colebemis](https://github.com/colebemis)! - Migrate `Heading` to TypeScript + + + +- [`25315571`](https://github.com/primer/components/commit/2531557171cd2e39b980a456d42e15880e16256f) [#976](https://github.com/primer/components/pull/976) Thanks [@colebemis](https://github.com/colebemis)! - Migrate `Label` to TypeScript + + + +- [`4076bf4e`](https://github.com/primer/components/commit/4076bf4e173d997c46ba1130c5f0f86f04952790) [#986](https://github.com/primer/components/pull/986) Thanks [@colebemis](https://github.com/colebemis)! - Migrate `Flex` to TypeScript + + + +- [`397a46fe`](https://github.com/primer/components/commit/397a46fe1edee9c2bb71e6ceedafff8dc4e76cb2) [#976](https://github.com/primer/components/pull/976) Thanks [@colebemis](https://github.com/colebemis)! - Migrate `LabelGroup` to TypeScript + + + +- [`e841e158`](https://github.com/primer/components/commit/e841e158dcc557169fce19c78d5d90af5fef6af6) [#983](https://github.com/primer/components/pull/983) Thanks [@shiftkey](https://github.com/shiftkey)! - Add supported `htmlFor` prop to `FormGroupLabelProps` type definition + + + +- [`dc0df4b2`](https://github.com/primer/components/commit/dc0df4b209d952b121f04fc86d0f2984a6e661cf) [#973](https://github.com/primer/components/pull/973) Thanks [@colebemis](https://github.com/colebemis)! - Migrate `BorderBox` to TypeScript + + + +- [`0cac0042`](https://github.com/primer/components/commit/0cac00426d4d29c51d9f110f091aac06c49ec054) [#974](https://github.com/primer/components/pull/974) Thanks [@colebemis](https://github.com/colebemis)! - Migrate `BranchName` to TypeScript + + + +- [`755a1a5c`](https://github.com/primer/components/commit/755a1a5c19f6d6298f9c6785b50fed71aaea59ad) [#977](https://github.com/primer/components/pull/977) Thanks [@colebemis](https://github.com/colebemis)! - Migrate `Pagehead` to TypeScript + + + +- [`34ff4885`](https://github.com/primer/components/commit/34ff4885311686699fbb6d2e3fab0337bad3d016) [#989](https://github.com/primer/components/pull/989) Thanks [@colebemis](https://github.com/colebemis)! - Migrate `Grid` to TypeScript diff --git a/contributor-docs/adrs/adr-001-typescript.md b/contributor-docs/adrs/adr-001-typescript.md new file mode 100644 index 00000000000..da69c19d689 --- /dev/null +++ b/contributor-docs/adrs/adr-001-typescript.md @@ -0,0 +1,23 @@ +# ADR 1: TypeScript + +## Status + +Approved 2021-01-15 + +## Context + +Primer React components was originally released without TypeScript type definitions, making it difficult for engineers to consume the library in TypeScript applications. In [July 2019](https://github.com/primer/components/commit/2983c935ea9ad600c04078adb25e40c3624c11fa#diff-7aa4473ede4abd9ec099e87fec67fd57afafaf39e05d493ab4533acc38547eb8), we created an [ambient declaration](https://www.geeksforgeeks.org/typescript-ambients-declaration/) file (`index.d.ts`) file to provide type definitions for TypeScript applications without having to rewrite Primer React components in TypeScript. + +`index.d.ts` has been an effective stopgap, enabling teams to build complex applications with Primer React components and TypeScript. However, because `index.d.ts` is disconnected from the implementation code, we've struggled to keep the type definitions up-to-date and accurate, as evidenced by [many](https://github.com/primer/components/issues/906) [TypeScript](https://github.com/primer/components/issues/540) [bug](https://github.com/primer/components/issues/520) [reports](https://github.com/primer/components/issues/534). As the library continues to grow in size and complexity, manually maintaining type definitions will become unsustainable. + +## Decision + +We will rewrite Primer React components in TypeScript. + +## Consequences + +- Type definitions can be generated by the TypeScript compiler, eliminating bugs caused by hand-written type definitions. +- Engineers can upstream components from other TypeScript projects at GitHub without having to remove type annotations, improving the contributor experience. +- We can refactor components with increased confidence. +- Component prop documentation can be generated by [react-docgen-typescript](https://github.com/styleguidist/react-docgen-typescript), eliminating inaccurate and out-of-date hand-written prop documentation. +- New contributors will need some familiarity with TypeScript in order to make code contributions. diff --git a/package.json b/package.json index 85cda9fb200..3bae654003a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@primer/components", - "version": "23.0.1", + "version": "23.0.2", "description": "Primer react components", "main": "lib/index.js", "module": "lib-esm/index.js", diff --git a/src/Flash.js b/src/Flash.tsx similarity index 67% rename from src/Flash.js rename to src/Flash.tsx index fe741443ab7..da4c15d7428 100644 --- a/src/Flash.js +++ b/src/Flash.tsx @@ -1,24 +1,21 @@ import PropTypes from 'prop-types' import styled from 'styled-components' import {variant} from 'styled-system' -import {COMMON, get} from './constants' +import {COMMON, get, SystemCommonProps} from './constants' import theme from './theme' -import sx from './sx' - -const schemeMap = { - red: 'danger', - blue: 'default', - yellow: 'warning', - green: 'success' -} +import sx, {SxProp} from './sx' const variants = variant({ scale: 'flash' }) -const getIconColor = (variant, theme) => get(`flashIcon.${variant}`)(theme) - -const Flash = styled.div` +const Flash = styled.div< + { + variant?: 'default' | 'warning' | 'success' | 'danger' + full?: boolean + } & SystemCommonProps & + SxProp +>` position: relative; color: ${get('colors.text.grayDark')}; padding: ${get('space.3')}; @@ -32,12 +29,12 @@ const Flash = styled.div` } svg { - color: ${props => getIconColor(props.variant, props.theme)}; + color: ${props => get(`flashIcon.${props.variant}`)(props.theme)}; margin-right: ${get('space.2')}; } ${COMMON}; - ${variants} + ${variants}; ${sx}; ` @@ -49,7 +46,6 @@ Flash.defaultProps = { Flash.propTypes = { children: PropTypes.node, full: PropTypes.bool, - scheme: PropTypes.oneOf(Object.keys(schemeMap)), // deprecate 20.0.0 variant: PropTypes.oneOf(['default', 'warning', 'success', 'danger']), ...COMMON.propTypes, ...sx.propTypes diff --git a/src/StyledOcticon.js b/src/StyledOcticon.js deleted file mode 100644 index 3138ddf69a7..00000000000 --- a/src/StyledOcticon.js +++ /dev/null @@ -1,31 +0,0 @@ -import React from 'react' -import PropTypes from 'prop-types' -import styled from 'styled-components' -import {COMMON} from './constants' -import theme from './theme' -import sx from './sx' - -function IconWrapper({icon: IconComponent, className, ...rest}) { - return -} - -const StyledOcticon = styled(IconWrapper)` - ${COMMON} - ${sx} -` - -StyledOcticon.defaultProps = { - theme, - size: 16 -} - -StyledOcticon.propTypes = { - ...COMMON.propTypes, - ...sx.propTypes, - icon: PropTypes.elementType.isRequired, - size: PropTypes.oneOfType([PropTypes.number, PropTypes.oneOf(['small', 'medium', 'large'])]), - theme: PropTypes.object, - verticalAlign: PropTypes.oneOf(['middle', 'text-bottom', 'text-top', 'top']) -} - -export default StyledOcticon diff --git a/src/StyledOcticon.tsx b/src/StyledOcticon.tsx new file mode 100644 index 00000000000..36a4a2bd518 --- /dev/null +++ b/src/StyledOcticon.tsx @@ -0,0 +1,36 @@ +import React from 'react' +import PropTypes from 'prop-types' +import styled from 'styled-components' +import {COMMON, SystemCommonProps} from './constants' +import theme from './theme' +import sx, {SxProp} from './sx' +import {IconProps} from '@primer/octicons-react' +import {ComponentProps} from './utils/types' + +type OcticonProps = {icon: React.ElementType} & IconProps + +function Octicon({icon: IconComponent, ...rest}: OcticonProps) { + return +} + +const StyledOcticon = styled(Octicon)` + ${COMMON} + ${sx} +` + +StyledOcticon.defaultProps = { + theme, + size: 16 +} + +StyledOcticon.propTypes = { + ...COMMON.propTypes, + ...sx.propTypes, + icon: PropTypes.any.isRequired, + size: PropTypes.any, + theme: PropTypes.object, + verticalAlign: PropTypes.oneOf(['middle', 'text-bottom', 'text-top', 'top']) +} + +export type StyledOcticonProps = ComponentProps +export default StyledOcticon diff --git a/src/Truncate.js b/src/Truncate.tsx similarity index 61% rename from src/Truncate.js rename to src/Truncate.tsx index f817301a106..db07b254373 100644 --- a/src/Truncate.js +++ b/src/Truncate.tsx @@ -1,11 +1,21 @@ -import styled from 'styled-components' -import {maxWidth} from 'styled-system' import PropTypes from 'prop-types' -import {TYPOGRAPHY, COMMON} from './constants' +import styled from 'styled-components' +import {maxWidth, MaxWidthProps} from 'styled-system' +import {COMMON, SystemCommonProps, SystemTypographyProps, TYPOGRAPHY} from './constants' +import sx, {SxProp} from './sx' import theme from './theme' -import sx from './sx' +import {ComponentProps} from './utils/types' + +type StyledTruncateProps = { + title: string + inline?: boolean + expandable?: boolean +} & MaxWidthProps & + SystemTypographyProps & + SystemCommonProps & + SxProp -const Truncate = styled('div')` +const Truncate = styled.div` ${TYPOGRAPHY} ${COMMON} display: ${props => (props.inline ? 'inline-block' : 'inherit')}; @@ -19,7 +29,6 @@ const Truncate = styled('div')` ` Truncate.defaultProps = { - as: 'div', expandable: false, inline: false, maxWidth: 125, @@ -37,4 +46,5 @@ Truncate.propTypes = { title: PropTypes.string.isRequired } +export type TruncateProps = ComponentProps export default Truncate diff --git a/src/__tests__/Flash.js b/src/__tests__/Flash.tsx similarity index 100% rename from src/__tests__/Flash.js rename to src/__tests__/Flash.tsx diff --git a/src/__tests__/StyledOcticon.js b/src/__tests__/StyledOcticon.tsx similarity index 88% rename from src/__tests__/StyledOcticon.js rename to src/__tests__/StyledOcticon.tsx index a29c4ffbdf9..fe63816ca21 100644 --- a/src/__tests__/StyledOcticon.js +++ b/src/__tests__/StyledOcticon.tsx @@ -15,10 +15,6 @@ describe('StyledOcticon', () => { default: StyledOcticon }) - it('implements system props', () => { - expect(StyledOcticon).toImplementSystemProps(COMMON) - }) - it('should have no axe violations', async () => { const {container} = HTMLRender() const results = await axe(container) diff --git a/src/__tests__/Truncate.js b/src/__tests__/Truncate.tsx similarity index 100% rename from src/__tests__/Truncate.js rename to src/__tests__/Truncate.tsx diff --git a/src/__tests__/__snapshots__/Flash.js.snap b/src/__tests__/__snapshots__/Flash.tsx.snap similarity index 100% rename from src/__tests__/__snapshots__/Flash.js.snap rename to src/__tests__/__snapshots__/Flash.tsx.snap diff --git a/src/__tests__/__snapshots__/StyledOcticon.js.snap b/src/__tests__/__snapshots__/StyledOcticon.tsx.snap similarity index 100% rename from src/__tests__/__snapshots__/StyledOcticon.js.snap rename to src/__tests__/__snapshots__/StyledOcticon.tsx.snap diff --git a/src/__tests__/__snapshots__/Truncate.js.snap b/src/__tests__/__snapshots__/Truncate.tsx.snap similarity index 100% rename from src/__tests__/__snapshots__/Truncate.js.snap rename to src/__tests__/__snapshots__/Truncate.tsx.snap