Skip to content

Commit

Permalink
[EuiPopover] Add hasDragDrop prop for popovers with draggable conte…
Browse files Browse the repository at this point in the history
…xts (elastic#6329)

* Add `hasDragDrop` prop and styles to EuiPopover

- which affords / accounts for styling for popovers that contain drag/droppable contexts

* Fix EuiDataGrid popovers with drag & drop

* Fix popover arrows no longer being visible

- due to using box-shadow instead of filter - we now need to add a custom drop shadow onto the arrows

+ add a CSS className hook to the arrow div

* Changelog
  • Loading branch information
Constance authored and chandlerprall committed Nov 1, 2022
1 parent 3733f71 commit 869f130
Show file tree
Hide file tree
Showing 15 changed files with 119 additions and 35 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,15 @@ exports[`useDataGridColumnSelector columnSelector renders a toolbar button/popov
aria-describedby="generated-id"
aria-live="off"
aria-modal="true"
class="euiPanel euiPanel--plain euiPanel--paddingSmall euiPopover__panel euiDataGrid__controlPopoverWithDragDrop emotion-euiPanel-grow-m-s-plain-euiPopover__panel"
class="euiPanel euiPanel--plain euiPanel--paddingSmall euiPopover__panel emotion-euiPanel-grow-m-s-plain-euiPopover__panel-hasDragDrop-bottom"
data-autofocus="true"
data-popover-panel="true"
role="dialog"
style="top: 16px; left: -22px; will-change: transform, opacity; z-index: 2000;"
tabindex="0"
>
<div
class="emotion-euiPopoverArrow-bottom"
class="euiPopover__arrow emotion-euiPopoverArrow-bottom"
data-popover-arrow="bottom"
style="left: 10px; top: 0px;"
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,15 @@ exports[`useDataGridColumnSorting columnSorting renders a toolbar button/popover
aria-describedby="generated-id"
aria-live="off"
aria-modal="true"
class="euiPanel euiPanel--plain euiPanel--paddingSmall euiPopover__panel euiDataGrid__controlPopoverWithDragDrop emotion-euiPanel-grow-m-s-plain-euiPopover__panel"
class="euiPanel euiPanel--plain euiPanel--paddingSmall euiPopover__panel emotion-euiPanel-grow-m-s-plain-euiPopover__panel-hasDragDrop-bottom"
data-autofocus="true"
data-popover-panel="true"
role="dialog"
style="top: 16px; left: -22px; will-change: transform, opacity; z-index: 2000;"
tabindex="0"
>
<div
class="emotion-euiPopoverArrow-bottom"
class="euiPopover__arrow emotion-euiPopoverArrow-bottom"
data-popover-arrow="bottom"
style="left: 10px; top: 0px;"
/>
Expand Down
8 changes: 0 additions & 8 deletions src/components/datagrid/controls/_data_grid_toolbar.scss
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,6 @@
}
}

.euiDataGrid__controlPopoverWithDragDrop {
// Hack because the fixed positions of drag and drop don't work inside of transformed elements
// sass-lint:disable-block no-important
transform: none !important;
transition: none !important;
margin-top: -$euiSizeS;
}

.euiDataGrid__controlScroll {
@include euiYScrollWithShadows;
max-height: $euiDataGridPopoverMaxHeight;
Expand Down
2 changes: 1 addition & 1 deletion src/components/datagrid/controls/column_selector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ export const useDataGridColumnSelector = (
closePopover={() => setIsOpen(false)}
anchorPosition="downLeft"
panelPaddingSize="s"
panelClassName="euiDataGrid__controlPopoverWithDragDrop"
hasDragDrop
button={
<EuiButtonEmpty
size="xs"
Expand Down
2 changes: 1 addition & 1 deletion src/components/datagrid/controls/column_sorting.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ export const useDataGridColumnSorting = (
closePopover={() => setIsOpen(false)}
anchorPosition="downLeft"
panelPaddingSize="s"
panelClassName="euiDataGrid__controlPopoverWithDragDrop"
hasDragDrop
button={
<EuiButtonEmpty
size="xs"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ exports[`EuiPopover snapshot testing renders with popover contents 1`] = `
tabindex="0"
>
<div
class="emotion-euiPopoverArrow-bottom"
class="euiPopover__arrow emotion-euiPopoverArrow-bottom"
data-popover-arrow="bottom"
style="left: 10px; top: 0px;"
/>
Expand Down
24 changes: 12 additions & 12 deletions src/components/popover/__snapshots__/popover.test.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ exports[`EuiPopover props arrowChildren is rendered 1`] = `
tabindex="0"
>
<div
class="emotion-euiPopoverArrow-bottom"
class="euiPopover__arrow emotion-euiPopoverArrow-bottom"
data-popover-arrow="bottom"
style="left: 10px; top: 0px;"
>
Expand Down Expand Up @@ -177,7 +177,7 @@ exports[`EuiPopover props buffer 1`] = `
tabindex="0"
>
<div
class="emotion-euiPopoverArrow-bottom"
class="euiPopover__arrow emotion-euiPopoverArrow-bottom"
data-popover-arrow="bottom"
style="left: 10px; top: 0px;"
/>
Expand Down Expand Up @@ -236,7 +236,7 @@ exports[`EuiPopover props buffer for all sides 1`] = `
tabindex="0"
>
<div
class="emotion-euiPopoverArrow-bottom"
class="euiPopover__arrow emotion-euiPopoverArrow-bottom"
data-popover-arrow="bottom"
style="left: 10px; top: 0px;"
/>
Expand Down Expand Up @@ -308,7 +308,7 @@ exports[`EuiPopover props focusTrapProps is rendered 1`] = `
tabindex="0"
>
<div
class="emotion-euiPopoverArrow-bottom"
class="euiPopover__arrow emotion-euiPopoverArrow-bottom"
data-popover-arrow="bottom"
style="left: 10px; top: 0px;"
/>
Expand Down Expand Up @@ -380,7 +380,7 @@ exports[`EuiPopover props isOpen renders true 1`] = `
tabindex="0"
>
<div
class="emotion-euiPopoverArrow-bottom"
class="euiPopover__arrow emotion-euiPopoverArrow-bottom"
data-popover-arrow="bottom"
style="left: 10px; top: 0px;"
/>
Expand Down Expand Up @@ -439,7 +439,7 @@ exports[`EuiPopover props offset with arrow 1`] = `
tabindex="0"
>
<div
class="emotion-euiPopoverArrow-bottom"
class="euiPopover__arrow emotion-euiPopoverArrow-bottom"
data-popover-arrow="bottom"
style="left: 10px; top: 0px;"
/>
Expand Down Expand Up @@ -552,7 +552,7 @@ exports[`EuiPopover props ownFocus defaults to true 1`] = `
tabindex="0"
>
<div
class="emotion-euiPopoverArrow-bottom"
class="euiPopover__arrow emotion-euiPopoverArrow-bottom"
data-popover-arrow="bottom"
style="left: 10px; top: 0px;"
/>
Expand Down Expand Up @@ -608,7 +608,7 @@ exports[`EuiPopover props ownFocus renders false 1`] = `
style="top: 16px; left: -22px; will-change: transform, opacity; z-index: 2000;"
>
<div
class="emotion-euiPopoverArrow-bottom"
class="euiPopover__arrow emotion-euiPopoverArrow-bottom"
data-popover-arrow="bottom"
style="left: 10px; top: 0px;"
/>
Expand Down Expand Up @@ -661,7 +661,7 @@ exports[`EuiPopover props panelClassName is rendered 1`] = `
tabindex="0"
>
<div
class="emotion-euiPopoverArrow-bottom"
class="euiPopover__arrow emotion-euiPopoverArrow-bottom"
data-popover-arrow="bottom"
style="left: 10px; top: 0px;"
/>
Expand Down Expand Up @@ -720,7 +720,7 @@ exports[`EuiPopover props panelPaddingSize is rendered 1`] = `
tabindex="0"
>
<div
class="emotion-euiPopoverArrow-bottom"
class="euiPopover__arrow emotion-euiPopoverArrow-bottom"
data-popover-arrow="bottom"
style="left: 10px; top: 0px;"
/>
Expand Down Expand Up @@ -780,7 +780,7 @@ exports[`EuiPopover props panelProps is rendered 1`] = `
tabindex="0"
>
<div
class="emotion-euiPopoverArrow-bottom"
class="euiPopover__arrow emotion-euiPopoverArrow-bottom"
data-popover-arrow="bottom"
style="left: 10px; top: 0px;"
/>
Expand Down Expand Up @@ -837,7 +837,7 @@ exports[`EuiPopover props popoverScreenReaderText 1`] = `
style="top: 16px; left: -22px; will-change: transform, opacity; z-index: 2000;"
>
<div
class="emotion-euiPopoverArrow-bottom"
class="euiPopover__arrow emotion-euiPopoverArrow-bottom"
data-popover-arrow="bottom"
style="left: 10px; top: 0px;"
/>
Expand Down
7 changes: 7 additions & 0 deletions src/components/popover/popover.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,11 @@ export interface EuiPopoverProps extends CommonProps {
* an `EuiPopover` in a scrollable container, `repositionOnScroll` should be `true`
*/
repositionOnScroll?: boolean;
/**
* Must be set to true if using `EuiDragDropContext` within a popover,
* otherwise your nested drag & drop will have incorrect positioning
*/
hasDragDrop?: boolean;
/**
* By default, popover content inherits the z-index of the anchor
* component; pass `zIndex` to override
Expand Down Expand Up @@ -613,6 +618,7 @@ export class EuiPopover extends Component<Props, State> {
hasArrow,
arrowChildren,
repositionOnScroll,
hasDragDrop,
zIndex,
attachToAnchor,
display,
Expand Down Expand Up @@ -709,6 +715,7 @@ export class EuiPopover extends Component<Props, State> {
position={this.state.arrowPosition}
isAttached={attachToAnchor}
className={classNames(panelClassName, panelProps?.className)}
hasDragDrop={hasDragDrop}
hasShadow={false}
paddingSize={panelPaddingSize}
tabIndex={tabIndex}
Expand Down
7 changes: 6 additions & 1 deletion src/components/popover/popover_arrow/_popover_arrow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,12 @@ export const EuiPopoverArrow: FunctionComponent<EuiPopoverArrowProps> = ({
const cssStyles = [styles.euiPopoverArrow, styles[position]];

return (
<div data-popover-arrow={position} css={cssStyles} {...rest}>
<div
className="euiPopover__arrow"
data-popover-arrow={position}
css={cssStyles}
{...rest}
>
{children}
</div>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,13 @@ exports[`EuiPopoverPanel is rendered 1`] = `
/>
`;

exports[`EuiPopoverPanel props hasDragDrop is rendered 1`] = `
<div
class="euiPanel euiPanel--plain euiPanel--paddingMedium euiPopover__panel emotion-euiPanel-grow-m-m-plain-hasShadow-euiPopover__panel-hasDragDrop"
data-popover-panel="true"
/>
`;

exports[`EuiPopoverPanel props isAttached is rendered 1`] = `
<div
class="euiPanel euiPanel--plain euiPanel--paddingMedium euiPopover__panel emotion-euiPanel-grow-m-m-plain-hasShadow-euiPopover__panel-isOpen"
Expand Down
47 changes: 46 additions & 1 deletion src/components/popover/popover_panel/_popover_panel.styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
euiShadowFlat,
euiShadowMedium,
} from '../../../themes/amsterdam/global_styling/mixins';
import { getShadowColor } from '../../../themes/amsterdam/global_styling/functions';
import { UseEuiTheme } from '../../../services';
import { euiCanAnimate, logicalCSS } from '../../../global_styling';

Expand All @@ -25,7 +26,7 @@ const translateDistance = 's';
*/

export const euiPopoverPanelStyles = (euiThemeContext: UseEuiTheme) => {
const { euiTheme } = euiThemeContext;
const { euiTheme, colorMode } = euiThemeContext;

return {
// Base
Expand Down Expand Up @@ -91,5 +92,49 @@ export const euiPopoverPanelStyles = (euiThemeContext: UseEuiTheme) => {
left: css``,
right: css``,
},

// Overrides for drag & drop contexts within popovers. This is required because
// the fixed positions of drag and drop don't work inside of transformed elements
hasDragDrop: {
hasDragDrop: css`
transform: none;
// Filter also causes a stacking context that interferes with the positioned children,
// so we disable it and recreate the shadow via box-shadow instead
filter: none;
${euiShadowMedium(euiThemeContext, { property: 'box-shadow' })};
`,
// The offset transforms must be recreated in margins
top: css`
margin-block-start: ${euiTheme.size[translateDistance]};
// Existing box-shadow of the popover is sufficient to see the arrow
`,
bottom: css`
margin-block-start: -${euiTheme.size[translateDistance]};
.euiPopover__arrow {
filter: drop-shadow(
0 -6px 6px ${getShadowColor(euiTheme.colors.shadow, 0.12, colorMode)}
);
}
`,
left: css`
margin-inline-start: ${euiTheme.size[translateDistance]};
.euiPopover__arrow {
filter: drop-shadow(
6px 0 6px ${getShadowColor(euiTheme.colors.shadow, 0.12, colorMode)}
);
}
`,
right: css`
margin-inline-start: -${euiTheme.size[translateDistance]};
.euiPopover__arrow {
filter: drop-shadow(
-6px 0 6px ${getShadowColor(euiTheme.colors.shadow, 0.12, colorMode)}
);
}
`,
},
};
};
6 changes: 6 additions & 0 deletions src/components/popover/popover_panel/_popover_panel.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,12 @@ describe('EuiPopoverPanel', () => {
expect(component).toMatchSnapshot();
});

test('hasDragDrop is rendered', () => {
const component = render(<EuiPopoverPanel hasDragDrop />);

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

describe('position', () => {
POSITIONS.forEach((position) => {
test(`${position} is rendered`, () => {
Expand Down
19 changes: 18 additions & 1 deletion src/components/popover/popover_panel/_popover_panel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ type EuiPopoverPanelInternalProps = {
isOpen?: boolean;
isAttached?: boolean;
position?: EuiPopoverArrowPositions | null;
hasDragDrop?: boolean;
};

/**
Expand All @@ -36,7 +37,15 @@ type EuiPopoverPanelInternalProps = {
*/
export const EuiPopoverPanel: FunctionComponent<
EuiPopoverPanelProps & EuiPopoverPanelInternalProps
> = ({ children, className, isOpen, isAttached, position, ...rest }) => {
> = ({
children,
className,
isOpen,
isAttached,
hasDragDrop,
position,
...rest
}) => {
const panelContext = useContext(EuiPopoverPanelContext);
if (rest.paddingSize) panelContext.paddingSize = rest.paddingSize;

Expand All @@ -59,6 +68,14 @@ export const EuiPopoverPanel: FunctionComponent<
];
}

if (hasDragDrop) {
panelCSS = [
...panelCSS,
styles.hasDragDrop.hasDragDrop,
position && styles.hasDragDrop[position],
];
}

return (
<EuiPopoverPanelContext.Provider value={panelContext}>
<EuiPanel
Expand Down
Loading

0 comments on commit 869f130

Please sign in to comment.