Repository: mui/material-ui (TypeScript)
Date: 2018-07-27 17:03:10+00:00
Task type: Feature

Issue:
How to position Switch label to the left of the switch?
- [x] This is a v1.x issue (v0.x is no longer maintained).
- [x] I have searched the [issues](https://github.com/mui-org/material-ui/issues) of this repository and believe that this is not a duplicate.

[The examples here](https://material-ui.com/demos/selection-controls/) demonstrate how to add a label to various forms of input, including the `Switch` component.

Unfortunately, every single example on that page that includes a label has it positioned to the right of the component. I've looked through the props of `FormControlLabel`, and there doesn't seem to be any option that allows me to change this. In fact, looking at the code of `FormControlLabel`, it seems to be hard-coded his way.

I was able to work around this by setting the Label's direction to rtl (and setting the Switch's direction back to ltr):
```
import React from "react";
import styled from "react-emotion";
import FormControlLabel from "@material-ui/core/FormControlLabel";
import Switch from "@material-ui/core/Switch";

const StyledLabel = styled(FormControlLabel)`
  direction: ${({ rtl }) => rtl && "rtl"};
  margin: 0;
`;

const StyledSwitch = styled(Switch)`
  direction: ltr;
`;

export default ({ label, rtl, ...props }) => (
  <StyledLabel rtl={rtl} control={<StyledSwitch {...props} />} label={label} />
);
```
But this feels very hacky and potentially unstable to me.

Is there any way I can have a `Switch` with its label on the left without resorting to `rtl` hacks? If so, can it please be documented? If not, please consider this a feature request.


Issue discussion:
`FormControlLabel` wasn't designed with this use case in mind. You would need to write custom CSS to get this behavior.
I have added the `waiting for users upvotes` tag. I'm closing the issue as I'm not sure people are looking for such abstraction. So please upvote this issue if you are. We will prioritize our effort based on the number of upvotes.
Hi, 
I hope I did the correct thing to upvote by using the thumbs up emoji.
Actually, everywhere in the Material design guidelines the switches are on the right of the label, so it would be very helpful to have an easy way to do this...
I too would like this. imagine that you have a pane to view some page of results, and you want a select all switch at the top right. You want the label on the left to nestle nicely into the top right corner. this is totally in line with mobile first design and hey, bonus! it works on a desktop layout too!

I've +1'ed the ticket! Material-UI is a component lib, and regardless if we "think" we would do something, the option to show a form label on one side or the other is ultimately a design decision which a flexible and powerful framework should be able to offer. *wink* :)
Alright, we can add a property to change the order of the control and the label:
https://github.com/mui-org/material-ui/blob/b3564a767135b933146f7fe73e3a34b14950c782/packages/material-ui/src/FormControlLabel/FormControlLabel.js#L75-L90
It should be easy to implement. In the mean time, you don't have to use the `FormControlLabel` component. You should be able to inverse the order in your code quite easily.
@oliviertassinari Any thoughts on prop name?
@mbrookes Not really, maybe we could follow the Tooltip wording. It's important to have a wording that works with right to left and left to right direction. 
What about:
```ts
controlPlacement?: 'start' : 'end';
```
or
```ts
labelPlacement?: 'start' : 'end';
```
Thanks for repoening :-)

Why not make it a boolean? e.g. "controlBeforeLabel"

Hmm... good point on LTR, although while Tooltip respects the prop wording (`placement="left"` is always on the left, even for RTL), it would seem more practical if the positioning was reversed for RTL, but then the naming becomes confusing. (That's a whole separate issue though). `start` / `end` work as expected.
> Why not make it a boolean? e.g. "controlBeforeLabel"

@caroe233 So we can accept more values, like top, bottom or center.
I haven't tried it with `FormControlLabel`, but Slider can potentially take two labels, so it might be interesting to try to accomadate that:

![image](https://user-images.githubusercontent.com/357702/42328031-3536484a-8065-11e8-9960-f096247b9b58.png)

it is compatible with the spirit of a switch:

```
OFF --o ON
OFF o-- ON
```

Solution patch:
diff --git a/docs/src/pages/demos/selection-controls/CheckboxesGroup.js b/docs/src/pages/demos/selection-controls/CheckboxesGroup.js
--- a/docs/src/pages/demos/selection-controls/CheckboxesGroup.js
+++ b/docs/src/pages/demos/selection-controls/CheckboxesGroup.js
@@ -1,4 +1,6 @@
 import React from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
 import FormLabel from '@material-ui/core/FormLabel';
 import FormControl from '@material-ui/core/FormControl';
 import FormGroup from '@material-ui/core/FormGroup';
@@ -6,11 +8,20 @@ import FormControlLabel from '@material-ui/core/FormControlLabel';
 import FormHelperText from '@material-ui/core/FormHelperText';
 import Checkbox from '@material-ui/core/Checkbox';
 
+const styles = theme => ({
+  root: {
+    display: 'flex',
+  },
+  formControl: {
+    margin: theme.spacing.unit * 3,
+  },
+});
+
 class CheckboxesGroup extends React.Component {
   state = {
     gilad: true,
     jason: false,
-    antoine: true,
+    antoine: false,
   };
 
   handleChange = name => event => {
@@ -18,45 +29,75 @@ class CheckboxesGroup extends React.Component {
   };
 
   render() {
+    const { classes } = this.props;
+    const { gilad, jason, antoine } = this.state;
+    const error = Object.values(this.state).filter(v => v).length !== 2;
+
     return (
-      <FormControl component="fieldset">
-        <FormLabel component="legend">Assign responsibility</FormLabel>
-        <FormGroup>
-          <FormControlLabel
-            control={
-              <Checkbox
-                checked={this.state.gilad}
-                onChange={this.handleChange('gilad')}
-                value="gilad"
-              />
-            }
-            label="Gilad Gray"
-          />
-          <FormControlLabel
-            control={
-              <Checkbox
-                checked={this.state.jason}
-                onChange={this.handleChange('jason')}
-                value="jason"
-              />
-            }
-            label="Jason Killian"
-          />
-          <FormControlLabel
-            control={
-              <Checkbox
-                checked={this.state.antoine}
-                onChange={this.handleChange('antoine')}
-                value="antoine"
-              />
-            }
-            label="Antoine Llorca"
-          />
-        </FormGroup>
-        <FormHelperText>Be careful</FormHelperText>
-      </FormControl>
+      <div className={classes.root}>
+        <FormControl component="fieldset" className={classes.formControl}>
+          <FormLabel component="legend">Assign responsibility</FormLabel>
+          <FormGroup>
+            <FormControlLabel
+              control={
+                <Checkbox checked={gilad} onChange={this.handleChange('gilad')} value="gilad" />
+              }
+              label="Gilad Gray"
+            />
+            <FormControlLabel
+              control={
+                <Checkbox checked={jason} onChange={this.handleChange('jason')} value="jason" />
+              }
+              label="Jason Killian"
+            />
+            <FormControlLabel
+              control={
+                <Checkbox
+                  checked={antoine}
+                  onChange={this.handleChange('antoine')}
+                  value="antoine"
+                />
+              }
+              label="Antoine Llorca"
+            />
+          </FormGroup>
+          <FormHelperText>Be careful</FormHelperText>
+        </FormControl>
+        <FormControl required error={error} component="fieldset" className={classes.formControl}>
+          <FormLabel component="legend">Pick two</FormLabel>
+          <FormGroup>
+            <FormControlLabel
+              control={
+                <Checkbox checked={gilad} onChange={this.handleChange('gilad')} value="gilad" />
+              }
+              label="Gilad Gray"
+            />
+            <FormControlLabel
+              control={
+                <Checkbox checked={jason} onChange={this.handleChange('jason')} value="jason" />
+              }
+              label="Jason Killian"
+            />
+            <FormControlLabel
+              control={
+                <Checkbox
+                  checked={antoine}
+                  onChange={this.handleChange('antoine')}
+                  value="antoine"
+                />
+              }
+              label="Antoine Llorca"
+            />
+          </FormGroup>
+          <FormHelperText>You can display an error</FormHelperText>
+        </FormControl>
+      </div>
     );
   }
 }
 
-export default CheckboxesGroup;
+CheckboxesGroup.propTypes = {
+  classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(CheckboxesGroup);
diff --git a/docs/src/pages/demos/selection-controls/RadioButtonsGroup.js b/docs/src/pages/demos/selection-controls/RadioButtonsGroup.js
--- a/docs/src/pages/demos/selection-controls/RadioButtonsGroup.js
+++ b/docs/src/pages/demos/selection-controls/RadioButtonsGroup.js
@@ -34,7 +34,7 @@ class RadioButtonsGroup extends React.Component {
 
     return (
       <div className={classes.root}>
-        <FormControl component="fieldset" required className={classes.formControl}>
+        <FormControl component="fieldset" className={classes.formControl}>
           <FormLabel component="legend">Gender</FormLabel>
           <RadioGroup
             aria-label="Gender"
@@ -54,7 +54,7 @@ class RadioButtonsGroup extends React.Component {
             />
           </RadioGroup>
         </FormControl>
-        <FormControl component="fieldset" required error className={classes.formControl}>
+        <FormControl component="fieldset" className={classes.formControl}>
           <FormLabel component="legend">Gender</FormLabel>
           <RadioGroup
             aria-label="gender"
@@ -63,17 +63,33 @@ class RadioButtonsGroup extends React.Component {
             value={this.state.value}
             onChange={this.handleChange}
           >
-            <FormControlLabel value="female" control={<Radio color="primary" />} label="Female" />
-            <FormControlLabel value="male" control={<Radio color="primary" />} label="Male" />
-            <FormControlLabel value="other" control={<Radio color="primary" />} label="Other" />
+            <FormControlLabel
+              value="female"
+              control={<Radio color="primary" />}
+              label="Female"
+              labelPlacement="start"
+            />
+            <FormControlLabel
+              value="male"
+              control={<Radio color="primary" />}
+              label="Male"
+              labelPlacement="start"
+            />
+            <FormControlLabel
+              value="other"
+              control={<Radio color="primary" />}
+              label="Other"
+              labelPlacement="start"
+            />
             <FormControlLabel
               value="disabled"
               disabled
               control={<Radio />}
               label="(Disabled option)"
+              labelPlacement="start"
             />
           </RadioGroup>
-          <FormHelperText>You can display an error</FormHelperText>
+          <FormHelperText>labelPlacement start</FormHelperText>
         </FormControl>
       </div>
     );
diff --git a/packages/material-ui/src/FormControlLabel/FormControlLabel.d.ts b/packages/material-ui/src/FormControlLabel/FormControlLabel.d.ts
--- a/packages/material-ui/src/FormControlLabel/FormControlLabel.d.ts
+++ b/packages/material-ui/src/FormControlLabel/FormControlLabel.d.ts
@@ -14,10 +14,11 @@ export interface FormControlLabelProps
   label: React.ReactNode;
   name?: string;
   onChange?: (event: React.ChangeEvent<{}>, checked: boolean) => void;
+  labelPlacement?: 'end' | 'start';
   value?: string;
 }
 
-export type FormControlLabelClassKey = 'root' | 'disabled' | 'label';
+export type FormControlLabelClassKey = 'root' | 'start' | 'disabled' | 'label';
 
 declare const FormControlLabel: React.ComponentType<FormControlLabelProps>;
 
diff --git a/packages/material-ui/src/FormControlLabel/FormControlLabel.js b/packages/material-ui/src/FormControlLabel/FormControlLabel.js
--- a/packages/material-ui/src/FormControlLabel/FormControlLabel.js
+++ b/packages/material-ui/src/FormControlLabel/FormControlLabel.js
@@ -22,6 +22,10 @@ export const styles = theme => ({
       cursor: 'default',
     },
   },
+  /* Styles applied to the root element if `position="start"`. */
+  start: {
+    flexDirection: 'row-reverse',
+  },
   /* Styles applied to the root element if `disabled={true}`. */
   disabled: {},
   /* Styles applied to the label's Typography component. */
@@ -45,6 +49,7 @@ function FormControlLabel(props, context) {
     disabled: disabledProp,
     inputRef,
     label,
+    labelPlacement,
     name,
     onChange,
     value,
@@ -74,6 +79,7 @@ function FormControlLabel(props, context) {
       className={classNames(
         classes.root,
         {
+          [classes.start]: labelPlacement === 'start',
           [classes.disabled]: disabled,
         },
         classNameProp,
@@ -121,6 +127,10 @@ FormControlLabel.propTypes = {
    * The text to be used in an enclosing label element.
    */
   label: PropTypes.node,
+  /**
+   * The position of the label.
+   */
+  labelPlacement: PropTypes.oneOf(['end', 'start']),
   /*
    * @ignore
    */
@@ -139,6 +149,10 @@ FormControlLabel.propTypes = {
   value: PropTypes.string,
 };
 
+FormControlLabel.defaultProps = {
+  labelPlacement: 'end',
+};
+
 FormControlLabel.contextTypes = {
   muiFormControl: PropTypes.object,
 };
diff --git a/pages/api/form-control-label.md b/pages/api/form-control-label.md
--- a/pages/api/form-control-label.md
+++ b/pages/api/form-control-label.md
@@ -22,6 +22,7 @@ Use this component if you want to display an extra label.
 | <span class="prop-name">disabled</span> | <span class="prop-type">bool |   | If `true`, the control will be disabled. |
 | <span class="prop-name">inputRef</span> | <span class="prop-type">union:&nbsp;func&nbsp;&#124;<br>&nbsp;object<br> |   | Use that property to pass a ref callback to the native input component. |
 | <span class="prop-name">label</span> | <span class="prop-type">node |   | The text to be used in an enclosing label element. |
+| <span class="prop-name">labelPlacement</span> | <span class="prop-type">enum:&nbsp;'end'&nbsp;&#124;<br>&nbsp;'start'<br> | <span class="prop-default">'end'</span> | The position of the label. |
 | <span class="prop-name">name</span> | <span class="prop-type">string |   |  |
 | <span class="prop-name">onChange</span> | <span class="prop-type">func |   | Callback fired when the state is changed.<br><br>**Signature:**<br>`function(event: object, checked: boolean) => void`<br>*event:* The event source of the callback. You can pull out the new value by accessing `event.target.checked`.<br>*checked:* The `checked` value of the switch |
 | <span class="prop-name">value</span> | <span class="prop-type">string |   | The value of the component. |
@@ -37,6 +38,7 @@ This property accepts the following keys:
 | Name | Description |
 |:-----|:------------|
 | <span class="prop-name">root</span> | Styles applied to the root element.
+| <span class="prop-name">start</span> | Styles applied to the root element if `position="start"`.
 | <span class="prop-name">disabled</span> | Styles applied to the root element if `disabled={true}`.
 | <span class="prop-name">label</span> | Styles applied to the label's Typography component.
 


Test patch:
diff --git a/packages/material-ui/src/FormControlLabel/FormControlLabel.test.js b/packages/material-ui/src/FormControlLabel/FormControlLabel.test.js
--- a/packages/material-ui/src/FormControlLabel/FormControlLabel.test.js
+++ b/packages/material-ui/src/FormControlLabel/FormControlLabel.test.js
@@ -55,6 +55,15 @@ describe('<FormControlLabel />', () => {
     });
   });
 
+  describe('prop: labelPlacement', () => {
+    it('should disable have the `start` class', () => {
+      const wrapper = shallow(
+        <FormControlLabel label="Pizza" labelPlacement="start" control={<div />} />,
+      );
+      assert.strictEqual(wrapper.hasClass(classes.start), true);
+    });
+  });
+
   it('should mount without issue', () => {
     const wrapper = mount(<FormControlLabel label="Pizza" control={<Checkbox />} />);
     assert.strictEqual(wrapper.type(), FormControlLabel);