Skip to content
This repository has been archived by the owner on Mar 4, 2020. It is now read-only.

feat(theme): support keyframes through animation property #414

Merged
merged 19 commits into from
Nov 16, 2018

Conversation

mnajdova
Copy link
Contributor

@mnajdova mnajdova commented Nov 1, 2018

Keyframes

This PR aims to add possibility for defining and using keyframes in the theme.

API Proposal

We should add keyframes prop in the theme, that will define different keyframes in the following manner:

<Provider theme={{
    // ..some theme props
    keyframes: {
      spinner: () => ({
        from: {
          transform: 'rotate(0deg)',
        },
        to: {
          transform: 'rotate(360deg)',
        },
      }),
    }
  }}
> <Component /> </Provider>

Then, inside the components the users can access this keyframes inside the styles, using the theme property. Something like:

<Icon name="umbrella" size="big"
      styles={({theme}) => (theme.keyframes.spinner ? {animation: 
        `${theme.renderer.renderKeyframe(theme.keyframes.spinner, {})} 1s infinite`} : {})}
    />

Another approach that I have tried is to evaluate the keyframes inside the Provider component once and then use them like this:

<Icon 
  name="umbrella" 
  size="big" 
  styles={({theme, props}) => ({
    animation: `${theme.keyframes.spinner} 1s infinite`})
  } 
/>

Altough this API is cleaner and easier for using, we are not able to provide any props to the keyframe, which is something that is not acceptable.

Please share your thoughts on this, so that we can conclude the final API.

Update

After discussion, we decided to add animation property to the components, that would encapsulate all things regarding the keyframes and will provide easier usage. The definition of the keyframes in the theme will remain the same, but the usage will be provided in the following manner:

using keyframe already defined in the theme

<Button
  circular
  content="C"
  animation={{
    name: 'spinner',
    duration: '2s',
    iterationCount: 'infinite',
  }}
/>

using custom keyframe

const keyframe = ({ startColor, endColor }) => ({
  from: { color: startColor },
  to: { color: endColor },
})

<Icon
  name="umbrella"
  size="big"
  animation={{
    keyframe,
    keyframeParams: { startColor: 'red', endColor: 'yellow' },
    duration: '5s',
    delay: '2s',
    iterationCount: 'infinite',
    direction: 'alternate',
    fillMode: 'backwards',
    timingFunction: 'ease',
  }}
/>

The animation property is actually defining all animation-related css properties. The interface looks like this:

export type Animation = {
  keyframe?: any // custom keyframe function
  name?: string // theme defined keyframe
  keyframeParams?: object // params for the keyframe function
  delay?: string // animation-delay CSS property
  direction?: string // animation-direction CSS property
  duration?: string // animation-duration CSS property
  fillMode?: string // animation-fill-mode CSS property
  iterationCount?: string // animation-iteration-count CSS property
  playState?: string // animation-play-state CSS property
  timingFunction?: string // animation-timing-function CSS property
}

@codecov
Copy link

codecov bot commented Nov 1, 2018

Codecov Report

Merging #414 into master will increase coverage by 0.03%.
The diff coverage is 90.9%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #414      +/-   ##
==========================================
+ Coverage   88.38%   88.42%   +0.03%     
==========================================
  Files          41       42       +1     
  Lines        1429     1451      +22     
  Branches      182      186       +4     
==========================================
+ Hits         1263     1283      +20     
- Misses        162      163       +1     
- Partials        4        5       +1
Impacted Files Coverage Δ
src/components/Provider/Provider.tsx 88.88% <ø> (ø) ⬆️
src/components/Attachment/Attachment.tsx 97.29% <ø> (ø) ⬆️
src/index.ts 100% <100%> (ø) ⬆️
src/components/Transition/Transition.tsx 90.47% <90.47%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update f8f49e6...cb7904a. Read the comment docs.

@mnajdova mnajdova added the RFC label Nov 1, 2018
@mnajdova mnajdova changed the title feat(theme): support keyframes feat(theme): support keyframes through animation property Nov 2, 2018
@levithomason
Copy link
Member

let's keep: using keyframe already defined in the theme

remove: using custom keyframe

Only the Provider will allow defining keyframes, for now.

We can iterate from there 👍

…g the keyframes

-added option for overriding the animation props
@mnajdova
Copy link
Contributor Author

mnajdova commented Nov 5, 2018

Update

The theme can define various animations through the animations property in the following manner:

<Provider theme={{
  animations: {
    colorChanger: {
      keyframe: ({ startColor, endColor }) => ({
        from: { backgroundColor: startColor },
        to: { backgroundColor: endColor },
      } as IStyle),
      keyframeParams: { startColor: 'red', endColor: 'yellow' },
      duration: '3s',
      iterationCount: 'infinite',
    },
 },
}} /> ... </Provider>

The usage of this animation then can be define in two manners:

by specifying the name of the animation

<Icon name='umbrella' animation='colorChanger' />

by specifying an animation object

<Icon 
  name='umbrella' 
  animation={{
    name: 'colorChanger', 
    duration: '1s', 
    keyframeParams: {
      startColor: 'blue', 
      endColor: 'green'
    }
  }} 
/>

With the second approach the user can if necessary change some properties of the animation, without having to redefine it in the Provider's theme.

@mnajdova
Copy link
Contributor Author

mnajdova commented Nov 5, 2018

Second approach

Using the new Transition component. The Transition component is a component that provides the mechanism for executing animation, and it simply wraps the element that needs to be animated. Some example usage:

<Transition
  animationName='spinner'>
    <Icon name='umbrella' circular />
</Transition>

Pros

  • no need for adding the animation property to all components
  • can be used with components outside of the Stardust library

Cons

  • it adds additional div around the animated component
  • as the animation is added on the outer div, if the child component has some margins different on some sides, the animation can behave strangely

manajdov added 2 commits November 6, 2018 18:33
-extracted logic for generating the animationStyle so that it can be reused in renderComponent, as well as the Transition component
Copy link
Member

@levithomason levithomason left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Merge after changes are addressed 👍

manajdov added 2 commits November 14, 2018 15:17
# Conflicts:
#	src/components/Button/Button.tsx
#	src/components/Icon/Icon.tsx
#	src/lib/mergeThemes.ts
-removed keyframeParams
-added transition examples
-added animation prop to all UI components
@mnajdova mnajdova merged commit f240d7a into master Nov 16, 2018
@layershifter layershifter deleted the feat/keyframes-support branch January 10, 2019 11:26
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants