FragmentFragment

Create a Context

Shared reactive value objects consumed by any Handle or Component.

A Context is a lightweight shared value object. Any Handle that calls handle:pull(ctx) subscribes to it and re-renders whenever ctx:patch() is called.

Contexts are ideal for cross-Handle state that doesn't belong to a specific data source — like which window is currently open, or which theme is active.


Define a Context

Each Context lives in its own ModuleScript inside your Contexts/ folder.

Contexts/WindowContext.luau
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Fragment = require(ReplicatedStorage.Fragment)

local WindowContext = Fragment.createContext({ 
    active = nil :: string?, 
}) 

WindowContext._value.open = function(name: string)
    WindowContext:patch({ active = name })
end

WindowContext._value.close = function(name: string)
    if WindowContext._value.active == name then
        WindowContext:patch({ active = Fragment.DELETE })
    end
end

WindowContext._value.toggle = function(name: string)
    if WindowContext._value.active == name then
        WindowContext:patch({ active = Fragment.DELETE })
    else
        WindowContext:patch({ active = name })
    end
end

return WindowContext

Fragment.DELETE removes the key from the value table entirely when passed to patch. Methods added to _value are available to any Handle or Component that pulls from the Context.

Use the structured loader

When using Fragment.load({ Contexts = ..., Handles = ... }), Contexts are required before Handles automatically — no manual require needed.

FragmentLoad.client.luau
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Fragment = require(ReplicatedStorage.Fragment)

Fragment.load({
    Contexts   = script.Parent.Contexts,   -- required before Handles --
    Components = script.Parent.Components,
    Handles    = script.Parent.Handles,
})

Connect a Context to a Handle

Use handle:pull(ctx) inside a renderer to subscribe the Handle and get the live value table back. The Handle re-renders whenever ctx:patch() is called.

Handles/ShopHandle.luau
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Fragment = require(ReplicatedStorage.Fragment)
local WindowContext = require(ReplicatedStorage.Parent.Contexts.WindowContext)

local Handle = Fragment.newHandle("Shop", { "HUD", "Shop", "MainFrame" })

return Handle(function(element: Frame)
    local win = Handle:pull(WindowContext) 

    element.Visible = win.active == "Shop"

    Handle.Action("Toggle", function(state: boolean)
        if state then
            win.open("Shop") 
        else
            win.close("Shop") 
        end
    end)

    local closeBtn = element.TopBar.Close :: TextButton
    Handle.Connect("Close", closeBtn.Activated, function()
        win.close("Shop") 
    end)
end)

Contexts work identically inside Component renderers via the handle argument:

Components/CloseButton.luau
local WindowContext = require(path.to.Contexts.WindowContext)

return Component(function(element, props, handle)
    local win = handle:pull(WindowContext) 

    handle.Connect("Close_" .. props.windowName, element.Activated, function()
        win.close(props.windowName) 
    end)
end)

Patching the Context directly

Call ctx:patch(partial) on the Context itself to merge values and notify all subscribed Handles and Components. This is how the methods defined in the Context body work under the hood.

WindowContext:patch({ active = "Shop" })         -- open shop
WindowContext:patch({ active = Fragment.DELETE }) -- close all

Multiple Handles sharing the same Context

The real power of Contexts is that any Handle can subscribe independently. Both the window Handle and its opener button can react to the same active value without knowing about each other.

Handles/ShopOpener.luau
local WindowContext = require(path.to.WindowContext)

local Handle = Fragment.newHandle("ShopOpener", { "HUD", "Buttons", "Shop" })

return Handle(function(element: TextButton)
    local win = Handle:pull(WindowContext) 

    element.BackgroundTransparency = win.active == "Shop" and 0 or 0.5

    Handle.Connect("Open", element.Activated, function()
        win.toggle("Shop") 
    end)
end)

For the full Context API see the Context reference.

On this page