Changes for version 0.07 - 2026-10-19

  • A widget that loses the focus hands it on instead of leaving nothing focused: when the focused widget is removed from the tree, disabled or told it cannot focus, the focus goes to the nearest ancestor that stays and can take it, or to the widget a focus_heir hook names (a closing popup names what was focused before it). The blur and the heir's focus fire in one batch, so listeners never see a moment without a focus.
  • A HasFocusOrder owner decides how the focus enters and leaves its subtree. get_entry_focus is asked when Tab or Shift+Tab arrive from outside, so a container can be a Tab stop of its own; focus_scope names the subtree its order covers, and Interaction::focus_after steps on from the end of a subtree, wrapping within the scope, so a modal dialog keeps the focus inside itself.
  • Text widgets have a bounding box like every other widget, appear under the pointer and may compose Hoverable and Pressable, so a label can react to the pointer without a box around it. Clay__OpenTextElement returns the id Clay gave the text.
  • Text that does not wrap (CLAY_TEXT_WRAP_NEWLINES and CLAY_TEXT_WRAP_NONE) no longer holds its parent wide: a long URL or path is cut off at its container's width, but only once nothing else in the container can shrink, so every layout that fits today stays as it is. CLAY_TEXT_WRAP_NEWLINES now breaks only at newlines, and CLAY_TEXT_WRAP_NONE keeps the whole text on one line; the documentation of both says so.
  • $ui->content_box answers the area inside a widget's padding for the last frame, so a composite widget no longer combines a bounding box with a fresh to_config run.
  • on($name, $handler, owner => $object) binds a listener to an owner it holds weakly: the handler is called with the owner and the event, and stops running once the owner is gone. A widget class can listen on its own parts without weakening a copy of $self in every handler.
  • HasParent answers every question about the tree: ancestors, closest, subtree, and the exported is_widget predicate; $ui->owns says whether a widget belongs to a UI.
  • A Preparable scroll container is prepared in the same render whenever it moved, by the wheel, a drag, momentum or scroll_to; no OnScroll listener is needed for that any more.
  • Clay_MinMemorySize and Clay_Initialize take explicit element and word counts, so a Clay::UI sizes its context without a throwaway seed context and never touches another UI's counts or Clay's defaults. A tree that does not fit max_element_count is reported with the number of widgets that would have fit, exiting transitions included.
  • The test suite now checks every exported enum constant against clay.h and every wrapper guard against the guard table, so a Clay bump cannot silently lose a constant or a guard. The callback dispatcher is private to the binding; nothing in Perl can call or replace it.

Documentation

recipes for common layout, rendering and interaction tasks
user guide for Clay::XS and Clay::UI
every struct and field Clay::XS accepts

Modules

widget layer over Clay::XS: build a widget tree, lay it out, turn pointer input into events
styled container widget role for Clay::UI
how far a Clay::UI event travels up the widget tree
what an event listener returns: stop the event or let it continue
base class of Clay::UI events, and how to make your own
fired at a widget that loses the focus
fired at a widget that receives the focus
fired when the pointer comes over a hoverable widget
fired when the pointer leaves a hovered widget
fired at the topmost pressable widget when the pointer goes down
fired when a press is released over an armed widget (a click)
fired when a scroll container's scroll position changed
table widget role for Clay::UI with automatically sized columns and rows
styled cell container for Clay::UI::Grid
row container that Clay::UI::Grid creates for each row
hover, press and focus state of a Clay::UI
process-wide counter that grows whenever a Clay::UI frame would look different
element widget role with public child mutators
base role of every Clay::UI element widget
let a widget rebuild its subtree right before the layout pass
require an explicit id on a Clay::UI widget
base role of every Clay::UI text widget
role that lets a widget fire events
role that lets every widget listen to events
role for widgets that can be switched off
role for widgets that can take the keyboard focus
role for containers that choose the focus order in their subtree
role for widgets that track the pointer hovering over them
role for widgets that can be pressed and clicked
mark a widget as a cell that Clay::UI::Grid uses as it is
floating attribute for Clay::UI widgets
layout attribute for Clay::UI widgets
parent, root and UI of a Clay::UI widget
make a Clay::UI widget a scroll container
give unrelated widgets a common width or height
background colour attribute for Clay::UI widgets
border attributes for Clay::UI widgets
corner radius attribute for Clay::UI widgets
named states such as selected or loading on a Clay::UI widget
text widget role for Clay::UI
what one Clay::UI frame laid out
how Clay::UI reports misuse (internal)
internal snake_case and camelCase key translator
internal attribute validation for Clay::UI widgets
low-level Perl binding for the Clay C layout library

Provides

in lib/Clay/UI/Grid.pm
in lib/Clay/XS.pm
in lib/Clay/XS.pm