--- /dev/null
+// FOUNDATION MOTION UI\r
+// Table of Contents\r
+//\r
+// 0. Variables\r
+// 1. Base Transitions\r
+// a. Slide\r
+// b. Fade\r
+// c. Hinge\r
+// d. Scale\r
+// e. Spin\r
+// 2. Base Animations\r
+// a. Shake\r
+// b. Spinners\r
+// c. Wiggle\r
+// 3. HTML Attributes\r
+\r
+// 0. Variables\r
+// - - - - - - - - - - - - - - - - - - - - - - - - -\r
+\r
+/// @Foundation.settings\r
+// Motion UI\r
+// Classes to use when triggering in/out animations\r
+$motion-class: (\r
+ in: "ng-enter",\r
+ out: "ng-leave",\r
+) !default;\r
+$motion-class-active: (\r
+ in: "ng-enter-active",\r
+ out: "ng-leave-active",\r
+) !default;\r
+$motion-class-stagger: (\r
+ in: "ng-enter-stagger",\r
+ out: "ng-leave-stagger",\r
+) !default;\r
+$motion-class-showhide: (\r
+ in: "ng-hide-remove",\r
+ out: "ng-hide-add",\r
+);\r
+$motion-class-showhide-active: (\r
+ in: "ng-hide-remove-active",\r
+ out: "ng-hide-add-active",\r
+);\r
+\r
+// Set if movement-based transitions should also fade the element in and out\r
+$motion-slide-and-fade: false !default;\r
+$motion-hinge-and-fade: true !default;\r
+$motion-scale-and-fade: true !default;\r
+$motion-spin-and-fade: true !default;\r
+\r
+// Default speed for transitions and animations\r
+$motion-duration-default: 500ms !default;\r
+\r
+// Slow and fast modifiders\r
+$motion-duration-slow: 750ms !default;\r
+$motion-duration-fast: 250ms !default;\r
+$motion-stagger-duration-default: 150ms !default;\r
+$motion-stagger-duration-short: 50ms !default;\r
+$motion-stagger-duration-long: 300ms !default;\r
+\r
+// Default timing function for transitions and animations\r
+$motion-timing-default: ease !default;\r
+\r
+// Built-in and custom easing functions\r
+// Every item in this map becomes a CSS class\r
+$motion-timings: (\r
+ linear: linear,\r
+ ease: ease,\r
+ easeIn: ease-in,\r
+ easeOut: ease-out,\r
+ easeInOut: ease-in-out,\r
+ bounceIn: cubic-bezier(0.485, 0.155, 0.240, 1.245),\r
+ bounceOut: cubic-bezier(0.485, 0.155, 0.515, 0.845),\r
+ bounceInOut: cubic-bezier(0.760, -0.245, 0.240, 1.245),\r
+) !default;\r
+\r
+// Default delay for all transitions and animations\r
+$motion-delay-default: 0 !default;\r
+// Short and long delay modifiers\r
+$motion-delay-short: 300ms !default;\r
+$motion-delay-long: 700ms !default;\r
+///\r
+\r
+// Looks for a timing function in the list of presets\r
+// If none are found, returns the value as-is.\r
+@function get-timing($timing) {\r
+ @if map-has-key($motion-timings, $timing) {\r
+ @return map-get($motion-timings, $timing);\r
+ }\r
+ @else {\r
+ @return $timing;\r
+ }\r
+}\r
+\r
+// Applies transition settings common to all mixins\r
+@mixin transition-basics(\r
+ $duration: $motion-duration-default,\r
+ $timing: $motion-timing-default,\r
+ $delay: $motion-delay-default\r
+) {\r
+ transition-duration: $duration;\r
+ transition-timing-function: get-timing($timing);\r
+ transition-delay: $delay;\r
+}\r
+\r
+// Wraps content in an enter/leave class, chained to the parent selector\r
+// Define the initial state of a transition here\r
+@mixin transition-start($dir) {\r
+ $sel1: map-get($motion-class, $dir);\r
+ $sel2: map-get($motion-class-showhide, $dir);\r
+\r
+ &.#{$sel1},\r
+ &.#{$sel2} {\r
+ @content;\r
+ }\r
+}\r
+\r
+// Wraps content in an enter/leave active class, chained to the matching\r
+// enter/leave class, chained to the parent selector\r
+// Define the end state of a transition here\r
+@mixin transition-end($dir) {\r
+ $sel1: map-get($motion-class, $dir);\r
+ $sel1A: map-get($motion-class-active, $dir);\r
+\r
+ $sel2: map-get($motion-class-showhide, $dir);\r
+ $sel2A: map-get($motion-class-showhide-active, $dir);\r
+\r
+ &.#{$sel1}.#{$sel1A},\r
+ &.#{$sel2}.#{$sel2A} {\r
+ @content;\r
+ }\r
+}\r
+\r
+@mixin stagger($delay-amount) {\r
+ transition-delay: $delay-amount;\r
+ // this is to avoid accidental CSS inheritance\r
+ transition-duration:0;\r
+}\r
+\r
+\r
+// 1. Base Transitions\r
+// - - - - - - - - - - - - - - - - - - - - - - - - -\r
+\r
+// SLIDE\r
+@mixin slide (\r
+ $dir: in,\r
+ $from: left,\r
+ $fade: $motion-slide-and-fade,\r
+ $duration: $motion-duration-default,\r
+ $timing: $motion-timing-default,\r
+ $delay: $motion-delay-default\r
+) {\r
+ $slideDirections: (\r
+ top: translateY(-100%),\r
+ right: translateX(100%),\r
+ bottom: translateY(100%),\r
+ left: translateX(-100%),\r
+ );\r
+ $start: '';\r
+ $end: '';\r
+\r
+ @if $dir == in {\r
+ $start: map-get($slideDirections, $from);\r
+ $end: translateX(0) translateY(0);\r
+ }\r
+ @else {\r
+ $start: translateX(0) translateY(0);\r
+ $end: map-get($slideDirections, $from);\r
+ }\r
+\r
+ // CSS Output\r
+ @include transition-start($dir) {\r
+ @include transition-basics($duration, $timing, $delay);\r
+ transition-property: transform, opacity;\r
+ backface-visibility: hidden;\r
+ transform: $start;\r
+\r
+ @if $fade { opacity: if($dir == in, 0, 1); }\r
+ }\r
+ @include transition-end($dir) {\r
+ transform: $end;\r
+\r
+ @if $fade { opacity: if($dir == in, 1, 0); }\r
+ }\r
+}\r
+\r
+// FADE\r
+@mixin fade(\r
+ $dir: in,\r
+ $from: 0,\r
+ $to: 1,\r
+ $duration: $motion-duration-default,\r
+ $timing: $motion-timing-default,\r
+ $delay: $motion-delay-default\r
+) {\r
+ @include transition-start($dir) {\r
+ @include transition-basics($duration, $timing, $delay);\r
+ transition-property: opacity;\r
+ opacity: $from;\r
+ }\r
+ @include transition-end($dir) {\r
+ opacity: $to;\r
+ }\r
+}\r
+\r
+// HINGE\r
+@mixin hinge (\r
+ $dir: in,\r
+ $from: left,\r
+ $axis: edge,\r
+ $perspective: 2000px,\r
+ $turn-origin: from-back,\r
+ $fade: $motion-hinge-and-fade,\r
+ $duration: $motion-duration-default,\r
+ $timing: $motion-timing-default,\r
+ $delay: $motion-delay-default\r
+) {\r
+\r
+ // Rotation directions when hinging from back vs. front\r
+ $rotationAmount: 90deg;\r
+ $rotationsBack: (\r
+ top: rotateX($rotationAmount * -1),\r
+ right: rotateY($rotationAmount * -1),\r
+ bottom: rotateX($rotationAmount),\r
+ left: rotateY($rotationAmount),\r
+ );\r
+ $rotationsFrom: (\r
+ top: rotateX($rotationAmount),\r
+ right: rotateY($rotationAmount),\r
+ bottom: rotateX($rotationAmount * -1),\r
+ left: rotateY($rotationAmount * -1),\r
+ );\r
+\r
+ // Rotation origin\r
+ $rotation: '';\r
+ @if $turn-origin == from-front {\r
+ $rotation: map-get($rotationsFrom, $from);\r
+ }\r
+ @else if $turn-origin == from-back {\r
+ $rotation: map-get($rotationsBack, $from);\r
+ }\r
+ @else {\r
+ @warn "`$turn-origin` must be either `from-back` or `from-front`";\r
+ }\r
+\r
+ // Start and end state\r
+ $start: '';\r
+ $end: '';\r
+ @if $dir == in {\r
+ $start: perspective($perspective) $rotation;\r
+ $end: rotate(0deg);\r
+ }\r
+ @else {\r
+ $start: rotate(0deg);\r
+ $end: perspective($perspective) $rotation;\r
+ }\r
+\r
+ // Turn axis\r
+ $origin: '';\r
+ @if $axis == edge {\r
+ $origin: $from;\r
+ }\r
+ @else {\r
+ $origin: center;\r
+ }\r
+\r
+ @include transition-start($dir) {\r
+ @include transition-basics($duration, $timing, $delay);\r
+ transition-property: transform, opacity;\r
+ transform: $start;\r
+ transform-origin: $origin;\r
+ @if $fade { opacity: if($dir == in, 0, 1); }\r
+ }\r
+ @include transition-end($dir) {\r
+ transform: $end;\r
+ @if $fade { opacity: if($dir == in, 1, 0); }\r
+ }\r
+}\r
+\r
+// SCALE\r
+@mixin scale(\r
+ $dir: in,\r
+ $from: 1.5,\r
+ $to: 1,\r
+ $fade: $motion-scale-and-fade,\r
+ $duration: $motion-duration-default,\r
+ $timing: $motion-timing-default,\r
+ $delay: $motion-delay-default\r
+) {\r
+ @include transition-start($dir) {\r
+ @include transition-basics($duration, $timing, $delay);\r
+ transition-property: transform, property;\r
+ transform: scale($from);\r
+ @if $fade { opacity: if($dir == in, 0, 1) }\r
+ }\r
+ @include transition-end($dir) {\r
+ transform: scale($to);\r
+ @if $fade { opacity: if($dir == in, 1, 0) }\r
+ }\r
+}\r
+\r
+// SPIN\r
+@mixin spin(\r
+ $dir: in,\r
+ $amount: 0.75turn,\r
+ $ccw: false,\r
+ $fade: $motion-spin-and-fade,\r
+ $duration: $motion-duration-default,\r
+ $timing: $motion-timing-default,\r
+ $delay: $motion-delay-default\r
+) {\r
+ $amount: turn-to-deg($amount);\r
+ $start: 0;\r
+ $end: 0;\r
+\r
+ @if $dir == in {\r
+ $start: if($ccw, $amount, $amount * -1);\r
+ $end: 0;\r
+ }\r
+ @else {\r
+ $start: 0;\r
+ $end: if($ccw, $amount * -1, $amount);\r
+ }\r
+\r
+ @include transition-start($dir) {\r
+ transition-property: transform, opacity;\r
+ transform: rotate($start);\r
+ @if $fade { opacity: if($dir == in, 0, 1); }\r
+ }\r
+ @include transition-end($dir) {\r
+ transform: rotate($end);\r
+ @if $fade { opacity: if($dir == in, 1, 0); }\r
+ }\r
+}\r
+\r
+\r
+// 2. Base Animations\r
+// - - - - - - - - - - - - - - - - - - - - - - - - -\r
+\r
+// SHAKE\r
+@keyframes shake {\r
+ 0%, 10%, 20%, 30%, 40%, 50%, 60%, 70%, 80%, 90% {\r
+ transform: translateX(7%);\r
+ }\r
+ 5%, 15%, 25%, 35%, 45%, 55%, 65%, 75%, 85%, 95% {\r
+ transform: translateX(-7%);\r
+ }\r
+ 100% { transform: translateX(0); }\r
+}\r
+\r
+// SPINNERS\r
+@keyframes spin-cw {\r
+ 0% { transform: rotate(0deg); }\r
+ 100% { transform: rotate(360deg); }\r
+}\r
+\r
+@keyframes spin-ccw {\r
+ 0% { transform: rotate(0deg); }\r
+ 100% { transform: rotate(-360deg); }\r
+}\r
+\r
+// WIGGLE\r
+@keyframes wiggle {\r
+ 40%, 50%, 60% {\r
+ transform: rotate(7deg);\r
+ }\r
+ 35%, 45%, 55%, 65% {\r
+ transform: rotate(-7deg);\r
+ }\r
+ 0%, 30%, 70%, 100% { transform: rotate(0); }\r
+}\r
+\r
+@mixin animation(\r
+ $animation,\r
+ $duration: $motion-duration-default,\r
+ $timing: $motion-timing-default,\r
+ $delay: $motion-delay-default,\r
+ $iterations: null\r
+) {\r
+ \r
+ animation-name: $animation;\r
+ animation-duration: $duration;\r
+ animation-timing-function: $timing;\r
+\r
+ backface-visibility: hidden;\r
+ transform: translate3d(0,0,0);\r
+\r
+ @if $delay != null {\r
+ animation-delay: $delay;\r
+ }\r
+ @if $iterations != null {\r
+ animation-iteration-count: $iterations;\r
+ }\r
+\r
+ @if $animation == null {\r
+ @warn "Please include an animation name";\r
+ }\r
+}\r
+\r
+// 3. HTML Exports\r
+// - - - - - - - - - - - - - - - - - - - - - - - - -\r
+\r
+@include exports(motion) {\r
+ /*\r
+ Transitions\r
+ */\r
+\r
+ // Slide\r
+ .slideInDown { @include slide($from: top); }\r
+ .slideInLeft { @include slide($from: right); }\r
+ .slideInUp { @include slide($from: bottom); }\r
+ .slideInRight { @include slide($from: left); }\r
+ .slideOutBottom { @include slide($dir: out, $from: bottom); }\r
+ .slideOutRight { @include slide($dir: out, $from: right); }\r
+ .slideOutUp { @include slide($dir: out, $from: top); }\r
+ .slideOutLeft { @include slide($dir: out, $from: left); }\r
+\r
+ // Fade\r
+ .fadeIn { @include fade(in, 0, 1); }\r
+ .fadeOut { @include fade(out, 1, 0); }\r
+\r
+ // Hinge\r
+ .hingeInFromTop { @include hinge($dir: in, $from: top); }\r
+ .hingeInFromRight { @include hinge($dir: in, $from: right); }\r
+ .hingeInFromBottom { @include hinge($dir: in, $from: bottom); }\r
+ .hingeInFromLeft { @include hinge($dir: in, $from: left); }\r
+ .hingeInFromMiddleX { @include hinge($dir: in, $from: top, $axis: center); }\r
+ .hingeInFromMiddleY { @include hinge($dir: in, $from: right, $axis: center); }\r
+ .hingeOutFromTop { @include hinge($dir: out, $from: top); }\r
+ .hingeOutFromRight { @include hinge($dir: out, $from: right); }\r
+ .hingeOutFromBottom { @include hinge($dir: out, $from: bottom); }\r
+ .hingeOutFromLeft { @include hinge($dir: out, $from: left); }\r
+ .hingeOutFromMiddleX { @include hinge($dir: out, $from: top, $axis: center); }\r
+ .hingeOutFromMiddleY { @include hinge($dir: out, $from: right, $axis: center); }\r
+\r
+ // Scale\r
+ .zoomIn { @include scale(in, 1.5, 1); }\r
+ .zoomOut { @include scale(out, 0.5, 1); }\r
+\r
+ // Spin\r
+ .spinIn { @include spin(in, 0.75turn); }\r
+ .spinOut { @include spin(out, 0.75turn); }\r
+ .spinInCCW { @include spin(in, 0.75turn, true); }\r
+ .spinOutCCW { @include spin(out, 0.75turn, true); }\r
+\r
+ /*\r
+ Transition modifiers\r
+ */\r
+\r
+ // Duration\r
+ .slow { transition-duration: $motion-duration-slow !important; }\r
+ .fast { transition-duration: $motion-duration-fast !important; }\r
+\r
+ // Easing\r
+ @each $easing in map-keys($motion-timings) {\r
+ .#{$easing} {\r
+ transition-timing-function: map-get($motion-timings, $easing) !important;\r
+ }\r
+ }\r
+\r
+ // Delay\r
+ .delay { transition-delay: $motion-delay-short !important; }\r
+ .long-delay { transition-delay: $motion-delay-long !important; }\r
+\r
+ /*\r
+ Animations\r
+ */\r
+\r
+ .shake { @include animation(shake); }\r
+ .spin-cw { @include animation(spin-cw); }\r
+ .spin-ccw { @include animation(spin-ccw); }\r
+ .wiggle { @include animation(wiggle); }\r
+\r
+ /*\r
+ Animation modifiers\r
+ */\r
+\r
+ .shake,\r
+ .spin-cw,\r
+ .spin-ccw,\r
+ .wiggle {\r
+ // Repeat\r
+ &.infinite { animation-iteration-count: infinite; }\r
+\r
+ // Easing\r
+ @each $timing in map-keys($motion-timings) {\r
+ &.#{$timing} {\r
+ animation-timing-function: map-get($motion-timings, $timing) !important;\r
+ }\r
+ }\r
+\r
+ // Duration\r
+ &.slow { animation-duration: $motion-duration-slow !important; }\r
+ &.fast { animation-duration: $motion-duration-fast !important; }\r
+\r
+ // Delay\r
+ &.delay { animation-delay: $motion-delay-short !important; }\r
+ &.long-delay { animation-delay: $motion-delay-long !important; }\r
+ }\r
+ .stagger { @include stagger($motion-stagger-duration-default); }\r
+ .stort-stagger { @include stagger($motion-stagger-duration-default); }\r
+ .long-stagger { @include stagger($motion-stagger-duration-default); }\r
+}\r
+\r
+// View animation classes\r
+// - - - - - - - - - - - - - - - - - - - -\r
+\r
+// Applied to the immediate parent of the animating views\r
+.position-absolute {\r
+ overflow: hidden;\r
+ position: relative;\r
+}\r
+\r
+// Applied to the animating views\r
+.ui-animation {\r
+ &.ng-enter-active, &.ng-leave-active {\r
+ position: absolute !important;\r
+ backface-visibility: hidden;\r
+ -webkit-transform-style: preserve-3d;\r
+ top: 0;\r
+ right: 0;\r
+ bottom: 0;\r
+ left: 0;\r
+ }\r
+}\r