Roact animation library - API feedback

Hi! I’m working on an animation library for Roact. It’s called Flick and my plan is to make it open source soon!

Right now, I’m wondering about how I can improve the ergonomics of the API.

The library works by giving you access to a prop named flick that lets you get animated values (which are just bindings) and change the goal values. Everything gets updated in the background.

To show the API, here’s a quick example of a button that will have a different color when hovering and being pressed:

local Button = Roact.Component:extend('Button')

function Button:init()
    self.onMouseEnter = function()
        self.props.flick:setGoals({ foo = Color3.new(0.75, 0.75, 0.75) })
    end
    self.onMouseLeave = function()
        self.props.flick:resetGoals() 
    end
    self.onMouseButton1Down = function()
        self.props.flick:setGoals({ foo = Color3.new(0.5, 0.5, 0.5) })
    end
    self.onMouseButton1Up = function()
        self.props.flick:resetGoals() 
    end
end

function Button:render()
    local props = self.props

    local flick = props.flick
    local text = props.text
    local onClick = props.onClick

    return Roact.createElement('TextButton', {
        AutoButtonColor = false,
        Text = 'Click'

        -- here we assign using the name of the generated binding
        BackgroundColor3 = flick.bindings.foo,

        [Roact.Event.MouseButton1Click] = onClick,
        [Roact.Event.MouseEnter] = self.onMouseEnter,
        [Roact.Event.MouseLeave] = self.onMouseLeave,
        [Roact.Event.MouseButton1Down] = self.onMouseButton1Down,
        [Roact.Event.MouseButton1Up] = self.onMouseButton1Up,
    })
end

From this example, we see the API of the flick object, which I am satisfied with, but if you have a suggestion for better function names let me know!

How do we get that flick prop to be in our button’s prop? That is probably where I’m the less sure how I should design the API. Right now, what I have is something similar to Rodux connect function. You pass a table that defines the initial values (you can put multiple values) and (what I’ve named) the optional motion.

-- generates a new component that wraps our 
-- Button and provides the flick prop
return Flick.withAnimation(
    {
        foo = Color3.new(1, 1, 1),
    }, 
    Flick.Motions.Timed(0.15)
)(Button)

Or maybe something like this (would makes it possible to exports Flick.withMotion(...) and reuse it with different values)

return Flick.withMotion(Flick.Motions.Timed(0.15))
    .withAnimation({
        foo = Color3.new(1, 1, 1),
    })(Button)

In brief:

  • how should the user wrap its components
  • how should the flick prop work

I’m sharing all this hoping to get feedback and ideas for the library! I really don’t mind criticism, even if you think the whole idea is the worst thing you’ve seen let me know why.

If tried to make the example as concise as possible, but let me know if I went to far and I just made it unclear.

My next steps before publishing this is to write a quick getting started/documentation site and then add springs as a possible motion type.

6 Likes