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

[Popper] Typing and documentation #12223

Merged
merged 4 commits into from
Jul 21, 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
83 changes: 83 additions & 0 deletions docs/src/pages/utils/popper/FakedReferencePopper.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import React from 'react';
import PropTypes from 'prop-types';
import { withStyles } from '@material-ui/core/styles';
import Popper from '@material-ui/core/Popper';
import Typography from '@material-ui/core/Typography';
import Fade from '@material-ui/core/Fade';
import Paper from '@material-ui/core/Paper';

const styles = theme => ({
typography: {
padding: theme.spacing.unit * 2,
},
});

class FakedReferencePopper extends React.Component {
state = {
anchorEl: null,
open: false,
};

handleMouseUp = () => {
const selection = window.getSelection();

// Resets when the selection has a length of 0
if (!selection || selection.anchorOffset === selection.focusOffset) {
this.handleClose();
return;
}

const getBoundingClientRect = () => selection.getRangeAt(0).getBoundingClientRect();

this.setState({
open: true,
anchorEl: {
clientWidth: getBoundingClientRect().width,
clientHeight: getBoundingClientRect().height,
getBoundingClientRect,
},
});
};

handleClose = () => {
if (!this.state.open) {
return;
}

this.setState({ open: false });
};

render() {
const { classes } = this.props;
const { anchorEl, open } = this.state;

return (
<div onMouseLeave={this.handleClose}>
<Typography onMouseUp={this.handleMouseUp}>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam ipsum purus, bibendum sit
amet vulputate eget, porta semper ligula. Donec bibendum vulputate erat, ac fringilla mi
finibus nec. Donec ac dolor sed dolor porttitor blandit vel vel purus. Fusce vel malesuada
ligula. Nam quis vehicula ante, eu finibus est. Proin ullamcorper fermentum orci, quis
finibus massa. Nunc lobortis, massa ut rutrum ultrices, metus metus finibus ex, sit amet
facilisis neque enim sed neque. Quisque accumsan metus vel maximus consequat. Suspendisse
lacinia tellus a libero volutpat maximus.
</Typography>
<Popper open={open} anchorEl={anchorEl} transition placement="bottom-start">
{({ TransitionProps }) => (
<Fade {...TransitionProps} timeout={350}>
<Paper>
<Typography className={classes.typography}>The content of the Popper.</Typography>
</Paper>
</Fade>
)}
</Popper>
</div>
);
}
}

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

export default withStyles(styles)(FakedReferencePopper);
14 changes: 13 additions & 1 deletion docs/src/pages/utils/popper/popper.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,13 @@ components: Popper
<p class="description">A Popper can be used to display some content on top of another.</p>

Things to know when using the `Popper` component:

- Poppers rely on the 3rd party library [Popper.js](https://github.com/FezVrasta/popper.js) for positioning.
- The children is [`Portal`](/utils/portal) to the body of the document to avoid rendering problems. You can disable this behavior with `disablePortal`.
- The children is [`Portal`](/utils/portal) to the body of the document to avoid rendering problems.
You can disable this behavior with `disablePortal`.
- The scroll and click away aren't blocked like with the [`Popover`](/utils/popover) component.
The placement of the popper updates with the available area in the viewport.
- The `anchorEl` is passed as the reference object to create a new `Popper.js` instance.

## Simple Popper

Expand All @@ -28,3 +31,12 @@ The placement of the popper updates with the available area in the viewport.
## Without transition Popper

{{"demo": "pages/utils/popper/NoTransitionPopper.js"}}

## Faked reference object

The `anchorEl` property can be a reference to a fake DOM element.
You just need to create an object shaped like the [`ReferenceObject`](https://github.com/FezVrasta/popper.js/blob/0642ce0ddeffe3c7c033a412d4d60ce7ec8193c3/packages/popper/index.d.ts#L118-L123).

Highlight part of the text to see the popper:

{{"demo": "pages/utils/popper/FakedReferencePopper.js"}}
3 changes: 2 additions & 1 deletion packages/material-ui/src/Popper/Popper.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import * as React from 'react';
import { ReferenceObject } from 'popper.js';
import { PortalProps } from '../Portal';
import { TransitionProps } from '../transitions/transition';

Expand All @@ -18,7 +19,7 @@ export type PopperPlacementType =

export interface PopperProps extends React.HTMLAttributes<HTMLDivElement> {
transition?: boolean;
anchorEl?: null | HTMLElement | ((element: HTMLElement) => HTMLElement);
anchorEl?: null | HTMLElement | ReferenceObject | ((element: HTMLElement) => HTMLElement);
children: (
props: {
placement: PopperPlacementType;
Expand Down
2 changes: 2 additions & 0 deletions packages/material-ui/src/Popper/Popper.js
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,8 @@ Popper.propTypes = {
/**
* This is the DOM element, or a function that returns the DOM element,
* that may be used to set the position of the popover.
* The return value will passed as the reference object of the Popper
* instance.
*/
anchorEl: PropTypes.oneOfType([PropTypes.object, PropTypes.func]),
/**
Expand Down
2 changes: 1 addition & 1 deletion pages/api/popper.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Poppers rely on the 3rd party library [Popper.js](https://github.com/FezVrasta/p

| Name | Type | Default | Description |
|:-----|:-----|:--------|:------------|
| <span class="prop-name">anchorEl</span> | <span class="prop-type">union:&nbsp;object&nbsp;&#124;<br>&nbsp;func<br> |   | This is the DOM element, or a function that returns the DOM element, that may be used to set the position of the popover. |
| <span class="prop-name">anchorEl</span> | <span class="prop-type">union:&nbsp;object&nbsp;&#124;<br>&nbsp;func<br> |   | This is the DOM element, or a function that returns the DOM element, that may be used to set the position of the popover. The return value will passed as the reference object of the Popper instance. |
| <span class="prop-name required">children *</span> | <span class="prop-type">union:&nbsp;node&nbsp;&#124;<br>&nbsp;func<br> |   | Popper render function or node. |
| <span class="prop-name">container</span> | <span class="prop-type">union:&nbsp;object&nbsp;&#124;<br>&nbsp;func<br> |   | A node, component instance, or function that returns either. The `container` will passed to the Modal component. By default, it uses the body of the anchorEl's top-level document object, so it's simply `document.body` most of the time. |
| <span class="prop-name">disablePortal</span> | <span class="prop-type">bool | <span class="prop-default">false</span> | Disable the portal behavior. The children stay within it's parent DOM hierarchy. |
Expand Down
7 changes: 7 additions & 0 deletions pages/utils/popper.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,13 @@ module.exports = require('fs')
raw: preval`
module.exports = require('fs')
.readFileSync(require.resolve('docs/src/pages/utils/popper/NoTransitionPopper'), 'utf8')
`,
},
'pages/utils/popper/FakedReferencePopper.js': {
js: require('docs/src/pages/utils/popper/FakedReferencePopper').default,
raw: preval`
module.exports = require('fs')
.readFileSync(require.resolve('docs/src/pages/utils/popper/FakedReferencePopper'), 'utf8')
`,
},
'pages/utils/popper/ScrollPlayground.js': {
Expand Down