Repository: mui/material-ui (TypeScript)
Date: 2021-04-22 10:33:24+00:00
Task type: Feature

Issue:
FormControlLabel should offer typography options
FormControlLabel offers no option to customize the typography variant. 

https://github.com/mui-org/material-ui/blob/master/packages/material-ui/src/FormControlLabel/FormControlLabel.js#L104

- [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.

## Summary 💡

I would suggest FormControlLabel should accept the following additional properties:

 + disableTypography
    + this will allow people to pass in their own typography element and it will still recieve the benefits of the "checked" css (which only affects the first level component)
+ labelTypographyProps
    + in the style of ListItemText, these props would be spread to the typography element for customization


## Examples 🌈

similar setup in ListItemText

https://github.com/mui-org/material-ui/blob/master/packages/material-ui/src/ListItemText/ListItemText.js#L56

## Motivation 🔦

We use material-ui as a basis for our own component library. so although we use Typography, we use it with restricted options and / or an altered typography set. In the perfect world, we will use `disableTypography` and pass 
(<Typography variant="body2">{label}/Typography>) in order to follow our own guidelines. It seemed odd that there were no options in this component compared to others



Issue discussion:
We have faced a similar problem in the past. So far (in the history of the project), we have used 4 options:

1. Nesting of two typography, one from the component, another from the developer. 
2. Disabled prop https://github.com/mui-org/material-ui/blob/018118626718d2f4c86212699912700682d80956/packages/material-ui/src/DialogTitle/DialogTitle.js#L56
3. Autodisable https://github.com/mui-org/material-ui/blob/018118626718d2f4c86212699912700682d80956/packages/material-ui/src/ListItemText/ListItemText.js#L94
4. Spread of extra props https://github.com/mui-org/material-ui/blob/018118626718d2f4c86212699912700682d80956/packages/material-ui/src/ListItemText/ListItemText.js#L101 

Solution patch:
diff --git a/docs/pages/api-docs/form-control-label.json b/docs/pages/api-docs/form-control-label.json
--- a/docs/pages/api-docs/form-control-label.json
+++ b/docs/pages/api-docs/form-control-label.json
@@ -3,7 +3,9 @@
     "control": { "type": { "name": "element" }, "required": true },
     "checked": { "type": { "name": "bool" } },
     "classes": { "type": { "name": "object" } },
+    "componentProps": { "type": { "name": "object" }, "default": "{}" },
     "disabled": { "type": { "name": "bool" } },
+    "disableTypography": { "type": { "name": "bool" } },
     "inputRef": { "type": { "name": "custom", "description": "ref" } },
     "label": { "type": { "name": "node" } },
     "labelPlacement": {
diff --git a/docs/translations/api-docs/form-control-label/form-control-label.json b/docs/translations/api-docs/form-control-label/form-control-label.json
--- a/docs/translations/api-docs/form-control-label/form-control-label.json
+++ b/docs/translations/api-docs/form-control-label/form-control-label.json
@@ -3,8 +3,10 @@
   "propDescriptions": {
     "checked": "If <code>true</code>, the component appears selected.",
     "classes": "Override or extend the styles applied to the component. See <a href=\"#css\">CSS API</a> below for more details.",
+    "componentProps": "The props used for each slot inside.",
     "control": "A control element. For instance, it can be a <code>Radio</code>, a <code>Switch</code> or a <code>Checkbox</code>.",
     "disabled": "If <code>true</code>, the control is disabled.",
+    "disableTypography": "If <code>true</code>, the label is rendered as it is passed without an additional typography node.",
     "inputRef": "Pass a ref to the <code>input</code> element.",
     "label": "The text to be used in an enclosing label element.",
     "labelPlacement": "The position of the label.",
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
@@ -1,6 +1,7 @@
 import * as React from 'react';
 import { SxProps } from '@material-ui/system';
 import { Theme, InternalStandardProps as StandardProps } from '..';
+import { TypographyProps } from '../Typography';
 
 export interface FormControlLabelProps
   extends StandardProps<React.LabelHTMLAttributes<HTMLLabelElement>, 'children' | 'onChange'> {
@@ -25,6 +26,18 @@ export interface FormControlLabelProps
     /** Styles applied to the label's Typography component. */
     label?: string;
   };
+  /**
+   * The props used for each slot inside.
+   * @default {}
+   */
+  componentProps?: {
+    /**
+     * Props applied to the Typography wrapper of the passed label.
+     * This is unused if disableTpography is true.
+     * @default {}
+     */
+    typography?: TypographyProps;
+  };
   /**
    * A control element. For instance, it can be a `Radio`, a `Switch` or a `Checkbox`.
    */
@@ -33,6 +46,10 @@ export interface FormControlLabelProps
    * If `true`, the control is disabled.
    */
   disabled?: boolean;
+  /**
+   * If `true`, the label is rendered as it is passed without an additional typography node.
+   */
+  disableTypography?: boolean;
   /**
    * Pass a ref to the `input` element.
    */
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
@@ -79,8 +79,10 @@ const FormControlLabel = React.forwardRef(function FormControlLabel(inProps, ref
   const {
     checked,
     className,
+    componentProps = {},
     control,
     disabled: disabledProp,
+    disableTypography,
     inputRef,
     label,
     labelPlacement = 'end',
@@ -127,9 +129,13 @@ const FormControlLabel = React.forwardRef(function FormControlLabel(inProps, ref
       {...other}
     >
       {React.cloneElement(control, controlProps)}
-      <Typography component="span" className={classes.label}>
-        {label}
-      </Typography>
+      {label.type === Typography || disableTypography ? (
+        label
+      ) : (
+        <Typography component="span" className={classes.label} {...componentProps.typography}>
+          {label}
+        </Typography>
+      )}
     </FormControlLabelRoot>
   );
 });
@@ -151,6 +157,11 @@ FormControlLabel.propTypes /* remove-proptypes */ = {
    * @ignore
    */
   className: PropTypes.string,
+  /**
+   * The props used for each slot inside.
+   * @default {}
+   */
+  componentProps: PropTypes.object,
   /**
    * A control element. For instance, it can be a `Radio`, a `Switch` or a `Checkbox`.
    */
@@ -159,6 +170,10 @@ FormControlLabel.propTypes /* remove-proptypes */ = {
    * If `true`, the control is disabled.
    */
   disabled: PropTypes.bool,
+  /**
+   * If `true`, the label is rendered as it is passed without an additional typography node.
+   */
+  disableTypography: PropTypes.bool,
   /**
    * Pass a ref to the `input` element.
    */


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
@@ -6,6 +6,7 @@ import FormControlLabel, {
 } from '@material-ui/core/FormControlLabel';
 import Checkbox from '@material-ui/core/Checkbox';
 import FormControl from '@material-ui/core/FormControl';
+import Typography from '@material-ui/core/Typography';
 
 describe('<FormControlLabel />', () => {
   const render = createClientRender();
@@ -90,6 +91,52 @@ describe('<FormControlLabel />', () => {
     });
   });
 
+  describe('prop: disableTypography', () => {
+    it('should not add a typography component', () => {
+      const { getByTestId } = render(
+        <FormControlLabel
+          label={<div name="test">Pizza</div>}
+          disableTypography
+          data-testid="FormControlLabel"
+          control={<div />}
+        />,
+      );
+
+      expect(getByTestId('FormControlLabel').children[1]).to.have.attribute('name', 'test');
+    });
+
+    it('should auto disable when passed a Typography component', () => {
+      const { getByTestId } = render(
+        <FormControlLabel
+          label={<Typography name="test">Pizza</Typography>}
+          data-testid="FormControlLabel"
+          control={<div />}
+        />,
+      );
+
+      expect(getByTestId('FormControlLabel').children[1]).to.have.attribute('name', 'test');
+    });
+  });
+
+  describe('componentProps: typography', () => {
+    it('should spread its contents to the typography element', () => {
+      const { getByTestId } = render(
+        <FormControlLabel
+          label="Pizza"
+          componentProps={{
+            typography: {
+              'data-testid': 'labelTypography',
+              name: 'test',
+            },
+          }}
+          control={<div />}
+        />,
+      );
+
+      expect(getByTestId('labelTypography')).to.have.attribute('name', 'test');
+    });
+  });
+
   describe('with FormControl', () => {
     describe('enabled', () => {
       it('should not have the disabled class', () => {