diff --git a/src/components/color_picker/_color_picker.scss b/src/components/color_picker/_color_picker.scss index a277e690bd5..9777d40bc16 100644 --- a/src/components/color_picker/_color_picker.scss +++ b/src/components/color_picker/_color_picker.scss @@ -16,17 +16,3 @@ // sass-lint:disable no-important padding-bottom: 0 !important; } - -.euiColorPicker__popoverPanel[class*='bottom']:not(.euiColorPicker__popoverPanel--customButton) { - border-top-color: transparentize($euiBorderColor, .2); - border-top-right-radius: 0; - border-top-left-radius: 0; -} - -.euiColorPicker__popoverPanel[class*='top']:not(.euiColorPicker__popoverPanel--customButton) { - @include euiBottomShadowFlat; - - border-bottom-color: transparentize($euiBorderColor, .2); - border-bottom-right-radius: 0; - border-bottom-left-radius: 0; -} diff --git a/src/components/form/range/range.js b/src/components/form/range/range.js index 6090bc75012..a634e8484df 100644 --- a/src/components/form/range/range.js +++ b/src/components/form/range/range.js @@ -87,7 +87,7 @@ export class EuiRange extends Component { style={style} showTicks={showTicks} showRange={showRange} - tabIndex={showInput ? -1 : tabIndex || null} + tabIndex={showInput === true ? -1 : tabIndex || null} {...rest} /> diff --git a/src/components/popover/_index.scss b/src/components/popover/_index.scss index b6fde53e362..0e2fd80cb05 100644 --- a/src/components/popover/_index.scss +++ b/src/components/popover/_index.scss @@ -3,3 +3,4 @@ @import 'popover'; @import 'popover_title'; @import 'popover_footer'; +@import 'input_popover'; diff --git a/src/components/popover/_input_popover.scss b/src/components/popover/_input_popover.scss new file mode 100644 index 00000000000..3790fb39611 --- /dev/null +++ b/src/components/popover/_input_popover.scss @@ -0,0 +1,5 @@ +.euiInputPopover { + &.euiInputPopover--fullWidth { + max-width: 100%; + } +} diff --git a/src/components/popover/_popover.scss b/src/components/popover/_popover.scss index 48bfc4f36e1..a932e658c05 100644 --- a/src/components/popover/_popover.scss +++ b/src/components/popover/_popover.scss @@ -146,6 +146,20 @@ &.euiPopover__panel-noArrow .euiPopover__panelArrow { display: none; } + + &.euiPopover__panel-isAttached.euiPopover__panel--bottom { + border-top-color: transparentize($euiBorderColor, .2); + border-top-right-radius: 0; + border-top-left-radius: 0; + } + + &.euiPopover__panel-isAttached.euiPopover__panel--top { + @include euiBottomShadowFlat; + + border-bottom-color: transparentize($euiBorderColor, .2); + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; + } } .euiPopover__panel.euiPopover__panel-isOpen.euiPopover__panel--top { diff --git a/src/components/popover/index.js b/src/components/popover/index.js index 153ecee093f..28728b6fd49 100644 --- a/src/components/popover/index.js +++ b/src/components/popover/index.js @@ -1,3 +1,4 @@ +export { EuiInputPopover } from './input_popover'; export { EuiPopover } from './popover'; export { EuiPopoverTitle } from './popover_title'; export { EuiPopoverFooter } from './popover_footer'; diff --git a/src/components/popover/input_popover.js b/src/components/popover/input_popover.js new file mode 100644 index 00000000000..8c2e4eccb75 --- /dev/null +++ b/src/components/popover/input_popover.js @@ -0,0 +1,89 @@ +import React, { useState, useEffect } from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; +import tabbable from 'tabbable'; + +import { EuiFocusTrap } from '../focus_trap'; +import { EuiPopover, EuiPopoverPropTypes } from './popover'; +import { cascadingMenuKeyCodes } from '../../services'; + +export const EuiInputPopover = ({ + children, + className, + fullWidth, + input, + popoverZIndex, + ...props +}) => { + const [inputEl, setInputEl] = useState(); + const [inputElWidth, setInputElWidth] = useState(); + const [panelEl, setPanelEl] = useState(); + const inputRef = node => setInputEl(node); + const panelRef = node => setPanelEl(node); + const setPanelWidth = () => { + if (panelEl && inputElWidth) { + panelEl.style.width = `${inputElWidth}px`; + } + }; + useEffect(() => { + if (inputEl) { + const width = inputEl.getBoundingClientRect().width; + setInputElWidth(width); + setPanelWidth(); + } + }, [inputEl]); + useEffect(() => { + setPanelWidth(); + }, [panelEl]); + const onKeyDown = e => { + if (e.keyCode === cascadingMenuKeyCodes.TAB) { + const tabbableItems = tabbable(panelEl).filter(el => { + return ( + [...el.attributes].map(el => el.name).indexOf('data-focus-guard') < 0 + ); + }); + if ( + tabbableItems.length && + tabbableItems[tabbableItems.length - 1] === document.activeElement + ) { + props.closePopover(); + } + } + }; + const classes = classnames( + 'euiInputPopover', + { + 'euiInputPopover--fullWidth': fullWidth, + }, + className + ); + return ( + + +
{children}
+
+
+ ); +}; + +const { button, buttonRef, ...propTypes } = EuiPopoverPropTypes; +EuiInputPopover.propTypes = { + fullWidth: PropTypes.bool, + input: EuiPopoverPropTypes.button, + inputRef: EuiPopoverPropTypes.buttonRef, + ...propTypes, +}; + +EuiInputPopover.defaultProps = { + anchorPosition: 'downLeft', + attachToAnchor: true, + display: 'block', + fullWidth: false, + panelPaddingSize: 's', +}; diff --git a/src/components/popover/popover.js b/src/components/popover/popover.js index ba6838e0948..481b2549799 100644 --- a/src/components/popover/popover.js +++ b/src/components/popover/popover.js @@ -345,6 +345,7 @@ export class EuiPopover extends Component { panelRef = node => { this.panel = node; + this.props.panelRef && this.props.panelRef(node); if (node == null) { // panel has unmounted, restore the state defaults @@ -363,13 +364,17 @@ export class EuiPopover extends Component { } }; - buttonRef = node => (this.button = node); + buttonRef = node => { + this.button = node; + this.props.buttonRef && this.props.buttonRef(node); + }; render() { const { anchorClassName, anchorPosition, button, + buttonRef, insert, isOpen, ownFocus, @@ -379,6 +384,7 @@ export class EuiPopover extends Component { closePopover, panelClassName, panelPaddingSize, + panelRef, popoverRef, hasArrow, repositionOnScroll, @@ -408,6 +414,7 @@ export class EuiPopover extends Component { { 'euiPopover__panel-isOpen': this.state.isOpening }, { 'euiPopover__panel-withTitle': withTitle }, { 'euiPopover__panel-noArrow': !hasArrow || attachToAnchor }, + { 'euiPopover__panel-isAttached': attachToAnchor }, panelClassName ); @@ -497,7 +504,7 @@ export class EuiPopover extends Component { } } -EuiPopover.propTypes = { +export const EuiPopoverPropTypes = { anchorClassName: PropTypes.string, anchorPosition: PropTypes.oneOf(ANCHOR_POSITIONS), isOpen: PropTypes.bool, @@ -505,9 +512,11 @@ EuiPopover.propTypes = { withTitle: PropTypes.bool, closePopover: PropTypes.func.isRequired, button: PropTypes.node.isRequired, + buttonRef: PropTypes.func, children: PropTypes.node, panelClassName: PropTypes.string, panelPaddingSize: PropTypes.oneOf(SIZES), + panelRef: PropTypes.func, popoverRef: PropTypes.func, hasArrow: PropTypes.bool, container: PropTypes.instanceOf(HTMLElement), @@ -532,6 +541,8 @@ EuiPopover.propTypes = { display: PropTypes.oneOf(DISPLAY), }; +EuiPopover.propTypes = EuiPopoverPropTypes; + EuiPopover.defaultProps = { isOpen: false, ownFocus: false,