Groups and search

Collapsible containers, per-section filtering, and window-wide search.

Groups#

A group is a container that opens and closes. Everything you put inside it goes away when it is shut.

Luau
local advanced = main:Group({ Text = "Advanced", Icon = "wrench", Open = false })
 
advanced:Toggle({ Text = "Debug logging" })
advanced:Slider({ Text = "Tick rate", Min = 1, Max = 60, Default = 30 })
Preview

My Script

v1.0

Debug logging
Verbose output

A group has the same methods a section does, so anything you can add to a section you can add to a group. It also has Show, Hide and Destroy, like any other row on the page.

Opening one scrolls it into view, the same as an opening dropdown, so a group near the bottom of a long page does not expand into space you cannot see.

OptionTypeDefaultWhat it does
TextreqstringThe group's heading.
DescriptionstringA quieter line beside the heading.
IconstringAn icon before the heading.
IconSizenumber13Read only when Icon is set.
IconColorColor3Read only when Icon is set. Defaults to the muted role.
OpenbooleantrueWhether it starts expanded.
LayoutOrdernumberPlaces it explicitly instead of in creation order.
TooltipstringShown while the pointer rests on the header.
DisabledbooleanfalseLocks the group and everything in it.
DisabledReasonstringShown as a tooltip while it is locked.
MethodReturnsWhat it does
SetOpen(state, animated)the groupOpens or closes it. Pass false as the second argument to skip the animation.
Open() / Close()the groupThe same thing, named
IsOpen()booleanWhether it is currently open
Show() / Hide() / SetVisible(v)the groupTakes it off the page without destroying it
Destroy()trueRemoves it and everything in it
SetDisabled(state, reason?)the groupLocks or unlocks it
Disable(reason?) / Enable()the groupThe same thing, named
IsDisabled()booleanWhether it is locked
SetTooltip(text)the groupChanges the hover text
.InstanceFrameThe container itself
Luau
advanced:SetOpen(true)          -- animates open
advanced:SetOpen(false, false)  -- snaps shut, no animation
advanced:Hide()                 -- gone from the page, still built

The container follows its contents. A dropdown opening inside it, or a description that wraps to a second line, re-targets the group's height while it is open.

Controls inside a group render flat

A group draws its own surface, so the controls inside it drop theirs. Pass Flat = false on a control to give it its card back.

Locking a group#

Disabled fades everything inside the container and stops it accepting input, not only the header:

Luau
local advanced = main:Group({
    Text = "Advanced",
    Icon = "wrench",
    Disabled = true,
    DisabledReason = "Available once you are in a game",
})
 
advanced:Toggle({ Text = "Debug logging" })
 
advanced:Enable()   -- and everything inside comes back with it
Preview

My Script

v1.0

Debug logging
Verbose output

Controls added after the lock are locked too, which is the usual order: the group is built with Disabled = true and filled in on the next line.

Turn on a filter box for one section:

Luau
local big = win:Section("Everything", "list", {
    Search = true,
    SearchPlaceholder = "Filter this section…",
})

The box sits at the top of the section and is never filtered away itself. SearchPlaceholder defaults to Search <section name>.

Typing filters the controls in that section. A control matches on its Text and Description, and on the heading of the group it sits in, so typing a group's name keeps everything inside it. Matching is case-insensitive and looks for the query anywhere in the text.

A group whose contents all fail the filter hides itself. So does a Title with nothing visible under it, along with the separators that trail it.

A search overrides Hide

Filtering decides a group's visibility from whether anything inside it matches, so a group you hid with Hide() comes back if the query matches one of its rows. Clearing the query hides it again.

The rail can carry its own search box that spans every section:

Luau
local win = Ember.new({
    Title = "My Script",
    Search = true,
    SearchPlaceholder = "Search...",
})

Matches are counted per section and shown next to each tab, in the accent colour when the count is above zero. If the section you are on has no matches and another does, Ember selects the first section that has some.

It is off by default, and turning it on takes 40px off the top of the tab list.

The two boxes combine. With both in use, a row has to match the window query and the section query to stay on the page.

Which to use#

SituationReach for
One section with a lot of rowsPer-section Search
Many sections, user does not know where a setting livesWindow Search
A block of rarely-touched optionsA Group, closed by default
Two or three related rowsA Title and a Separator