Skip to content

Commit

Permalink
[ButtonGroup] New component (mui#15744)
Browse files Browse the repository at this point in the history
* [WIP] Grouped & split buttons

* WIP: support outlined

* Outlined complete, SplitButton own demo

* Move styles from Button to new ButtonGroup component

* Misc tweaks

* Fix Olivier's feedback

* Apply suggestions from code review

Co-Authored-By: Olivier Tassinari <[email protected]>

* color transparent

* add TypeScript version

* take the class name into account

* Fix TypeScript fail

* Apply suggestions from code review

Co-Authored-By: Sebastian Silbermann <[email protected]>

* remove dead styles, remove SSR test

* Update grouped demo layout

* Revise tests

* prettier

* revise test description wording

* docs:api

* refinement

* fix Matt feedback
  • Loading branch information
mbrookes authored and oliviertassinari committed Jun 3, 2019
1 parent 9ff7491 commit d914dbc
Show file tree
Hide file tree
Showing 15 changed files with 707 additions and 14 deletions.
81 changes: 81 additions & 0 deletions docs/src/pages/components/buttons/GroupedButtons.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import React from 'react';
import Grid from '@material-ui/core/Grid';
import Button from '@material-ui/core/Button';
import ButtonGroup from '@material-ui/core/ButtonGroup';

export default function GroupedButtons() {
return (
<Grid container spacing={3}>
<Grid item xs={12} md={6}>
<Grid container spacing={1} direction="column" alignItems="center">
<Grid item>
<ButtonGroup size="small" aria-label="Small outlined button group">
<Button>One</Button>
<Button>Two</Button>
<Button>Three</Button>
</ButtonGroup>
</Grid>
<Grid item>
<ButtonGroup color="primary" aria-label="Outlined primary button group">
<Button>One</Button>
<Button>Two</Button>
<Button>Three</Button>
</ButtonGroup>
</Grid>
<Grid item>
<ButtonGroup
color="secondary"
size="large"
aria-label="Large outlined secondary button group"
>
<Button>One</Button>
<Button>Two</Button>
<Button>Three</Button>
</ButtonGroup>
</Grid>
</Grid>
</Grid>
<Grid item xs={12} md={6}>
<Grid container spacing={1} direction="column" alignItems="center">
<Grid item>
<ButtonGroup variant="contained" size="small" aria-label="Small contained button group">
<Button>One</Button>
<Button>Two</Button>
<Button>Three</Button>
</ButtonGroup>
</Grid>
<Grid item>
<ButtonGroup
variant="contained"
color="primary"
aria-label="Full-width contained primary button group"
>
<Button>One</Button>
<Button>Two</Button>
<Button>Three</Button>
</ButtonGroup>
</Grid>
<Grid item>
<ButtonGroup
variant="contained"
color="secondary"
size="large"
aria-label="Large contained secondary button group"
>
<Button>One</Button>
<Button>Two</Button>
<Button>Three</Button>
</ButtonGroup>
</Grid>
</Grid>
</Grid>
<Grid item xs={12}>
<ButtonGroup fullWidth aria-label="Full width outlined button group">
<Button>Full</Button>
<Button>width</Button>
<Button>ButtonGroup</Button>
</ButtonGroup>
</Grid>
</Grid>
);
}
87 changes: 87 additions & 0 deletions docs/src/pages/components/buttons/SplitButton.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import React from 'react';
import Grid from '@material-ui/core/Grid';
import Button from '@material-ui/core/Button';
import ButtonGroup from '@material-ui/core/ButtonGroup';
import ArrowDropDownIcon from '@material-ui/icons/ArrowDropDown';
import ClickAwayListener from '@material-ui/core/ClickAwayListener';
import Grow from '@material-ui/core/Grow';
import Paper from '@material-ui/core/Paper';
import Popper from '@material-ui/core/Popper';
import MenuItem from '@material-ui/core/MenuItem';
import MenuList from '@material-ui/core/MenuList';

const options = ['Create a merge commit', 'Squash and merge', 'Rebase and merge'];

export default function SplitButton() {
const [open, setOpen] = React.useState(false);
const anchorRef = React.useRef(null);
const [selectedIndex, setSelectedIndex] = React.useState(1);

function handleClick() {
alert(`You clicked ${options[selectedIndex]}`);
}

function handleMenuItemClick(event, index) {
setSelectedIndex(index);
setOpen(false);
}

function handleToggle() {
setOpen(prevOpen => !prevOpen);
}

function handleClose(event) {
if (anchorRef.current && anchorRef.current.contains(event.target)) {
return;
}

setOpen(false);
}

return (
<Grid container>
<Grid item xs={12} align="center">
<ButtonGroup variant="contained" color="primary" ref={anchorRef} aria-label="Split button">
<Button onClick={handleClick}>{options[selectedIndex]}</Button>
<Button
color="primary"
variant="contained"
size="small"
aria-owns={open ? 'menu-list-grow' : undefined}
aria-haspopup="true"
onClick={handleToggle}
>
<ArrowDropDownIcon />
</Button>
</ButtonGroup>
<Popper open={open} anchorEl={anchorRef.current} transition disablePortal>
{({ TransitionProps, placement }) => (
<Grow
{...TransitionProps}
style={{
transformOrigin: placement === 'bottom' ? 'center top' : 'center bottom',
}}
>
<Paper id="menu-list-grow">
<ClickAwayListener onClickAway={handleClose}>
<MenuList>
{options.map((option, index) => (
<MenuItem
key={option}
disabled={index === 2}
selected={index === selectedIndex}
onClick={event => handleMenuItemClick(event, index)}
>
{option}
</MenuItem>
))}
</MenuList>
</ClickAwayListener>
</Paper>
</Grow>
)}
</Popper>
</Grid>
</Grid>
);
}
14 changes: 13 additions & 1 deletion docs/src/pages/components/buttons/buttons.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Button React component
components: Button, Fab, IconButton, ButtonBase, Zoom
components: Button, ButtonGroup, Fab, IconButton, ButtonBase, Zoom
---

# Buttons
Expand Down Expand Up @@ -50,6 +50,18 @@ or a higher emphasis alternative to text buttons.

{{"demo": "pages/components/buttons/OutlinedButtons.js"}}

## Grouped Buttons

The ButtonGroup component can be used to group outlined (the default) or contained buttons.

{{"demo": "pages/components/buttons/GroupedButtons.js"}}

## Split Button

ButtonGroup can also be used to create a split button. The dropdown can change the button action (as in this example), or be use to immediately trigger a related action.

{{"demo": "pages/components/buttons/SplitButton.js"}}

## Floating Action Buttons

A [floating action button](https://material.io/design/components/buttons-floating-action-button.html)
Expand Down
20 changes: 11 additions & 9 deletions packages/material-ui/src/Button/Button.js
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,6 @@ export const styles = theme => ({
/* Styles applied to the root element if `size="small"`. */
sizeSmall: {
padding: '4px 8px',
minWidth: 64,
fontSize: theme.typography.pxToRem(13),
},
/* Styles applied to the root element if `size="large"`. */
Expand Down Expand Up @@ -200,20 +199,23 @@ const Button = React.forwardRef(function Button(props, ref) {
...other
} = props;

const contained = variant === 'contained';
const text = variant === 'text';
const outlined = variant === 'outlined';
const contained = variant === 'contained';
const primary = color === 'primary';
const secondary = color === 'secondary';
const className = clsx(
classes.root,
{
[classes.text]: text,
[classes.textPrimary]: text && color === 'primary',
[classes.textSecondary]: text && color === 'secondary',
[classes.textPrimary]: text && primary,
[classes.textSecondary]: text && secondary,
[classes.outlined]: outlined,
[classes.outlinedPrimary]: outlined && primary,
[classes.outlinedSecondary]: outlined && secondary,
[classes.contained]: contained,
[classes.containedPrimary]: contained && color === 'primary',
[classes.containedSecondary]: contained && color === 'secondary',
[classes.outlined]: variant === 'outlined',
[classes.outlinedPrimary]: variant === 'outlined' && color === 'primary',
[classes.outlinedSecondary]: variant === 'outlined' && color === 'secondary',
[classes.containedPrimary]: contained && primary,
[classes.containedSecondary]: contained && secondary,
[classes[`size${capitalize(size)}`]]: size !== 'medium',
[classes.disabled]: disabled,
[classes.fullWidth]: fullWidth,
Expand Down
33 changes: 33 additions & 0 deletions packages/material-ui/src/ButtonGroup/ButtonGroup.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import * as React from 'react';
import { PropTypes } from '..';
import { OverridableComponent, SimplifiedPropsOf } from '../OverridableComponent';

declare const ButtonGroup: OverridableComponent<{
props: {
color?: PropTypes.Color;
disabled?: boolean;
disableFocusRipple?: boolean;
disableRipple?: boolean;
fullWidth?: boolean;
size?: 'small' | 'medium' | 'large';
variant?: 'outlined' | 'contained';
};
defaultComponent: 'div';
classKey: ButtonGroupClassKey;
}>;

export type ButtonGroupClassKey =
| 'root'
| 'contained'
| 'fullWidth'
| 'grouped'
| 'groupedOutlined'
| 'groupedOutlinedPrimary'
| 'groupedOutlinedSecondary'
| 'groupedContained'
| 'groupedContainedPrimary'
| 'groupedContainedSecondary';

export type ButtonGroupProps = SimplifiedPropsOf<typeof ButtonGroup>;

export default ButtonGroup;
Loading

0 comments on commit d914dbc

Please sign in to comment.