diff --git a/src-docs/src/views/popover/popover_container.js b/src-docs/src/views/popover/popover_container.js new file mode 100644 index 000000000000..39c0de0872ab --- /dev/null +++ b/src-docs/src/views/popover/popover_container.js @@ -0,0 +1,69 @@ +import React, { + Component, +} from 'react'; + +import { + EuiButton, + EuiCode, + EuiPanel, + EuiPopover, + EuiSpacer, +} from '../../../../src/components'; + +export default class PopoverContainer extends Component { + constructor(props) { + super(props); + + this.state = { + isPopoverOpen: false, + }; + } + + onButtonClick = () => { + this.setState({ + isPopoverOpen: !this.state.isPopoverOpen, + }); + } + + closePopover = () => { + this.setState({ + isPopoverOpen: false, + }); + } + + setPanelRef = node => this.panel = node; + + render() { + const button = ( + + Show constrained popover + + ); + + return ( + + +
+ Popover is positioned downCenter but + constrained to fit within the panel. +
+
+ + {/* create adequate room for the popover */} + + +
+ ); + } +} diff --git a/src-docs/src/views/popover/popover_example.js b/src-docs/src/views/popover/popover_example.js index 057b0c038498..356ad0fee10d 100644 --- a/src-docs/src/views/popover/popover_example.js +++ b/src-docs/src/views/popover/popover_example.js @@ -40,6 +40,10 @@ import PopoverHTMLElementAnchor from './popover_htmlelement_anchor'; const popoverHTMLElementAnchorSource = require('!!raw-loader!./popover_htmlelement_anchor'); const popoverHTMLElementAnchorHtml = renderToHtml(PopoverHTMLElementAnchor); +import PopoverContainer from './popover_container'; +const popoverContainerSource = require('!!raw-loader!./popover_htmlelement_anchor'); +const popoverContainerHtml = renderToHtml(PopoverHTMLElementAnchor); + export const PopoverExample = { title: 'Popover', @@ -163,6 +167,25 @@ export const PopoverExample = { ), demo: , + }, { + title: 'Constraining a popover inside a container', + source: [{ + type: GuideSectionTypes.JS, + code: popoverContainerSource, + }, { + type: GuideSectionTypes.HTML, + code: popoverContainerHtml, + }], + text: ( +
+

+ EuiPopover can accept a React or DOM element as + a container prop and restrict the popover from + overflowing that container. +

+
+ ), + demo: , }, { title: 'Popover using an HTMLElement as the anchor', source: [{ diff --git a/src/components/popover/popover.js b/src/components/popover/popover.js index 5a0afd770473..1e9e3957a0f1 100644 --- a/src/components/popover/popover.js +++ b/src/components/popover/popover.js @@ -224,6 +224,7 @@ export class EuiPopover extends Component { if (this.button == null || this.panel == null) return; const { top, left, position, arrow } = findPopoverPosition({ + container: this.props.container, position: getPopoverPositionFromAnchorPosition(this.props.anchorPosition), align: getPopoverAlignFromAnchorPosition(this.props.anchorPosition), anchor: this.button, @@ -235,7 +236,7 @@ export class EuiPopover extends Component { } }); - // the popver's z-index must inherit from the button + // the popover's z-index must inherit from the button // this keeps a button's popover under a flyout that would cover the button // but a popover triggered inside a flyout will appear over that flyout const zIndex = getElementZIndex(this.button, this.panel); @@ -403,15 +404,16 @@ EuiPopover.propTypes = { ownFocus: PropTypes.bool, withTitle: PropTypes.bool, closePopover: PropTypes.func.isRequired, - button: PropTypes.oneOfType([ - PropTypes.node, - PropTypes.instanceOf(HTMLElement), - ]).isRequired, + button: PropTypes.node.isRequired, children: PropTypes.node, anchorPosition: PropTypes.oneOf(ANCHOR_POSITIONS), panelClassName: PropTypes.string, panelPaddingSize: PropTypes.oneOf(SIZES), - popoverRef: PropTypes.func + popoverRef: PropTypes.func, + container: PropTypes.oneOfType([ + PropTypes.node, + PropTypes.instanceOf(HTMLElement) + ]), }; EuiPopover.defaultProps = { diff --git a/src/components/popover/wrapping_popover.js b/src/components/popover/wrapping_popover.js index 9f14f274ae1d..542d779af561 100644 --- a/src/components/popover/wrapping_popover.js +++ b/src/components/popover/wrapping_popover.js @@ -1,5 +1,6 @@ import React, { Component } from 'react'; import { findDOMNode } from 'react-dom'; +import PropTypes from 'prop-types'; import { EuiPopover } from './popover'; import { EuiPortal } from '../portal'; @@ -55,3 +56,7 @@ export class EuiWrappingPopover extends Component { ); } } + +EuiWrappingPopover.propTypes = { + button: PropTypes.instanceOf(HTMLElement), +};