> For the complete documentation index, see [llms.txt](https://docs.flatredball.com/gum/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.flatredball.com/gum/gum-tool/gum-elements/states/categories.md).

# Categories

## Introduction

Categories can be used to organize similar states into one group (such as a button's Pressed and Unpressed states).

A category can contain one or more states. States within a category have special behavior:

1. If one state in a category explicitly sets a variable (such as X), then all other states in that category will also explicitly set the variable.
2. Each category can be set individually on an instance of a component or standard element. In other words, if a component has two categories, each category can be assigned to a state within that category independently.

## Creating Categories

To create a new category:

1. Select a Screen, Component, or Standard element which should contain the new category
2. Right-click in the States tab in an empty space
3. Select the Add Category item\\

   <figure><img src="/files/WDiHUX5NCQ0e81YOAj2V" alt=""><figcaption><p>Right click Add Category item</p></figcaption></figure>
4. Enter a name for the new category

After the new category is created it appears in the States tab as a folder.

<figure><img src="/files/rpNUeItRMSAzHmcen7sx" alt=""><figcaption><p>Newly-created category</p></figcaption></figure>

## Adding States to a Category

To add states to a category:

1. Right-click on the desired category
2. Select Add State\\

   <figure><img src="/files/IxYt4pXXAMIpqHO1YMZd" alt=""><figcaption><p>Right click Add State item</p></figcaption></figure>
3. Enter a name for the new state

Once the state has been created it can be selected and variables can be changed to add them to the new state.

## Categories Create Variables

Once a category is created, the screen, component, or standard element which contains the category is automatically given a variable for that category type. This variable can be assigned on the element itself or on instances of the element.

For example, consider a component with a category named ExampleCategory with two states: State1 and State2.

<figure><img src="/files/E3DYLQDIqGJvnnsXOrIu" alt=""><figcaption><p>ExampleCategory with two states</p></figcaption></figure>

This component is given a variable named Example Category State.

<figure><img src="/files/ilJL7Euav7u2XIKGjCe9" alt=""><figcaption><p>Example Category State variable</p></figcaption></figure>

This value can be assigned in the default state, making the selected state automatically set by default on the component.

For example, the DefaultComponent can select State1 as its Example Category State.

<figure><img src="/files/yQdaFUglmZweE8PS12DZ" alt=""><figcaption><p>Example Category State assigned by default</p></figcaption></figure>

Doing so results in this value automatically being selected on new instances of the DefaultComponent.

## States Set by Other States

Once a category is created, it adds a variable to the component. This variable behaves like any other variable including being able to be set by other states.

For example, consider a component with the following categories and states:

* ColorCategory
  * Bright
  * Dark
* SizeCategory
  * Big
  * Small

These states can be combined in a new category. For example, a category called CombinedCategory can be created which can include states such as BrightBig or DarkSmall which in turn sets category variables.

<figure><img src="/files/7jxsnXstFzCTLwixIDt9" alt=""><figcaption><p>States setting variables created by other categories</p></figcaption></figure>

## Explicit Values Across States in a Category

Normally, when a new category is created and new states are added, all states are *empty* - they do not assign any variables. The value displayed in the properties window is inherited from the default state.

For example, the following image shows a component with a state called **State1** with no variables explicitly assigned. Notice all values are green:

![](/files/xuHjsGTmaqmubQVcPabl)

As mentioned in the introduction, if a variable is explicitly set on one state in a category, then all other states in that category will that same variable set to its default. For example, if we set the **X** variable in the **LeftSide** state, the **X** variable in the **RightSide** state will become explicitly set (black instead of green).

![Setting X on LeftSide also sets X on other states](/files/urxuQiHCCF6utfdnDENi)

Once the **X** variable is set on one state in a category, all other states in the same category will automatically have this value set - even new states:

![New state automatically having variables set](/files/DxTclj8EhoEhYRAmZhJQ)

## Removing Variables from Categories

Variables can be removed from states, but this removal must be done at the category level rather than at the individual state. Doing so will remove all variables from all states within a category. To remove a variable in all states in a category:

1. Select the category itself (not the state)
2. Click the "X" button next to the variable
3. Confirm that you would like to remove the variable. Warning: this will remove the variable from all contained states.

![](/files/-Mb9SlSWn9QlGmYNcsEj)

This will remove the assignment of the variable from all states in the category.

## GUM0002: Variable Reference Conflicts With Explicit Set

When a categorized state's `VariableReferences` row implies a value for a variable, and a parent element also has an explicit local value for the same variable, the explicit local value wins at lookup time. The reference is silently ineffective. Gum surfaces this with warning code **GUM0002**.

### Example

`UpgradeButton` derives from `Button`. The author sets two things on `UpgradeButton.DefaultState`:

* `TextInstance.TextCategoryState = "Title"` (the Title state on the inherited Label includes a VariableReference that resolves `FontSize` to e.g. 28).
* `TextInstance.FontSize = 14` (a plain explicit override).

These conflict. At lookup time, Gum walks the local explicit value first and returns 14. Changing `TextCategoryState` between values appears to do nothing for `FontSize` because the local override always wins.

### How it got there

Most commonly: the author set `FontSize` interactively via a reference that has since been undone or changed, leaving the materialized scalar behind as an orphan. Hand edits and AI-authored XML can also produce this shape.

### Fixing it

Decide which value you want and remove the other:

* To let the state's reference drive `FontSize`, delete the local explicit `TextInstance.FontSize` from the parent element's state.
* To keep the local explicit value, change or remove the reference inside the categorized state — or pick a `TextCategoryState` whose effective value matches what you want.

### Detection scope

The check fires for two cases, on every state of every Screen and Component:

* A `VariableReferences` row authored on the same state as a conflicting explicit scalar.
* A `VariableReferences` row inherited via an active categorized-state assignment on an instance (the `UpgradeButton` shape).

`StandardElements` are skipped — their references commonly evaluate to default values whose missing materialization is the correct on-disk state, not a conflict.

## GUM0003: Category State Sets Its Own Category Selector

A category's selector variable (e.g. `TextBoxCategoryState` for the `TextBoxCategory` category) chooses which state in that category is active. When a state *inside* the category sets that same selector, the result is circular: applying the state re-drives the whole category, which re-applies a (possibly different) state and discards the original state's authored values. Gum surfaces this with warning code **GUM0003**.

### Example

`TextBox` has a `TextBoxCategory` with states `Enabled`, `Disabled`, `Highlighted`, and `Focused`. The `Focused` state sets `Border.ColorCategoryState = "Primary"` (the normal cascade onto a child instance) — but it *also* sets `TextBoxCategoryState = "Enabled"`. Selecting `Focused` immediately re-applies `Enabled`, so the border never shows the `Focused` colors.

### How it got there

This is not normally hand-authored. It is usually materialized data: a tool pass that drives a category selector from a Forms property (for design-time preview) wrote the selector into whichever state was selected at the time, including the category's own states. The applier no longer does this — it only materializes into the default state — but projects edited before that fix can carry the orphaned assignments.

### Fixing it

Remove the self-referential selector variable from the category's states. The selector belongs only on the default (uncategorized) state, where it picks the element's resting state; it should never appear inside the category it selects.

### Detection scope

The check fires on every Screen and Component, for any state inside a category that sets that same category's selector. A state setting a *child instance's* selector (e.g. `Border.ColorCategoryState`, which carries a source object) is the intended cascade and is not flagged.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.flatredball.com/gum/gum-tool/gum-elements/states/categories.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
