- the scrollbar is .ui-scrollbar with a .ui-thumb, styled by the default sheet or a theme; a press on the thumb holds it at the point it was taken and the pointer moves it in proportion, a press on the track jumps the thumb's middle there and holds it, and neither presses what is under the bar (it used to centre the thumb on the pointer and press the row beneath as well); - while a popover is up only scroll boxes inside it take the pointer, and a press outside it that closes it forgets any press in progress; - a transition ends exactly on its value (it stopped a rounding error short, at every frame rate). Tests: ui_popover_mouse, ui_scrollbar, ui_ease (60/120/180/240 Hz). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
6.1 KiB
bump: minor
type: feature
Default parameters, components, views and templates. A parameter can have a default (pad: float = 8.0).
A call leaves out what it does not change, and may pass its first arguments by position and the
rest by name.
A view declaration is the one bridge between a program and its UI. It names the fields a
template may read, the functions it may ask and the on events it may send, and it writes
view_<name>() -> UiView.
A component Name { prop, state, fields, functions, on events } declaration beside Name.xml and
Name.lss is a UI component. Its template and styles are compiled in (with @import inlined), each
mounted instance keeps its own props and state, styles are scoped to it, and a parent's class,
style and id land on its root.
ludic.ui is now a template runtime. Screens and components are XML files loaded at run time,
with:
-
{expression}bindings; -
<if>,<else>and<each>; -
props,
<slot/>and per-instance<state>; -
on-pressactions that send events,setstate oremitto the component's user; -
component libraries (
export="true",<import src as>); -
HTML's elements (
div,p,h1-h6,ul/li,img,hr, ...), with a default stylesheet; -
HTML's attributes:
id,class,style,hidden,disabledandonclick, with any other attribute kept for selectors; -
the CSS box model (padding and margin in 1-4 values, borders,
pxand%) and flex layout (flex-grow,justify-content,align-items/align-self,flex-wrap, min and max sizes) under CSS's property names; -
stylesheets, in a
<style>or an.lssfile (a Ludic StyleSheet) that others import and that can@importmore; -
CSS's selectors:
#id, compound classes,[attr=value], descendant and>combinators,:hover,:disabled,:first-child,:last-child,:nth-child,:notand more, weighed by specificity. -
more CSS: custom properties and
var(),positionwith insets andz-index,em/rem/vw/vh,@media, wrapping text and ellipsis,overflow,+/~,:nth-child(an+b),:checked,:active; -
more React: keyed lists,
<let>,<provide>context,<fragment>, named slots,on-mountandon-unmount; -
native elements a program draws itself (
ui_native,ui_fire), and form controls; -
errors with file and line, hot reload (
ui_reload), and an inspector-style dump.
The runtime is a UI framework, not only a template engine:
- it takes input itself: focus and keyboard navigation, the pointer, scroll boxes,
autofocus; - it has built-in controls (button, checkbox, radio, range, select, text, key), styled as CSS parts;
ludic.ui/render3d.ludicis a render3d backend, with textures, atlases, nine-slices, clipping and scale;- more CSS:
rgba()/#rrggbbaa,border-radius,outline,box-shadow,background-image,border-image, groupopacity,@keyframes/animation/transition; - HTML mixed content, and boolean attributes;
popover(a top layer that keeps the pointer and keys, with light dismissal),titletooltips, and<progress>/<meter>;- importing
ludic.ui/render3d.ludicinstalls the backend, and atlases take rows; - hooks for the program's language, sounds and clock.
What a game's screens found missing, now in ludic.ui:
<input type="number" min max step>: typed digits, Enter or leaving it commits them clamped, the arrows step it;<input type="key">listens for any key (Tab and the arrows included) once Enter or a click starts it; Esc stops it, Backspace clears it,shownnames the value, andui_capturing()tells the host;note="..."under any control's label (.ui-note); a range'sdecimals,format="percent"andunit; a track laid out as a row, with the range's fill as tall as it;- popovers anchored beside an element (
anchor="id", or a bareanchorfor the element before it,placement), flipped to the other side and kept on the screen; flex-shrink(a scroll box in a column takes the room its siblings leave),flex: grow shrink,order, and text in a row wrapping in the room its siblings leave;calc()over px, %, em, rem, vw, vh andvar();width: 0andheight: 0mean 0;text-shadow; tooltips of several lines;ui_opacity()for a native's draw;border-imagedrawn as painted with no background colour, tinted by one, and not at all undertransparent; a picture file drawn untinted (an atlas cell still takescolor);- the render3d backend loads a picture again when its file changes (
ui_image_reload), draws a path with a drive letter as a path, and slices a nine-slice by its texture's own width and height; - a component root that is itself a component takes every user's class, style and id, and the sheets that style it are weighed together by specificity;
- a component's event may be called
set; astringprop given a number reads it as text; two components of one name are an error naming both files; - the scrollbar is
.ui-scrollbarand.ui-thumb: a press on the thumb holds it where it was taken, a press on the track jumps the thumb's middle there, and neither presses what is under the bar; - a popover's own controls take its presses whatever lies under it, a press outside only closes it, and while one is up the scroll boxes outside it do not take the pointer;
- a transition lands exactly on its end value (it had stopped a rounding error short of it, at every frame rate).
render3d gains tex_width / tex_height, and the XML reader keeps text runs among elements in
order (mixed).
A view field set to a literal or a named function's result needs no type.
Screens are drawn through a registered renderer. Value gains a float kind.
Also:
- A program's function named like one of the runtime's is refused; it had been silently taking the runtime's own calls.
- An index is evaluated before the slice's elements are read. A
xs[f()]whosefgrewxsread stale memory. - A runtime error names the file its expression is in, not the program's.
Two declarations with one name (a package's private global and a program's, say) are reported as such before type checking. They used to surface as a page of type errors about the wrong type.