Skip to content

[core] Standardize the component injection pattern #11204

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

Merged
merged 1 commit into from
May 3, 2018
Merged
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
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}
TransitionComponent={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}
TransitionComponent={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}
TransitionComponent={Fade}
>
<MenuItem onClick={this.handleClose}>Profile</MenuItem>
<MenuItem onClick={this.handleClose}>My account</MenuItem>
Expand Down
8 changes: 4 additions & 4 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,7 +43,7 @@ class DirectionSnackbar extends React.Component {
<Snackbar
open={this.state.open}
onClose={this.handleClose}
transition={this.state.transition}
TransitionComponent={this.state.Transition}
ContentProps={{
'aria-describedby': 'message-id',
}}
Expand Down
2 changes: 1 addition & 1 deletion docs/src/pages/demos/snackbars/FadeSnackbar.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class FadeSnackbar extends React.Component {
<Snackbar
open={this.state.open}
onClose={this.handleClose}
transition={Fade}
TransitionComponent={Fade}
ContentProps={{
'aria-describedby': 'message-id',
}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ class CustomPaginationActionsTable extends React.Component {
page={page}
onChangePage={this.handleChangePage}
onChangeRowsPerPage={this.handleChangeRowsPerPage}
Actions={TablePaginationActionsWrapped}
ActionsComponent={TablePaginationActionsWrapped}
/>
</TableRow>
</TableFooter>
Expand Down
15 changes: 8 additions & 7 deletions docs/src/pages/guides/api/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,13 +70,14 @@ const styles = {
};
```

### Internal components

Internal components have:
- their own flattened properties when these are key to the abstraction.
- their own `xxxProps` property when users might need to tweak the internal render method's sub-components,
for instance, exposing the `inputProps` and `InputProps` properties on components that use `Input` internally.
For instance, exposing a `value` property.
### Nested components

Nested components inside a component have:
- their own flattened properties when these are key to the top level component abstraction.
For instance and `id` property for the `Input` component.
- their own `xxxProps` property when users might need to tweak the internal render method's sub-components.
For instance, exposing the `inputProps` and `InputProps` properties on components that use `Input` internally.
- their own `xxxComponent` property for performing component injection.
- their own `xxxRef` property when user might need to perform imperative actions.
For instance, exposing a `inputRef` property to access the native `input` on the `Input` component.
It help answering the following question. [How can I access the DOM element?](/getting-started/faq#how-can-i-access-the-dom-element-)
Expand Down
15 changes: 10 additions & 5 deletions packages/material-ui-lab/src/SpeedDial/SpeedDial.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ class SpeedDial extends React.Component {
onKeyDown,
open,
openIcon,
transition: Transition,
TransitionComponent,
transitionDuration,
TransitionProps,
...other
Expand Down Expand Up @@ -137,7 +137,12 @@ class SpeedDial extends React.Component {

return (
<div className={classNames(classes.root, classNameProp)} {...other}>
<Transition in={!hidden} timeout={transitionDuration} unmountOnExit {...TransitionProps}>
<TransitionComponent
in={!hidden}
timeout={transitionDuration}
unmountOnExit
{...TransitionProps}
>
<Button
variant="fab"
color="primary"
Expand All @@ -155,7 +160,7 @@ class SpeedDial extends React.Component {
>
{icon()}
</Button>
</Transition>
</TransitionComponent>
<div
id={`${id}-actions`}
className={classNames(classes.actions, { [classes.actionsClosed]: !open })}
Expand Down Expand Up @@ -227,7 +232,7 @@ SpeedDial.propTypes = {
/**
* Transition component.
*/
transition: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
TransitionComponent: 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 @@ -244,7 +249,7 @@ SpeedDial.propTypes = {

SpeedDial.defaultProps = {
hidden: false,
transition: Zoom,
TransitionComponent: Zoom,
transitionDuration: {
enter: duration.enteringScreen,
exit: duration.leavingScreen,
Expand Down
2 changes: 1 addition & 1 deletion packages/material-ui/src/Dialog/Dialog.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export interface DialogProps
fullWidth?: boolean;
maxWidth?: 'xs' | 'sm' | 'md' | false;
PaperProps?: Partial<PaperProps>;
transition?: React.ReactType;
TransitionComponent?: React.ReactType;
transitionDuration?: TransitionProps['timeout'];
TransitionProps?: TransitionProps;
}
Expand Down
10 changes: 5 additions & 5 deletions packages/material-ui/src/Dialog/Dialog.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ function Dialog(props) {
onExiting,
open,
PaperProps,
transition: TransitionProp,
TransitionComponent,
transitionDuration,
TransitionProps,
...other
Expand All @@ -95,7 +95,7 @@ function Dialog(props) {
role="dialog"
{...other}
>
<TransitionProp
<TransitionComponent
appear
in={open}
timeout={transitionDuration}
Expand All @@ -119,7 +119,7 @@ function Dialog(props) {
>
{children}
</Paper>
</TransitionProp>
</TransitionComponent>
</Modal>
);
}
Expand Down Expand Up @@ -214,7 +214,7 @@ Dialog.propTypes = {
/**
* Transition component.
*/
transition: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
TransitionComponent: 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,7 +235,7 @@ Dialog.defaultProps = {
fullScreen: false,
fullWidth: false,
maxWidth: 'sm',
transition: Fade,
TransitionComponent: Fade,
transitionDuration: { enter: duration.enteringScreen, exit: duration.leavingScreen },
};

Expand Down
6 changes: 3 additions & 3 deletions packages/material-ui/src/Dialog/Dialog.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,17 @@ describe('<Dialog />', () => {
assert.strictEqual(wrapper.type(), Modal);
});

it('should render a Modal with transition', () => {
it('should render a Modal with TransitionComponent', () => {
const Transition = props => <div className="cloned-element-class" {...props} />;
const wrapper = shallow(
<Dialog {...defaultProps} transition={Transition}>
<Dialog {...defaultProps} TransitionComponent={Transition}>
foo
</Dialog>,
);
assert.strictEqual(
wrapper.find(Transition).length,
1,
'should include element given in transition',
'should include element given in TransitionComponent',
);
});

Expand Down
2 changes: 1 addition & 1 deletion packages/material-ui/src/Popover/Popover.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export interface PopoverProps
PaperProps?: Partial<PaperProps>;
role?: string;
transformOrigin?: PopoverOrigin;
transition?: React.ReactType;
TransitionComponent?: React.ReactType;
transitionDuration?: TransitionProps['timeout'] | 'auto';
TransitionProps?: TransitionProps;
}
Expand Down
10 changes: 5 additions & 5 deletions packages/material-ui/src/Popover/Popover.js
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ class Popover extends React.Component {
PaperProps,
role,
transformOrigin,
transition: TransitionProp,
TransitionComponent,
transitionDuration,
TransitionProps,
...other
Expand All @@ -304,7 +304,7 @@ class Popover extends React.Component {

return (
<Modal container={container} open={open} BackdropProps={{ invisible: true }} {...other}>
<TransitionProp
<TransitionComponent
appear
in={open}
onEnter={this.handleEnter}
Expand All @@ -328,7 +328,7 @@ class Popover extends React.Component {
<EventListener target="window" onResize={this.handleResize} />
{children}
</Paper>
</TransitionProp>
</TransitionComponent>
</Modal>
);
}
Expand Down Expand Up @@ -472,7 +472,7 @@ Popover.propTypes = {
/**
* Transition component.
*/
transition: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
TransitionComponent: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
/**
* Set to 'auto' to automatically calculate transition time based on height.
*/
Expand All @@ -499,7 +499,7 @@ Popover.defaultProps = {
vertical: 'top',
horizontal: 'left',
},
transition: Grow,
TransitionComponent: Grow,
transitionDuration: 'auto',
};

Expand Down
10 changes: 5 additions & 5 deletions packages/material-ui/src/Snackbar/Snackbar.js
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ class Snackbar extends React.Component {
onMouseLeave,
open,
resumeHideDuration,
transition: TransitionProp,
TransitionComponent,
transitionDuration,
TransitionProps,
...other
Expand Down Expand Up @@ -236,7 +236,7 @@ class Snackbar extends React.Component {
onFocus={disableWindowBlurListener ? undefined : this.handleResume}
onBlur={disableWindowBlurListener ? undefined : this.handlePause}
/>
<TransitionProp
<TransitionComponent
appear
in={open}
onEnter={onEnter}
Expand All @@ -250,7 +250,7 @@ class Snackbar extends React.Component {
{...TransitionProps}
>
{children || <SnackbarContent message={message} action={action} {...ContentProps} />}
</TransitionProp>
</TransitionComponent>
</div>
</ClickAwayListener>
);
Expand Down Expand Up @@ -368,7 +368,7 @@ Snackbar.propTypes = {
/**
* Transition component.
*/
transition: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
TransitionComponent: 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 @@ -389,7 +389,7 @@ Snackbar.defaultProps = {
horizontal: 'center',
},
disableWindowBlurListener: false,
transition: Slide,
TransitionComponent: Slide,
transitionDuration: {
enter: duration.enteringScreen,
exit: duration.leavingScreen,
Expand Down
8 changes: 4 additions & 4 deletions packages/material-ui/src/Snackbar/Snackbar.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -362,14 +362,14 @@ describe('<Snackbar />', () => {
});
});

describe('prop: transition', () => {
it('should render a Snackbar with transition', () => {
describe('prop: TransitionComponent', () => {
it('should render a Snackbar with TransitionComponent', () => {
const Transition = props => <div className="cloned-element-class" {...props} />;
const wrapper = shallow(<Snackbar open transition={Transition} />);
const wrapper = shallow(<Snackbar open TransitionComponent={Transition} />);
assert.strictEqual(
wrapper.find(Transition).length,
1,
'should include element given in transition',
'should include element given in TransitionComponent',
);
});
});
Expand Down
2 changes: 1 addition & 1 deletion packages/material-ui/src/Stepper/StepContent.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export interface StepContentProps
last?: boolean;
optional?: boolean;
orientation?: Orientation;
transition?: React.ComponentType<TransitionProps>;
TransitionComponent?: React.ComponentType<TransitionProps>;
transitionDuration?: TransitionProps['timeout'] | 'auto';
TransitionProps?: TransitionProps;
}
Expand Down
10 changes: 5 additions & 5 deletions packages/material-ui/src/Stepper/StepContent.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ function StepContent(props) {
last,
optional,
orientation,
transition: Transition,
TransitionComponent,
transitionDuration,
TransitionProps,
...other
Expand All @@ -45,15 +45,15 @@ function StepContent(props) {

return (
<div className={classNames(classes.root, { [classes.last]: last }, className)} {...other}>
<Transition
<TransitionComponent
in={active}
className={classes.transition}
timeout={transitionDuration}
unmountOnExit
{...TransitionProps}
>
{children}
</Transition>
</TransitionComponent>
</div>
);
}
Expand Down Expand Up @@ -101,7 +101,7 @@ StepContent.propTypes = {
/**
* Collapse component.
*/
transition: PropTypes.func,
TransitionComponent: PropTypes.func,
/**
* Adjust the duration of the content expand transition.
* Passed as a property to the transition component.
Expand All @@ -120,7 +120,7 @@ StepContent.propTypes = {
};

StepContent.defaultProps = {
transition: Collapse,
TransitionComponent: Collapse,
transitionDuration: 'auto',
};

Expand Down
Loading