Skip to content

Commit

Permalink
Remove system props from TextInput & fix prop types (#1414)
Browse files Browse the repository at this point in the history
  • Loading branch information
jfuchs authored Sep 9, 2021
1 parent 1101c23 commit f4e1de6
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 30 deletions.
5 changes: 5 additions & 0 deletions .changeset/cuddly-rice-march.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@primer/components': major
---

Removed system props support from `<TextInput>` and fixed its type definition.
12 changes: 1 addition & 11 deletions docs/content/TextInput.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,11 @@ TextInput is a form component to add default styling to the native text input.
```jsx live
<TextInput aria-label="Zipcode" name="zipcode" placeholder="Zipcode" autoComplete="postal-code" />

<TextInput sx={{ml: 4}} aria-label="City" name="city" placeholder="City" contrast />
<TextInput sx={{ml: 4}} aria-label="City" name="city" placeholder="City" contrast />

<TextInput sx={{ml: 4}} icon={SearchIcon} aria-label="Zipcode" name="zipcode" placeholder="Find user" autoComplete="postal-code" />
```

## System props

<Note variant="warning">

System props are deprecated in all components except [Box](/Box). Please use the [`sx` prop](/overriding-styles) instead.

</Note>

TextInput components get `COMMON` system props. Read our [System Props](/system-props) doc page for a full list of available props.

## Component props

Native `<input>` attributes are forwarded to the underlying React `input` component and are not listed below.
Expand Down
56 changes: 38 additions & 18 deletions src/TextInput.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import {omit, pick} from '@styled-system/props'
import classnames from 'classnames'
import React from 'react'
import styled, {css} from 'styled-components'
import {maxWidth, MaxWidthProps, minWidth, MinWidthProps, variant, width, WidthProps} from 'styled-system'
import {COMMON, get, SystemCommonProps} from './constants'
import {get} from './constants'
import sx, {SxProp} from './sx'
import {ComponentProps} from './utils/types'

Expand Down Expand Up @@ -43,8 +42,7 @@ type StyledWrapperProps = {
block?: boolean
contrast?: boolean
variant?: 'small' | 'large'
} & SystemCommonProps &
WidthProps &
} & WidthProps &
MinWidthProps &
MaxWidthProps &
SxProp
Expand Down Expand Up @@ -113,38 +111,60 @@ const Wrapper = styled.span<StyledWrapperProps>`
@media (min-width: ${get('breakpoints.1')}) {
font-size: ${get('fontSizes.1')};
}
${COMMON}
${width}
${minWidth}
${maxWidth}
${sizeVariants}
${sx};
`

type TextInputInternalProps = {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
as?: any // This is a band-aid fix until we have better type support for the `as` prop
// Props that are not passed through to Input:
type NonPassthroughProps = {
className?: string
icon?: React.ComponentType<{className?: string}>
} & ComponentProps<typeof Wrapper> &
ComponentProps<typeof Input>
} & Pick<
ComponentProps<typeof Wrapper>,
'block' | 'contrast' | 'disabled' | 'sx' | 'theme' | 'width' | 'maxWidth' | 'minWidth' | 'variant'
>

type TextInputInternalProps = NonPassthroughProps &
// Note: using ComponentProps instead of ComponentPropsWithoutRef here would cause a type issue where `css` is a required prop.
Omit<React.ComponentPropsWithoutRef<typeof Input>, keyof NonPassthroughProps>

// using forwardRef is important so that other components (ex. SelectMenu) can autofocus the input
const TextInput = React.forwardRef<HTMLInputElement, TextInputInternalProps>(
({icon: IconComponent, contrast, className, block, disabled, theme, sx: sxProp, ...rest}, ref) => {
(
{
icon: IconComponent,
block,
className,
contrast,
disabled,
sx: sxProp,
theme,
width: widthProp,
minWidth: minWidthProp,
maxWidth: maxWidthProp,
variant: variantProp,
...inputProps
},
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}
className={wrapperClasses}
contrast={contrast}
disabled={disabled}
hasIcon={!!IconComponent}
sx={sxProp}
{...wrapperProps}
theme={theme}
width={widthProp}
minWidth={minWidthProp}
maxWidth={maxWidthProp}
variant={variantProp}
>
{IconComponent && <IconComponent className="TextInput-icon" />}
<Input ref={ref} disabled={disabled} {...inputProps} />
Expand Down
2 changes: 1 addition & 1 deletion src/stories/DropdownMenu.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export function FavoriteColorStory(): JSX.Element {
return (
<>
<h1>Favorite Color</h1>
<TextInput placeholder="Input for focus testing" mb={2} />
<TextInput placeholder="Input for focus testing" sx={{mb: 2}} />
<div id="favorite-color-label">Please select your favorite color:</div>
<DropdownMenu
renderAnchor={({children, 'aria-labelledby': ariaLabelledBy, ...anchorProps}) => (
Expand Down

0 comments on commit f4e1de6

Please sign in to comment.