aboutsummaryrefslogtreecommitdiffstats
path: root/packages/instant/src/components/animations
diff options
context:
space:
mode:
Diffstat (limited to 'packages/instant/src/components/animations')
-rw-r--r--packages/instant/src/components/animations/position_animation.tsx110
-rw-r--r--packages/instant/src/components/animations/slide_animation.tsx26
-rw-r--r--packages/instant/src/components/animations/slide_animations.tsx54
3 files changed, 136 insertions, 54 deletions
diff --git a/packages/instant/src/components/animations/position_animation.tsx b/packages/instant/src/components/animations/position_animation.tsx
new file mode 100644
index 000000000..8b3b294b7
--- /dev/null
+++ b/packages/instant/src/components/animations/position_animation.tsx
@@ -0,0 +1,110 @@
+import { InterpolationValue } from 'styled-components';
+
+import { media, OptionallyScreenSpecific, stylesForMedia } from '../../style/media';
+import { css, keyframes, styled } from '../../style/theme';
+
+export interface TransitionInfo {
+ from: string;
+ to: string;
+}
+
+const generateTransitionInfoCss = (
+ key: keyof TransitionInfo,
+ top?: TransitionInfo,
+ bottom?: TransitionInfo,
+ left?: TransitionInfo,
+ right?: TransitionInfo,
+): string => {
+ const topStringIfExists = top ? `top: ${top[key]};` : '';
+ const bottomStringIfExists = bottom ? `bottom: ${bottom[key]};` : '';
+ const leftStringIfExists = left ? `left: ${left[key]};` : '';
+ const rightStringIfExists = right ? `right: ${right[key]};` : '';
+ return `
+ ${topStringIfExists}
+ ${bottomStringIfExists}
+ ${leftStringIfExists}
+ ${rightStringIfExists}
+ `;
+};
+
+const slideKeyframeGenerator = (
+ position: string,
+ top?: TransitionInfo,
+ bottom?: TransitionInfo,
+ left?: TransitionInfo,
+ right?: TransitionInfo,
+) => keyframes`
+ from {
+ position: ${position};
+ ${generateTransitionInfoCss('from', top, bottom, left, right)}
+ }
+
+ to {
+ position: ${position};
+ ${generateTransitionInfoCss('to', top, bottom, left, right)}
+ }
+`;
+
+export interface PositionAnimationSettings {
+ top?: TransitionInfo;
+ bottom?: TransitionInfo;
+ left?: TransitionInfo;
+ right?: TransitionInfo;
+ timingFunction: string;
+ duration?: string;
+ position?: string;
+}
+
+const generatePositionAnimationCss = (positionSettings: PositionAnimationSettings) => {
+ return css`
+ animation-name: ${slideKeyframeGenerator(
+ positionSettings.position || 'relative',
+ positionSettings.top,
+ positionSettings.bottom,
+ positionSettings.left,
+ positionSettings.right,
+ )};
+ animation-duration: ${positionSettings.duration || '0.3s'};
+ animation-timing-function: ${positionSettings.timingFunction};
+ animation-delay: 0s;
+ animation-iteration-count: 1;
+ animation-fill-mode: forwards;
+ position: ${positionSettings.position || 'relative'};
+ width: 100%;
+ `;
+};
+
+export interface PositionAnimationProps {
+ positionSettings: OptionallyScreenSpecific<PositionAnimationSettings>;
+ zIndex?: OptionallyScreenSpecific<number>;
+ height?: string;
+}
+
+const defaultAnimation = (positionSettings: OptionallyScreenSpecific<PositionAnimationSettings>) => {
+ const bestDefault = 'default' in positionSettings ? positionSettings.default : positionSettings;
+ return generatePositionAnimationCss(bestDefault);
+};
+const animationForSize = (
+ positionSettings: OptionallyScreenSpecific<PositionAnimationSettings>,
+ sizeKey: 'sm' | 'md' | 'lg',
+ mediaFn: (...args: any[]) => InterpolationValue[],
+) => {
+ // checking default makes sure we have a PositionAnimationSettings object
+ // and then we check to see if we have a setting for the specific `sizeKey`
+ const animationSettingsForSize = 'default' in positionSettings && positionSettings[sizeKey];
+ return animationSettingsForSize && mediaFn`${generatePositionAnimationCss(animationSettingsForSize)}`;
+};
+
+export const PositionAnimation =
+ styled.div <
+ PositionAnimationProps >
+ `
+ && {
+ ${props => props.zIndex && stylesForMedia<number>('z-index', props.zIndex)}
+ ${props => defaultAnimation(props.positionSettings)}
+ ${props => animationForSize(props.positionSettings, 'sm', media.small)}
+ ${props => animationForSize(props.positionSettings, 'md', media.medium)}
+ ${props => animationForSize(props.positionSettings, 'lg', media.large)}
+ ${props => (props.height ? `height: ${props.height};` : '')}
+ }
+`;
diff --git a/packages/instant/src/components/animations/slide_animation.tsx b/packages/instant/src/components/animations/slide_animation.tsx
new file mode 100644
index 000000000..9adb1c674
--- /dev/null
+++ b/packages/instant/src/components/animations/slide_animation.tsx
@@ -0,0 +1,26 @@
+import * as React from 'react';
+
+import { OptionallyScreenSpecific } from '../../style/media';
+
+import { PositionAnimation, PositionAnimationSettings } from './position_animation';
+
+export type SlideAnimationState = 'slidIn' | 'slidOut' | 'none';
+export interface SlideAnimationProps {
+ animationState: SlideAnimationState;
+ slideInSettings: OptionallyScreenSpecific<PositionAnimationSettings>;
+ slideOutSettings: OptionallyScreenSpecific<PositionAnimationSettings>;
+ zIndex?: OptionallyScreenSpecific<number>;
+ height?: string;
+}
+
+export const SlideAnimation: React.StatelessComponent<SlideAnimationProps> = props => {
+ if (props.animationState === 'none') {
+ return <React.Fragment>{props.children}</React.Fragment>;
+ }
+ const positionSettings = props.animationState === 'slidIn' ? props.slideInSettings : props.slideOutSettings;
+ return (
+ <PositionAnimation height={props.height} positionSettings={positionSettings} zIndex={props.zIndex}>
+ {props.children}
+ </PositionAnimation>
+ );
+};
diff --git a/packages/instant/src/components/animations/slide_animations.tsx b/packages/instant/src/components/animations/slide_animations.tsx
deleted file mode 100644
index 1f10a2ed6..000000000
--- a/packages/instant/src/components/animations/slide_animations.tsx
+++ /dev/null
@@ -1,54 +0,0 @@
-import * as React from 'react';
-
-import { keyframes, styled } from '../../style/theme';
-
-const slideKeyframeGenerator = (fromY: string, toY: string) => keyframes`
- from {
- position: relative;
- top: ${fromY};
- }
-
- to {
- position: relative;
- top: ${toY};
- }
-`;
-
-export interface SlideAnimationProps {
- keyframes: string;
- animationType: string;
- animationDirection?: string;
-}
-
-export const SlideAnimation =
- styled.div <
- SlideAnimationProps >
- `
- animation-name: ${props => props.keyframes};
- animation-duration: 0.3s;
- animation-timing-function: ${props => props.animationType};
- animation-delay: 0s;
- animation-iteration-count: 1;
- animation-fill-mode: ${props => props.animationDirection || 'none'};
- position: relative;
-`;
-
-export interface SlideAnimationComponentProps {
- downY: string;
-}
-
-export const SlideUpAnimation: React.StatelessComponent<SlideAnimationComponentProps> = props => (
- <SlideAnimation animationType="ease-in" keyframes={slideKeyframeGenerator(props.downY, '0px')}>
- {props.children}
- </SlideAnimation>
-);
-
-export const SlideDownAnimation: React.StatelessComponent<SlideAnimationComponentProps> = props => (
- <SlideAnimation
- animationDirection="forwards"
- animationType="cubic-bezier(0.25, 0.1, 0.25, 1)"
- keyframes={slideKeyframeGenerator('0px', props.downY)}
- >
- {props.children}
- </SlideAnimation>
-);