From 6254179d0c82df53a62dad0a5f3faa4f2223e497 Mon Sep 17 00:00:00 2001 From: Ariya Hidayat <ariya@metabase.com> Date: Wed, 20 Oct 2021 07:07:31 -0700 Subject: [PATCH] For reduced motion, snap the motion translation (#18564) Also, in case reduced motion is preferred, increase the spring stiffness of the motion to finish the transition faster (timing-wide, the actual animation won't appear due to the above snapping). --- frontend/src/metabase/lib/dom.js | 5 +++ .../notebook/NotebookStepPreview.jsx | 37 +++++++++++++------ .../query_builder/components/view/View.jsx | 32 +++++++++++----- 3 files changed, 53 insertions(+), 21 deletions(-) diff --git a/frontend/src/metabase/lib/dom.js b/frontend/src/metabase/lib/dom.js index cd140a42362..820a3294ad8 100644 --- a/frontend/src/metabase/lib/dom.js +++ b/frontend/src/metabase/lib/dom.js @@ -426,3 +426,8 @@ export function isEventOverElement(event, element) { return y >= top && y <= bottom && x >= left && x <= right; } + +export function isReducedMotionPreferred() { + const mediaQuery = window.matchMedia("(prefers-reduced-motion: reduce)"); + return mediaQuery && mediaQuery.matches; +} diff --git a/frontend/src/metabase/query_builder/components/notebook/NotebookStepPreview.jsx b/frontend/src/metabase/query_builder/components/notebook/NotebookStepPreview.jsx index a418235c108..e340b2cd24d 100644 --- a/frontend/src/metabase/query_builder/components/notebook/NotebookStepPreview.jsx +++ b/frontend/src/metabase/query_builder/components/notebook/NotebookStepPreview.jsx @@ -4,6 +4,8 @@ import React from "react"; import cx from "classnames"; import _ from "underscore"; +import { isReducedMotionPreferred } from "metabase/lib/dom"; + import Icon from "metabase/components/Icon"; import Button from "metabase/components/Button"; import { Box, Flex } from "grid-styled"; @@ -47,6 +49,11 @@ class NotebookStepPreview extends React.Component { const isDirty = this.getIsDirty(); + const preferReducedMotion = isReducedMotionPreferred(); + const springOpts = preferReducedMotion + ? { stiffness: 500 } + : { stiffness: 170 }; + return ( <Box pt={2}> <Flex align="center" justify="space-between" mb={1}> @@ -72,18 +79,26 @@ class NotebookStepPreview extends React.Component { {({ rawSeries, result }) => ( <Motion defaultStyle={{ height: 36 }} - style={{ height: spring(getPreviewHeightForResult(result)) }} + style={{ + height: spring(getPreviewHeightForResult(result), springOpts), + }} > - {({ height }) => ( - <Visualization - rawSeries={rawSeries} - error={result && result.error} - className={cx("bordered shadowed rounded bg-white", { - p2: result && result.error, - })} - style={{ minHeight: height }} - /> - )} + {({ height }) => { + const targetHeight = getPreviewHeightForResult(result); + const snapHeight = + height > targetHeight / 2 ? targetHeight : 0; + const minHeight = preferReducedMotion ? snapHeight : height; + return ( + <Visualization + rawSeries={rawSeries} + error={result && result.error} + className={cx("bordered shadowed rounded bg-white", { + p2: result && result.error, + })} + style={{ minHeight }} + /> + ); + }} </Motion> )} </QuestionResultLoader> diff --git a/frontend/src/metabase/query_builder/components/view/View.jsx b/frontend/src/metabase/query_builder/components/view/View.jsx index a1eda306792..29f9ba04d72 100644 --- a/frontend/src/metabase/query_builder/components/view/View.jsx +++ b/frontend/src/metabase/query_builder/components/view/View.jsx @@ -4,6 +4,8 @@ import { t } from "ttag"; import cx from "classnames"; +import { isReducedMotionPreferred } from "metabase/lib/dom"; + import ExplicitSize from "metabase/components/ExplicitSize"; import Popover from "metabase/components/Popover"; import DebouncedFrame from "metabase/components/DebouncedFrame"; @@ -193,6 +195,14 @@ export default class View extends React.Component { const isSidebarOpen = leftSideBar || rightSideBar; + const MOTION_Y = -100; + + const preferReducedMotion = isReducedMotionPreferred(); + + const springOpts = preferReducedMotion + ? { stiffness: 500 } + : { stiffness: 170 }; + return ( <div className={fitClassNames}> <div className={cx("QueryBuilder flex flex-column bg-white spread")}> @@ -226,34 +236,36 @@ export default class View extends React.Component { defaultStyle={ isNewQuestion ? { opacity: 1, translateY: 0 } - : { opacity: 0, translateY: -100 } + : { opacity: 0, translateY: MOTION_Y } } style={ queryBuilderMode === "notebook" ? { - opacity: spring(1), - translateY: spring(0), + opacity: spring(1, springOpts), + translateY: spring(0, springOpts), } : { - opacity: spring(0), - translateY: spring(-100), + opacity: spring(0, springOpts), + translateY: spring(MOTION_Y, springOpts), } } > - {({ opacity, translateY }) => - opacity > 0 ? ( + {({ opacity, translateY }) => { + const snapY = translateY < MOTION_Y / 2 ? MOTION_Y : 0; + const shiftY = preferReducedMotion ? snapY : translateY; + return opacity > 0 ? ( // note the `bg-white class here is necessary to obscure the other layer <div className="spread bg-white scroll-y z2 border-top border-bottom" style={{ // opacity: opacity, - transform: `translateY(${translateY}%)`, + transform: `translateY(${shiftY}%)`, }} > <Notebook {...this.props} /> </div> - ) : null - } + ) : null; + }} </Motion> )} -- GitLab