Repository: mui/material-ui (TypeScript) — Feature

Issue:
"Dense" AppBar
Material-design defines a "dense" version of the AppBar for Desktop. It makes sense, because the AppBar is generally way too large on Desktop.

The `<AppBar>` component misses this `dense` prop.

![2018-05-29_0103](https://user-images.githubusercontent.com/99944/40631352-1e35943a-62dc-11e8-9cf6-e2e411017866.png)



Discussion:
I'm wondering if the prop should only be available only to the AppBar or also for the Toolbar component
Is anyone working on this feature? i'd love to work on it.
@adeelibr it seems nobody does, feel free to give it a go!
@fzaninotto I am going to start working on it from tomorrow. I am already working on this table thing. It's kind of a patch. Anyways i'll do this by tomorrow. :) Cheers. 

Resolving patch:
diff --git a/docs/src/pages/demos/app-bar/ButtonAppBar.js b/docs/src/pages/demos/app-bar/ButtonAppBar.js
--- a/docs/src/pages/demos/app-bar/ButtonAppBar.js
+++ b/docs/src/pages/demos/app-bar/ButtonAppBar.js
@@ -13,7 +13,7 @@ const styles = {
     flexGrow: 1,
   },
   flex: {
-    flex: 1,
+    flexGrow: 1,
   },
   menuButton: {
     marginLeft: -12,
@@ -31,7 +31,7 @@ function ButtonAppBar(props) {
             <MenuIcon />
           </IconButton>
           <Typography variant="title" color="inherit" className={classes.flex}>
-            Title
+            News
           </Typography>
           <Button color="inherit">Login</Button>
         </Toolbar>
diff --git a/docs/src/pages/demos/app-bar/DenseAppBar.js b/docs/src/pages/demos/app-bar/DenseAppBar.js
new file mode 100644
--- /dev/null
+++ b/docs/src/pages/demos/app-bar/DenseAppBar.js
@@ -0,0 +1,42 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { withStyles } from '@material-ui/core/styles';
+import AppBar from '@material-ui/core/AppBar';
+import Toolbar from '@material-ui/core/Toolbar';
+import Typography from '@material-ui/core/Typography';
+import IconButton from '@material-ui/core/IconButton';
+import MenuIcon from '@material-ui/icons/Menu';
+
+const styles = {
+  root: {
+    flexGrow: 1,
+  },
+  menuButton: {
+    marginLeft: -18,
+    marginRight: 10,
+  },
+};
+
+function DenseAppBar(props) {
+  const { classes } = props;
+  return (
+    <div className={classes.root}>
+      <AppBar position="static">
+        <Toolbar variant="dense">
+          <IconButton className={classes.menuButton} color="inherit" aria-label="Menu">
+            <MenuIcon />
+          </IconButton>
+          <Typography variant="title" color="inherit">
+            Photos
+          </Typography>
+        </Toolbar>
+      </AppBar>
+    </div>
+  );
+}
+
+DenseAppBar.propTypes = {
+  classes: PropTypes.object.isRequired,
+};
+
+export default withStyles(styles)(DenseAppBar);
diff --git a/docs/src/pages/demos/app-bar/MenuAppBar.js b/docs/src/pages/demos/app-bar/MenuAppBar.js
--- a/docs/src/pages/demos/app-bar/MenuAppBar.js
+++ b/docs/src/pages/demos/app-bar/MenuAppBar.js
@@ -18,7 +18,7 @@ const styles = {
     flexGrow: 1,
   },
   flex: {
-    flex: 1,
+    flexGrow: 1,
   },
   menuButton: {
     marginLeft: -12,
@@ -65,7 +65,7 @@ class MenuAppBar extends React.Component {
               <MenuIcon />
             </IconButton>
             <Typography variant="title" color="inherit" className={classes.flex}>
-              Title
+              Photos
             </Typography>
             {auth && (
               <div>
diff --git a/docs/src/pages/demos/app-bar/SimpleAppBar.js b/docs/src/pages/demos/app-bar/SimpleAppBar.js
--- a/docs/src/pages/demos/app-bar/SimpleAppBar.js
+++ b/docs/src/pages/demos/app-bar/SimpleAppBar.js
@@ -18,7 +18,7 @@ function SimpleAppBar(props) {
       <AppBar position="static" color="default">
         <Toolbar>
           <Typography variant="title" color="inherit">
-            Title
+            Photos
           </Typography>
         </Toolbar>
       </AppBar>
diff --git a/docs/src/pages/demos/app-bar/app-bar.md b/docs/src/pages/demos/app-bar/app-bar.md
--- a/docs/src/pages/demos/app-bar/app-bar.md
+++ b/docs/src/pages/demos/app-bar/app-bar.md
@@ -22,3 +22,7 @@ It can transform into a contextual action bar.
 ## App Bar with menu
 
 {{"demo": "pages/demos/app-bar/MenuAppBar.js"}}
+
+## Dense (desktop only)
+
+{{"demo": "pages/demos/app-bar/DenseAppBar.js"}}
diff --git a/packages/material-ui/src/Button/Button.js b/packages/material-ui/src/Button/Button.js
--- a/packages/material-ui/src/Button/Button.js
+++ b/packages/material-ui/src/Button/Button.js
@@ -287,7 +287,7 @@ Button.propTypes = {
    */
   type: PropTypes.string,
   /**
-   * The type of button.
+   * The variant to use.
    */
   variant: PropTypes.oneOf([
     'text',
diff --git a/packages/material-ui/src/CircularProgress/CircularProgress.js b/packages/material-ui/src/CircularProgress/CircularProgress.js
--- a/packages/material-ui/src/CircularProgress/CircularProgress.js
+++ b/packages/material-ui/src/CircularProgress/CircularProgress.js
@@ -171,8 +171,8 @@ CircularProgress.propTypes = {
    */
   value: PropTypes.number,
   /**
-   * The variant of progress indicator. Use indeterminate
-   * when there is no progress value.
+   * The variant to use.
+   * Use indeterminate when there is no progress value.
    */
   variant: PropTypes.oneOf(['determinate', 'indeterminate', 'static']),
 };
diff --git a/packages/material-ui/src/Drawer/Drawer.js b/packages/material-ui/src/Drawer/Drawer.js
--- a/packages/material-ui/src/Drawer/Drawer.js
+++ b/packages/material-ui/src/Drawer/Drawer.js
@@ -234,7 +234,7 @@ Drawer.propTypes = {
     PropTypes.shape({ enter: PropTypes.number, exit: PropTypes.number }),
   ]),
   /**
-   * The variant of drawer.
+   * The variant to use.
    */
   variant: PropTypes.oneOf(['permanent', 'persistent', 'temporary']),
 };
diff --git a/packages/material-ui/src/LinearProgress/LinearProgress.js b/packages/material-ui/src/LinearProgress/LinearProgress.js
--- a/packages/material-ui/src/LinearProgress/LinearProgress.js
+++ b/packages/material-ui/src/LinearProgress/LinearProgress.js
@@ -239,8 +239,8 @@ LinearProgress.propTypes = {
    */
   valueBuffer: PropTypes.number,
   /**
-   * The variant of progress indicator. Use indeterminate or query
-   * when there is no progress value.
+   * The variant to use.
+   * Use indeterminate or query when there is no progress value.
    */
   variant: PropTypes.oneOf(['determinate', 'indeterminate', 'buffer', 'query']),
 };
diff --git a/packages/material-ui/src/MobileStepper/MobileStepper.js b/packages/material-ui/src/MobileStepper/MobileStepper.js
--- a/packages/material-ui/src/MobileStepper/MobileStepper.js
+++ b/packages/material-ui/src/MobileStepper/MobileStepper.js
@@ -128,7 +128,7 @@ MobileStepper.propTypes = {
    */
   steps: PropTypes.number.isRequired,
   /**
-   * The type of mobile stepper to use.
+   * The variant to use.
    */
   variant: PropTypes.oneOf(['text', 'dots', 'progress']),
 };
diff --git a/packages/material-ui/src/Toolbar/Toolbar.d.ts b/packages/material-ui/src/Toolbar/Toolbar.d.ts
--- a/packages/material-ui/src/Toolbar/Toolbar.d.ts
+++ b/packages/material-ui/src/Toolbar/Toolbar.d.ts
@@ -3,10 +3,11 @@ import { StandardProps } from '..';
 
 export interface ToolbarProps
   extends StandardProps<React.HTMLAttributes<HTMLDivElement>, ToolbarClassKey> {
+  variant?: 'regular' | 'dense';
   disableGutters?: boolean;
 }
 
-export type ToolbarClassKey = 'root' | 'gutters';
+export type ToolbarClassKey = 'root' | 'gutters' | 'regular' | 'dense';
 
 declare const Toolbar: React.ComponentType<ToolbarProps>;
 
diff --git a/packages/material-ui/src/Toolbar/Toolbar.js b/packages/material-ui/src/Toolbar/Toolbar.js
--- a/packages/material-ui/src/Toolbar/Toolbar.js
+++ b/packages/material-ui/src/Toolbar/Toolbar.js
@@ -5,19 +5,23 @@ import withStyles from '../styles/withStyles';
 
 export const styles = theme => ({
   root: {
-    ...theme.mixins.toolbar,
     position: 'relative',
     display: 'flex',
     alignItems: 'center',
   },
   gutters: theme.mixins.gutters(),
+  regular: theme.mixins.toolbar,
+  dense: {
+    minHeight: 48,
+  },
 });
 
 function Toolbar(props) {
-  const { children, classes, className: classNameProp, disableGutters, ...other } = props;
+  const { children, classes, className: classNameProp, disableGutters, variant, ...other } = props;
 
   const className = classNames(
     classes.root,
+    classes[variant],
     {
       [classes.gutters]: !disableGutters,
     },
@@ -49,10 +53,15 @@ Toolbar.propTypes = {
    * If `true`, disables gutter padding.
    */
   disableGutters: PropTypes.bool,
+  /**
+   * The variant to use.
+   */
+  variant: PropTypes.oneOf(['regular', 'dense']),
 };
 
 Toolbar.defaultProps = {
   disableGutters: false,
+  variant: 'regular',
 };
 
 export default withStyles(styles, { name: 'MuiToolbar' })(Toolbar);
diff --git a/pages/api/button.md b/pages/api/button.md
--- a/pages/api/button.md
+++ b/pages/api/button.md
@@ -26,7 +26,7 @@ title: Button API
 | <span class="prop-name">href</span> | <span class="prop-type">string |   | The URL to link to when the button is clicked. If defined, an `a` element will be used as the root node. |
 | <span class="prop-name">mini</span> | <span class="prop-type">bool | <span class="prop-default">false</span> | If `true`, and `variant` is `'fab'`, will use mini floating action button styling. |
 | <span class="prop-name">size</span> | <span class="prop-type">enum:&nbsp;'small'&nbsp;&#124;<br>&nbsp;'medium'&nbsp;&#124;<br>&nbsp;'large'<br> | <span class="prop-default">'medium'</span> | The size of the button. `small` is equivalent to the dense button styling. |
-| <span class="prop-name">variant</span> | <span class="prop-type">enum:&nbsp;'text', 'flat', 'outlined', 'contained', 'raised', 'fab', 'extendedFab'<br> | <span class="prop-default">'text'</span> | The type of button. |
+| <span class="prop-name">variant</span> | <span class="prop-type">enum:&nbsp;'text', 'flat', 'outlined', 'contained', 'raised', 'fab', 'extendedFab'<br> | <span class="prop-default">'text'</span> | The variant to use. |
 
 Any other properties supplied will be spread to the root element ([ButtonBase](/api/button-base)).
 
diff --git a/pages/api/circular-progress.md b/pages/api/circular-progress.md
--- a/pages/api/circular-progress.md
+++ b/pages/api/circular-progress.md
@@ -24,7 +24,7 @@ attribute to `true` on that region until it has finished loading.
 | <span class="prop-name">size</span> | <span class="prop-type">union:&nbsp;number&nbsp;&#124;<br>&nbsp;string<br> | <span class="prop-default">40</span> | The size of the circle. |
 | <span class="prop-name">thickness</span> | <span class="prop-type">number | <span class="prop-default">3.6</span> | The thickness of the circle. |
 | <span class="prop-name">value</span> | <span class="prop-type">number | <span class="prop-default">0</span> | The value of the progress indicator for the determinate and static variants. Value between 0 and 100. |
-| <span class="prop-name">variant</span> | <span class="prop-type">enum:&nbsp;'determinate'&nbsp;&#124;<br>&nbsp;'indeterminate'&nbsp;&#124;<br>&nbsp;'static'<br> | <span class="prop-default">'indeterminate'</span> | The variant of progress indicator. Use indeterminate when there is no progress value. |
+| <span class="prop-name">variant</span> | <span class="prop-type">enum:&nbsp;'determinate'&nbsp;&#124;<br>&nbsp;'indeterminate'&nbsp;&#124;<br>&nbsp;'static'<br> | <span class="prop-default">'indeterminate'</span> | The variant to use. Use indeterminate when there is no progress value. |
 
 Any other properties supplied will be spread to the root element (native element).
 
diff --git a/pages/api/drawer.md b/pages/api/drawer.md
--- a/pages/api/drawer.md
+++ b/pages/api/drawer.md
@@ -26,7 +26,7 @@ when `variant="temporary"` is set.
 | <span class="prop-name">PaperProps</span> | <span class="prop-type">object |   | Properties applied to the [`Paper`](/api/paper) element. |
 | <span class="prop-name">SlideProps</span> | <span class="prop-type">object |   | Properties applied to the [`Slide`](/api/slide) element. |
 | <span class="prop-name">transitionDuration</span> | <span class="prop-type">union:&nbsp;number&nbsp;&#124;<br>&nbsp;{ enter?: number, exit?: number }<br> | <span class="prop-default">{ enter: duration.enteringScreen, exit: duration.leavingScreen }</span> | The duration for the transition, in milliseconds. You may specify a single timeout for all transitions, or individually with an object. |
-| <span class="prop-name">variant</span> | <span class="prop-type">enum:&nbsp;'permanent'&nbsp;&#124;<br>&nbsp;'persistent'&nbsp;&#124;<br>&nbsp;'temporary'<br> | <span class="prop-default">'temporary'</span> | The variant of drawer. |
+| <span class="prop-name">variant</span> | <span class="prop-type">enum:&nbsp;'permanent'&nbsp;&#124;<br>&nbsp;'persistent'&nbsp;&#124;<br>&nbsp;'temporary'<br> | <span class="prop-default">'temporary'</span> | The variant to use. |
 
 Any other properties supplied will be spread to the root element (native element).
 
diff --git a/pages/api/linear-progress.md b/pages/api/linear-progress.md
--- a/pages/api/linear-progress.md
+++ b/pages/api/linear-progress.md
@@ -23,7 +23,7 @@ attribute to `true` on that region until it has finished loading.
 | <span class="prop-name">color</span> | <span class="prop-type">enum:&nbsp;'primary'&nbsp;&#124;<br>&nbsp;'secondary'<br> | <span class="prop-default">'primary'</span> | The color of the component. It supports those theme colors that make sense for this component. |
 | <span class="prop-name">value</span> | <span class="prop-type">number |   | The value of the progress indicator for the determinate and buffer variants. Value between 0 and 100. |
 | <span class="prop-name">valueBuffer</span> | <span class="prop-type">number |   | The value for the buffer variant. Value between 0 and 100. |
-| <span class="prop-name">variant</span> | <span class="prop-type">enum:&nbsp;'determinate'&nbsp;&#124;<br>&nbsp;'indeterminate'&nbsp;&#124;<br>&nbsp;'buffer'&nbsp;&#124;<br>&nbsp;'query'<br> | <span class="prop-default">'indeterminate'</span> | The variant of progress indicator. Use indeterminate or query when there is no progress value. |
+| <span class="prop-name">variant</span> | <span class="prop-type">enum:&nbsp;'determinate'&nbsp;&#124;<br>&nbsp;'indeterminate'&nbsp;&#124;<br>&nbsp;'buffer'&nbsp;&#124;<br>&nbsp;'query'<br> | <span class="prop-default">'indeterminate'</span> | The variant to use. Use indeterminate or query when there is no progress value. |
 
 Any other properties supplied will be spread to the root element (native element).
 
diff --git a/pages/api/mobile-stepper.md b/pages/api/mobile-stepper.md
--- a/pages/api/mobile-stepper.md
+++ b/pages/api/mobile-stepper.md
@@ -21,7 +21,7 @@ title: MobileStepper API
 | <span class="prop-name">nextButton</span> | <span class="prop-type">node |   | A next button element. For instance, it can be be a `Button` or a `IconButton`. |
 | <span class="prop-name">position</span> | <span class="prop-type">enum:&nbsp;'bottom'&nbsp;&#124;<br>&nbsp;'top'&nbsp;&#124;<br>&nbsp;'static'<br> | <span class="prop-default">'bottom'</span> | Set the positioning type. |
 | <span class="prop-name required">steps *</span> | <span class="prop-type">number |   | The total steps. |
-| <span class="prop-name">variant</span> | <span class="prop-type">enum:&nbsp;'text'&nbsp;&#124;<br>&nbsp;'dots'&nbsp;&#124;<br>&nbsp;'progress'<br> | <span class="prop-default">'dots'</span> | The type of mobile stepper to use. |
+| <span class="prop-name">variant</span> | <span class="prop-type">enum:&nbsp;'text'&nbsp;&#124;<br>&nbsp;'dots'&nbsp;&#124;<br>&nbsp;'progress'<br> | <span class="prop-default">'dots'</span> | The variant to use. |
 
 Any other properties supplied will be spread to the root element ([Paper](/api/paper)).
 
diff --git a/pages/api/toolbar.md b/pages/api/toolbar.md
--- a/pages/api/toolbar.md
+++ b/pages/api/toolbar.md
@@ -18,6 +18,7 @@ title: Toolbar API
 | <span class="prop-name">children</span> | <span class="prop-type">node |   | Toolbar children, usually a mixture of `IconButton`, `Button` and `Typography`. |
 | <span class="prop-name">classes</span> | <span class="prop-type">object |   | Override or extend the styles applied to the component. See [CSS API](#css-api) below for more details. |
 | <span class="prop-name">disableGutters</span> | <span class="prop-type">bool | <span class="prop-default">false</span> | If `true`, disables gutter padding. |
+| <span class="prop-name">variant</span> | <span class="prop-type">enum:&nbsp;'regular'&nbsp;&#124;<br>&nbsp;'dense'<br> | <span class="prop-default">'regular'</span> | The variant to use. |
 
 Any other properties supplied will be spread to the root element (native element).
 
@@ -27,6 +28,8 @@ You can override all the class names injected by Material-UI thanks to the `clas
 This property accepts the following keys:
 - `root`
 - `gutters`
+- `regular`
+- `dense`
 
 Have a look at [overriding with classes](/customization/overrides#overriding-with-classes) section
 and the [implementation of the component](https://github.com/mui-org/material-ui/tree/master/packages/material-ui/src/Toolbar/Toolbar.js)
diff --git a/pages/demos/app-bar.js b/pages/demos/app-bar.js
--- a/pages/demos/app-bar.js
+++ b/pages/demos/app-bar.js
@@ -27,6 +27,13 @@ module.exports = require('fs')
           raw: preval`
 module.exports = require('fs')
   .readFileSync(require.resolve('docs/src/pages/demos/app-bar/MenuAppBar'), 'utf8')
+`,
+        },
+        'pages/demos/app-bar/DenseAppBar.js': {
+          js: require('docs/src/pages/demos/app-bar/DenseAppBar').default,
+          raw: preval`
+module.exports = require('fs')
+  .readFileSync(require.resolve('docs/src/pages/demos/app-bar/DenseAppBar'), 'utf8')
 `,
         },
       }}


Test patch:
diff --git a/packages/material-ui/src/Toolbar/Toolbar.test.js b/packages/material-ui/src/Toolbar/Toolbar.test.js
--- a/packages/material-ui/src/Toolbar/Toolbar.test.js
+++ b/packages/material-ui/src/Toolbar/Toolbar.test.js
@@ -29,10 +29,12 @@ describe('<Toolbar />', () => {
   it('should disable the gutters', () => {
     const wrapper = shallow(<Toolbar disableGutters>foo</Toolbar>);
     assert.strictEqual(wrapper.hasClass(classes.root), true);
-    assert.strictEqual(
-      wrapper.hasClass(classes.gutters),
-      false,
-      'should not have the gutters class',
-    );
+    assert.strictEqual(wrapper.hasClass(classes.gutters), false);
+  });
+
+  it('should condense itself', () => {
+    const wrapper = shallow(<Toolbar variant="dense">foo</Toolbar>);
+    assert.strictEqual(wrapper.hasClass(classes.root), true);
+    assert.strictEqual(wrapper.hasClass(classes.dense), true);
   });
 });