Skip to content

Commit

Permalink
[TextField] Make it meet the guidelines (#6566)
Browse files Browse the repository at this point in the history
* Adjusted styles accordingto specs, fixed #6425

* Fixes, simplified styles

* Removed dead `TextFieldLabel` component as for #6580

* Added colors according to specs, `InputLabel` disabled prop

* Avoiding label flicker and blurry text in webkit browsers

* More smooth label animation.

* More smooth font-size animation

* Proper error color, added `FormHelperText` component

* FormHelperText docs

* Fixed lint errors

* Added new component to styles order, fixes

* Fixed disabled border style

* FormHelperText exports

* Remove unused TextFieldLabel

* Form helper fixes, test, docs

* TextField tests for FormHelperText

* Get rid of TextFieldLabel.md, added tests for InputLabel

* Added tests for FormControl

* Make dirty if `defaultValue` is set

* Fix helper text font

* Fix label "flicker" in webkit browsers.

* Use `theme.spacing.unit` instead of number values

* Disabled composed text field demo

* Fixed type check

* Fixed type check error

* Make `ComposedTextFiled` accept disabled prop

* Fixed lint

* Fixed docs and input

* Exposed FormHelperTextProps and InputLabelProps

* Fixed docs

* Fixed multiline styles

* Placeholder + Label behaviour

* Fixes

Placeholder styles look ugly. laceholder prefixing is to be impplemented
in next JSS versions.

* Fixed lint errors

* Typo fixes

* Typo fixes 2
  • Loading branch information
kybarg authored and oliviertassinari committed May 30, 2017
1 parent 08075b1 commit 1c96695
Show file tree
Hide file tree
Showing 28 changed files with 424 additions and 176 deletions.
1 change: 1 addition & 0 deletions docs/src/pages/component-api/Form/FormControl.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ Provides context such as dirty/focused/error/required for form inputs.
|:-----|:-----|:--------|:------------|
| children | node | | The contents of the form control. |
| classes | object | | Useful to extend the style applied to components. |
| disabled | bool | false | If `true`, the label should be displayed in an disabled state. |
| error | bool | false | If `true`, the label should be displayed in an error state. |
| required | bool | false | If `true`, the label will indicate that the input is required. |

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# TextFieldLabel
# FormHelperText



Expand All @@ -7,24 +7,22 @@
|:-----|:-----|:--------|:------------|
| children | node | | The content of the component. |
| classes | object | | Useful to extend the style applied to components. |
| disableAnimation | bool | false | If `true`, the transition animation is disabled. |
| error | bool | | If `true`, the label is displayed in an error state. |
| focused | bool | | If `true`, the input of this label is focused. |
| required | bool | | If `true`, the label will indicate that the input is required. |
| shrink | bool | false | If `true`, the label is shrunk. |
| className | string | | The CSS class name of the root element. |
| disabled | bool | | Whether the helper text should be displayed in an disabled state. |
| error | bool | | Whether the helper text should be displayed in an error state. |

Any other properties supplied will be spread to the root element.
## Classes

You can overrides all the class names injected by Material-UI thanks to the `classes` property.
This property accepts the following keys:
- `root`
- `shrink`
- `animated`
- `error`
- `disabled`

Have a look at [overriding with class names](/customization/overrides#overriding-with-class-names)
section for more detail.

If using the `overrides` key of the theme as documented
[here](/customization/themes#customizing-all-instances-of-a-component-type),
you need to use the following style sheet name: `MuiTextFieldLabel`.
you need to use the following style sheet name: `MuiFormHelperText`.
2 changes: 2 additions & 0 deletions docs/src/pages/component-api/Form/FormLabel.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
|:-----|:-----|:--------|:------------|
| children | node | | The content of the component. |
| classes | object | | Useful to extend the style applied to components. |
| disabled | bool | | Whether the label should be displayed in an disabled state. |
| error | bool | | Whether the label should be displayed in an error state. |
| focused | bool | | If `true`, the input of this label is focused (used by `FormGroup` components). |
| required | bool | | If `true`, the label will indicate that the input is required. |
Expand All @@ -19,6 +20,7 @@ This property accepts the following keys:
- `root`
- `focused`
- `error`
- `disabled`

Have a look at [overriding with class names](/customization/overrides#overriding-with-class-names)
section for more detail.
Expand Down
2 changes: 1 addition & 1 deletion docs/src/pages/component-api/Input/Input.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
| className | string | | The CSS class name of the wrapper element. |
| component | union:&nbsp;string<br>&nbsp;func<br> | | The component used for the root node. Either a string to use a DOM element or a component. It's an `input` by default. |
| defaultValue | string | | The default value of the `Input` element. |
| disabled | bool | false | If `true`, the input will be disabled. |
| disabled | bool | | If `true`, the input will be disabled. |
| disableUnderline | bool | false | If `true`, the input will not have an underline. |
| error | bool | | If `true`, the input will indicate an error. |
| id | string | | |
Expand Down
2 changes: 2 additions & 0 deletions docs/src/pages/component-api/Input/InputLabel.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
| children | node | | The contents of the `InputLabel`. |
| classes | object | | Useful to extend the style applied to components. |
| disableAnimation | bool | false | If `true`, the transition animation is disabled. |
| disabled | bool | false | If `true`, apply disabled class. |
| error | bool | | If `true`, the label will be displayed in an error state. |
| focused | bool | | If `true`, the input of this label is focused. |
| required | bool | | if `true`, the label will indicate that the input is required. |
Expand All @@ -22,6 +23,7 @@ This property accepts the following keys:
- `formControl`
- `shrink`
- `animated`
- `disabled`

Have a look at [overriding with class names](/customization/overrides#overriding-with-class-names)
section for more detail.
Expand Down
6 changes: 3 additions & 3 deletions docs/src/pages/component-api/Progress/CircularProgress.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@
| Name | Type | Default | Description |
|:-----|:-----|:--------|:------------|
| classes | object | | Useful to extend the style applied to components. |
| size | number | 40 | The size of the circle. |
| mode | enum:<br>&nbsp;'determinate'<br>&nbsp;'indeterminate' | 'indeterminate' | The mode of show your progress. Indeterminate for when there is no value for progress. Determinate for controlled progress value. |
| max | number | 100 | The max value of progress in determinate mode. |
| min | number | 0 | TThe min value of progress in determinate mode. |
| min | number | 0 | The min value of progress in determinate mode. |
| mode | enum:&nbsp;'determinate'<br>&nbsp;'indeterminate'<br> | 'indeterminate' | The mode of show your progress. Indeterminate for when there is no value for progress. Determinate for controlled progress value. |
| size | number | 40 | The size of the circle. |
| value | number | 0 | The value of progress in determinate mode. |

Any other properties supplied will be spread to the root element.
Expand Down
4 changes: 4 additions & 0 deletions docs/src/pages/component-api/TextField/TextField.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,13 @@
| defaultValue | string | | The default value of the `Input` element. |
| disabled | bool | | If `true`, the input will be disabled. |
| error | bool | | If `true`, the label will be displayed in an error state. |
| helperText | node | | The helper text content. |
| helperTextClassName | string | | The CSS class name of the helper text element. |
| FormHelperTextProps | object | | Properties applied to the `FormHelperText` element. |
| id | string | | |
| inputClassName | string | | The CSS class name of the `input` element. |
| InputClassName | string | | The CSS class name of the `Input` element. |
| InputLabelProps | object | | Properties applied to the `InputLabel` element. |
| inputProps | object | | Properties applied to the `input` element. |
| InputProps | object | | Properties applied to the `Input` element. |
| inputRef | function | | Use that property to pass a ref callback to the native input component. |
Expand Down
22 changes: 22 additions & 0 deletions docs/src/pages/component-demos/text-fields/ComposedTextField.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { withStyles, createStyleSheet } from 'material-ui/styles';
import Input from 'material-ui/Input';
import InputLabel from 'material-ui/Input/InputLabel';
import FormControl from 'material-ui/Form/FormControl';
import FormHelperText from 'material-ui/Form/FormHelperText';

const styleSheet = createStyleSheet('ComposedTextField', theme => ({
container: {
Expand Down Expand Up @@ -37,6 +38,27 @@ class ComposedTextField extends Component {
</InputLabel>
<Input id="name" value={this.state.name} onChange={this.handleChange} />
</FormControl>
<FormControl className={classes.input}>
<InputLabel htmlFor="name">
Name
</InputLabel>
<Input id="name" value={this.state.name} onChange={this.handleChange} />
<FormHelperText>Some important helper text</FormHelperText>
</FormControl>
<FormControl className={classes.input} disabled>
<InputLabel htmlFor="name">
Name
</InputLabel>
<Input id="name" value={this.state.name} onChange={this.handleChange} />
<FormHelperText>Some important helper text</FormHelperText>
</FormControl>
<FormControl className={classes.input} error>
<InputLabel htmlFor="name">
Name
</InputLabel>
<Input id="name" value={this.state.name} onChange={this.handleChange} />
<FormHelperText>Some important helper text</FormHelperText>
</FormControl>
</div>
);
}
Expand Down
16 changes: 16 additions & 0 deletions docs/src/pages/component-demos/text-fields/TextFields.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,22 @@ class TextFields extends Component {
defaultValue="2017-05-24"
className={classes.input}
/>
<TextField
id="helperText"
label="Helper text"
type="text"
defaultValue="Default Value"
className={classes.input}
helperText="Some important text"
/>
<TextField
id="placeholder"
label="Label"
className={classes.input}
type="text"
InputProps={{ placeholder: 'Placeholder' }}
helperText="Helper text"
/>
</div>
);
}
Expand Down
2 changes: 1 addition & 1 deletion docs/src/pages/component-demos/text-fields/text-fields.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
components: Input, TextField, TextFieldLabel
components: Input, TextField, FormHelperText
---

# Text Fields
Expand Down
20 changes: 18 additions & 2 deletions src/Form/FormControl.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
// @flow weak

import React, { Component } from 'react';
import React, { Children, Component } from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import { createStyleSheet } from 'jss-theme-reactor';
import withStyles from '../styles/withStyles';
import { isDirty } from '../Input/Input';

export const styleSheet = createStyleSheet('MuiFormControl', {
root: {
Expand All @@ -22,6 +23,7 @@ export const styleSheet = createStyleSheet('MuiFormControl', {
*/
class FormControl extends Component {
static defaultProps = {
disabled: false,
error: false,
required: false,
};
Expand All @@ -32,12 +34,13 @@ class FormControl extends Component {
};

getChildContext() {
const { error, required } = this.props;
const { disabled, error, required } = this.props;
const { dirty, focused } = this.state;

return {
muiFormControl: {
dirty,
disabled,
error,
focused,
required,
Expand All @@ -49,6 +52,14 @@ class FormControl extends Component {
};
}

componentWillMount() {
Children.forEach(this.props.children, child => {
if (child && child.type && child.type.muiName === 'Input' && isDirty(child.props)) {
this.setState({ dirty: true });
}
});
}

handleFocus = () => {
if (this.props.onFocus) {
this.props.onFocus();
Expand Down Expand Up @@ -84,6 +95,7 @@ class FormControl extends Component {
children,
classes,
className,
disabled, // eslint-disable-line no-unused-vars
error, // eslint-disable-line no-unused-vars
...other
} = this.props;
Expand Down Expand Up @@ -114,6 +126,10 @@ FormControl.propTypes = {
* @ignore
*/
className: PropTypes.string,
/**
* If `true`, the label, input and helper text should be displayed in a disabled state.
*/
disabled: PropTypes.bool,
/**
* If `true`, the label should be displayed in an error state.
*/
Expand Down
13 changes: 13 additions & 0 deletions src/Form/FormControl.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import React from 'react';
import { spy } from 'sinon';
import { assert } from 'chai';
import { createShallow } from '../test-utils';
import Input from '../Input';
import FormControl, { styleSheet } from './FormControl';

describe('<FormControl />', () => {
Expand Down Expand Up @@ -47,6 +48,18 @@ describe('<FormControl />', () => {
});
});

describe('should be dirty if has input with value set', () => {
let wrapper;

beforeEach(() => {
wrapper = shallow(<FormControl><Input value="bar" /></FormControl>);
});

it('should be dirty initially', () => {
assert.strictEqual(wrapper.state().dirty, true);
});
});

describe('muiFormControl child context', () => {
let wrapper;
let muiFormControlContext;
Expand Down
90 changes: 90 additions & 0 deletions src/Form/FormHelperText.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
// @flow weak

import React from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import { createStyleSheet } from 'jss-theme-reactor';
import withStyles from '../styles/withStyles';

export const styleSheet = createStyleSheet('MuiFormHelperText', theme => ({
root: {
color: theme.palette.input.helperText,
fontFamily: theme.typography.fontFamily,
fontSize: 12,
lineHeight: 1.4,
margin: 0,
},
error: {
color: theme.palette.error.A400,
},
disabled: {
color: theme.palette.input.disabled,
},
}));

function FormHelperText(props, context) {
const {
children,
classes,
className: classNameProp,
disabled: disabledProp,
error: errorProp,
...other
} = props;
const { muiFormControl } = context;

let disabled = disabledProp;
let error = errorProp;

if (muiFormControl && typeof disabled === 'undefined') {
disabled = muiFormControl.disabled;
}

if (muiFormControl && typeof error === 'undefined') {
error = muiFormControl.error;
}

const className = classNames(
classes.root,
{
[classes.disabled]: disabled,
[classes.error]: error,
},
classNameProp,
);

return (
<p className={className} {...other}>
{children}
</p>
);
}

FormHelperText.propTypes = {
/**
* The content of the component.
*/
children: PropTypes.node,
/**
* Useful to extend the style applied to components.
*/
classes: PropTypes.object.isRequired,
/**
* @ignore
*/
className: PropTypes.string,
/**
* If `true`, the helper text should be displayed in a disabled state.
*/
disabled: PropTypes.bool,
/**
* If `true`, helper text should be displayed in an error state.
*/
error: PropTypes.bool,
};

FormHelperText.contextTypes = {
muiFormControl: PropTypes.object,
};

export default withStyles(styleSheet)(FormHelperText);
Loading

0 comments on commit 1c96695

Please sign in to comment.