Skip to content

Commit

Permalink
Merge branch 'main' into VanAnderson/migrate-tab-nav-to-tsx
Browse files Browse the repository at this point in the history
  • Loading branch information
colebemis committed Feb 9, 2021
2 parents 91389e0 + d2d5063 commit adcb4b3
Show file tree
Hide file tree
Showing 18 changed files with 167 additions and 96 deletions.
5 changes: 5 additions & 0 deletions .changeset/kind-spies-call.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@primer/components": patch
---

Migrate `CircleBadge` to TypeScript
5 changes: 5 additions & 0 deletions .changeset/quiet-lobsters-sing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@primer/components": patch
---

Migrate `CircleOcticon` to TypeScript
5 changes: 5 additions & 0 deletions .changeset/seven-islands-rest.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@primer/components": patch
---

Migrate `Position` to TypeScript
5 changes: 5 additions & 0 deletions .changeset/stupid-seals-explode.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@primer/components": patch
---

Migrate `TextInput` to TypeScript
1 change: 1 addition & 0 deletions @types/@styled-system/props/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
declare module '@styled-system/props'
48 changes: 29 additions & 19 deletions src/CircleBadge.js → src/CircleBadge.tsx
Original file line number Diff line number Diff line change
@@ -1,45 +1,54 @@
import React from 'react'
import PropTypes from 'prop-types'
import styled from 'styled-components'
import {COMMON, get} from './constants'
import isNumeric from './utils/isNumeric'
import theme from './theme'
import sx from './sx'
import {COMMON, get, SystemCommonProps} from './constants'
import StyledOcticon from './StyledOcticon'
import sx, {SxProp} from './sx'
import theme from './theme'
import isNumeric from './utils/isNumeric'
import {ComponentProps} from './utils/types'

const variantSizes = {
small: 56,
medium: 96,
large: 128
}

const sizeStyles = ({size, variant}) => {
type StyledCircleBadgeProps = {
inline?: boolean
variant?: keyof typeof variantSizes
size?: number
} & SystemCommonProps &
SxProp

const sizeStyles = ({size, variant = 'medium'}: StyledCircleBadgeProps) => {
const calc = isNumeric(size) ? size : variantSizes[variant]
return {
width: calc,
height: calc
}
}

const CircleBadge = styled.div`
const CircleBadge = styled.div<StyledCircleBadgeProps>`
display: ${props => (props.inline ? 'inline-flex' : 'flex')};
align-items: center;
justify-content: center;
background-color: ${get('colors.white')};
border-radius: 50%;
box-shadow: ${get('shadows.medium')};
${COMMON} ${sizeStyles};
${COMMON};
${sizeStyles};
${sx};
`

CircleBadge.Icon = props => (
<StyledOcticon {...props} sx={Object.assign(props.sx, {height: 'auto', maxWidth: '60%', maxHeight: '55%'})} />
)
const CircleBadgeIcon = styled(StyledOcticon)`
height: auto;
max-width: 60%;
max-height: 55%;
`

CircleBadge.defaultProps = {
inline: false,
theme,
variant: 'medium'
theme
}

CircleBadge.propTypes = {
Expand All @@ -51,15 +60,16 @@ CircleBadge.propTypes = {
...sx.propTypes
}

CircleBadge.Icon.defaultProps = {
theme,
sx: {}
CircleBadgeIcon.defaultProps = {
theme
}

CircleBadge.Icon.propTypes = {
CircleBadgeIcon.propTypes = {
...StyledOcticon.propTypes
}

CircleBadge.Icon.displayName = 'CircleBadge.Icon'
CircleBadgeIcon.displayName = 'CircleBadge.Icon'

export default CircleBadge
export type CircleBadgeProps = ComponentProps<typeof CircleBadge>
export type CircleBadgeIconProps = ComponentProps<typeof CircleBadgeIcon>
export default Object.assign(CircleBadge, {Icon: CircleBadgeIcon})
13 changes: 10 additions & 3 deletions src/CircleOcticon.js → src/CircleOcticon.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
import React from 'react'
import PropTypes from 'prop-types'
import Flex from './Flex'
import Flex, {FlexProps} from './Flex'
import theme from './theme'
import BorderBox from './BorderBox'
import {IconProps} from '@primer/octicons-react'

function CircleOcticon(props) {
export type CircleOcticonProps = {
as?: React.ElementType
size?: number
icon: React.ComponentType<{size?: IconProps['size']}>
} & FlexProps

function CircleOcticon(props: CircleOcticonProps) {
const {size, as} = props
const {icon: IconComponent, bg, as: asProp, ...rest} = props
const {icon: IconComponent, bg, ...rest} = props
return (
<BorderBox as={as} bg={bg} overflow="hidden" borderWidth={0} size={size} borderRadius="50%">
<Flex {...rest} alignItems="center" justifyContent="center">
Expand Down
42 changes: 0 additions & 42 deletions src/Position.js

This file was deleted.

61 changes: 61 additions & 0 deletions src/Position.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import PropTypes from 'prop-types'
import React from 'react'
import styled from 'styled-components'
import Box from './Box'
import {POSITION, SystemPositionProps} from './constants'
import sx from './sx'
import theme from './theme'
import {ComponentProps} from './utils/types'

type StyledPositionProps = {as?: React.ElementType} & SystemPositionProps

const Position = styled(Box)<StyledPositionProps>`
${POSITION};
${sx};
`

Position.defaultProps = {
theme
}

Position.propTypes = {
...Box.propTypes,
...POSITION.propTypes,
theme: PropTypes.object,
...sx.propTypes
}

export type PositionProps = ComponentProps<typeof Position>
export default Position

// Absolute
export type AbsoluteProps = Omit<PositionProps, 'position'>
export function Absolute(props: AbsoluteProps) {
return <Position {...props} position="absolute" />
}
Absolute.defaultProps = Position.defaultProps
Absolute.propTypes = Position.propTypes

// Fixed
export type FixedProps = Omit<PositionProps, 'position'>
export function Fixed(props: AbsoluteProps) {
return <Position {...props} position="fixed" />
}
Fixed.defaultProps = Position.defaultProps
Fixed.propTypes = Position.propTypes

// Relative
export type RelativeProps = Omit<PositionProps, 'position'>
export function Relative(props: RelativeProps) {
return <Position {...props} position="relative" />
}
Relative.defaultProps = Position.defaultProps
Relative.propTypes = Position.propTypes

// Sticky
export type StickyProps = Omit<PositionProps, 'position'>
export function Sticky(props: StickyProps) {
return <Position {...props} position="sticky" />
}
Sticky.defaultProps = {...Position.defaultProps, top: 0, zIndex: 1}
Sticky.propTypes = Position.propTypes
72 changes: 45 additions & 27 deletions src/TextInput.js → src/TextInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ import classnames from 'classnames'
import systemPropTypes from '@styled-system/prop-types'
import {omit, pick} from '@styled-system/props'
import styled, {css} from 'styled-components'
import {variant, width, minWidth, maxWidth} from 'styled-system'
import {COMMON, get} from './constants'
import {variant, width, minWidth, maxWidth, MaxWidthProps, WidthProps, MinWidthProps} from 'styled-system'
import {COMMON, get, SystemCommonProps} from './constants'
import theme from './theme'
import sx from './sx'
import sx, {SxProp} from './sx'
import {ComponentProps} from './utils/types'

const sizeVariants = variant({
variants: {
Expand All @@ -26,28 +27,6 @@ const sizeVariants = variant({
}
})

// using forwardRef is important so that other components (ex. SelectMenu) can autofocus the input
const TextInput = React.forwardRef(({icon: IconComponent, className, block, disabled, sx, ...rest}, ref) => {
// this class is necessary to style FilterSearch, plz no touchy!
const wrapperClasses = classnames(className, 'TextInput-wrapper')
const wrapperProps = pick(rest)
const inputProps = omit(rest)
return (
<Wrapper
className={wrapperClasses}
hasIcon={!!IconComponent}
block={block}
theme={theme}
disabled={disabled}
sx={sx}
{...wrapperProps}
>
{IconComponent && <IconComponent className="TextInput-icon" />}
<Input ref={ref} disabled={disabled} {...inputProps} />
</Wrapper>
)
})

const Input = styled.input`
border: 0;
font-size: inherit;
Expand All @@ -60,7 +39,18 @@ const Input = styled.input`
}
`

const Wrapper = styled.span`
type StyledWrapperProps = {
disabled?: boolean
hasIcon?: boolean
block?: boolean
variant?: 'small' | 'large'
} & SystemCommonProps &
WidthProps &
MinWidthProps &
MaxWidthProps &
SxProp

const Wrapper = styled.span<StyledWrapperProps>`
display: inline-flex;
align-items: stretch;
min-height: 34px;
Expand Down Expand Up @@ -126,14 +116,41 @@ const Wrapper = styled.span`
${sx};
`

type TextInputInternalProps = {icon?: React.ComponentType<{className?: string}>} & ComponentProps<typeof Wrapper> &
ComponentProps<typeof Input>

// using forwardRef is important so that other components (ex. SelectMenu) can autofocus the input
const TextInput = React.forwardRef<HTMLInputElement, TextInputInternalProps>(
({icon: IconComponent, className, block, disabled, sx, ...rest}, ref) => {
// this class is necessary to style FilterSearch, plz no touchy!
const wrapperClasses = classnames(className, 'TextInput-wrapper')
const wrapperProps = pick(rest)
const inputProps = omit(rest)
return (
<Wrapper
className={wrapperClasses}
hasIcon={!!IconComponent}
block={block}
theme={theme}
disabled={disabled}
sx={sx}
{...wrapperProps}
>
{IconComponent && <IconComponent className="TextInput-icon" />}
<Input ref={ref} disabled={disabled} {...inputProps} />
</Wrapper>
)
}
)

TextInput.defaultProps = {
theme,
type: 'text'
}

TextInput.propTypes = {
block: PropTypes.bool,
icon: PropTypes.elementType,
icon: PropTypes.any,
maxWidth: systemPropTypes.layout.maxWidth,
minWidth: systemPropTypes.layout.minWidth,
variant: PropTypes.oneOf(['small', 'large']),
Expand All @@ -144,4 +161,5 @@ TextInput.propTypes = {

TextInput.displayName = 'TextInput'

export type TextInputProps = ComponentProps<typeof TextInput>
export default TextInput
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,7 @@ describe('CircleBadge', () => {
})

describe('CircleBadge.Icon', () => {
behavesAsComponent(CircleBadge.Icon, [COMMON], () => (
<CircleBadge.Icon icon={CheckIcon}>
<div />
</CircleBadge.Icon>
))
behavesAsComponent(CircleBadge.Icon, [COMMON], () => <CircleBadge.Icon icon={CheckIcon} />)
})

it('should have no axe violations', async () => {
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.

0 comments on commit adcb4b3

Please sign in to comment.