Skip to content

Text Input enhancements #1661

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

Merged
merged 10 commits into from
Dec 15, 2021
Merged

Text Input enhancements #1661

merged 10 commits into from
Dec 15, 2021

Conversation

pksjce
Copy link
Contributor

@pksjce pksjce commented Nov 29, 2021

Describe your changes here.

Closes # https://github.com/github/primer/issues/501

Screenshots

Some additions

Error condition
image

Warning condition
image

Trailing Icon
image

Merge checklist

  • Added/updated tests
  • Added/updated documentation
  • Tested in Chrome
  • Tested in Firefox
  • Tested in Safari
  • Tested in Edge

Take a look at the What we look for in reviews section of the contributing guidelines for more information on how we review PRs.

@pksjce pksjce requested review from mperrotti, rezrah and a team November 29, 2021 10:30
@changeset-bot
Copy link

changeset-bot bot commented Nov 29, 2021

🦋 Changeset detected

Latest commit: 34a05fa

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 Nov 29, 2021

size-limit report 📦

Path Size
dist/browser.esm.js 57.5 KB (+0.41% 🔺)
dist/browser.umd.js 57.8 KB (+0.37% 🔺)

Comment on lines 9 to 10
// deprecate icon prop
icon?: React.ComponentType<{className?: string}>
Copy link
Contributor

Choose a reason for hiding this comment

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

I think using a JSDoc comment here will give us some nice in-editor warnings for free.

Suggested change
// deprecate icon prop
icon?: React.ComponentType<{className?: string}>
/** @deprecated Use `leadingIcon` prop instead */
icon?: React.ComponentType<{className?: string}>

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Nice will do that!

Copy link
Contributor

@colebemis colebemis left a comment

Choose a reason for hiding this comment

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

What do you think of having a composable API for leading and trailing visuals similar to action list? Maybe something like this:

<InputGroup>
  <InputGroup.LeadingVisual><SearchIcon /></InputGroup.LeadingVisual>
  <TextInput placeholder="Search" />
</InputGroup>

This is similar to Chakra UI's API: https://chakra-ui.com/docs/form/input#add-elements-inside-input

cc @siddharthkp

@pksjce
Copy link
Contributor Author

pksjce commented Nov 30, 2021

Yep! Definitely looks like the composite component is our way forward seeing all the other component implementations too. My only qualm is that it gets verbose when composed at higher levels. If its a pattern we'll follow then our users should probably get used to it.
However, in this case I'm only fixing up current issues with TextInput. Do you think we want to change this api for beta?

@siddharthkp
Copy link
Member

siddharthkp commented Nov 30, 2021

What do you think of having a composable API for leading and trailing visuals similar to action list?

<InputGroup>
  <InputGroup.LeadingVisual><SearchIcon /></InputGroup.LeadingVisual>
  <TextInput placeholder="Search" />
</InputGroup>

What's the benefit of using that API here?

Yep! Definitely looks like the composite component is our way forward seeing all the other component implementations too. My only qualm is that it gets verbose when composed at higher levels.

I agree with @pksjce here, the additional verbosity doesn't seem to give us any benefits here.

I don't think composite/compound components should not be our go-to API choice. They are useful when we're composing application components within primer components with. In TextInput, we tightly control "how" the Icon renders (size, color, spacing, etc) so <TextInput leadingVisual={SearchIcon} makes a lot of sense to me.

icon?: React.ComponentType<{className?: string}>
leadingIcon?: React.ComponentType<{className?: string}>
trailingIcon?: React.ComponentType<{className?: string}>
Copy link
Contributor

Choose a reason for hiding this comment

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

Same feedback as the leading icon, but I think it's even more likely we'll use this space for things besides icons. Here's an example from Codespaces settings where we're using this space to show a "minutes" unit:

Screen Shot 2021-11-30 at 2 45 01 PM

Copy link
Contributor

Choose a reason for hiding this comment

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

Another thing to consider for this space: we might want to render a button inside the input. For example: in the project board search, we show a button to clear the input.

Screen Shot 2021-11-30 at 2 58 18 PM

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Will update to trailingVisual property for the first comment.

Yes, I see in this
image
from https://github.com/github/primer/issues/156
I was wondering if your work in https://github.com/primer/react/pull/1611/files would cover TextInput with actions. I'm still reviewing your PR to find that out.

Copy link
Contributor

Choose a reason for hiding this comment

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

No, my work in #1611 doesn't touch anything inside the inputs. It just handles the layout and passing the correct attributes for screenreader accessibility (e.g.: matching the label's for attribute to the input's id attribute)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hmmm then I think we should discuss this in a separate PR. It's common to have trailingVisual and trailingAction in our components. Possibly we can think of adding trailingAction onto the TextInput?

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm happy with addressing this in a separate PR. Agreed - trailingAction should be on the TextInput

contrast={contrast}
disabled={disabled}
hasIcon={!!IconComponent}
hasIcon={!!IconComponent || !!(LeadingIconComponent || TrailingIconComponent)}
Copy link
Contributor

Choose a reason for hiding this comment

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

Non-blocking nitpick: I prefer Boolean(isTruthy) over !!isTruthy just because I find it more readable.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed this check. It was not required after all

@@ -25,45 +43,50 @@ type StyledWrapperProps = {
hasIcon?: boolean
block?: boolean
contrast?: boolean
validationStatus?: 'error' | 'warning'
Copy link
Contributor

Choose a reason for hiding this comment

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

Copy link
Contributor

Choose a reason for hiding this comment

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

I didn't include 'warning' because I couldn't figure out where we use it, but I'm fine with keeping it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Does that mean I have to handle success case in TextInput?

Copy link
Contributor

Choose a reason for hiding this comment

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

We don't have a special style for inputs with a validation status of success. We just style any success message we might show.

For example:
Screen Shot 2021-12-02 at 8 35 57 AM

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Isn't it unnecessary for me to use that type then since it has success in it too.

Copy link
Contributor

Choose a reason for hiding this comment

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

Correct :)

background-repeat: no-repeat; // Repeat and position set for form states (success, error, etc)
background-position: right 8px center; // For form validation. This keeps images 8px from right and centered vertically.
border: 1px solid ${get('colors.border.default')};
border-radius: ${get('radii.2')};
outline: none;
box-shadow: ${get('shadows.primer.shadow.inset')};
cursor: text;
padding: 6px 12px;
display: grid;
grid-template-areas: 'leadingIcon input trailingIcon';
Copy link
Contributor

Choose a reason for hiding this comment

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

We should add grid-template-columns: auto 1fr auto; so that the empty grid cells collapse when no content is passed.

Stuff like this will happen if we don't:
Screen Shot 2021-11-30 at 3 29 10 PM

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, I've been trying to fix this as well.
But your solution results in
image

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Adding

grid-template-columns: auto 1fr auto;
justify-items: end;

seems to help. WDYT?

Copy link
Contributor

Choose a reason for hiding this comment

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

It looks like the text input is getting sized with auto when it's the first child. We might need to change the grid-template-columns based on what children are there.

leadingVisual + input + trailingVisual

grid-template-columns: auto 1fr auto;

leadingVisual + input

grid-template-columns: auto 1fr;

input + trailingVisual

grid-template-columns: 1fr auto;

input

grid-template-columns: 1fr;
or
grid-template-columns: unset;

Copy link
Contributor

Choose a reason for hiding this comment

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

I was hoping grid would have some fancy way of handling this without having to specify different column templates for each case, but I couldn't figure it out :(

Maybe another reviewer will know?

Copy link
Contributor

Choose a reason for hiding this comment

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

Or maybe we could just use flexbox instead of grid? Is there something we need from grid that can't be done with flexbox?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah I'm not particularly attached to the grid way. Do you want to pair on this for a bit tomorrow?

Copy link
Contributor

Choose a reason for hiding this comment

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

Sounds great! I love a CSS pairing sesh :)

background-repeat: no-repeat; // Repeat and position set for form states (success, error, etc)
background-position: right 8px center; // For form validation. This keeps images 8px from right and centered vertically.
border: 1px solid ${get('colors.border.default')};
border-radius: ${get('radii.2')};
outline: none;
box-shadow: ${get('shadows.primer.shadow.inset')};
cursor: text;
padding: 6px 12px;
Copy link
Contributor

Choose a reason for hiding this comment

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

i'm afraid there's too much horizontal padding for a text input in here. We should aim for more compact UIs where possible 😇.

Screen Shot 2021-12-06 at 15 22 06

Suggested change
padding: 6px 12px;
padding: 6px 8px;

Copy link
Contributor

Choose a reason for hiding this comment

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

Also, because this padding is being set in the wrapper, and not in the <input> itself, the surroundings of the input element aren't interactive.

Screen.Recording.2021-12-06.at.15.27.53.mov

We should make sure the <input> area covers as much room as possible (saving for leading and trailing elements) within the wrapper.

Copy link
Contributor

Choose a reason for hiding this comment

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

One last thing :)

The vertical padding of 6px is ignoring the border, resulting in an input field height of 34px1. We should make sure the component height as a whole matches 32px.

🙇

Footnotes

  1. 20px of line height, 6px+6px of vertical padding, 1px+1px of border

Copy link
Contributor Author

@pksjce pksjce Dec 8, 2021

Choose a reason for hiding this comment

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

This is great feedback! Had not considered the area covered by the input. Fixing this right away.

Edit - Looking more deeply into this, the wrapper is the same as the one used in TextInputWithTokens. The height on that component is a minimum of 34px and the padding is the same as this component. Do you have similar feedback on that component as well? Or should i work on having independent logic and not reuse whats been done there?
https://primer.style/react/storybook?path=/story/forms-text-input-with-tokens--default

cc - @mperrotti

Copy link
Contributor

@vdepizzol vdepizzol Dec 14, 2021

Choose a reason for hiding this comment

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

The height on that component is a minimum of 34px and the padding is the same as this component.

We should probably fix it in there too. We should make sure the form components match sizes with buttons at a 32px height for the default size variant. c/c @mperrotti

🙇

Copy link
Contributor

@mperrotti mperrotti Dec 14, 2021

Choose a reason for hiding this comment

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

@vdepizzol - I'm going to take care of this in a follow-up PR. It's not a trivial amount of work to add to these changes.

Edit: this was actually much simpler than I was expecting, so I added the changes in this PR.

cc @pksjce

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.

Everything is looking good! After @pksjce and I pair on the layout of the leading/trailing visuals and the input, this should be ready to merge.

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.

Add a changeset, and then it's good to go!

@pksjce pksjce merged commit 6f13441 into main Dec 15, 2021
@pksjce pksjce deleted the pk/text-input-enhancements branch December 15, 2021 05:19
@mperrotti mperrotti mentioned this pull request Dec 15, 2021
6 tasks
@primer-css primer-css mentioned this pull request Dec 15, 2021
pksjce added a commit that referenced this pull request Dec 20, 2021
* Enhance text input component

* Add tests

* Fix up review comments

* 1. Add leading and trailing visual
2. Change grid logic
3. Update stories and docs

* Fix up documentation

* Update documentation and css layout

* fixes text input height and padding

* fixes spacing with leading and trailing visuals

* Lint issues

* Create clever-shrimps-search.md

Co-authored-by: Mike Perrotti <mperrotti@github.com>
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.

5 participants