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

[TextField] Add in support for multiline text fields #6553

Merged
merged 66 commits into from
May 13, 2017

Conversation

peteratticusberg
Copy link
Contributor

Keeps the api consistent with the api from v0.x.

Are we good with this implementation? Happy to make changes if need to be.

@peteratticusberg peteratticusberg changed the title Adds in support for multiline text fields [TextField] Adds in support for multiline text fields (v1.0.0) Apr 8, 2017
Copy link
Member

@oliviertassinari oliviertassinari left a comment

Choose a reason for hiding this comment

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

That's a good start, thanks for working on it!

@@ -108,10 +123,14 @@ export default class TextField extends Component {
)}
<Input
className={inputClassName}
value={value}
component={multiLine ? 'textarea' : 'input'}
Copy link
Member

Choose a reason for hiding this comment

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

I'm wondering, shouldn't it be the Input responsibility to render 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.

yea I think that's right. I'll change this.

Copy link
Contributor Author

@peteratticusberg peteratticusberg Apr 9, 2017

Choose a reason for hiding this comment

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

When I started making this change I realized it didn't make as much sense as I thought :(

The <Input /> component takes a component prop, and it feels wrong to sometimes determine the rendered component via the component prop and other times determine the rendered component via the multiLine prop. We'd have to do something like this:

const InputComponent = multiLine ? 'textarea' : ComponentProp;

Which feels like unexpected behavior to me. Still happy to change this over if you like, but at this point I'm leaning towards keeping it the way it is.

Copy link
Member

@oliviertassinari oliviertassinari Apr 9, 2017

Choose a reason for hiding this comment

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

I have two thoughs here:

  1. The Input component is public and can be used on his own, hence all the multiline logic should be at the same place, in the Input.
  2. Exposing a component property means user can override it. Hence, it should always take precedence, no matter the multiline state.

@@ -67,6 +67,12 @@ export const styleSheet = createStyleSheet('MuiInput', (theme) => {
appearance: 'none',
},
},
multiLine: {
resize: 'none',
Copy link
Member

Choose a reason for hiding this comment

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

We don't want to allow users to resize?

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 used v0 as the spec for this, which doesn't allow manual resizing for multiline text fields.

I should've used the official spec though...

Which says multiline text fields should work like this:

multilinetext

Note that the spec also talks about Text Areas which are different from multi-line text fields, and which I think we'll also want to implement in a separate PR.

screen shot 2017-04-09 at 9 56 52 am

Copy link
Member

@oliviertassinari oliviertassinari Apr 9, 2017

Choose a reason for hiding this comment

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

You raise a good point but I think that the concern is different. Mine isn't about the spec but the UX. What do we win by disabling the resize feature?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If the users are allowed to resize the textbox it could result in unexpected things happening in the UI (the user could make it too wide, or too tall). Especially if we allow them to resize textareas horizontally, which I think would really be a break with convention.

We could allow users to resize textareas vertically but it would cause text to be cutoff mid-line unless we added javascript in to snap to (line-height * lines) sizes. Either solution here doesn't feel particularly clean to me.

My preference here would be to either a) not do this at all or b) handle this in a separate PR. Let me know though if you want me to add it in here and I can take care of it.

@@ -18,6 +18,10 @@ export default class TextField extends Component {
*/
className: PropTypes.string,
/**
* The default value for the TextField
Copy link
Member

Choose a reason for hiding this comment

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

Default value of the `Input` element.

@@ -114,6 +124,10 @@ export default class Input extends Component {
*/
inputClassName: PropTypes.string,
/**
* If true, a textarea element will be rendered.
*/
multiLine: PropTypes.bool,
Copy link
Member

Choose a reason for hiding this comment

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

Should it be called multiline? cc @mbrookes

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yea, I actually had it as multiline originally but I noticed that in v0 it was multiLine so I refactored it to keep the API consistent. "multi-line" is one word, not two, so I think multiline would be more correct here.

I know v1 is already going to be introducing breaking changes, so maybe we just change it to multiline here?

Copy link
Member

Choose a reason for hiding this comment

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

Breaking changes aren't a concern. That new property name sounds better.

Copy link
Member

Choose a reason for hiding this comment

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

Sorry, missed the cc. FWIW, I agree.

@@ -98,6 +104,10 @@ export default class Input extends Component {
PropTypes.func,
]),
/**
* The default value for the string
Copy link
Member

Choose a reason for hiding this comment

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

Default value of the input element.

@@ -280,6 +302,7 @@ export default class Input extends Component {
onFocus={this.handleFocus}
onChange={this.handleChange}
disabled={disabled}
defaultValue={defaultValue}
Copy link
Member

Choose a reason for hiding this comment

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

I don't think that we need to explicit the property, it's already inside the other variable when not destructured.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yea, that's a good point. So everything was working find with regular text fields based on an <input /> but the defaultValue wasn't getting set for <textarea>'s until I explicitly passed defaultValue through as prop.

This probably isn't the best solution... Any ideas on how to improve this? Or why it might not have been working via the other object for textareas?

Copy link
Member

Choose a reason for hiding this comment

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

I confirm, you don't need that line.

@oliviertassinari oliviertassinari added next PR: needs revision The pull request can't be merged. More details is available on the code review or fails in the CI and removed PR: Needs Review labels Apr 9, 2017
@oliviertassinari oliviertassinari changed the title [TextField] Adds in support for multiline text fields (v1.0.0) [TextField] Add in support for multiline text fields Apr 9, 2017
@oliviertassinari oliviertassinari added the component: text field This is the name of the generic UI component, not the React module! label Apr 9, 2017
@peteratticusberg
Copy link
Contributor Author

of course, thanks for the comments, I'll push up some changes in a bit 👨‍💻

@peteratticusberg
Copy link
Contributor Author

Hey, so after I merged in the latest version of next here I can no longer get my dev environment working. I get an issue with the command webpack --config webpack.dll.config.js:

ERROR in dll lib
Module not found: Error: Can't resolve 'babel-runtime' in '/Users/pete/code/mui/docs'
 @ dll lib

You'd think this would be easy to fix -- just install the babel-runtime dependency -- but the babel runtime dependency is already installed. I tried adding it to the dependencies of the docs project and still I got the same error. I'm running OSX Sierra, can't imagine that's affecting anything given this in a node error but who knows.

@oliviertassinari I know you added this recently, any ideas what the issue might be here? If not I can keep digging on this one.

@peteratticusberg
Copy link
Contributor Author

Alright so here's the issue:

the babel runtime dependency doesn't specify a 'main' file in it's package.json and it also does not have an index.js file in it's root. The entry point is core-js.js. I was able to fix this by manually editing the package.json file in the babel-runtime dependency to include 'main': 'core-js.js'.

This is of course not the right solution to this problem.

I'm not sure what the right solution is but I'd imagine that it involves changing what we're doing in webpack.dll.config.js. I wonder if we could change the way we're dealing with dependencies there.

I'm also curious -- is it just me that's having this problem? Are you able to run yarn start on the latest version of next?

@mbixby
Copy link

mbixby commented May 11, 2017

@peteratticusberg any ideas about how to remove the setTimeout call in AutoResizingTextArea#handleChange? Seems hackish.

On my original branch I ran into issues with input height not being increased with newline on some slower devices (Safari on iPhone SE, complex app).

@peteratticusberg
Copy link
Contributor Author

@mbixby yea that's a fair point. This removes it. I still don't feel great about this but I do think it's an improvement.

@peteratticusberg
Copy link
Contributor Author

@oliviertassinari I recorded two new baselines, one for a Multiline TextField and another for the TextField demos page.

It looks like Argos does not recognize these new baselines and is still testing against the old ones. Have you seen this happen before? Any ideas how to fix it? yarn test:regressions passes locally

@oliviertassinari
Copy link
Member

@peteratticusberg Thanks for pushing that branch forward! I'm gonna have a look at it tomorrow :). Regarding argos, that's expected. We shouldn't have to generate baselines in the first place, accepting changes is simpler (only members with write access can do so).

Copy link
Member

@oliviertassinari oliviertassinari left a comment

Choose a reason for hiding this comment

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

test/regressions/screenshots/chrome/TextField/TextFieldMultiLine.png seems to be a dead image.


export default function TextFieldMultiline() {
return (
<div>
Copy link
Member

Choose a reason for hiding this comment

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

I don't think that we need that extra div.

@@ -47,6 +51,10 @@ export default class TextField extends Component {
*/
labelClassName: PropTypes.string,
/**
* If `true`, a textarea element will be rendered.
Copy link
Member

Choose a reason for hiding this comment

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

may be we could add instead of an input.

multiline: {
resize: 'none',
padding: '0',
'margin-top': '12',
Copy link
Member

Choose a reason for hiding this comment

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

That's dead code, maybe you meant?

  marginTop: 12,

},
multiline: {
resize: 'none',
padding: '0',
Copy link
Member

Choose a reason for hiding this comment

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

  padding: 0,

padding: '0',
'margin-top': '12',
},
'multiline-wrapper': {
Copy link
Member

Choose a reason for hiding this comment

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

  multilineWrapper: {

label="MultiLine"
multiline
defaultValue="Default Value"
className={classes.input}
Copy link
Member

Choose a reason for hiding this comment

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

What about adding rowsMax={6}?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

good call

this.syncHeightWithShadow(undefined, event);
};

getInputNode() {
Copy link
Member

Choose a reason for hiding this comment

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

I don't think that we need that function indirection

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yea I agree

return this.input;
}

setValue(value) {
Copy link
Member

Choose a reason for hiding this comment

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

I don't think that we should expose such method

rows={this.props.rows}
defaultValue={this.props.defaultValue}
readOnly
value={this.props.value}
Copy link
Member

Choose a reason for hiding this comment

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

I guess we should add aria-hidden="true".

tabIndex="-1"
rows={1}
readOnly
value={''}
Copy link
Member

Choose a reason for hiding this comment

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

I guess we should add aria-hidden="true".

Copy link
Contributor Author

Choose a reason for hiding this comment

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

good call

@peteratticusberg
Copy link
Contributor Author

Thanks for the review! Will fix this stuff up.

And that's weird, TextFieldMultiline.png should be present: https://github.com/peteratticusberg/material-ui/blob/3161ccab80b454250b3288eb7eadd4a42e850757/test/regressions/screenshots/chrome/regression-TextField/TextFieldMultiline.png

@peteratticusberg
Copy link
Contributor Author

Alright! Addressed all those comments. Had to push up a new baseline for the TextField demo page (the difference was changing the label from MultiLine --> Multiline) don't know if we need to let argo know about that.

Let me know if there's anything else you think we need to address before we merge this in.

Copy link
Member

@oliviertassinari oliviertassinari left a comment

Choose a reason for hiding this comment

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

Let's go for it, I have seen some small issue I'm gonna take care of. Thanks.

@oliviertassinari oliviertassinari added PR: Review Accepted and removed PR: Needs Review PR: needs revision The pull request can't be merged. More details is available on the code review or fails in the CI labels May 13, 2017
@oliviertassinari oliviertassinari merged commit d6685e8 into mui:next May 13, 2017
@muibot muibot added the PR: needs revision The pull request can't be merged. More details is available on the code review or fails in the CI label May 13, 2017
@oliviertassinari oliviertassinari removed the PR: needs revision The pull request can't be merged. More details is available on the code review or fails in the CI label May 13, 2017
@peteratticusberg
Copy link
Contributor Author

peteratticusberg commented May 13, 2017

Awesome. Thanks for the help with this! 🎊

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
component: text field This is the name of the generic UI component, not the React module!
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants