Seam - A reactive state library with rich functionality (for UI, gameplay mechanics, and more)

What is Seam?

Seam is a lightweight reactive state library with built-in animations and more. Easily create impactful visuals and simple-yet-scalable states.

See this crate opening animation in Slap Battles, which was programmed with Seam!

The syntax is very familiar to others’, making a the learning curve very flat.

Why try this out? Why does this exist?

Seam is three parts: states, animation, and utilities.

Using states is a great way to solve many messy codebases. Examples of systems that would benefit from Seam include:

  • UI/UX frontend
  • Complex mechanics
  • Level puzzles backend
  • Tools and weapons
  • Moving environment parts
  • Visual effects
  • And more!

Seam was originally built for UI and has since expanded to be for your entire game, both server and client. Seam states are simple and generic, meaning they can be used in many different places. Compared to other state libraries, Seam is much more feature-rich, flexible, and more performant.

Your job is to solve problems without overengineering, and Seam can help with that!

Expressive buttons example:

RobloxStudioBeta_wJCy3wSuQ5

Moving platform example:

moving-platform-e1b7dca70dd4eefb4de95a25d3bad999

Where do I start?

View documentation, installation instructions, tutorials, and more at Seam’s website:

Are there any known issues? What do I do if I come across any?

Bugs are always being squashed!

If you ever find any issues, please report them to me in my DMs, or in the replies below! Seam is also open-sourced, so if you want to contribute fixes and more, check out the repository here:

Need help?

You can get support and more by participating in Seam’s thread in my support server: iGottic OSS

Once you join that server, navigate to Projects → Seam.

Any other questions and comments outside of that can be placed in the replies below!

55 Likes

Update 0.1.0

  • Improved typechecking
  • Improved backend comment docs
  • Added the .Changed signal to Computed
  • Children now supports a Computed input
  • Attempting to create conflicting components of the same name now produces an error
  • Various backend changes
  • Stability improvements
  • Documentation improvements

First off, Seam should be much more stable now. It uses a bit of a weird hacky way to fix this behind the scenes though, so in the future this will be fixed.

Most notably, you can now use Computed as the Children value if you want dynamic children. It looks something like this:

local Names = Value({"Bob", "Rob", "Billy", "Bobby"})

local DynamicChildren = Computed(function(Use)
    local CreatedChildren = {}
    
    for Index, Name in Use(Names) do
      table.insert(CreatedChildren, New("TextLabel", {
            Text = Name,
            -- And let's pretend there are properties
      }))
    end
    
    return CreatedChildren
end)

New(ExistingFrame, {
    [Children] = DynamicChildren
})

-- At first, there will be four children, each a text label that corresponds to each value in the Names state
-- Then, we change the value, doing the same thing and deleting the old children

Names.Value = {"Jon"} -- When we call this, there will now only be a singular text label, with the text "Jon"

I also did some stuff behind the scenes to make it all look more cohesive and whatnot. If you look at the source code, you might see some new notes I made.

The framework is now stable enough to go from 0.0.3 to 0.1.0, bringing it from an alpha to a beta.

Happy coding!

3 Likes

looks like Fusion

1 Like

So, do you have any plans to release it as a complete framework?

The syntax is definitely similar to Fusion, and that’s intentional to help make it familiar and easy to learn.

1 Like

Yes. The complete framework will likely be more feature-rich, but as of right now it should still do everything you need. If you think something is missing, let me know, and I can add it to the backlog.

I really like what you create, I will look forward for more updates. : )

1 Like

Very much appreciate this resource, this has and will save me a lot of time on my projects

1 Like

The documentation website has been completely revamped for improved UX and more! It’s still at the same domain (https://www.seaminterface.com/), but now utilizes the Docusaurus framework.

I’ll be improving it over time, but let me know if you have any feedback for it :3

This looks amazing! If you could port this to wally, that would be much appreciated

2 Likes

Here ya go!

1 Like

Update v0.2.0

Excited for the next major version of Seam? So am I! Check out my blog post about this update here:

In that blog post you can learn more specifics about this update.

Summary:

  • Signifigantly improved typechecking
  • Added StageGui preset component
  • Removed ScaledUIStroke preset component
  • Bug fixes and more backend changes

As a reminder, you can now find Seam on Wally, and the docs are revamped! Check out the documentation here: https://www.seaminterface.com/

Are you using Seam in a project? Let me know in the replies!

Update v0.2.1

Quick patch for Seam is here! This patch just fixes up some typechecking issues with Scope, especially with autofill.

Check it out here: Release v0.2.1-beta · MiaGobble/Seam · GitHub

It’s a great project! But I am new to this, would you mind creating a game for example to use this module? Thank you

This framework looks.. interesting. I don’t mean to cast any shade, and I know this project is still relatively new, but it looks like if someone was asked to write a UI framework like Fusion, but with only a very vague concept of what Fusion actually is and with some additional preset components as well.

The declaritive nature of Fusion components makes them very simple and easy to learn and use (since they’re just functions), where as with Seam it’s not exactly clear what’s going on with them. You just call this mysterious DeclareComponent function and now you can reuse it everywhere without having to import it. (which can cause issues if code dependant on these components existing somehow executes before those components are declared!)

I feel like this project may have been better suited as maybe a fork of Fusion, considering the similarities between them. Still I commend you for atleast trying something new, keep up the great work!

I’ll be providing more examples in the documentation soon!

DeclareComponent is just a single part of the entire Seam library. Could you clarify what you mean by this some more? What about Seam makes it unclear?

It wouldn’t have worked as a fork because, behind the scenes, it works completely different than Fusion. It’s built to not rely on dependencies, and because of that, it runs better and is easier to read+change.

I was focusing on components in both Fusion and Seam specifically, everything else is fairly straightforward since they have some direct parallel to Fusion.

What I personally find unclear about Seam’s component system is the way that you can use components without having a direct “link” to them, the only form of connection being through Seam indirectly. The fact that all components are stored internally within Seam kind of obscures what’s really going on when you use DeclareComponent and From. Whereas with Fusion, “components” are just functions that you can directly require from another file and use, while also keeping typechecking.

I already mentioned this in my last comment, but Seam’s components can lead to race conditions, say if you’re creating some UI that requires a component that hasn’t been declared yet. Fusion doesn’t really have this issue, since you can just declare/import them from another file and it’ll just work.

I’m not entirely sure what you mean by this. Based off of a quick glance at Seam’s source code it definitely is using some form of dependencies (there’s literally a file named DependenciesManager.lua). It also seems like you’re making RBXScriptSignal connections to RenderStepped for each dependency, which I’m not one to make judgements on performance, but I’m pretty sure doesn’t make it “run better.”

I do agree that it internally works completely different than Fusion (although whether this is actually good is debatable), but from an API/user standpoint you’re trying to mimic what Fusion already has. The overuse of metatables and metamethods just makes it hard (for me anyway) to understand what’s going on inside of Seam (not to mention that the typesolver still has issues with metatables!).

Again, I’m not trying to put down your project, it’s always interesting to see how other people go about something like this, but I just don’t really see a reason to use this over Fusion since it already provides a lot of what Seam has to offer. :coefficients:

3 Likes

In your opinion, what design change could improve this?

…ish. I moreso meant that, unlike Fusion, dependencies do not affect the state of other internal modules, and instead use signals.

Where do you see this? Signals don’t fire every frame.

1 Like

Honestly, I’m not entirely sure. The only thing I can think of currently is just removing the internal component store inside of Seam in favor or something more like react-lua, where you can create a component object that contains information about how it should be rendered and pass it into a createElement (which would be New in Seam’s case) function.

Alternatively you could forgo the whole components thing and have them be handled like how Fusion does it. (raw functions that return preset instances), but this feels a little too extreme (and would obviously further reduce the gap between this and Fusion…)

Really it’s up to you what you do with them, it’s fine to leave it as is if you prefer how it currently works. (I’m just one person on the internet, you don’t have to take everything I say as the absolute truth!!!)

A signal would count as a sort of dependency link would it not? Fusion’s internal graph sort of behaves like how signals function. Again I only took a brief glance at the source code so I apologize if I got anything wrong.

Also how does Seam handle recursive state recomputations? I know Fusion has some safeguards in place to prevent them from wreaking havoc, but as far as I know Seam doesn’t have anything like that.

I could be confused, but I remember seeing it inside the aforementioned DependenciesManager.lua file. The structure of everything inside of Seam confuses me a lot, so sorry if I accidentally got that one wrong…