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

[EuiSuperSelect] Add popoverProps prop #5214

Merged
merged 13 commits into from
Sep 28, 2021
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).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yay for MD renderer!! 🎉

* 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'>>;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oof, this Omit<> did not parse well 💀


/**
* 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