Skip to content

Commit

Permalink
[EuiSuperSelect] Add popoverProps prop (#5214)
Browse files Browse the repository at this point in the history
* [EuiSuperSelect] Add `popoverPanelClassName` prop

Which gives users some way of targeting the portalled popover panel itself, rather than the outer popover wrapper

* Add unit test

* Add changelog entry

* [REVERT ME] Add documentation test example

- which also demonstrates the UI behavior @scottybollinger wants

* [PR feedback] Add popoverProps obj
- instead of single static popoverPanelClassName string

- this is more flexible and allows users more control of the underlying popover

* [REVERT ME] update example with popoverProps

* Fix bug in popover.className override

:facepalm: whoops

* Better documentation

should probably actually test these things..

* [PR feedback] Remove `isOpen` prop from being

* Revert documentation example

* [PR feedback] Changelog copy

Co-authored-by: Caroline Horn <549577+cchaos@users.noreply.github.com>

Co-authored-by: Caroline Horn <549577+cchaos@users.noreply.github.com>
  • Loading branch information
Constance and cchaos authored Sep 28, 2021
1 parent 8feb1cd commit 91abf40
Show file tree
Hide file tree
Showing 4 changed files with 276 additions and 12 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

- Updated `EuiRangeLevel` `color` property to accept CSS color values ([#5171](https://github.com/elastic/eui/pull/5171))
- Added optional visual line highlighting to `EuiCodeBlock` ([#5207](https://github.com/elastic/eui/pull/5207))
- Added `popoverProps` to `EuiSuperSelect` and deprecated `popoverClassName` & `repositionOnScroll` ([#5214](https://github.com/elastic/eui/pull/5214))

**Bug fixes**

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -703,6 +703,233 @@ exports[`EuiSuperSelect props options are rendered when select is open 1`] = `
</div>
`;

exports[`EuiSuperSelect props renders popoverProps on the underlying EuiPopover 1`] = `
<EuiSuperSelect
compressed={false}
fullWidth={false}
hasDividers={false}
isInvalid={false}
isLoading={false}
onChange={[Function]}
options={
Array [
Object {
"inputDisplay": "Option #1",
"value": "1",
},
Object {
"inputDisplay": "Option #2",
"value": "2",
},
]
}
popoverProps={
Object {
"className": "goes-on-outermost-wrapper",
"panelClassName": "goes-on-popover-panel",
"repositionOnScroll": true,
}
}
valueOfSelected="2"
>
<EuiInputPopover
anchorPosition="downLeft"
attachToAnchor={true}
className="euiSuperSelect goes-on-outermost-wrapper"
closePopover={[Function]}
display="block"
fullWidth={false}
input={
<EuiSuperSelectControl
className=""
compressed={false}
fullWidth={false}
isInvalid={false}
isLoading={false}
onClick={[Function]}
onKeyDown={[Function]}
options={
Array [
Object {
"inputDisplay": "Option #1",
"value": "1",
},
Object {
"inputDisplay": "Option #2",
"value": "2",
},
]
}
value="2"
/>
}
isOpen={false}
panelClassName="goes-on-popover-panel"
panelPaddingSize="none"
repositionOnScroll={true}
>
<EuiPopover
anchorPosition="downLeft"
attachToAnchor={true}
button={
<EuiResizeObserver
onResize={[Function]}
>
[Function]
</EuiResizeObserver>
}
buttonRef={[Function]}
className="euiInputPopover euiSuperSelect goes-on-outermost-wrapper"
closePopover={[Function]}
display="block"
hasArrow={true}
isOpen={false}
ownFocus={false}
panelClassName="goes-on-popover-panel"
panelPaddingSize="none"
panelRef={[Function]}
repositionOnScroll={true}
>
<EuiOutsideClickDetector
onOutsideClick={[Function]}
>
<div
className="euiPopover euiPopover--anchorDownLeft euiPopover--displayBlock euiInputPopover euiSuperSelect goes-on-outermost-wrapper"
onKeyDown={[Function]}
onMouseDown={[Function]}
onMouseUp={[Function]}
onTouchEnd={[Function]}
onTouchStart={[Function]}
>
<div
className="euiPopover__anchor"
>
<EuiResizeObserver
onResize={[Function]}
>
<div>
<EuiSuperSelectControl
className=""
compressed={false}
fullWidth={false}
isInvalid={false}
isLoading={false}
onClick={[Function]}
onKeyDown={[Function]}
options={
Array [
Object {
"inputDisplay": "Option #1",
"value": "1",
},
Object {
"inputDisplay": "Option #2",
"value": "2",
},
]
}
value="2"
>
<input
type="hidden"
value="2"
/>
<EuiFormControlLayout
compressed={false}
fullWidth={false}
icon={
Object {
"side": "right",
"type": "arrowDown",
}
}
isLoading={false}
>
<div
className="euiFormControlLayout"
>
<div
className="euiFormControlLayout__childrenWrapper"
>
<EuiScreenReaderOnly>
<span
className="euiScreenReaderOnly"
id="generated-id"
>
<EuiI18n
default="Select an option: {selectedValue}, is selected"
token="euiSuperSelectControl.selectAnOption"
values={
Object {
"selectedValue": "Option #2",
}
}
>
Select an option: Option #2, is selected
</EuiI18n>
</span>
</EuiScreenReaderOnly>
<button
aria-haspopup="true"
aria-labelledby="generated-id"
className="euiSuperSelectControl"
onClick={[Function]}
onKeyDown={[Function]}
type="button"
>
Option #2
</button>
<EuiFormControlLayoutIcons
compressed={false}
icon={
Object {
"side": "right",
"type": "arrowDown",
}
}
isLoading={false}
>
<div
className="euiFormControlLayoutIcons euiFormControlLayoutIcons--right"
>
<EuiFormControlLayoutCustomIcon
size="m"
type="arrowDown"
>
<span
className="euiFormControlLayoutCustomIcon"
>
<EuiIcon
aria-hidden="true"
className="euiFormControlLayoutCustomIcon__icon"
size="m"
type="arrowDown"
>
<span
aria-hidden="true"
className="euiFormControlLayoutCustomIcon__icon"
data-euiicon-type="arrowDown"
size="m"
/>
</EuiIcon>
</span>
</EuiFormControlLayoutCustomIcon>
</div>
</EuiFormControlLayoutIcons>
</div>
</div>
</EuiFormControlLayout>
</EuiSuperSelectControl>
</div>
</EuiResizeObserver>
</div>
</div>
</EuiOutsideClickDetector>
</EuiPopover>
</EuiInputPopover>
</EuiSuperSelect>
`;

exports[`EuiSuperSelect props select component is rendered 1`] = `
<div
class="euiPopover euiPopover--anchorDownLeft euiPopover--displayBlock euiInputPopover euiSuperSelect"
Expand Down
17 changes: 17 additions & 0 deletions src/components/form/super_select/super_select.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -161,5 +161,22 @@ describe('EuiSuperSelect', () => {

expect(takeMountedSnapshot(component)).toMatchSnapshot();
});

test('renders popoverProps on the underlying EuiPopover', () => {
const component = mount(
<EuiSuperSelect
options={options}
valueOfSelected="2"
onChange={() => {}}
popoverProps={{
className: 'goes-on-outermost-wrapper',
panelClassName: 'goes-on-popover-panel',
repositionOnScroll: true,
}}
/>
);

expect(component).toMatchSnapshot();
});
});
});
43 changes: 31 additions & 12 deletions src/components/form/super_select/super_select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import {
EuiSuperSelectControlProps,
EuiSuperSelectOption,
} from './super_select_control';
import { EuiInputPopover } from '../../popover';
import { EuiInputPopover, EuiPopoverProps } from '../../popover';
import {
EuiContextMenuItem,
EuiContextMenuItemLayoutAlignment,
Expand Down Expand Up @@ -69,20 +69,34 @@ export type EuiSuperSelectProps<T extends string> = CommonProps &
itemLayoutAlign?: EuiContextMenuItemLayoutAlignment;

/**
* Applied to the outermost wrapper (popover)
* Controls whether the options are shown. Default: false
*/
popoverClassName?: string;
isOpen?: boolean;

/**
* Controls whether the options are shown. Default: false
* Optional props to pass to the underlying [EuiPopover](/#/layout/popover).
* Allows fine-grained control of the popover dropdown menu, including
* `repositionOnScroll` for EuiSuperSelects used within scrollable containers,
* and customizing popover panel styling.
*
* Does not accept a nested `popoverProps.isOpen` property - use the top level
* `isOpen` API instead.
*/
isOpen?: boolean;
popoverProps?: Partial<CommonProps & Omit<EuiPopoverProps, 'isOpen'>>;

/**
* Applied to the outermost wrapper (popover)
*
* **DEPRECATED: Use `popoverProps.className` instead (will take precedence over this prop if set).**
*/
popoverClassName?: string;

/**
* When `true`, the popover's position is re-calculated when the user
* scrolls, this supports having fixed-position popover anchors. This value is passed
* to the EuiInputPopover component. When nesting an `EuiSuperSelect` in a scrollable container,
* scrolls. When nesting an `EuiSuperSelect` in a scrollable container,
* `repositionOnScroll` should be `true`
*
* **DEPRECATED: Use `popoverProps.repositionOnScroll` instead (will take precedence over this prop if set).**
*/
repositionOnScroll?: boolean;
};
Expand Down Expand Up @@ -259,12 +273,16 @@ export class EuiSuperSelect<T extends string> extends Component<
itemLayoutAlign,
fullWidth,
popoverClassName,
popoverProps,
compressed,
repositionOnScroll,
...rest
} = this.props;

const popoverClasses = classNames('euiSuperSelect', popoverClassName);
const popoverClasses = classNames(
'euiSuperSelect',
popoverProps?.className ?? popoverClassName
);

const buttonClasses = classNames(
{
Expand Down Expand Up @@ -321,13 +339,14 @@ export class EuiSuperSelect<T extends string> extends Component<

return (
<EuiInputPopover
className={popoverClasses}
input={button}
isOpen={isOpen || this.state.isPopoverOpen}
closePopover={this.closePopover}
panelPaddingSize="none"
fullWidth={fullWidth}
repositionOnScroll={repositionOnScroll}
{...popoverProps}
className={popoverClasses}
isOpen={isOpen || this.state.isPopoverOpen}
input={button}
fullWidth={fullWidth}
>
<EuiScreenReaderOnly>
<p role="alert">
Expand Down

0 comments on commit 91abf40

Please sign in to comment.