Kostom.net

Pseudo-Classes


Whirl brings a Tailwind-like pseudo-class system to Unity UI Toolkit, allowing you to style elements based on interaction states such as hover, active, focus, selected, and more.

Because Unity USS does not support : characters, Whirl uses a compiler transformation so that you can write pseudo-class utilities in your scripts just like Tailwind (hover:bg-red), while still being compatible with UXML files and UI Builder (hover---bg-red).

Whirl handles all pseudo-class activation internally — you don’t have to write custom C# code unless you want to create new states.

Supported Pseudo-Classes

Pseudo-ClassMeaning
hover:When the pointer is over the element
active:While the element is pressed
inactive:A user stops to interact with the element
focus:The element has focus
disabled:The element is in a disabled state
enabled:The element is in an enabled state
checked:The element is a Toggle or RadioButton element and it’s selected

Example:

UXML
<Button class="flex hover---hidden ...">Save changes</Button>
C#
element.AddClass(flex, hover---hidden...);

Group state

`group-*` state makes it easy for you to style any element based on the state of the parent element. Groups can also be used with other pseudo-classes, e.g, `group-hover`, `group-active`, `group-focus`, etc.

Check out this link for more example of how it works.

Group state with name

Dealing with nested groups, and you want to style a descendant element based on a specific ancestor group without colliding with the other group? Then you can give each ancestor group a unique name using `group/{name}`, you can also use them with pseudo classes like `group-focus/{name}`.

Check out this link for more example of how it works.

Arbitrary groups

You can create your own selector as an arbitrary value between square brackets.

You can select a group that contains a specific class by doing `group-[.class]:hidden`, you can also do one with id `group-[#name]:hidden`, and you can also do any custom variant, e.g `group-[:hover]:hidden` or `group-[:focus_>_VisualElement]:hidden`.

Child Selector

Direct children styling

Although you can add the utility classes directly to the visual element, there are some cases where the visual element is unreachable, e.g TextField, ScrollView, etc. or when you want all the direct children of the visual element to share the same style, then you can use the `*` variant.

<ui:VisualElement class="*:min-w-10 *:bg-slate-50 *:rounded-2xl *:m-0 *:px-5 *:py-3 ....">
    <ui:VisualElement />
    <ui:VisualElement />
    <ui:VisualElement />
    ....
</ui:VisualElement>
        

Styling descendants

To style all descendants, you can use `**` variant. Although this works similarly to `*` variant but the biggest difference is that the styles would be applied to all the descendants of the element.

<ui:VisualElement class="**:min-w-10 **:bg-slate-50 **:rounded-2xl **:m-0 **:px-5 **:py-3 ....">
    <ui:VisualElement>
          <ui:VisualElement />
    </ ui:VisualElement>
    <ui:VisualElement />
    <ui:VisualElement />
    ....
</ui:VisualElement>
        

Arbitrary variants

Arbitrary variants are another way of writing custom variants in your UXML element. For an arbitrary value to be recognized as a variant, it needs to be a value that starts with `&` and is wrapped in square brackets. It can also be stacked with other states.

The following example selects all Label elements within the visual element that contains the specified class. To add spaces in your selector, you can use an underscore.

<ui:VisualElement class="[&_Label]:w-10 [&_Label]:hover:w-24  [&_Label:hover]:w-24 ....">
    ....
</ui:VisualElement>
        
<ui:VisualElement class="[&.child]:w-10 [&.child]:hover:w-24 [&.child:hover]:w-24 ....">
    ....
</ui:VisualElement>
        
<ui:VisualElement class="[&>.child]:w-10 [&>.child]:hover:w-24 [&>.child:hover]:w-24 ....">
    ....
</ui:VisualElement>