0.13 - Simplified Config, Multi Instance Support
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.
// 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
}
// 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:
- The available configuration options are naturally discoverable for those using intellisense just by pressing
.insideCLAY({ }), whereas previously you had to look up the macros in the documentation. - You can define the configuration for an entire element and save it as a struct:
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.
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.
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.
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
- Wrap the inside of the
CLAY(...)macro in braces for the new formCLAY({ ... })
- CLAY(
+ CLAY({
CLAY_ID(...),
CLAY_RECTANGLE({ ... }),
CLAY_BORDER({ ... }),
CLAY_FLOATING({ ... })
- )
+ })
- Mass rename the following macros:
CLAY_BORDER({ ... })CLAY_IMAGE({ ... })CLAY_SCROLL({ ... })CLAY_FLOATING({ ... })CLAY_CUSTOM({ ... })
into struct fields of the form .border = { ... }, .floating = { ... } etc
CLAY({
CLAY_ID(...),
CLAY_RECTANGLE({ ... }),
- CLAY_BORDER({ ... }),
+ .border = { ... },
- CLAY_FLOATING({ ... })
+ .floating = { ... },
})
- Replace the
CLAY_IDmacro with the struct field.id = CLAY_ID
CLAY({
- CLAY_ID(...),
+ .id = CLAY_ID(...),
CLAY_RECTANGLE({ ... }),
.border = { ... },
.floating = { ... }
})
- Replace
CLAY_RECTANGLEmacros with two struct fields,.backgroundColorand.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.
CLAY({
.id = CLAY_ID(...),
- CLAY_RECTANGLE({ .color = COLOR_RED, .cornerRadius = { 10, 10, 10, 10 } }),
+ .backgroundColor = COLOR_RED,
+ .cornerRadius = { 10, 10, 10, 10 },
.border = { ... },
.floating = { ... }
})
- 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.
- 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 } });
- Depending on your language and compiler,
CLAY_SIZING_GROWmight need to be passed0when you don't specify min and max size:
- CLAY({ .layout = { .width = CLAY_SIZING_GROW() } });
+ CLAY({ .layout = { .width = CLAY_SIZING_GROW(0) } });
- Update border declarations
Borders now share a single color, and use the shared .cornerRadius from the outer declaration.
- 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 }
- 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.
// 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") };
-
Clay_SetMeasureTextFunctionmust now be called afterClay_Initialize -
Clay_Initializenow requires an error handler callback.
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 });
- Update to new
Clay_MeasureTextFunctionsignature Since 0.12, the function signature of the user providedClay_MeasureTexthas changed for consistency and additional features.
- Clay_Dimensions Raylib_MeasureText(Clay_String *text, Clay_TextElementConfig *config) {
+ Clay_Dimensions Raylib_MeasureText(Clay_StringSlice text, Clay_TextElementConfig *config, void *userData) {
- Update custom renderer implementations
The structure of
Clay_RenderCommandhas 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:
After:
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
- @27justin made their first contribution in https://github.com/nicbarker/clay/pull/47
- @OleksiiBulba made their first contribution in https://github.com/nicbarker/clay/pull/55
- @AMurkin made their first contribution in https://github.com/nicbarker/clay/pull/59
- @mrneo240 made their first contribution in https://github.com/nicbarker/clay/pull/78
- @CrackedPixel made their first contribution in https://github.com/nicbarker/clay/pull/109
- @FintasticMan made their first contribution in https://github.com/nicbarker/clay/pull/81
- @juniorrantila made their first contribution in https://github.com/nicbarker/clay/pull/130
- @SuperOptimizer made their first contribution in https://github.com/nicbarker/clay/pull/123
- @St0wy made their first contribution in https://github.com/nicbarker/clay/pull/134
- @peter15914 made their first contribution in https://github.com/nicbarker/clay/pull/153
- @bullyingteen made their first contribution in https://github.com/nicbarker/clay/pull/162
- @davidstyrbjorn made their first contribution in https://github.com/nicbarker/clay/pull/167
- @monodop made their first contribution in https://github.com/nicbarker/clay/pull/174
- @Funto made their first contribution in https://github.com/nicbarker/clay/pull/178
- @Mathys-Gasnier made their first contribution in https://github.com/nicbarker/clay/pull/125
- @ppebb made their first contribution in https://github.com/nicbarker/clay/pull/208
- @Zettexe made their first contribution in https://github.com/nicbarker/clay/pull/210
- @LiquidityC made their first contribution in https://github.com/nicbarker/clay/pull/107
- @emoon made their first contribution in https://github.com/nicbarker/clay/pull/212
- @TimothyHoytBSME made their first contribution in https://github.com/nicbarker/clay/pull/205
- @ArnauNau made their first contribution in https://github.com/nicbarker/clay/pull/219
- @CJFEdu made their first contribution in https://github.com/nicbarker/clay/pull/216
- @noflashbang made their first contribution in https://github.com/nicbarker/clay/pull/233
- @radiant64 made their first contribution in https://github.com/nicbarker/clay/pull/232
- @steviegt6 made their first contribution in https://github.com/nicbarker/clay/pull/245
- @nadako made their first contribution in https://github.com/nicbarker/clay/pull/252
- @Orcolom made their first contribution in https://github.com/nicbarker/clay/pull/247
- @FelixBreitweiser made their first contribution in https://github.com/nicbarker/clay/pull/255
Full List of Changes
- [Documentation] docs: remove some inconsistencies with current API by @27justin in https://github.com/nicbarker/clay/pull/47
- [Core] Forward declare Clay__OpenTextElement by @bullno1 in https://github.com/nicbarker/clay/pull/49
- [Renderers/Cairo] Include new cairo renderer by @27justin in https://github.com/nicbarker/clay/pull/48
- [Core] Fix text cache overflow by @nicbarker in https://github.com/nicbarker/clay/pull/51
- [Core] Improve overflow handling / CLAY_MAX_ELEMENT_COUNT exceeded by @nicbarker in https://github.com/nicbarker/clay/pull/52
- [Core] Fix: moved CLAY__MIN and CLAY__MAX to public macros by @OleksiiBulba in https://github.com/nicbarker/clay/pull/55
- [Renderers/HTML] Implement native scroll containers in HTML renderer by @nicbarker in https://github.com/nicbarker/clay/pull/54
- [Renderers/Raylib] Added window dimensions and title to Clay_Raylib_Initialize function by @OleksiiBulba in https://github.com/nicbarker/clay/pull/56
- [Documentation] Fix variable name in README.md by @AMurkin in https://github.com/nicbarker/clay/pull/59
- [Core] Allow floating configuration to capture pointer by @nicbarker in https://github.com/nicbarker/clay/pull/66
- [Core] fix: move internal types to stdint specific. by @mrneo240 in https://github.com/nicbarker/clay/pull/78
- [Core] Implement Error Handler / Callback by @nicbarker in https://github.com/nicbarker/clay/pull/105
- [Renderers/raylib] Update files for v5.5 by @CrackedPixel in https://github.com/nicbarker/clay/pull/109
- [Core] Fix a couple of standards-compliance issues with C99 by @FintasticMan in https://github.com/nicbarker/clay/pull/81
- [Renderers/SDL2] Create initial SDL2 renderer by @nicbarker in https://github.com/nicbarker/clay/pull/115
- [Examples/Intro] Fix NULL pointer deref due to huuge malloc by @FintasticMan in https://github.com/nicbarker/clay/pull/120
- [Core] Add Clay_IsDebugModeEnabled() by @juniorrantila in https://github.com/nicbarker/clay/pull/130
- [Core] Fix more C99 compliance issues by @FintasticMan in https://github.com/nicbarker/clay/pull/118
- [Compilers] C projects should use C flags rather than CXX flags by @SuperOptimizer in https://github.com/nicbarker/clay/pull/123
- [Compilers] C++ projects should use CXX flags by @SuperOptimizer in https://github.com/nicbarker/clay/pull/136
- [Renderers/Cairo] Add FindCairo.cmake by @SuperOptimizer in https://github.com/nicbarker/clay/pull/122
- [Compilers] Fixed compilation when using Clang on Windows by @St0wy in https://github.com/nicbarker/clay/pull/134
- [Bindings/Odin] Update Odin bindings to latest by @nicbarker in https://github.com/nicbarker/clay/pull/151
- [Core] Simplify CLAY macro by @FintasticMan in https://github.com/nicbarker/clay/pull/119