Add tag() action for CollectionService tags

Adds a built-in `vide.tag()` action that wraps `Instance:AddTag()` /
`Instance:RemoveTag()` so tags can be applied through `create()` props.

It accepts a static string or array of strings, or a reactive source
returning either. The reactive variant diffs the previous and new tag
sets so only the delta is applied. All tags added by the action are
removed when the surrounding scope is destroyed.

Includes mock support for `AddTag`/`RemoveTag`/`HasTag`/`GetTags`,
tests, API reference docs, and a closing note in the actions tutorial.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Andrea Fletcher 2026-05-26 22:10:47 -07:00
parent 19eaeb424f
commit 18c1d02d43
No known key found for this signature in database
7 changed files with 276 additions and 0 deletions

View file

@ -66,6 +66,7 @@ local Instance = {} :: any do
children: { Data },
changed: { [string]: RBXScriptSignal },
properties: { [string]: unknown },
tags: { [string]: true },
destroying: RBXScriptSignal,
class: string,
type: "Instance"
@ -158,6 +159,7 @@ local Instance = {} :: any do
children = {},
changed = {},
properties = {},
tags = {},
class = class,
destroying = Signal.new() :: any,
type = "Instance" :: "Instance"
@ -211,6 +213,29 @@ local Instance = {} :: any do
return data.changed[property]
end
function methods.AddTag(userdata: userdata, tag: string)
if type(tag) ~= "string" then error("tag must be a string", 2) end
get_data(userdata).tags[tag] = true
end
function methods.RemoveTag(userdata: userdata, tag: string)
if type(tag) ~= "string" then error("tag must be a string", 2) end
get_data(userdata).tags[tag] = nil
end
function methods.HasTag(userdata: userdata, tag: string): boolean
if type(tag) ~= "string" then error("tag must be a string", 2) end
return get_data(userdata).tags[tag] == true
end
function methods.GetTags(userdata: userdata): { string }
local out = {}
for name in get_data(userdata).tags do
table.insert(out, name)
end
return out
end
function methods.Destroy(userdata: userdata)
local data = get_data(userdata);
Signal.fire(data.destroying)