diff --git a/src/components/datagrid/controls/__snapshots__/column_selector.test.tsx.snap b/src/components/datagrid/controls/__snapshots__/column_selector.test.tsx.snap index 7bcf150efde..e1e8d65ead3 100644 --- a/src/components/datagrid/controls/__snapshots__/column_selector.test.tsx.snap +++ b/src/components/datagrid/controls/__snapshots__/column_selector.test.tsx.snap @@ -80,20 +80,20 @@ exports[`useDataGridColumnSelector columnSelector [React 17] renders a toolbar b class="euiDataGrid__controlScroll" >

- + <> {filteredColumns.map((id, index) => ( {(provided, state) => (

))} - +
diff --git a/src/components/datagrid/controls/column_sorting_draggable.tsx b/src/components/datagrid/controls/column_sorting_draggable.tsx index a26b08b00c0..2fa7f1264b3 100644 --- a/src/components/datagrid/controls/column_sorting_draggable.tsx +++ b/src/components/datagrid/controls/column_sorting_draggable.tsx @@ -7,6 +7,8 @@ */ import React, { FunctionComponent } from 'react'; +import classNames from 'classnames'; + import { EuiScreenReaderOnly } from '../../accessibility'; import { EuiButtonGroup, EuiButtonIcon } from '../../button'; import { EuiDraggable } from '../../drag_and_drop'; @@ -78,9 +80,9 @@ export const EuiDataGridColumnSortingDraggable: FunctionComponent< > {(provided, state) => (

diff --git a/src/components/datagrid/data_grid.test.tsx b/src/components/datagrid/data_grid.test.tsx index 6310d80483c..c6c48e0fa77 100644 --- a/src/components/datagrid/data_grid.test.tsx +++ b/src/components/datagrid/data_grid.test.tsx @@ -1813,7 +1813,7 @@ describe('EuiDataGrid', () => { let popover = openColumnSelector(component); expect( popover - .find('.euiDataGridColumnSelector__item') + .find('div.euiDataGridColumnSelector__item') .map((item) => item.text()) ).toEqual(['A', 'B']); closeColumnSelector(component); @@ -1831,7 +1831,7 @@ describe('EuiDataGrid', () => { popover = openColumnSelector(component); expect( popover - .find('.euiDataGridColumnSelector__item') + .find('div.euiDataGridColumnSelector__item') .map((item) => item.text()) ).toEqual(['A', 'C']); closeColumnSelector(component); diff --git a/src/components/drag_and_drop/__snapshots__/drag_drop_context.test.tsx.snap b/src/components/drag_and_drop/__snapshots__/drag_drop_context.test.tsx.snap index 0cebb4a6dc4..1514a4db265 100644 --- a/src/components/drag_and_drop/__snapshots__/drag_drop_context.test.tsx.snap +++ b/src/components/drag_and_drop/__snapshots__/drag_drop_context.test.tsx.snap @@ -1,3 +1,3 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`EuiDragDropContext is rendered 1`] = `

`; +exports[`EuiDragDropContext renders 1`] = `
`; diff --git a/src/components/drag_and_drop/__snapshots__/draggable.test.tsx.snap b/src/components/drag_and_drop/__snapshots__/draggable.test.tsx.snap index 5057e393180..9784c6be25d 100644 --- a/src/components/drag_and_drop/__snapshots__/draggable.test.tsx.snap +++ b/src/components/drag_and_drop/__snapshots__/draggable.test.tsx.snap @@ -2,25 +2,25 @@ exports[`[React 17] EuiDraggable renders 1`] = `
Hello
@@ -33,25 +33,25 @@ exports[`[React 17] EuiDraggable renders 1`] = ` exports[`[React 18] EuiDraggable renders 1`] = `
Hello
diff --git a/src/components/drag_and_drop/__snapshots__/droppable.test.tsx.snap b/src/components/drag_and_drop/__snapshots__/droppable.test.tsx.snap index ca502ceeded..5fec44c8567 100644 --- a/src/components/drag_and_drop/__snapshots__/droppable.test.tsx.snap +++ b/src/components/drag_and_drop/__snapshots__/droppable.test.tsx.snap @@ -1,89 +1,93 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`[React 17] EuiDroppable can be given ReactElement children 1`] = ` -
-
+exports[`[React 17] EuiDroppable renders 1`] = ` +
-
-`; - -exports[`[React 17] EuiDroppable can be given multiple ReactElement children 1`] = ` -
-
-
-
-
-`; - -exports[`[React 17] EuiDroppable is rendered 1`] = ` -
-
+
+
+
+
+
+
-
+ + `; -exports[`[React 18] EuiDroppable can be given ReactElement children 1`] = ` -
-
+exports[`[React 18] EuiDroppable renders 1`] = ` +
-
-`; - -exports[`[React 18] EuiDroppable can be given multiple ReactElement children 1`] = ` -
-
-
-
-
-`; - -exports[`[React 18] EuiDroppable is rendered 1`] = ` -
-
+
+
+
+
+
+
-
+ + `; diff --git a/src/components/drag_and_drop/_draggable.scss b/src/components/drag_and_drop/_draggable.scss deleted file mode 100644 index b631df02198..00000000000 --- a/src/components/drag_and_drop/_draggable.scss +++ /dev/null @@ -1,41 +0,0 @@ -.euiDraggable { - &.euiDraggable--isDragging { - // Overriding inline styles on JS-inserted HTML elements - z-index: $euiZLevel9 !important; // stylelint-disable-line declaration-no-important - } - - &.euiDraggable--hasClone:not(.euiDraggable--isDragging) { - // Overriding inline styles on JS-inserted HTML elements - transform: none !important; // stylelint-disable-line declaration-no-important - } - - &.euiDraggable--withoutDropAnimation { - // Overriding inline styles on JS-inserted HTML elements - transition-duration: .001s !important; // stylelint-disable-line declaration-no-important - } - - &:focus > .euiDraggable__item, - &.euiDraggable--hasCustomDragHandle > .euiDraggable__item [data-react-beautiful-dnd-drag-handle]:focus { - @include euiFocusRing; - } - - .euiDraggable__item { - &.euiDraggable__item--isDisabled { - cursor: not-allowed; - } - - &.euiDraggable__item--isDragging { - // TODO: Resolve below - // Commenting this out for now, - // I'm thinking about adding an optional prop to auto-add these styles versus always having them - // @include euiBottomShadow; - // @include euiFocusRing; - } - } -} - -@each $size, $spacing in $euiDragAndDropSpacing { - .euiDraggable--#{$size} { - padding: $spacing; - } -} diff --git a/src/components/drag_and_drop/_droppable.scss b/src/components/drag_and_drop/_droppable.scss deleted file mode 100644 index de9e73c002d..00000000000 --- a/src/components/drag_and_drop/_droppable.scss +++ /dev/null @@ -1,40 +0,0 @@ -.euiDroppable { - $euiDroppableColor: $euiColorSuccess; - transition: background-color $euiAnimSpeedExtraSlow ease; - - &.euiDroppable--isDraggingType:not(.euiDroppable--isDisabled) { - background-color: transparentize($euiDroppableColor, .9); - - &.euiDroppable--isDraggingOver { - background-color: transparentize($euiDroppableColor, .75); - } - } - - .euiDroppable__placeholder { - &.euiDroppable__placeholder--isHidden { - // Overriding inline styles on JS-inserted HTML elements - display: none !important; // stylelint-disable-line declaration-no-important - } - } -} - -@include euiPanel($selector: '.euiDroppable--withPanel'); - -.euiDroppable--withPanel { - @include euiBottomShadowMedium; - border-radius: $euiBorderRadius; -} - -.euiDroppable--noGrow { - flex-grow: 0; -} - -.euiDroppable--grow { - flex-grow: 1; -} - -@each $size, $spacing in $euiDragAndDropSpacing { - .euiDroppable--#{$size} { - padding: $spacing; - } -} diff --git a/src/components/drag_and_drop/_index.scss b/src/components/drag_and_drop/_index.scss deleted file mode 100644 index e3ae587b279..00000000000 --- a/src/components/drag_and_drop/_index.scss +++ /dev/null @@ -1,3 +0,0 @@ -@import 'variables'; -@import 'draggable'; -@import 'droppable'; diff --git a/src/components/drag_and_drop/_variables.scss b/src/components/drag_and_drop/_variables.scss deleted file mode 100644 index 65dc0d6a8b0..00000000000 --- a/src/components/drag_and_drop/_variables.scss +++ /dev/null @@ -1,5 +0,0 @@ -$euiDragAndDropSpacing: ( - s: ($euiSizeXS / 2), - m: ($euiSizeS / 2), - l: ($euiSize / 2), -); diff --git a/src/components/drag_and_drop/drag_drop_context.test.tsx b/src/components/drag_and_drop/drag_drop_context.test.tsx index 6768442df9f..5e800d8f726 100644 --- a/src/components/drag_and_drop/drag_drop_context.test.tsx +++ b/src/components/drag_and_drop/drag_drop_context.test.tsx @@ -7,59 +7,40 @@ */ import React from 'react'; -import { mount, ReactWrapper } from 'enzyme'; - -import { findTestSubject } from '../../test'; +import { render } from '../../test/rtl'; import { requiredProps } from '../../test/required_props'; -import { EuiDragDropContext } from './'; -import { EuiDragDropContextContext } from './drag_drop_context'; - -function snapshotDragDropContext(component: ReactWrapper) { - // Get the Portal's sibling and return its html - const renderedHtml = component.html(); - const container = document.createElement('div'); - container.innerHTML = renderedHtml; - return container.firstChild; -} +import { + EuiDragDropContext, + EuiDragDropContextContext, +} from './drag_drop_context'; describe('EuiDragDropContext', () => { - test('is rendered', () => { - const handler = jest.fn(); - const component = mount( - + it('renders', () => { + const { container } = render( + {}} {...requiredProps}>
); - expect(snapshotDragDropContext(component)).toMatchSnapshot(); + expect(container.firstChild).toMatchSnapshot(); }); - describe('custom behavior', () => { - describe('isDraggingType', () => { - test('is set on proprietary context', () => { - jest.mock('react', () => { - const react = jest.requireActual('react'); - return { - ...react, - useLayoutEffect: react.useEffect, - }; - }); - const handler = jest.fn(); - const component = mount( - - - {(value) => ( -
- {value.hasOwnProperty('isDraggingType') ? 'true' : 'false'} -
- )} -
-
- ); - - expect(findTestSubject(component, 'child').text()).toBe('true'); - }); + describe('isDraggingType', () => { + test('is set on proprietary context', () => { + const { getByTestSubject } = render( + {}}> + + {(value) => ( +
+ {value.hasOwnProperty('isDraggingType') ? 'true' : 'false'} +
+ )} +
+
+ ); + + expect(getByTestSubject('child')).toHaveTextContent('true'); }); }); }); diff --git a/src/components/drag_and_drop/draggable.styles.ts b/src/components/drag_and_drop/draggable.styles.ts new file mode 100644 index 00000000000..553147a1327 --- /dev/null +++ b/src/components/drag_and_drop/draggable.styles.ts @@ -0,0 +1,49 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { css } from '@emotion/react'; + +import { UseEuiTheme } from '../../services'; +import { sharedSpacingPadding } from './droppable.styles'; + +export const euiDraggableStyles = (euiThemeContext: UseEuiTheme) => { + const { euiTheme } = euiThemeContext; + + return { + euiDraggable: css` + &:focus { + outline: none; + + & > .euiDraggable__item { + outline: auto; + } + } + + /* !importants in this file override inline styles on JS-inserted HTML elements */ + /* stylelint-disable declaration-no-important */ + `, + isDragging: css` + z-index: ${euiTheme.levels.toast} !important; + `, + hasClone: css` + transform: none !important; + `, + isRemovable: css` + /* Removes the drop animation */ + transition-duration: 0.001s !important; + `, + spacing: sharedSpacingPadding(euiThemeContext), + }; +}; + +export const euiDraggableItemStyles = { + euiDraggable__item: css``, + disabled: css` + cursor: not-allowed; + `, +}; diff --git a/src/components/drag_and_drop/draggable.test.tsx b/src/components/drag_and_drop/draggable.test.tsx index 3b7d4dd43f2..8de9ca0c5dd 100644 --- a/src/components/drag_and_drop/draggable.test.tsx +++ b/src/components/drag_and_drop/draggable.test.tsx @@ -7,84 +7,90 @@ */ import React from 'react'; -import { render, screen } from '../../test/rtl'; +import { render } from '../../test/rtl'; import { requiredProps } from '../../test'; -import { describeByReactVersion } from '../../test/internal'; -import { EuiDragDropContext, EuiDraggable, EuiDroppable } from './'; +import { + shouldRenderCustomStyles, + describeByReactVersion, +} from '../../test/internal'; + +import { EuiDragDropContext, EuiDroppable } from './'; +import { EuiDraggable } from './draggable'; describeByReactVersion('EuiDraggable', () => { - it('renders', () => { - const handler = jest.fn(); + const TestContextWrapper = ({ children }: { children: any }) => ( + {}}> + {children} + + ); + + shouldRenderCustomStyles( + + {() =>
Hello
} +
, + { wrapper: TestContextWrapper } + ); + it('renders', () => { const { container } = render( - - - - {() =>
Hello
} -
-
-
+ + + {() =>
Hello
} +
+
); - expect(screen.getByTestSubject('draggable')).toBeVisible(); expect(container.firstChild).toMatchSnapshot(); }); it('renders with render prop children', () => { - const handler = jest.fn(); - - render( - - - - {() =>
Hello
} -
-
-
+ const { getByTestSubject } = render( + + + {() =>
Hello
} +
+
); - expect(screen.getByText('Hello')).toBeVisible(); + expect(getByTestSubject('draggable')).toHaveTextContent('Hello'); }); it('renders with react element children', () => { - const handler = jest.fn(); - - render( - - - -
Hello
-
-
-
+ const { getByTestSubject } = render( + + +
Hello
+
+
); - expect(screen.getByText('Hello')).toBeVisible(); + expect(getByTestSubject('draggable')).toHaveTextContent('Hello'); }); it('should render with role="group" and no tabIndex when hasInteractiveChildren is true', () => { - const handler = jest.fn(); - - const doRender = (hasInteractiveChildren: boolean) => - render( - - - -
Hello
-
-
-
- ); + const Test = ({ + hasInteractiveChildren, + }: { + hasInteractiveChildren: boolean; + }) => ( + + +
Hello
+
+
+ ); - doRender(false); - expect(screen.queryByRole('group')).toBeNull(); + const { queryByRole, rerender } = render( + + ); + expect(queryByRole('group')).toBeNull(); - doRender(true); - expect(screen.getByRole('group')).toBeVisible(); - expect(screen.getByRole('group')).not.toHaveAttribute('tabindex', 0); + rerender(); + expect(queryByRole('group')).toBeVisible(); + expect(queryByRole('group')).not.toHaveAttribute('tabindex', 0); }); }); diff --git a/src/components/drag_and_drop/draggable.tsx b/src/components/drag_and_drop/draggable.tsx index 0d343deacab..a9fb66dacc5 100644 --- a/src/components/drag_and_drop/draggable.tsx +++ b/src/components/drag_and_drop/draggable.tsx @@ -8,25 +8,18 @@ import React, { CSSProperties, - Fragment, FunctionComponent, ReactElement, - cloneElement, useContext, } from 'react'; import { Draggable, DraggableProps } from '@hello-pangea/dnd'; import classNames from 'classnames'; -import { CommonProps } from '../common'; -import { EuiDroppableContext } from './droppable'; -const spacingToClassNameMap = { - none: null, - s: 'euiDraggable--s', - m: 'euiDraggable--m', - l: 'euiDraggable--l', -}; +import { useEuiTheme, cloneElementWithCss } from '../../services'; +import { CommonProps } from '../common'; -export type EuiDraggableSpacing = keyof typeof spacingToClassNameMap; +import { EuiDroppableContext, SPACINGS } from './droppable'; +import { euiDraggableStyles, euiDraggableItemStyles } from './draggable.styles'; export interface EuiDraggableProps extends CommonProps, @@ -52,7 +45,7 @@ export interface EuiDraggableProps /** * Adds padding to the draggable item */ - spacing?: EuiDraggableSpacing; + spacing?: (typeof SPACINGS)[number]; style?: CSSProperties; } @@ -72,6 +65,9 @@ export const EuiDraggable: FunctionComponent = ({ }) => { const { cloneItems } = useContext(EuiDroppableContext); + const euiTheme = useEuiTheme(); + const styles = euiDraggableStyles(euiTheme); + return ( = ({ {...rest} > {(provided, snapshot, rubric) => { - const classes = classNames( - 'euiDraggable', - { - 'euiDraggable--hasClone': cloneItems, - 'euiDraggable--hasCustomDragHandle': customDragHandle, - 'euiDraggable--isDragging': snapshot.isDragging, - 'euiDraggable--withoutDropAnimation': isRemovable, - }, - spacingToClassNameMap[spacing], - className - ); + const { isDragging } = snapshot; + + const cssStyles = [ + styles.euiDraggable, + cloneItems && !isDragging && styles.hasClone, + isDragging && styles.isDragging, + isRemovable && styles.isRemovable, + styles.spacing[spacing], + ]; + + const classes = classNames('euiDraggable', className); const childClasses = classNames('euiDraggable__item', { - 'euiDraggable__item--hasCustomDragHandle': customDragHandle, - 'euiDraggable__item--isDisabled': isDragDisabled, - 'euiDraggable__item--isDragging': snapshot.isDragging, - 'euiDraggable__item--isDropAnimating': snapshot.isDropAnimating, + 'euiDraggable__item-isDisabled': isDragDisabled, }); const DraggableElement: ReactElement = typeof children === 'function' ? (children(provided, snapshot, rubric) as ReactElement) : children; return ( - + <>
= ({ : provided.dragHandleProps?.tabIndex } > - {cloneElement(DraggableElement, { + {cloneElementWithCss(DraggableElement, { className: classNames( DraggableElement.props.className, childClasses ), + css: [ + euiDraggableItemStyles.euiDraggable__item, + isDragDisabled && euiDraggableItemStyles.disabled, + ], })}
- {cloneItems && snapshot.isDragging && ( -
+ {cloneItems && isDragging && ( +
{DraggableElement}
)} - + ); }} diff --git a/src/components/drag_and_drop/droppable.styles.ts b/src/components/drag_and_drop/droppable.styles.ts new file mode 100644 index 00000000000..dd4bf3726d2 --- /dev/null +++ b/src/components/drag_and_drop/droppable.styles.ts @@ -0,0 +1,53 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { css } from '@emotion/react'; + +import { UseEuiTheme, transparentize } from '../../services'; +import { euiCanAnimate } from '../../global_styling'; + +export const euiDroppableStyles = (euiThemeContext: UseEuiTheme) => { + const { euiTheme } = euiThemeContext; + + const droppableColor = euiTheme.colors.success; + + return { + euiDroppable: css` + ${euiCanAnimate} { + transition: background-color ${euiTheme.animation.slow} ease; + } + `, + isDragging: css` + background-color: ${transparentize(droppableColor, 0.1)}; + `, + isDraggingOver: css` + background-color: ${transparentize(droppableColor, 0.25)}; + `, + grow: css` + flex-grow: 1; + `, + noGrow: css` + flex-grow: 0; + `, + spacing: sharedSpacingPadding(euiThemeContext), + }; +}; + +// Droppable and draggable components both have the same shared spacing/padding values +export const sharedSpacingPadding = ({ euiTheme }: UseEuiTheme) => ({ + none: null, + s: css` + padding: ${euiTheme.size.xxs}; + `, + m: css` + padding: ${euiTheme.size.xs}; + `, + l: css` + padding: ${euiTheme.size.s}; + `, +}); diff --git a/src/components/drag_and_drop/droppable.test.tsx b/src/components/drag_and_drop/droppable.test.tsx index 6fee1e123b7..71fabfa6056 100644 --- a/src/components/drag_and_drop/droppable.test.tsx +++ b/src/components/drag_and_drop/droppable.test.tsx @@ -7,140 +7,91 @@ */ import React from 'react'; -import { mount, ReactWrapper } from 'enzyme'; import { resetServerContext } from '@hello-pangea/dnd'; - -import { findTestSubject, requiredProps } from '../../test'; +import { render } from '../../test/rtl'; +import { requiredProps } from '../../test'; import { + shouldRenderCustomStyles, invokeOnReactVersion, describeByReactVersion, } from '../../test/internal'; -import { EuiDragDropContext, EuiDroppable } from './'; -import { EuiDroppableContext } from './droppable'; - -function snapshotDragDropContext(component: ReactWrapper) { - // Get the Portal's sibling and return its html - const renderedHtml = component.html(); - const container = document.createElement('div'); - container.innerHTML = renderedHtml; - return container.firstChild; -} +import { EuiDragDropContext } from './drag_drop_context'; +import { EuiDroppable, EuiDroppableContext } from './droppable'; describeByReactVersion('EuiDroppable', () => { + const requiredContextProps = { onDragEnd: () => {} }; + afterEach(() => { // Resetting DND server context is only required in older versions of React invokeOnReactVersion(['16', '17'], resetServerContext); }); - test('is rendered', () => { - const handler = jest.fn(); - jest.mock('react', () => { - const react = jest.requireActual('react'); - return { - ...react, - useLayoutEffect: react.useEffect, - }; - }); - const component = mount( - - {() =>
} + shouldRenderCustomStyles( + {() =>
}, + { wrapper: EuiDragDropContext } + ); + + it('renders', () => { + const { baseElement } = render( + + + {() =>
} + ); - expect(snapshotDragDropContext(component)).toMatchSnapshot(); + expect(baseElement).toMatchSnapshot(); }); - test('can be given ReactElement children', () => { - const handler = jest.fn(); - jest.mock('react', () => { - const react = jest.requireActual('react'); - return { - ...react, - useLayoutEffect: react.useEffect, - }; - }); - const component = mount( - + it('can be given ReactElement children', () => { + const { getByTestSubject } = render( + -
+
); - expect(snapshotDragDropContext(component)).toMatchSnapshot(); + expect(getByTestSubject('reactChildren')).toBeInTheDocument(); }); - test('can be given multiple ReactElement children', () => { - const handler = jest.fn(); - jest.mock('react', () => { - const react = jest.requireActual('react'); - return { - ...react, - useLayoutEffect: react.useEffect, - }; - }); - - const component = mount( - + it('can be given multiple ReactElement children', () => { + const { getByTestSubject } = render( + -
-
-
+
+
+
); - expect(snapshotDragDropContext(component)).toMatchSnapshot(); + expect(getByTestSubject('A')).toBeInTheDocument(); + expect(getByTestSubject('B')).toBeInTheDocument(); + expect(getByTestSubject('C')).toBeInTheDocument(); }); - describe('custom behavior', () => { - describe('cloneDraggables', () => { - jest.mock('react', () => { - const react = jest.requireActual('react'); - return { - ...react, - useLayoutEffect: react.useEffect, - }; - }); - - test('sets `cloneItems` on proprietary context', () => { - const handler = jest.fn(); - const component = mount( - - - - {({ cloneItems }) => ( -
- {cloneItems ? 'true' : 'false'} -
- )} -
-
-
- ); - - expect(findTestSubject(component, 'child').text()).toBe('true'); - }); - - test('sets `isDropDisabled`', () => { - const handler = jest.fn(); - const component = mount( - - - - {({ cloneItems }) => ( -
- {cloneItems ? 'true' : 'false'} -
- )} -
-
-
- ); - - expect(component.find('.euiDroppable--isDisabled').length).toBe(1); - }); + describe('cloneDraggables', () => { + it('sets `cloneItems` and `isDropDisabled` on proprietary context', () => { + const { container, getByTestSubject } = render( + + + + {({ cloneItems }) => ( +
+ {cloneItems ? 'true' : 'false'} +
+ )} +
+
+
+ ); + + expect(getByTestSubject('child')).toHaveTextContent('true'); + expect( + container.querySelector('.euiDroppable-isDisabled') + ).toBeInTheDocument(); }); }); }); diff --git a/src/components/drag_and_drop/droppable.tsx b/src/components/drag_and_drop/droppable.tsx index 735dc01f26b..a836cd05e47 100644 --- a/src/components/drag_and_drop/droppable.tsx +++ b/src/components/drag_and_drop/droppable.tsx @@ -14,17 +14,15 @@ import React, { } from 'react'; import { Droppable, DroppableProps } from '@hello-pangea/dnd'; import classNames from 'classnames'; + +import { useEuiTheme } from '../../services'; import { CommonProps } from '../common'; -import { EuiDragDropContextContext } from './drag_drop_context'; +import { EuiPanel } from '../panel'; -const spacingToClassNameMap = { - none: null, - s: 'euiDroppable--s', - m: 'euiDroppable--m', - l: 'euiDroppable--l', -}; +import { EuiDragDropContextContext } from './drag_drop_context'; +import { euiDroppableStyles } from './droppable.styles'; -export type EuiDroppableSpacing = keyof typeof spacingToClassNameMap; +export const SPACINGS = ['none', 's', 'm', 'l'] as const; export interface EuiDroppableProps extends CommonProps, @@ -42,7 +40,7 @@ export interface EuiDroppableProps /** * Adds padding to the droppable area */ - spacing?: EuiDroppableSpacing; + spacing?: (typeof SPACINGS)[number]; /** * Adds an EuiPanel style to the droppable area */ @@ -74,6 +72,10 @@ export const EuiDroppable: FunctionComponent = ({ }) => { const { isDraggingType } = useContext(EuiDragDropContextContext); const dropIsDisabled: boolean = cloneDraggables ? true : isDropDisabled; + + const euiTheme = useEuiTheme(); + const styles = euiDroppableStyles(euiTheme); + return ( = ({ {...rest} > {(provided, snapshot) => { + const { isDraggingOver } = snapshot; + + const PanelOrDiv = withPanel ? EuiPanel : 'div'; + const panelOrDivProps = withPanel + ? { + panelRef: provided.innerRef, + hasShadow: true, + paddingSize: 'none' as const, + } + : { ref: provided.innerRef }; + + const cssStyles = [ + styles.euiDroppable, + isDraggingType === type && !dropIsDisabled && styles.isDragging, + isDraggingOver && styles.isDraggingOver, + grow ? styles.grow : styles.noGrow, + styles.spacing[spacing], + ]; + const classes = classNames( 'euiDroppable', - { - 'euiDroppable--isDisabled': dropIsDisabled, - 'euiDroppable--isDraggingOver': snapshot.isDraggingOver, - 'euiDroppable--isDraggingType': isDraggingType === type, - 'euiDroppable--withPanel': withPanel, - 'euiDroppable--grow': grow, - 'euiDroppable--noGrow': !grow, - }, - spacingToClassNameMap[spacing], + { 'euiDroppable-isDisabled': dropIsDisabled }, className ); - const placeholderClasses = classNames('euiDroppable__placeholder', { - 'euiDroppable__placeholder--isHidden': cloneDraggables, - }); + const DroppableElement = typeof children === 'function' ? children(provided, snapshot) : children; + return ( -
= ({ > {DroppableElement} -
{provided.placeholder}
-
+ + ); }}
diff --git a/src/components/index.scss b/src/components/index.scss index a381f8cdea8..e916bfccef7 100644 --- a/src/components/index.scss +++ b/src/components/index.scss @@ -6,7 +6,6 @@ @import 'control_bar/index'; @import 'date_picker/index'; @import 'datagrid/index'; -@import 'drag_and_drop/index'; @import 'empty_prompt/index'; @import 'form/index'; @import 'markdown_editor/index'; diff --git a/upcoming_changelogs/7187.md b/upcoming_changelogs/7187.md new file mode 100644 index 00000000000..369e9205a09 --- /dev/null +++ b/upcoming_changelogs/7187.md @@ -0,0 +1,3 @@ +**CSS-in-JS conversions** + +- Converted `EuiDroppable` and `EuiDraggable` to Emotion; Removed `$euiDragAndDropSpacing` Sass variables