Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[core] Add a components property #11198

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,6 @@ that **are needed for the stable version**:
+import Button from '@material-ui/core/Button';
```

- [ ] Look into the Render Props API over the Component Injection API. This one is an area of investigation. For instance, there is potential for simplifying the customization of the transitions.

These breaking changes will be spread into different releases over the next few months to make the upgrade path as smooth as possible.
Not only does the Material-UI project have to be upgraded for each breaking change,
but we also have to upgrade our own projects.
Expand Down
46 changes: 23 additions & 23 deletions docs/src/modules/components/AppWrapper.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,29 +29,6 @@ function uiThemeSideEffect(uiTheme) {
}

class AppWrapper extends React.Component {
static getDerivedStateFromProps(nextProps, prevState) {
if (typeof prevState.pageContext === 'undefined') {
return {
prevProps: nextProps,
pageContext: nextProps.pageContext || getPageContext(),
};
}

const { prevProps } = prevState;

if (
nextProps.uiTheme.paletteType !== prevProps.uiTheme.paletteType ||
nextProps.uiTheme.direction !== prevProps.uiTheme.direction
) {
return {
prevProps: nextProps,
pageContext: updatePageContext(nextProps.uiTheme),
};
}

return null;
}

state = {};

componentDidMount() {
Expand Down Expand Up @@ -96,6 +73,29 @@ class AppWrapper extends React.Component {
}
}

AppWrapper.getDerivedStateFromProps = (nextProps, prevState) => {
if (typeof prevState.pageContext === 'undefined') {
return {
prevProps: nextProps,
pageContext: nextProps.pageContext || getPageContext(),
};
}

const { prevProps } = prevState;

if (
nextProps.uiTheme.paletteType !== prevProps.uiTheme.paletteType ||
nextProps.uiTheme.direction !== prevProps.uiTheme.direction
) {
return {
prevProps: nextProps,
pageContext: updatePageContext(nextProps.uiTheme),
};
}

return null;
};

AppWrapper.propTypes = {
children: PropTypes.node.isRequired,
pageContext: PropTypes.object,
Expand Down
2 changes: 1 addition & 1 deletion docs/src/modules/components/Notifications.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ class Notifications extends React.Component {
<Snackbar
key={message.id}
anchorOrigin={{ vertical: 'top', horizontal: 'center' }}
SnackbarContentProps={{ 'aria-describedby': 'notification-message' }}
ContentProps={{ 'aria-describedby': 'notification-message' }}
message={
<span id="notification-message" dangerouslySetInnerHTML={{ __html: message.text }} />
}
Expand Down
2 changes: 1 addition & 1 deletion docs/src/pages/demos/dialogs/AlertDialogSlide.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class AlertDialogSlide extends React.Component {
<Button onClick={this.handleClickOpen}>Slide in alert dialog</Button>
<Dialog
open={this.state.open}
transition={Transition}
components={{ Transition }}
keepMounted
onClose={this.handleClose}
aria-labelledby="alert-dialog-slide-title"
Expand Down
2 changes: 1 addition & 1 deletion docs/src/pages/demos/dialogs/FullScreenDialog.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ class FullScreenDialog extends React.Component {
fullScreen
open={this.state.open}
onClose={this.handleClose}
transition={Transition}
components={{ Transition }}
>
<AppBar className={classes.appBar}>
<Toolbar>
Expand Down
2 changes: 1 addition & 1 deletion docs/src/pages/demos/menus/FadeMenu.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class FadeMenu extends React.Component {
anchorEl={anchorEl}
open={Boolean(anchorEl)}
onClose={this.handleClose}
transition={Fade}
components={{ Transition: Fade }}
>
<MenuItem onClick={this.handleClose}>Profile</MenuItem>
<MenuItem onClick={this.handleClose}>My account</MenuItem>
Expand Down
2 changes: 1 addition & 1 deletion docs/src/pages/demos/snackbars/ConsecutiveSnackbars.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ class ConsecutiveSnackbars extends React.Component {
autoHideDuration={6000}
onClose={this.handleClose}
onExited={this.handleExited}
SnackbarContentProps={{
ContentProps={{
'aria-describedby': 'message-id',
}}
message={<span id="message-id">{message}</span>}
Expand Down
10 changes: 5 additions & 5 deletions docs/src/pages/demos/snackbars/DirectionSnackbar.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@ function TransitionDown(props) {
class DirectionSnackbar extends React.Component {
state = {
open: false,
transition: null,
Transition: null,
};

handleClick = transition => () => {
this.setState({ open: true, transition });
handleClick = Transition => () => {
this.setState({ open: true, Transition });
};

handleClose = () => {
Expand All @@ -43,8 +43,8 @@ class DirectionSnackbar extends React.Component {
<Snackbar
open={this.state.open}
onClose={this.handleClose}
transition={this.state.transition}
SnackbarContentProps={{
components={{ Transition: this.state.Transition }}
ContentProps={{
'aria-describedby': 'message-id',
}}
message={<span id="message-id">I love snacks</span>}
Expand Down
2 changes: 1 addition & 1 deletion docs/src/pages/demos/snackbars/FabIntegrationSnackbar.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ class FabIntegrationSnackbar extends React.Component {
open={open}
autoHideDuration={4000}
onClose={this.handleClose}
SnackbarContentProps={{
ContentProps={{
'aria-describedby': 'snackbar-fab-message-id',
className: classes.snackbarContent,
}}
Expand Down
4 changes: 2 additions & 2 deletions docs/src/pages/demos/snackbars/FadeSnackbar.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ class FadeSnackbar extends React.Component {
<Snackbar
open={this.state.open}
onClose={this.handleClose}
transition={Fade}
SnackbarContentProps={{
components={{ Transition: Fade }}
ContentProps={{
'aria-describedby': 'message-id',
}}
message={<span id="message-id">I love snacks</span>}
Expand Down
2 changes: 1 addition & 1 deletion docs/src/pages/demos/snackbars/PositionedSnackbar.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class PositionedSnackbar extends React.Component {
anchorOrigin={{ vertical, horizontal }}
open={open}
onClose={this.handleClose}
SnackbarContentProps={{
ContentProps={{
'aria-describedby': 'message-id',
}}
message={<span id="message-id">I love snacks</span>}
Expand Down
2 changes: 1 addition & 1 deletion docs/src/pages/demos/snackbars/SimpleSnackbar.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class SimpleSnackbar extends React.Component {
open={this.state.open}
autoHideDuration={6000}
onClose={this.handleClose}
SnackbarContentProps={{
ContentProps={{
'aria-describedby': 'message-id',
}}
message={<span id="message-id">Note archived</span>}
Expand Down
4 changes: 3 additions & 1 deletion docs/src/pages/demos/tables/CustomPaginationActionsTable.js
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,9 @@ class CustomPaginationActionsTable extends React.Component {
page={page}
onChangePage={this.handleChangePage}
onChangeRowsPerPage={this.handleChangeRowsPerPage}
Actions={TablePaginationActionsWrapped}
components={{
Actions: TablePaginationActionsWrapped,
}}
/>
</TableRow>
</TableFooter>
Expand Down
43 changes: 30 additions & 13 deletions packages/material-ui-lab/src/SpeedDial/SpeedDial.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@ import ReactDOM from 'react-dom';
import keycode from 'keycode';
import { withStyles } from 'material-ui/styles';
import Zoom from 'material-ui/transitions/Zoom';
import { duration } from 'material-ui/styles/transitions';
import Button from 'material-ui/Button';
import { isMuiElement } from 'material-ui/utils/reactHelpers';
import { duration } from 'material-ui/styles/transitions';
import { getComponents } from 'material-ui/utils/helpers';

const styles = theme => ({
root: {
Expand All @@ -25,6 +26,10 @@ const styles = theme => ({
},
});

const defaultComponents = {
Transition: Zoom,
};

class SpeedDial extends React.Component {
state = {
nextKey: null,
Expand Down Expand Up @@ -91,18 +96,21 @@ class SpeedDial extends React.Component {
children: childrenProp,
classes,
className: classNameProp,
components: componentsProp,
hidden,
icon: iconProp,
onClick,
onClose,
onKeyDown,
open,
openIcon,
transition: Transition,
transitionDuration,
TransitionProps,
...other
} = this.props;

const components = getComponents(defaultComponents, this.props);

// Filter the label for valid id characters.
const id = ariaLabel.replace(/^[^a-z]+|[^\w:.-]+/gi, '');

Expand Down Expand Up @@ -136,7 +144,13 @@ class SpeedDial extends React.Component {

return (
<div className={classNames(classes.root, classNameProp)} {...other}>
<Transition in={!hidden} timeout={transitionDuration} mountOnEnter unmountOnExit>
<components.Transition
in={!hidden}
timeout={transitionDuration}
mountOnEnter
unmountOnExit
{...TransitionProps}
>
<Button
variant="fab"
color="primary"
Expand All @@ -154,7 +168,7 @@ class SpeedDial extends React.Component {
>
{icon()}
</Button>
</Transition>
</components.Transition>
<div
id={`${id}-actions`}
className={classNames(classes.actions, { [classes.actionsClosed]: !open })}
Expand Down Expand Up @@ -191,6 +205,12 @@ SpeedDial.propTypes = {
* @ignore
*/
className: PropTypes.string,
/**
* The components injection property.
*/
components: PropTypes.shape({
Transition: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
}),
/**
* If `true`, the SpeedDial will be hidden.
*/
Expand Down Expand Up @@ -223,10 +243,6 @@ SpeedDial.propTypes = {
* The icon to display in the SpeedDial Floating Action Button when the SpeedDial is open.
*/
openIcon: PropTypes.node,
/**
* Transition component.
*/
transition: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
/**
* The duration for the transition, in milliseconds.
* You may specify a single timeout for all transitions, or individually with an object.
Expand All @@ -235,15 +251,16 @@ SpeedDial.propTypes = {
PropTypes.number,
PropTypes.shape({ enter: PropTypes.number, exit: PropTypes.number }),
]),
/**
* Properties applied to the `Transition` element.
*/
TransitionProps: PropTypes.object,
};

SpeedDial.defaultProps = {
components: defaultComponents,
transitionDuration: { enter: duration.enteringScreen, exit: duration.leavingScreen },
hidden: false,
transition: Zoom,
transitionDuration: {
enter: duration.enteringScreen,
exit: duration.leavingScreen,
},
};

export default withStyles(styles)(SpeedDial);
44 changes: 22 additions & 22 deletions packages/material-ui/src/ButtonBase/ButtonBase.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,28 +50,6 @@ export const styles = {
* It contains a load of style reset and some focus/ripple logic.
*/
class ButtonBase extends React.Component {
static getDerivedStateFromProps(nextProps, prevState) {
if (typeof prevState.focusVisible === 'undefined') {
return {
focusVisible: false,
lastDisabled: nextProps.disabled,
};
}

// The blur won't fire when the disabled state is set on a focused input.
// We need to book keep the focused state manually.
if (!prevState.prevState && nextProps.disabled && prevState.focusVisible) {
return {
focusVisible: false,
lastDisabled: nextProps.disabled,
};
}

return {
lastDisabled: nextProps.disabled,
};
}

state = {};

componentDidMount() {
Expand Down Expand Up @@ -295,6 +273,28 @@ class ButtonBase extends React.Component {
}
}

ButtonBase.getDerivedStateFromProps = (nextProps, prevState) => {
if (typeof prevState.focusVisible === 'undefined') {
return {
focusVisible: false,
lastDisabled: nextProps.disabled,
};
}

// The blur won't fire when the disabled state is set on a focused input.
// We need to book keep the focused state manually.
if (!prevState.prevState && nextProps.disabled && prevState.focusVisible) {
return {
focusVisible: false,
lastDisabled: nextProps.disabled,
};
}

return {
lastDisabled: nextProps.disabled,
};
};

ButtonBase.propTypes = {
/**
* Use that property to pass a ref callback to the native button component.
Expand Down
3 changes: 2 additions & 1 deletion packages/material-ui/src/Chip/Chip.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ export const styles = theme => {
transition: theme.transitions.create(['background-color', 'box-shadow']),
// label will inherit this from root, then `clickable` class overrides this for both
cursor: 'default',
outline: 'none', // No outline on focused element in Chrome (as triggered by tabIndex prop)
// We disable the focus ring for mouse, touch and keyboard users.
outline: 'none',
border: 'none', // Remove `button` border
padding: 0, // Remove `button` padding
},
Expand Down
Loading