Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix TextInput types #1959

Merged
merged 18 commits into from
Mar 16, 2022
Merged

Fix TextInput types #1959

merged 18 commits into from
Mar 16, 2022

Conversation

colebemis
Copy link
Contributor

@colebemis colebemis commented Mar 14, 2022

Problem

The type for TextInput props was resolving to any, causing a bad developer experience for consumers.

After doing some digging, I found that the issue was caused by this line:

type TextInputInternalProps = Merge<React.ComponentPropsWithoutRef<typeof UnstyledTextInput>, NonPassthroughProps>
// any & React.RefAttributes & React.Attributes

Passing a styled component type to React.ComponentPropsWithoutRef yields an any type.

Solution

I fixed the type issue by rewriting the TextInputProps to avoid using React.ComponentPropsWithoutRef with a styled component.

Fixing the TextInput type revealed 50+ type errors in our codebase 😅 I fixed those errors in this PR as well.

Closes #1948

@changeset-bot
Copy link

changeset-bot bot commented Mar 14, 2022

🦋 Changeset detected

Latest commit: ac292b3

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@primer/react Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions
Copy link
Contributor

github-actions bot commented Mar 14, 2022

size-limit report 📦

Path Size
dist/browser.esm.js 63.19 KB (+0.01% 🔺)
dist/browser.umd.js 63.55 KB (+0.01% 🔺)

>

// Note: using ComponentProps instead of ComponentPropsWithoutRef here would cause a type issue where `css` is a required prop.
type TextInputInternalProps = Merge<React.ComponentPropsWithoutRef<typeof UnstyledTextInput>, NonPassthroughProps>
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line was the root of the problem. Passing a styled component type to React.ComponentPropsWithoutRef yields an any type

import styled from 'styled-components'
import React from 'react'

const StyledComponent = styled.div`...`

type Props = 
  React.ComponentPropsWithoutRef<typeof StyledComponent>
// any

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good to know so we don't make this mistake in the future.

| 'minWidth'
| 'variant'
| 'size'
| 'validationStatus'
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This type was missing validationStatus

/** @deprecated Use `leadingVisual` or `trailingVisual` prop instead */
icon?: React.ComponentType<{className?: string}>
leadingVisual?: string | React.ComponentType<{className?: string}>
trailingVisual?: string | React.ComponentType<{className?: string}>
} & Pick<
ComponentProps<typeof TextInputWrapper>,
'block' | 'contrast' | 'disabled' | 'monospace' | 'sx' | 'width' | 'maxWidth' | 'minWidth' | 'variant' | 'size'
StyledWrapperProps,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ComponentProps<> wasn't necessary here. We should avoid using ComponentProps<> when possible because it can yield unexpected results somtimes.

@@ -78,13 +87,12 @@ const TextInput = React.forwardRef<HTMLInputElement, TextInputInternalProps>(
</TextInputWrapper>
)
}
)
) as PolymorphicForwardRefComponent<'input', TextInputProps>
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using the polymorphic type utility from Radix here to implement correct types for the as prop.

Eventually, we should deprecate the as prop for TextInput. I can't think of a good use case for it now that we have the Textarea component

@@ -53,7 +52,7 @@ type TextInputWithTokensInternalProps<TokenComponentType extends AnyReactCompone
* The number of tokens to display before truncating
*/
visibleTokenCount?: number
} & TextInputProps
} & Omit<TextInputProps, 'size'>
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The size prop from TextInputProps was clashing with the size prop defined above

}: TextInputWithTokensInternalProps<TokenComponentType> & {
selectedTokenIndex: number | undefined
setSelectedTokenIndex: React.Dispatch<React.SetStateAction<number | undefined>>
},
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think selectedTokenIndex and setSelectedTokenIndex are props that we use in this component

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right. I'm not sure how these types made it here 🤔

@colebemis colebemis marked this pull request as ready for review March 15, 2022 23:08
@colebemis colebemis requested review from a team and siddharthkp March 15, 2022 23:08
Copy link
Contributor

@mperrotti mperrotti left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for fixing all of these. Code looks good, and everything in the preview deployment looks good

@@ -311,7 +311,7 @@ export const NestedOverlays = () => {
Create a list to organize your starred repositories.
</Text>
<TextInput placeholder="Name this list" sx={{mb: 2}} />
<TextInput as="textarea" placeholder="Write a description" rows="3" sx={{mb: 2, textarea: {p: 2}}} />
<TextInput as="textarea" placeholder="Write a description" rows={3} sx={{mb: 2, textarea: {p: 2}}} />
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we just change this to a Textarea?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, but until we deprecate the as prop for TextInput I think consumers will still do this. If people do this in their apps, I like that we are type-checking this use-case in our codebase.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah ok. Let's keep it as-is then.

@colebemis
Copy link
Contributor Author

colebemis commented Mar 16, 2022

@dusave tested these changes in Memex and didn't run into any build or type errors. Thanks, @dusave!

@colebemis colebemis merged commit 2025036 into main Mar 16, 2022
@colebemis colebemis deleted the fix-textinput-types branch March 16, 2022 22:57
@primer-css primer-css mentioned this pull request Mar 16, 2022
pksjce pushed a commit that referenced this pull request Mar 17, 2022
* Add failing TextInput type test

* Create loud-schools-own.md

* Update TextInput types

* Add another TextInput type test

* Update TextInput props type

* Update TextInputWithTokens types

* Fix incorrect uses of TextInputWithTokens

* Update SelectMenu types test

* Fix TextInput tests

* Update snapshot tests

* autocomplete -> autoComplete

* Remove theme prop SelectMenuFilter

* Fix TextInput in Overlay story

* Fix TextInputWithTokens stories
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

No props typings for TextInput
2 participants