-
-
Notifications
You must be signed in to change notification settings - Fork 32.5k
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
Changes from 12 commits
d90eef5
e1bf713
ab6dfdd
a763d47
ac69a5b
050e3b1
0ed3174
126e94e
9456d66
9d18e60
9ad7d98
e9ede40
108c76f
c3d1de3
f0feccf
8df8a6f
31268d3
c17afe7
9d3635e
38608e9
3f9e522
ddd51d9
6bed551
94ac535
b3b0534
3812485
65e9441
2cd3fa7
31ed81a
99eddaf
2959331
8d6b599
fe7494f
1f74023
2a2577b
6b681ed
00c7e92
4bd4b41
dd21104
bbdd7db
1f6a0f9
7abc53b
b49e7b3
eb536d8
5b6d156
b8195a2
65e1924
b5fee37
d6a5ea1
5c66857
22e7650
ab8a3bf
62a615f
98df3d6
ed12ff3
da71e70
0fe9bbc
25647aa
3161cca
8f02f4e
a068813
929e6c7
3cde356
0b4509b
043d843
647d625
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -56,8 +56,15 @@ export default class TextFields extends Component { | |
defaultValue="Hello World" | ||
className={classes.input} | ||
/> | ||
<TextField | ||
id="multiLine" | ||
label="MultiLine" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
multiLine | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
rows={3} | ||
defaultValue="Default Value" | ||
className={classes.input} | ||
/> | ||
</div> | ||
); | ||
} | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -67,6 +67,12 @@ export const styleSheet = createStyleSheet('MuiInput', (theme) => { | |
appearance: 'none', | ||
}, | ||
}, | ||
multiLine: { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
resize: 'none', | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We don't want to allow users to resize? There was a problem hiding this comment. Choose a reason for hiding this commentThe 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: 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. There was a problem hiding this comment. Choose a reason for hiding this commentThe 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? There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. |
||
'line-height': 'inherit', | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No need for that style once you rebase the PR on |
||
padding: '0px', | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. padding: 0, |
||
'margin-top': '12px', | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. marginTop: 12, |
||
}, | ||
disabled: { | ||
color: theme.palette.text.disabled, | ||
cursor: 'not-allowed', | ||
|
@@ -97,6 +103,10 @@ export default class Input extends Component { | |
PropTypes.string, | ||
PropTypes.func, | ||
]), | ||
/** | ||
* The default value for the string | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
*/ | ||
defaultValue: PropTypes.string, | ||
/** | ||
* If `true`, the input will be disabled. | ||
*/ | ||
|
@@ -113,6 +123,10 @@ export default class Input extends Component { | |
* The CSS class name of the input element. | ||
*/ | ||
inputClassName: PropTypes.string, | ||
/** | ||
* If true, a textarea element will be rendered. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
*/ | ||
multiLine: PropTypes.bool, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should it be called There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yea, I actually had it as I know v1 is already going to be introducing breaking changes, so maybe we just change it to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Breaking changes aren't a concern. That new property name sounds better. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sorry, missed the cc. FWIW, I agree. |
||
/** | ||
* @ignore | ||
*/ | ||
|
@@ -133,6 +147,10 @@ export default class Input extends Component { | |
* @ignore | ||
*/ | ||
onFocus: PropTypes.func, | ||
/** | ||
* Number of rows to display when multiLine option is set to true. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
*/ | ||
rows: PropTypes.number, | ||
/** | ||
* Type of the input element. It should be a valid HTML5 input type. | ||
*/ | ||
|
@@ -152,6 +170,7 @@ export default class Input extends Component { | |
disabled: false, | ||
type: 'text', | ||
disableUnderline: false, | ||
multiLine: false, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
}; | ||
|
||
static contextTypes = { | ||
|
@@ -238,10 +257,12 @@ export default class Input extends Component { | |
const { | ||
className: classNameProp, | ||
component: ComponentProp, | ||
inputClassName: inputClassNameProp, | ||
defaultValue, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No need for that line. |
||
disabled, | ||
disableUnderline, | ||
error: errorProp, | ||
inputClassName: inputClassNameProp, | ||
multiLine, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
onBlur, // eslint-disable-line no-unused-vars | ||
onFocus, // eslint-disable-line no-unused-vars | ||
onChange, // eslint-disable-line no-unused-vars | ||
|
@@ -265,6 +286,7 @@ export default class Input extends Component { | |
}, classNameProp); | ||
|
||
const inputClassName = classNames(classes.input, { | ||
[classes.multiLine]: multiLine, | ||
[classes.underline]: !disableUnderline, | ||
[classes.disabled]: disabled, | ||
}, inputClassNameProp); | ||
|
@@ -280,6 +302,7 @@ export default class Input extends Component { | |
onFocus={this.handleFocus} | ||
onChange={this.handleChange} | ||
disabled={disabled} | ||
defaultValue={defaultValue} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 This probably isn't the best solution... Any ideas on how to improve this? Or why it might not have been working via the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I confirm, you don't need that line. |
||
aria-required={required ? true : undefined} | ||
{...other} | ||
/> | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -33,6 +33,12 @@ describe('<Input />', () => { | |
'should not have the area-required prop'); | ||
}); | ||
|
||
it('should render an <textarea /> inside the div when passed component="textarea"', () => { | ||
const wrapper = shallow(<Input component="textarea" />); | ||
const input = wrapper.find('textarea'); | ||
assert.strictEqual(input.is('textarea'), true, 'should be a <input>'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. just tried this but the test fails for |
||
}); | ||
|
||
it('should render a disabled <input />', () => { | ||
const wrapper = shallow(<Input disabled />); | ||
const input = wrapper.find('input'); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,6 +17,10 @@ export default class TextField extends Component { | |
* The CSS class name of the root element. | ||
*/ | ||
className: PropTypes.string, | ||
/** | ||
* The default value for the TextField | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
*/ | ||
defaultValue: PropTypes.string, | ||
/** | ||
* If `true`, the input will be disabled. | ||
*/ | ||
|
@@ -45,6 +49,10 @@ export default class TextField extends Component { | |
* The CSS class name of the label element. | ||
*/ | ||
labelClassName: PropTypes.string, | ||
/** | ||
* If true, a textarea element will be rendered. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
*/ | ||
multiLine: PropTypes.bool, | ||
/** | ||
* Name attribute of the `Input` element. | ||
*/ | ||
|
@@ -53,6 +61,10 @@ export default class TextField extends Component { | |
* If `true`, the label is displayed as required. | ||
*/ | ||
required: PropTypes.bool, | ||
/** | ||
* Number of rows to display when multiLine option is set to true. | ||
*/ | ||
rows: PropTypes.number, | ||
/** | ||
* Type attribute of the `Input` element. It should be a valid HTML5 input type. | ||
*/ | ||
|
@@ -81,6 +93,7 @@ export default class TextField extends Component { | |
render() { | ||
const { | ||
className, | ||
defaultValue, | ||
disabled, | ||
error, | ||
inputClassName, | ||
|
@@ -90,6 +103,8 @@ export default class TextField extends Component { | |
name, | ||
required, | ||
type, | ||
multiLine, | ||
rows, | ||
value, | ||
...other | ||
} = this.props; | ||
|
@@ -108,10 +123,14 @@ export default class TextField extends Component { | |
)} | ||
<Input | ||
className={inputClassName} | ||
value={value} | ||
component={multiLine ? 'textarea' : 'input'} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm wondering, shouldn't it be the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yea I think that's right. I'll change this. There was a problem hiding this comment. Choose a reason for hiding this commentThe 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
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. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have two thoughs here:
|
||
defaultValue={defaultValue} | ||
disabled={disabled} | ||
multiLine={multiLine} | ||
name={name} | ||
rows={rows} | ||
type={type} | ||
disabled={disabled} | ||
value={value} | ||
{...inputProps} | ||
/> | ||
</FormControl> | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -32,6 +32,11 @@ describe('<TextField />', () => { | |
assert.strictEqual(wrapper.childAt(0).is('Input'), true); | ||
}); | ||
|
||
it('should render an Input with component="textarea" when passed the multiLine prop', () => { | ||
wrapper = shallow(<TextField multiLine />); | ||
assert.strictEqual(wrapper.childAt(0).prop('component'), 'textarea'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I find the following more idiomatic, but do it as you prefer .props().component |
||
}); | ||
|
||
it('should pass inputClassName to the Input as className', () => { | ||
wrapper.setProps({ inputClassName: 'foo' }); | ||
assert.strictEqual(wrapper.find('Input').hasClass('foo'), true); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
// @flow weak | ||
|
||
import React from 'react'; | ||
import TextField from 'material-ui/TextField'; | ||
|
||
export default function TextFieldError() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
return ( | ||
<div> | ||
<TextField | ||
label="Foo" | ||
multiLine | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. multiline |
||
rows={4} | ||
value="Default text" | ||
/> | ||
</div> | ||
); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Multiline
?