Skip to content

Commit

Permalink
[ToggleButtons]: Add toggle buttons (#10144)
Browse files Browse the repository at this point in the history
  • Loading branch information
phallguy authored and mbrookes committed Jul 4, 2018
1 parent ae6be9a commit 263b428
Show file tree
Hide file tree
Showing 22 changed files with 1,101 additions and 2 deletions.
2 changes: 1 addition & 1 deletion .size-limit.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ module.exports = [
name: 'The main bundle of the docs',
webpack: false,
path: getMainFile().path,
limit: '177 KB',
limit: '177.1 KB',
},
{
name: 'The home page of the docs',
Expand Down
5 changes: 4 additions & 1 deletion docs/src/modules/components/withRoot.js
Original file line number Diff line number Diff line change
Expand Up @@ -185,11 +185,14 @@ const pages = [
pathname: '/lab/about',
title: 'About The Lab',
},
{
pathname: '/lab/slider',
},
{
pathname: '/lab/speed-dial',
},
{
pathname: '/lab/slider',
pathname: '/lab/toggle-button',
},
findPages[2].children[1],
],
Expand Down
106 changes: 106 additions & 0 deletions docs/src/pages/lab/toggle-button/ToggleButtons.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import React from 'react';
import PropTypes from 'prop-types';
import { withStyles } from '@material-ui/core/styles';
import FormatAlignLeftIcon from '@material-ui/icons/FormatAlignLeft';
import FormatAlignCenterIcon from '@material-ui/icons/FormatAlignCenter';
import FormatAlignRightIcon from '@material-ui/icons/FormatAlignRight';
import FormatAlignJustifyIcon from '@material-ui/icons/FormatAlignJustify';
import FormatBoldIcon from '@material-ui/icons/FormatBold';
import FormatItalicIcon from '@material-ui/icons/FormatItalic';
import FormatUnderlinedIcon from '@material-ui/icons/FormatUnderlined';
import FormatColorFillIcon from '@material-ui/icons/FormatColorFill';
import ArrowDropDownIcon from '@material-ui/icons/ArrowDropDown';
import Typography from '@material-ui/core/Typography';
import Grid from '@material-ui/core/Grid';
import ToggleButton, { ToggleButtonGroup } from '@material-ui/lab/ToggleButton';

const styles = theme => ({
toggleContainer: {
height: 56,
padding: `${theme.spacing.unit}px ${theme.spacing.unit * 2}px`,
display: 'flex',
alignItems: 'center',
justifyContent: 'flex-start',
margin: `${theme.spacing.unit}px 0`,
background: theme.palette.background.default,
},
});

class ToggleButtons extends React.Component {
state = {
alignment: 'left',
formats: ['bold'],
};

handleFormat = formats => this.setState({ formats });

handleAlignment = alignment => this.setState({ alignment });

render() {
const { classes } = this.props;
const { alignment, formats } = this.state;

return (
<Grid container spacing={16}>
<Grid item xs={12} sm={6}>
<div className={classes.toggleContainer}>
<ToggleButtonGroup value={alignment} exclusive onChange={this.handleAlignment}>
<ToggleButton value="left">
<FormatAlignLeftIcon />
</ToggleButton>
<ToggleButton value="center">
<FormatAlignCenterIcon />
</ToggleButton>
<ToggleButton value="right">
<FormatAlignRightIcon />
</ToggleButton>
<ToggleButton value="justify" disabled>
<FormatAlignJustifyIcon />
</ToggleButton>
</ToggleButtonGroup>
</div>
<Typography type="caption" gutterBottom>
Exclusive Selection
</Typography>
<Typography type="caption">
Text justification toggle buttons present options for left, right, center, full, and
justified text with only one item available for selection at a time. Selecting one
option deselects any other.
</Typography>
</Grid>
<Grid item xs={12} sm={6}>
<div className={classes.toggleContainer}>
<ToggleButtonGroup value={formats} onChange={this.handleFormat}>
<ToggleButton value="bold">
<FormatBoldIcon />
</ToggleButton>
<ToggleButton value="italic">
<FormatItalicIcon />
</ToggleButton>
<ToggleButton value="underlined">
<FormatUnderlinedIcon />
</ToggleButton>
<ToggleButton disabled value="color">
<FormatColorFillIcon />
<ArrowDropDownIcon />
</ToggleButton>
</ToggleButtonGroup>
</div>
<Typography type="caption" gutterBottom>
Multiple Selection
</Typography>
<Typography type="caption">
Logically-grouped options, like Bold, Italic, and Underline, allow multiple options to
be selected.
</Typography>
</Grid>
</Grid>
);
}
}

ToggleButtons.propTypes = {
classes: PropTypes.object.isRequired,
};

export default withStyles(styles)(ToggleButtons);
16 changes: 16 additions & 0 deletions docs/src/pages/lab/toggle-button/toggle-button.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
title: Toggle Button React component
components: ToggleButton, ToggleButtonGroup
---

# Toggle Buttons

<p class="description">Toggle buttons can be used to group related options.</p>

To emphasize groups of related [Toggle buttons](https://material.io/design/components/buttons.html#toggle-button),
a group should share a common container.

The `ToggleButtonGroup` will control the selected of its child buttons when
given its own `value` prop.

{{"demo": "pages/lab/toggle-button/ToggleButtons.js"}}
20 changes: 20 additions & 0 deletions packages/material-ui-lab/src/ToggleButton/ToggleButton.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import * as React from 'react';
import { StandardProps, PropTypes } from '..';
import { ButtonBaseProps, ButtonBaseClassKey } from '../ButtonBase';

export interface ToggleButtonProps
extends StandardProps<ButtonBaseProps, ToggleButtonClassKey, 'component'> {
component?: React.ReactType<ToggleButtonProps>;
disabled?: boolean;
disableFocusRipple?: boolean;
disableRipple?: boolean;
selected?: boolean;
type?: string;
value?: any;
}

export type ToggleButtonClassKey = ButtonBaseClassKey | 'label' | 'selected';

declare const ToggleButton: React.ComponentType<ToggleButtonProps>;

export default ToggleButton;
189 changes: 189 additions & 0 deletions packages/material-ui-lab/src/ToggleButton/ToggleButton.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
// @inheritedComponent ButtonBase

import React from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import { withStyles } from '@material-ui/core/styles';
import { fade } from '@material-ui/core/styles/colorManipulator';
import ButtonBase from '@material-ui/core/ButtonBase';

export const styles = theme => ({
root: {
...theme.typography.button,
height: 32,
minWidth: 48,
margin: 0,
padding: `${theme.spacing.unit - 4}px ${theme.spacing.unit * 1.5}px`,
borderRadius: 2,
willChange: 'opacity',
color: fade(theme.palette.action.active, 0.38),
'&:hover': {
textDecoration: 'none',
// Reset on mouse devices
backgroundColor: fade(theme.palette.text.primary, 0.12),
'@media (hover: none)': {
backgroundColor: 'transparent',
},
'&$disabled': {
backgroundColor: 'transparent',
},
},

'&:not(:first-child)': {
borderTopLeftRadius: 0,
borderBottomLeftRadius: 0,
},

'&:not(:last-child)': {
borderTopRightRadius: 0,
borderBottomRightRadius: 0,
},
},
label: {
width: '100%',
display: 'inherit',
alignItems: 'inherit',
justifyContent: 'inherit',
},
disabled: {
color: fade(theme.palette.action.disabled, 0.12),
},
selected: {
color: theme.palette.action.active,
'&:after': {
content: '""',
display: 'block',
position: 'absolute',
overflow: 'hidden',
borderRadius: 'inherit',
width: '100%',
height: '100%',
left: 0,
top: 0,
pointerEvents: 'none',
zIndex: 0,
backgroundColor: 'currentColor',
opacity: 0.38,
},

'& + &:before': {
content: '""',
display: 'block',
position: 'absolute',
overflow: 'hidden',
width: 1,
height: '100%',
left: 0,
top: 0,
pointerEvents: 'none',
zIndex: 0,
backgroundColor: 'currentColor',
opacity: 0.12,
},
},
});

class ToggleButton extends React.Component {
handleChange = event => {
const { onChange, onClick, value } = this.props;

if (onClick) {
onClick(event);
if (event.isDefaultPrevented()) {
return;
}
}

if (onChange) {
onChange(value);
}
};

render() {
const {
children,
className: classNameProp,
classes,
disableFocusRipple,
disabled,
selected,
...other
} = this.props;

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

return (
<ButtonBase
className={className}
disabled={disabled}
focusRipple={!disableFocusRipple}
onClick={this.handleChange}
{...other}
>
<span className={classes.label}>{children}</span>
</ButtonBase>
);
}
}

ToggleButton.propTypes = {
/**
* The content of the button.
*/
children: PropTypes.node.isRequired,
/**
* Useful to extend the style applied to components.
*/
classes: PropTypes.object.isRequired,
/**
* @ignore
*/
className: PropTypes.string,
/**
* If `true`, the button will be disabled.
*/
disabled: PropTypes.bool,
/**
* If `true`, the keyboard focus ripple will be disabled.
* `disableRipple` must also be true.
*/
disableFocusRipple: PropTypes.bool,
/**
* If `true`, the ripple effect will be disabled.
*/
disableRipple: PropTypes.bool,
/**
* @ignore
*/
onChange: PropTypes.func,
/**
* @ignore
*/
onClick: PropTypes.func,
/**
* If `true`, the button will be rendered in an active state.
*/
selected: PropTypes.bool,
/**
* The value to associate with the button when selected in a
* ToggleButtonGroup.
*/
value: PropTypes.any.isRequired,
};

ToggleButton.defaultProps = {
disabled: false,
disableFocusRipple: false,
disableRipple: false,
};

ToggleButton.muiName = 'ToggleButton';

export default withStyles(styles, { name: 'MuiToggleButton' })(ToggleButton);
Loading

0 comments on commit 263b428

Please sign in to comment.