Download Latest Version 0.14 - Aspect Ratio Elements, Better Clipping source code.tar.gz (3.6 MB)
Email in envelope

Get an email when there's a new version of Clay

Home / v0.13
Name Modified Size InfoDownloads / Week
Parent folder
clay-odin.zip 2025-02-12 358.2 kB
clay.h 2025-02-12 245.4 kB
0.13 - Simplified Config, Multi Instance Support source code.tar.gz 2025-02-12 3.1 MB
0.13 - Simplified Config, Multi Instance Support source code.zip 2025-02-12 3.2 MB
README.md 2025-02-12 23.1 kB
Totals: 5 Items   6.9 MB 2

New Features

Replace Element Macros with a Single Configuration Struct

We've removed the majority of the configuration macros in favour of a large config struct that you pass to CLAY. You can find exhaustive documentation of this struct and its fields in the README.

:::C
// Before - macros
CLAY(
    CLAY_ID("FloatingContainer"),
    CLAY_LAYOUT({
        .sizing = {
            .width = CLAY_SIZING_FIXED(300),
            .height = CLAY_SIZING_FIXED(300)
        },
        .padding = { 16, 16, 16, 16 }
    }),
    CLAY_FLOATING({
        .zIndex = 1,
        .attachment = {
            CLAY_ATTACH_POINT_CENTER_TOP,
            CLAY_ATTACH_POINT_CENTER_TOP
        },
        .offset = { 0, 0 }
    }),
    CLAY_BORDER_OUTSIDE({ .color = {80, 80, 80, 255}, .width = 2 }),
    CLAY_RECTANGLE({ .color = {140,80, 200, 200 }}
) {
    // children
}

:::C
// After - single struct
CLAY({
    .id = CLAY_ID("FloatingContainer"),
    .layout = {
        .sizing = {
            .width = CLAY_SIZING_FIXED(300),
            .height = CLAY_SIZING_FIXED(300)
        },
        .padding = { 16, 16, 16, 16 }
    },
    .backgroundColor = { 140, 80, 200, 200 },
    .floating = {
        .attachTo = CLAY_ATTACH_TO_PARENT,
        .zIndex = 1,
        .attachPoints = {
            CLAY_ATTACH_POINT_CENTER_TOP,
            CLAY_ATTACH_POINT_CENTER_TOP
        },
        .offset = { 0, 0 }
    },
    .border = {
        .width = { 2, 2, 2, 2 },
        .color = { 80, 80, 80, 255 }
    },
}) {
    // children
}

The two main benefits we get from this approach are:

  1. The available configuration options are naturally discoverable for those using intellisense just by pressing . inside CLAY({ }), whereas previously you had to look up the macros in the documentation.
  2. You can define the configuration for an entire element and save it as a struct:

    :::C Clay_ElementDeclaration buttonStyle = (Clay_ElementDeclaration) { .layout = { .padding = { .left = 16, .right = 16 } }, .backgroundColor = COLOR_RED, .cornerRadius = { 16, 16, 16, 16 } }

    // later CLAY(buttonStyle) { // button contents }

    // Or return a declaration from a function Clay_ElementDeclaration GetButtonStyle(bool hovered) { return (Clay_ElementDeclaration) { .layout = { ... }, .backgroundColor = hovered ? BLUE : RED }; }

    // Generate element style from template CLAY(GetButtonStyle(Clay_Hovered())) { // button contents }

"Context" support (i.e. Multiple independent Clay instances & groundwork for multithreading support)

Thanks to some great discussions in the Clay discord and great work by @monodop here: https://github.com/nicbarker/clay/pull/174 Clay now supports creation and management of multiple "instances" which are separate from one another. This is not only useful for systems with separate internal "windows" requiring different layout trees, but also paves the way for us to support running these instances on separate threads.

Screenshot 2025-02-12 at 9 35 56 am An example of the same layout rendered twice by two separate Clay instances

For more information, see the Multi Context Example

Error Handler

Clay now requires that you bind an error handler callback function when calling Clay_Initialize. This allows us to catch and report some common mistakes such as forgetting to bind a text measurement function with Clay_SetMeasureText.

image

Clay_GetElementData for querying bounding box data

A new function, Clay_GetElementData(Clay_ElementId id) is available for directly looking up the final calculated bounding box of an element by ID.

.textAlignment support for CLAY_TEXT_CONFIG

Wrapped text can now be aligned to LEFT, CENTER or RIGHT using the .textAlignment field of CLAY_TEXT_CONFIG.

Screenshot 2025-02-12 at 10 49 19 am

MSVC Support & C99 Compliance

Thanks to some tireless work from @FintasticMan, Clay can now be compiled using MSVC with C11, 17, and 23, has much closer strict C99 compliance, and compiles with -Wextra and -Wpedantic.

New Renderers

Thanks to some hard work from our contributors, there are a number of new example renderers in 0.13, including: - SDL2 - SDL3 - Cairo

New Language Bindings

Thanks to some hard work from our contributors, there are a number of new language bindings in 0.13, including:

Zig https://codeberg.org/Zettexe/clay-zig https://github.com/johan0A/clay-zig-bindings

Rust https://github.com/clay-ui-rs/clay https://crates.io/crates/clay-layout

C# https://github.com/Orcolom/clay-cs

C++ https://github.com/TimothyHoytBSME/ClayMan

Deprecations

The preprocessor defines used for adding additional fields to element configuration structs such as CLAY_EXTEND_CONFIG_RECTANGLE have been removed in favour of the new .userData pointer field of Clay_ElementDeclaration. This was out of necessity and can be explained in more detail upon request 😅

Migration Guide

  1. Wrap the inside of the CLAY(...) macro in braces for the new form CLAY({ ... })

    :::diff - CLAY( + CLAY({ CLAY_ID(...), CLAY_RECTANGLE({ ... }), CLAY_BORDER({ ... }), CLAY_FLOATING({ ... }) - ) + })

  2. Mass rename the following macros:

  3. CLAY_BORDER({ ... })

  4. CLAY_IMAGE({ ... })
  5. CLAY_SCROLL({ ... })
  6. CLAY_FLOATING({ ... })
  7. CLAY_CUSTOM({ ... })

into struct fields of the form .border = { ... }, .floating = { ... } etc

:::diff
CLAY({
    CLAY_ID(...),
    CLAY_RECTANGLE({ ... }),
-   CLAY_BORDER({ ... }),
+   .border = { ... },
-   CLAY_FLOATING({ ... })
+   .floating = { ... },
})
  1. Replace the CLAY_ID macro with the struct field .id = CLAY_ID

    :::diff CLAY({ - CLAY_ID(...), + .id = CLAY_ID(...), CLAY_RECTANGLE({ ... }), .border = { ... }, .floating = { ... } })

  2. Replace CLAY_RECTANGLE macros with two struct fields, .backgroundColor and .cornerRadius

Previous, fields like .cornerRadius would need to be repeated for rectangle, image, and border configuration macros. .backgroundColor and .cornerRadius are now shared fields that affect multiple render commands, and are declared once at the top level.

:::diff
CLAY({
    .id = CLAY_ID(...),
-   CLAY_RECTANGLE({ .color = COLOR_RED, .cornerRadius = { 10, 10, 10, 10 } }),
+   .backgroundColor = COLOR_RED,
+   .cornerRadius = { 10, 10, 10, 10 },
    .border = { ... },
    .floating = { ... }
})
  1. Padding is now represented by four values, not just two

Padding in 0.12 was represented as a mirrored .x, .y pair. It's been changed in 0.13 to a more standard .left, .right, .top, .bottom. You'll need to update your padding to match the new structure.

:::diff
- CLAY({ .layout = { .padding = { 8, 12 } });
+ CLAY({ .layout = { .padding = { 8, 8, 12, 12 } });

// Designated initializers
- CLAY({ .layout = { .padding = { .x = 8, .y = 12 } });
+ CLAY({ .layout = { .padding = { .left = 8, .right = 8, .top = 12, .bottom = 12 } });
  1. Depending on your language and compiler, CLAY_SIZING_GROW might need to be passed 0 when you don't specify min and max size:

    :::diff - CLAY({ .layout = { .width = CLAY_SIZING_GROW() } }); + CLAY({ .layout = { .width = CLAY_SIZING_GROW(0) } });

  2. Update border declarations

Borders now share a single color, and use the shared .cornerRadius from the outer declaration.

:::diff
- CLAY_BORDER({ .left = { 20, COLOR_BLUE }, .right = { 20, COLOR_BLUE }, .bottom = { 20, COLOR_BLUE }, .cornerRadius = { 10, 10, 10, 10 } })
+ .cornerRadius = { 10, 10, 10, 10 },
+ .border = { .width = { .left = 20, .right = 20, .bottom = 20 }, .color = COLOR_BLUE }
  1. Changes to Floating Elements

Replacing CLAY_FLOATING, The .floating config of the declaration struct now has a new field, .attachTo, which can be one of several values:

CLAY_ATTACH_TO_NONE (default) CLAY_ATTACH_TO_PARENT CLAY_ATTACH_TO_ELEMENT_ID CLAY_ATTACH_TO_ROOT

Unlike previously where just calling CLAY_FLOATING was enough to switch an element to floating mode, now .attachTo has to be set to some value other than the default NONE. CLAY_ATTACH_TO_PARENT is the old default behaviour, CLAY_ATTACH_TO_ELEMENT_ID requires that you set a parentId to attach the floating element to, and the new CLAY_ATTACH_TO_ROOT option allows you to position the element relative to the root of the layout (i.e. the entire screen), by using the .offset field.

:::diff
// Attach to parent
- CLAY_FLOATING({ .offset = { 12, 12 } });
+ .floating = { .attachTo = CLAY_ATTACH_TO_PARENT,  .offset = { 12, 12 } };

// Attach to specific ID
- CLAY_FLOATING({ .parentId = CLAY_ID("targetElement") });
+ .floating = { .attachTo = CLAY_ATTACH_TO_ELEMENT_ID,  .parentId = CLAY_ID("targetElement") };
  1. Clay_SetMeasureTextFunction must now be called after Clay_Initialize

  2. Clay_Initialize now requires an error handler callback.

    :::diff void HandleClayErrors(Clay_ErrorData errorData) { // See the Clay_ErrorData struct for more information printf("%s", errorData.errorText.chars); switch(errorData.errorType) { // etc } }

    • Clay_Initialize(arena, (Clay_Dimensions) { screenWidth, screenHeight });
    • Clay_Initialize(arena, (Clay_Dimensions) { screenWidth, screenHeight }, (Clay_ErrorHandler) { HandleClayErrors });
  3. Update to new Clay_MeasureTextFunction signature Since 0.12, the function signature of the user provided Clay_MeasureText has changed for consistency and additional features.

    :::diff - Clay_Dimensions Raylib_MeasureText(Clay_String text, Clay_TextElementConfig config) { + Clay_Dimensions Raylib_MeasureText(Clay_StringSlice text, Clay_TextElementConfig config, void userData) {

  4. Update custom renderer implementations The structure of Clay_RenderCommand has changed significantly, and should offer better performance and convenience. Custom renderers will need to be updated to handle the new structure.

The easiest way to get started would be to look at the diff of the updated Raylib Renderer, and the new README documentation for Clay_RenderCommand

Bug Fixes

0.13 contains a large number of bug fixes both to edge case handling and the core layout algorithm, but it's worth specifically highlighting that elements now shrink much more gracefully & sensibly than they did in 0.12:

Before: Screenshot 2025-01-08 at 7 20 11 pm

After: Screenshot 2025-01-08 at 7 19 26 pm

Special Thanks

Special thanks to @emoon, @FintasticMan, @monodop, @bullno1 and @TimothyHoytBSME for their significant contributions to this release, not just from a code perspective but also for their tireless work helping people in the Discord and on Github issues. Couldn't have done it without you!

New Contributors

Full List of Changes

Source: README.md, updated 2025-02-12