diff --git a/src/plugins/wizard/public/application/components/data_tab/dropbox.scss b/src/plugins/wizard/public/application/components/data_tab/dropbox.scss index dd2ab9c9d980..118c475ec590 100644 --- a/src/plugins/wizard/public/application/components/data_tab/dropbox.scss +++ b/src/plugins/wizard/public/application/components/data_tab/dropbox.scss @@ -13,24 +13,28 @@ &__container { display: grid; - grid-gap: $euiSizeXS; - padding: $euiSizeS; - background-color: #e9edf3; + grid-gap: $euiSizeXS / 2; + padding: $euiSizeS - ($euiSizeXS / 2) $euiSizeS $euiSizeS $euiSizeS; + background-color: $euiColorLightShade; border-radius: $euiBorderRadius; } &__field { display: grid; grid-template-columns: 1fr auto; - - // grid-template-columns: auto 1fr auto; grid-gap: $euiSizeS; padding: $euiSizeS $euiSizeM; align-items: center; } &__draggable { - padding: 2px 0; + padding: $euiSizeXS / 2 0; + animation: pop-in $euiAnimSpeedSlow $euiAnimSlightResistance forwards; + transform-origin: bottom; + + &.closing { + animation: pop-out $euiAnimSpeedSlow $euiAnimSlightResistance forwards; // Also update speed in dropbox.tsx + } } &__field_text { @@ -41,6 +45,8 @@ &__dropTarget { color: $euiColorDarkShade; grid-template-columns: 1fr auto; + transform-origin: top; + animation: pop-in $euiAnimSpeedFast $euiAnimSlightResistance forwards; &.validField { background-color: #a8d9e7; @@ -54,3 +60,43 @@ } } } + +@keyframes pop-in { + from { + max-height: 0; + opacity: 0; + } + + to { + max-height: 1000px; + opacity: 1; + } +} + +@keyframes pop-out { + from { + max-height: 1000px; + opacity: 1; + } + + to { + max-height: 0; + opacity: 0; + } +} + +@media (prefers-reduced-motion) { + .dropBox { + &__draggable { + animation: none; + + &.closing { + animation: none; + } + } + + &__dropTarget { + animation: none; + } + } +} diff --git a/src/plugins/wizard/public/application/components/data_tab/dropbox.tsx b/src/plugins/wizard/public/application/components/data_tab/dropbox.tsx index 451bbe4e52eb..9c6c9e290f8c 100644 --- a/src/plugins/wizard/public/application/components/data_tab/dropbox.tsx +++ b/src/plugins/wizard/public/application/components/data_tab/dropbox.tsx @@ -13,11 +13,12 @@ import { EuiText, DropResult, } from '@elastic/eui'; -import React, { useCallback } from 'react'; +import React, { useCallback, useState } from 'react'; import { IDropAttributes, IDropState } from '../../utils/drag_drop'; import './dropbox.scss'; import { useDropbox } from './use'; import { UseDropboxProps } from './use/use_dropbox'; +import { usePrefersReducedMotion } from './use/use_prefers_reduced_motion'; export interface DropboxDisplay { label: string; @@ -55,6 +56,8 @@ const DropboxComponent = ({ canDrop, dropProps, }: DropboxProps) => { + const prefersReducedMotion = usePrefersReducedMotion(); + const [closing, setClosing] = useState(false); const handleDragEnd = useCallback( ({ source, destination }: DropResult) => { if (!destination) return; @@ -67,13 +70,32 @@ const DropboxComponent = ({ [fields, onReorderField] ); + const animateDelete = useCallback( + (id: string) => { + setClosing(id); + setTimeout( + () => { + onDeleteField(id); + setClosing(false); + }, + prefersReducedMotion ? 0 : 350 // Also update speed in dropbox.scss + ); + }, + [onDeleteField, prefersReducedMotion] + ); + return (
{fields.map(({ id, label }, index) => ( - + onEditField(id)}> @@ -85,7 +107,7 @@ const DropboxComponent = ({ iconType="cross" aria-label="clear-field" iconSize="s" - onClick={() => onDeleteField(id)} + onClick={() => animateDelete(id)} /> diff --git a/src/plugins/wizard/public/application/components/data_tab/use/use_prefers_reduced_motion.ts b/src/plugins/wizard/public/application/components/data_tab/use/use_prefers_reduced_motion.ts new file mode 100644 index 000000000000..b88c3bc444d0 --- /dev/null +++ b/src/plugins/wizard/public/application/components/data_tab/use/use_prefers_reduced_motion.ts @@ -0,0 +1,31 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { useEffect, useState } from 'react'; + +const QUERY = '(prefers-reduced-motion: no-preference)'; + +export function usePrefersReducedMotion() { + const [prefersReducedMotion, setPrefersReducedMotion] = useState( + !window.matchMedia(QUERY).matches + ); + + useEffect(() => { + const mediaQueryList = window.matchMedia(QUERY); + const listener = (event) => { + setPrefersReducedMotion(!event.matches); + }; + + if (mediaQueryList.addEventListener) { + mediaQueryList.addEventListener('change', listener); + } + + return () => { + mediaQueryList.removeEventListener('change', listener); + }; + }, []); + + return prefersReducedMotion; +} diff --git a/src/plugins/wizard/public/application/components/workspace.tsx b/src/plugins/wizard/public/application/components/workspace.tsx index 94e0d037b4f6..0ce78eba9074 100644 --- a/src/plugins/wizard/public/application/components/workspace.tsx +++ b/src/plugins/wizard/public/application/components/workspace.tsx @@ -44,6 +44,7 @@ export const Workspace: FC = ({ children }) => { if (errorMsg) { toasts.addWarning(errorMsg); } + setExpression(undefined); return; } const exp = await toExpression(rootState);