From dacfd324704144cf911fc1ef516fab778ee1c6f9 Mon Sep 17 00:00:00 2001 From: Joen Asmussen Date: Mon, 21 Jan 2019 12:59:53 +0100 Subject: [PATCH 01/26] Try menu appear animation & start work on handbook This PR aims to start work on #8029, by creating an animation for use with popovers, and by starting documentation for hwo to best use animation. It: - Adds a "scale and appear" animation to the block toolbar, the more menu, and the block library - It adds a very very early draft of an animation document, which includes an early inventory of current animations in use. --- assets/stylesheets/_animations.scss | 5 +++++ packages/components/src/popover/style.scss | 12 ++++++++++++ packages/edit-post/src/style.scss | 11 +++++++++++ 3 files changed, 28 insertions(+) diff --git a/assets/stylesheets/_animations.scss b/assets/stylesheets/_animations.scss index 755161bc852ff..2683c7bb35698 100644 --- a/assets/stylesheets/_animations.scss +++ b/assets/stylesheets/_animations.scss @@ -6,3 +6,8 @@ animation: edit-post__fade-in-animation $speed ease-out $delay; animation-fill-mode: forwards; } + +@mixin components-popover__appear-animation($speed: 0.2s, $delay: 0s) { + animation: components-popover__appear-animation $speed cubic-bezier(0, 0, 0.2, 1) $delay; + animation-fill-mode: forwards; +} diff --git a/packages/components/src/popover/style.scss b/packages/components/src/popover/style.scss index 6b9ed471028d5..7c5e3d6f49629 100644 --- a/packages/components/src/popover/style.scss +++ b/packages/components/src/popover/style.scss @@ -177,6 +177,18 @@ $arrow-size: 8px; .components-popover:not(.is-mobile):not(.is-middle).is-left & { margin-right: -24px; } + + // Animate some of the popovers + .editor-inserter__popover &, + .edit-post-more-menu__content &, + .editor-block-settings-menu__popover & { + @include components-popover__appear-animation(); + transform-origin: top left; + } + + .edit-post-more-menu__content & { + transform-origin: top right; + } } // The withFocusReturn div diff --git a/packages/edit-post/src/style.scss b/packages/edit-post/src/style.scss index 90fac100e15ee..6bcae4d97760d 100644 --- a/packages/edit-post/src/style.scss +++ b/packages/edit-post/src/style.scss @@ -50,6 +50,17 @@ } } +// maybe add an additional animation that just animates upwards and down, and then the content inside uses scale + +@keyframes components-popover__appear-animation { + from { + transform: translateY(-2em) scaleY(0) scaleX(0); + } + to { + transform: translateY(0%) scaleY(1) scaleX(1); + } +} + // In order to use mix-blend-mode, this element needs to have an explicitly set background-color // We scope it to .wp-toolbar to be wp-admin only, to prevent bleed into other implementations html.wp-toolbar { From 1d1f16457420ac5625cd15c6ddba39d855f97b4f Mon Sep 17 00:00:00 2001 From: Joen Asmussen Date: Fri, 1 Feb 2019 09:29:37 +0100 Subject: [PATCH 02/26] Faster animation & commit docs. --- assets/stylesheets/_animations.scss | 2 +- .../designers/animation.md | 69 +++++++++++++++++++ packages/edit-post/src/style.scss | 2 - 3 files changed, 70 insertions(+), 3 deletions(-) create mode 100644 docs/designers-developers/designers/animation.md diff --git a/assets/stylesheets/_animations.scss b/assets/stylesheets/_animations.scss index 2683c7bb35698..9d4be3e72d795 100644 --- a/assets/stylesheets/_animations.scss +++ b/assets/stylesheets/_animations.scss @@ -7,7 +7,7 @@ animation-fill-mode: forwards; } -@mixin components-popover__appear-animation($speed: 0.2s, $delay: 0s) { +@mixin components-popover__appear-animation($speed: 0.1s, $delay: 0s) { animation: components-popover__appear-animation $speed cubic-bezier(0, 0, 0.2, 1) $delay; animation-fill-mode: forwards; } diff --git a/docs/designers-developers/designers/animation.md b/docs/designers-developers/designers/animation.md new file mode 100644 index 0000000000000..5f8b6aba03298 --- /dev/null +++ b/docs/designers-developers/designers/animation.md @@ -0,0 +1,69 @@ +# Animation + +Animation can help reinforce a sense of hierarchy and spatial orientation. This documents goes into principles you should follow when you add animation. + +## Principles + +### Point of Origin + +- Animation can help anchor an interface element. For example a menu can scale up from the button that opened it. +- Animation can help give a sense of place; for example a sidebar can animate in from the side, implying it was always hidden off-screen. +- Design your animations as if you're working with real-world materials. Imagine your user interface elements are made real materials — when not on screen, where are they? User animation to help express that. + +### Speed + +- Animations should never block a user interaction. The should be fast, almost always complete in less than 0.2 seconds. +- A user should not have to wait for an animation to finish before they can interact. +- Animations should be performant. Use `transform` CSS properties when you can, these render elements on the GPU making them smooth. +- If an animation can't be made fast & performant, leave it out. + +### Simple + +- Don't bounce if the material isn't made of rubber. +- Don't rotate, fold, or animate on a curve. Keep it simple. + +### Consistency + +In creating consistent animations, we have to establish physical rules for how elements behave when animated. When all animations follow these rules, they feel consistent, related, and predictable. An animation should match user expectations, if it doesn't, it's probably not the right animation for the job. + +Reuse animations if one already exists for your task. + +## Inventory, Reused animations + +The following is a running list of existing animations, and how they fit with the above principles. + +### `edit-post__loading-fade-animation` + +This is a "pulsing fade" animation that is used when an element is _transient_. For example when an image is being uploaded. It is simple, and indicates background work. + +### `edit-post__fade-in-animation` + +This is the most basic fade in animation. It simply fades from transparent to opaque. + +### `components-popover__appear-animation` + +This animation is meant for popover content, such as menus appearing. It shows the popover scaling from 0 to full size, from its point of origin. Be sure to combine it with the correct point of origin. For example the Block Library opens down and to the right, which means it needs a `transform-origin: top left;` to scale diagonally from the top left corner. + +### `components-button__busy-animation` + +When a button is working, there's a set of diagonal stripes that animate from left to right. + +### `components-modal__appear-animation` + +Modal windows are cards that live below the viewport. When invoked, they animate in fro the button and upwards. Because of their relative size, this is a brief animation that includes a fade. + +### `components-spinner__animation` + +This is a simple rotation used for a loading-state spinner. + +### `edit-post-fullscreen-mode__slide-in-animation` + +When you enter fullscreen mode, the editor bar animates downwards from the top. + +### `edit-post-layout__slide-in-animation` + +The Publish sidebar lives to the right of the viewport, and when you press the Publish... button, it slides in from the right. + +### `nux-pulse` + +This animation is used for the dot indicators that appear in the out of box experience. They create a "pulsing" effect behind the dot indicators. \ No newline at end of file diff --git a/packages/edit-post/src/style.scss b/packages/edit-post/src/style.scss index 6bcae4d97760d..f985fe8d803ae 100644 --- a/packages/edit-post/src/style.scss +++ b/packages/edit-post/src/style.scss @@ -50,8 +50,6 @@ } } -// maybe add an additional animation that just animates upwards and down, and then the content inside uses scale - @keyframes components-popover__appear-animation { from { transform: translateY(-2em) scaleY(0) scaleX(0); From 5f17198186c1bf207204f8184a509f94b605afee Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Fri, 1 Feb 2019 11:16:15 +0100 Subject: [PATCH 03/26] Try an animate component --- assets/stylesheets/_animations.scss | 5 -- .../designers/animation.md | 6 +- packages/components/src/animate/index.js | 25 ++++++++ packages/components/src/animate/style.scss | 28 ++++++++ packages/components/src/index.js | 1 + packages/components/src/popover/index.js | 64 ++++++++++--------- packages/components/src/popover/style.scss | 12 ---- packages/components/src/style.scss | 1 + packages/components/src/tooltip/index.js | 1 + packages/edit-post/src/style.scss | 9 --- 10 files changed, 92 insertions(+), 60 deletions(-) create mode 100644 packages/components/src/animate/index.js create mode 100644 packages/components/src/animate/style.scss diff --git a/assets/stylesheets/_animations.scss b/assets/stylesheets/_animations.scss index 9d4be3e72d795..755161bc852ff 100644 --- a/assets/stylesheets/_animations.scss +++ b/assets/stylesheets/_animations.scss @@ -6,8 +6,3 @@ animation: edit-post__fade-in-animation $speed ease-out $delay; animation-fill-mode: forwards; } - -@mixin components-popover__appear-animation($speed: 0.1s, $delay: 0s) { - animation: components-popover__appear-animation $speed cubic-bezier(0, 0, 0.2, 1) $delay; - animation-fill-mode: forwards; -} diff --git a/docs/designers-developers/designers/animation.md b/docs/designers-developers/designers/animation.md index 5f8b6aba03298..f888bcfd0d009 100644 --- a/docs/designers-developers/designers/animation.md +++ b/docs/designers-developers/designers/animation.md @@ -40,10 +40,6 @@ This is a "pulsing fade" animation that is used when an element is _transient_. This is the most basic fade in animation. It simply fades from transparent to opaque. -### `components-popover__appear-animation` - -This animation is meant for popover content, such as menus appearing. It shows the popover scaling from 0 to full size, from its point of origin. Be sure to combine it with the correct point of origin. For example the Block Library opens down and to the right, which means it needs a `transform-origin: top left;` to scale diagonally from the top left corner. - ### `components-button__busy-animation` When a button is working, there's a set of diagonal stripes that animate from left to right. @@ -66,4 +62,4 @@ The Publish sidebar lives to the right of the viewport, and when you press the P ### `nux-pulse` -This animation is used for the dot indicators that appear in the out of box experience. They create a "pulsing" effect behind the dot indicators. \ No newline at end of file +This animation is used for the dot indicators that appear in the out of box experience. They create a "pulsing" effect behind the dot indicators. diff --git a/packages/components/src/animate/index.js b/packages/components/src/animate/index.js new file mode 100644 index 0000000000000..5ead6124633f0 --- /dev/null +++ b/packages/components/src/animate/index.js @@ -0,0 +1,25 @@ +/** + * External dependencies + */ +import classnames from 'classnames'; + +function Animate( { type, options, children } ) { + if ( type === 'appear' ) { + const { origin = 'top' } = options; + const [ yAxis, xAxis = 'center' ] = origin.split( ' ' ); + + return children( { + className: classnames( + 'components-animate__appear', + { + [ 'is-from-' + xAxis ]: xAxis !== 'center', + [ 'is-from-' + yAxis ]: yAxis !== 'middle', + }, + ), + } ); + } + + return children( {} ); +} + +export default Animate; diff --git a/packages/components/src/animate/style.scss b/packages/components/src/animate/style.scss new file mode 100644 index 0000000000000..0a725ce0032d4 --- /dev/null +++ b/packages/components/src/animate/style.scss @@ -0,0 +1,28 @@ +.components-animate__appear { + animation: components-animate__appear-animation 0.1s cubic-bezier(0, 0, 0.2, 1) 0s; + animation-fill-mode: forwards; + + &.is-from-top, + &.is-from-top.is-from-left { + transform-origin: top left; + } + &.is-from-top.is-from-right { + transform-origin: top right; + } + &.is-from-bottom, + &.is-from-bottom.is-from-left { + transform-origin: bottom left; + } + &.is-from-bottom.is-from-right { + transform-origin: bottom right; + } +} + +@keyframes components-animate__appear-animation { + from { + transform: translateY(-2em) scaleY(0) scaleX(0); + } + to { + transform: translateY(0%) scaleY(1) scaleX(1); + } +} diff --git a/packages/components/src/index.js b/packages/components/src/index.js index f892867c7a400..2bc81c542f019 100644 --- a/packages/components/src/index.js +++ b/packages/components/src/index.js @@ -1,6 +1,7 @@ // Components export * from './primitives'; // eslint-disable-next-line camelcase +export { default as Animate } from './animate'; export { default as Autocomplete } from './autocomplete'; export { default as BaseControl } from './base-control'; export { default as Button } from './button'; diff --git a/packages/components/src/popover/index.js b/packages/components/src/popover/index.js index 643d032984181..7f8b205e44fcf 100644 --- a/packages/components/src/popover/index.js +++ b/packages/components/src/popover/index.js @@ -22,6 +22,7 @@ import IconButton from '../icon-button'; import ScrollLock from '../scroll-lock'; import IsolatedEventContainer from '../isolated-event-container'; import { Slot, Fill, Consumer } from '../slot-fill'; +import Animate from '../animate'; const FocusManaged = withConstrainedTabbing( withFocusReturn( ( { children } ) => children ) ); @@ -258,6 +259,7 @@ class Popover extends Component { focusOnMount, getAnchorRect, expandOnMobile, + animate = true, /* eslint-enable no-unused-vars */ ...contentProps } = this.props; @@ -289,36 +291,40 @@ class Popover extends Component { /* eslint-disable jsx-a11y/no-static-element-interactions */ let content = ( - - { isMobile && ( -
- - { headerTitle } - - -
+ + { ( { className: animateClassName } ) => ( + + { isMobile && ( +
+ + { headerTitle } + + +
+ ) } +
+ { children } +
+
) } -
- { children } -
-
+
); /* eslint-enable jsx-a11y/no-static-element-interactions */ diff --git a/packages/components/src/popover/style.scss b/packages/components/src/popover/style.scss index 7c5e3d6f49629..6b9ed471028d5 100644 --- a/packages/components/src/popover/style.scss +++ b/packages/components/src/popover/style.scss @@ -177,18 +177,6 @@ $arrow-size: 8px; .components-popover:not(.is-mobile):not(.is-middle).is-left & { margin-right: -24px; } - - // Animate some of the popovers - .editor-inserter__popover &, - .edit-post-more-menu__content &, - .editor-block-settings-menu__popover & { - @include components-popover__appear-animation(); - transform-origin: top left; - } - - .edit-post-more-menu__content & { - transform-origin: top right; - } } // The withFocusReturn div diff --git a/packages/components/src/style.scss b/packages/components/src/style.scss index 046c7b6264efd..379b48208904c 100644 --- a/packages/components/src/style.scss +++ b/packages/components/src/style.scss @@ -1,3 +1,4 @@ +@import "./animate//style.scss"; @import "./autocomplete/style.scss"; @import "./base-control/style.scss"; @import "./button-group/style.scss"; diff --git a/packages/components/src/tooltip/index.js b/packages/components/src/tooltip/index.js index 3bb1f6c8b7ccb..f20bb647c3cb8 100644 --- a/packages/components/src/tooltip/index.js +++ b/packages/components/src/tooltip/index.js @@ -115,6 +115,7 @@ class Tooltip extends Component { position={ position } className="components-tooltip" aria-hidden="true" + animate={ false } > { text } diff --git a/packages/edit-post/src/style.scss b/packages/edit-post/src/style.scss index f985fe8d803ae..90fac100e15ee 100644 --- a/packages/edit-post/src/style.scss +++ b/packages/edit-post/src/style.scss @@ -50,15 +50,6 @@ } } -@keyframes components-popover__appear-animation { - from { - transform: translateY(-2em) scaleY(0) scaleX(0); - } - to { - transform: translateY(0%) scaleY(1) scaleX(1); - } -} - // In order to use mix-blend-mode, this element needs to have an explicitly set background-color // We scope it to .wp-toolbar to be wp-admin only, to prevent bleed into other implementations html.wp-toolbar { From b028d512e3f7685b3f9e1fe15e703b433b9ee423 Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Fri, 1 Feb 2019 11:53:36 +0100 Subject: [PATCH 04/26] Fix popover initial position --- packages/components/src/animate/index.js | 2 +- packages/components/src/popover/index.js | 25 ++++++++++++++++++++++-- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/packages/components/src/animate/index.js b/packages/components/src/animate/index.js index 5ead6124633f0..a144e6ee8b27d 100644 --- a/packages/components/src/animate/index.js +++ b/packages/components/src/animate/index.js @@ -3,7 +3,7 @@ */ import classnames from 'classnames'; -function Animate( { type, options, children } ) { +function Animate( { type, options = {}, children } ) { if ( type === 'appear' ) { const { origin = 'top' } = options; const [ yAxis, xAxis = 'center' ] = origin.split( ' ' ); diff --git a/packages/components/src/popover/index.js b/packages/components/src/popover/index.js index 7f8b205e44fcf..052e53189ba84 100644 --- a/packages/components/src/popover/index.js +++ b/packages/components/src/popover/index.js @@ -56,6 +56,11 @@ class Popover extends Component { contentWidth: null, isMobile: false, popoverSize: null, + + // Delay the animation after the initial render + // because the animation have impact on the height of the popover + // causing the computed position to be wrong. + isReadyToAnimate: false, }; // Property used keep track of the previous anchor rect @@ -151,7 +156,7 @@ class Popover extends Component { popoverSize.height !== this.state.popoverSize.height ); if ( didPopoverSizeChange ) { - this.setState( { popoverSize } ); + this.setState( { popoverSize, isReadyToAnimate: true } ); } this.anchorRect = anchorRect; this.computePopoverPosition( popoverSize, anchorRect ); @@ -272,8 +277,21 @@ class Popover extends Component { contentWidth, popoverSize, isMobile, + isReadyToAnimate, } = this.state; + // Compute the animation position + const yAxisMapping = { + top: 'bottom', + bottom: 'top', + }; + const xAxisMapping = { + left: 'right', + right: 'left', + }; + const animateYAxis = yAxisMapping[ yAxis ] || 'middle'; + const animateXAxis = xAxisMapping[ xAxis ] || 'center'; + const classes = classnames( 'components-popover', className, @@ -291,7 +309,10 @@ class Popover extends Component { /* eslint-disable jsx-a11y/no-static-element-interactions */ let content = ( - + { ( { className: animateClassName } ) => ( Date: Fri, 1 Feb 2019 11:35:51 -0500 Subject: [PATCH 05/26] Minor documentation spelling + grammar fixes. --- .../designers/animation.md | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/docs/designers-developers/designers/animation.md b/docs/designers-developers/designers/animation.md index f888bcfd0d009..2ece14eda4bd5 100644 --- a/docs/designers-developers/designers/animation.md +++ b/docs/designers-developers/designers/animation.md @@ -1,6 +1,6 @@ # Animation -Animation can help reinforce a sense of hierarchy and spatial orientation. This documents goes into principles you should follow when you add animation. +Animation can help reinforce a sense of hierarchy and spatial orientation. This document goes into principles you should follow when you add animation. ## Principles @@ -8,13 +8,13 @@ Animation can help reinforce a sense of hierarchy and spatial orientation. This - Animation can help anchor an interface element. For example a menu can scale up from the button that opened it. - Animation can help give a sense of place; for example a sidebar can animate in from the side, implying it was always hidden off-screen. -- Design your animations as if you're working with real-world materials. Imagine your user interface elements are made real materials — when not on screen, where are they? User animation to help express that. +- Design your animations as if you're working with real-world materials. Imagine your user interface elements are made of real materials — when not on screen, where are they? Use animation to help express that. ### Speed -- Animations should never block a user interaction. The should be fast, almost always complete in less than 0.2 seconds. +- Animations should never block a user interaction. They should be fast, almost always complete in less than 0.2 seconds. - A user should not have to wait for an animation to finish before they can interact. -- Animations should be performant. Use `transform` CSS properties when you can, these render elements on the GPU making them smooth. +- Animations should be performant. Use `transform` CSS properties when you can, these render elements on the GPU, making them smooth. - If an animation can't be made fast & performant, leave it out. ### Simple @@ -28,29 +28,29 @@ In creating consistent animations, we have to establish physical rules for how e Reuse animations if one already exists for your task. -## Inventory, Reused animations +## Inventory of Reused Animations The following is a running list of existing animations, and how they fit with the above principles. ### `edit-post__loading-fade-animation` -This is a "pulsing fade" animation that is used when an element is _transient_. For example when an image is being uploaded. It is simple, and indicates background work. +A "pulsing fade" animation that is used when an element is _transient_. For example when an image is being uploaded. It is simple, and indicates background work. ### `edit-post__fade-in-animation` -This is the most basic fade in animation. It simply fades from transparent to opaque. +The most basic fade-in animation. It simply fades from transparent to opaque. ### `components-button__busy-animation` -When a button is working, there's a set of diagonal stripes that animate from left to right. +When a button is working, this animation adds a set of diagonal stripes that animate from left to right. ### `components-modal__appear-animation` -Modal windows are cards that live below the viewport. When invoked, they animate in fro the button and upwards. Because of their relative size, this is a brief animation that includes a fade. +Modal windows are cards that live below the viewport. When invoked, they animate in front of the button and upwards. Because of their relative size, this is a very brief fade animation. ### `components-spinner__animation` -This is a simple rotation used for a loading-state spinner. +A simple rotation used for a loading-state spinner. ### `edit-post-fullscreen-mode__slide-in-animation` @@ -58,7 +58,7 @@ When you enter fullscreen mode, the editor bar animates downwards from the top. ### `edit-post-layout__slide-in-animation` -The Publish sidebar lives to the right of the viewport, and when you press the Publish... button, it slides in from the right. +The Publish sidebar lives to the right of the viewport. When you press the "Publish..." button, it slides in from the right. ### `nux-pulse` From ce7d7f141d6d12f7feb4a39212accf449c7defb2 Mon Sep 17 00:00:00 2001 From: jasmussen Date: Mon, 4 Feb 2019 13:27:44 +0100 Subject: [PATCH 06/26] Fix typo and clarify doc. --- docs/designers-developers/designers/animation.md | 2 +- packages/components/src/style.scss | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/designers-developers/designers/animation.md b/docs/designers-developers/designers/animation.md index 2ece14eda4bd5..b3f8e3f3cb342 100644 --- a/docs/designers-developers/designers/animation.md +++ b/docs/designers-developers/designers/animation.md @@ -20,7 +20,7 @@ Animation can help reinforce a sense of hierarchy and spatial orientation. This ### Simple - Don't bounce if the material isn't made of rubber. -- Don't rotate, fold, or animate on a curve. Keep it simple. +- Don't rotate, fold, or animate on a curved path. Keep it simple. ### Consistency diff --git a/packages/components/src/style.scss b/packages/components/src/style.scss index 379b48208904c..66d20f3427df8 100644 --- a/packages/components/src/style.scss +++ b/packages/components/src/style.scss @@ -1,4 +1,4 @@ -@import "./animate//style.scss"; +@import "./animate/style.scss"; @import "./autocomplete/style.scss"; @import "./base-control/style.scss"; @import "./button-group/style.scss"; From a883d303f3f2cbe4208a03e93f3d290c694cfee5 Mon Sep 17 00:00:00 2001 From: Grzegorz Ziolkowski Date: Mon, 4 Feb 2019 13:40:41 +0100 Subject: [PATCH 07/26] Fix failing unit tests by updating snapshots --- .../components/src/popover/test/__snapshots__/index.js.snap | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/components/src/popover/test/__snapshots__/index.js.snap b/packages/components/src/popover/test/__snapshots__/index.js.snap index ff10c3fe5ceb3..a9c4ed32102d3 100644 --- a/packages/components/src/popover/test/__snapshots__/index.js.snap +++ b/packages/components/src/popover/test/__snapshots__/index.js.snap @@ -7,7 +7,7 @@ exports[`Popover #render() should pass additional props to portaled element 1`] >