Ranger tree literals — Radix components

← conformance playground

Seven treefactory declarations, each naming its own tags over the same EVGElement, painted by EVG's WebGL painter. Three of them rebuild the whole tree on every control; the motion showcase, the table and the dropdown keep theirs, because a transition remembers where a value was and a rebuilt element remembers nothing.

effects.css — live

Try evg-fx-density, -hue, -speed on .fx-sky, or -sweep-speed on .fx-glass. Change evg-surface-effect to plasma-wave, raindrop or ambient-light and paste a block from lib/evg/gl/effect-presets.css to see another one.

Drag a row onto another and the list reorders — and it is rebuilt, not moved: the page holds an order and hands it over, and the tree literal builds whatever it is given. Click a row and use Space, ↑ ↓ and Escape for the same thing from the keyboard. The behaviour is the one gallery/ui/src/SortableCtl.rgr is measured against, item for item, with @dnd-kit/sortable as the reference.

The state is not this demo's. Sorting, page-scoped selection and the paging arithmetic all live in gallery/ui/src/TableCtl.rgr, which the conformance harness measures against @tanstack/react-table — the library ReUI's table is built on. This file is the other half: a treefactory and a stylesheet, and nothing else. The controller decides what is true; the tree literal decides what it looks like.

The rows are siblings. There is no group per folder: the visible rows are one flat list and the nesting is carried by aria-level alone, because that is what @headless-tree/core renders and therefore what ReUI's tree renders. The indent is a spacer this demo adds; a reader never sees it and does not need to. Open/closed, focus and every key are gallery/ui/src/TreeCtl.rgr’s.

This demo owns no state at all. Open/closed, the roving focus, the submenu stack, the 100 ms hover delay and every key are gallery/ui/src/MenuCtl.rgr’s, which five conformance specs measure against @radix-ui/react-dropdown-menu. What is here is a treefactory, a stylesheet, and which icon goes on which row. Compare it with the menubar demo above, whose keyboard is hand-written and matched against nothing.

Anything can go inside. WindowCtl owns a frame and a title bar; bodyEl is an ordinary EVGElement the caller fills, and build() re-makes the chrome around it without touching it. Here one holds a form and the other a small table, from two unrelated tree literals. The older EVGWindow could hold neither: its vocabulary is label, button, radio, checkbox, and one rectangle whose pixels the owner paints by hand.

Hover the cards at the bottom. Nothing in MotionDemo.rgr knows what a pointer is: the tree is boxes with class names, and every hover, press and journey on this page is a rule in motion.css. The page’s only job is to turn a theme over every 1.7 seconds and to hand the engine the real elapsed time each frame.

Cross the slow card quickly. Its transition is 900ms, and leaving half way through does not take another 900ms to come back — a reversal is shortened by how far the value actually got, measured after the easing curve rather than off the clock. On ease-in at the midpoint those differ by nearly a factor of two.

Click it. The canvas answers the pointer through EVG’s own hit testing: a press is resolved against the same laid-out tree that was drawn, topmost first, so a click inside an open panel reaches the panel and not the trigger it covers. Hovering Share opens the submenu; Escape closes; ← and → walk the bar, ↑ and ↓ the rows. The sidebar is a second view of the same state.

And read it. A canvas hands a screen reader one empty graphic no matter what was drawn into it, so the page also publishes what the frame means: EVGA11yFromTree walks the same elements and emits roles, names, states and rectangles, and evg-a11y.js mirrors those into transparent DOM over the canvas — which is what a reader actually walks. Nothing is described twice: the roles are on the treefactory tags beside the classes. A reader activating a node is answered by pressing the app at that node’s rectangle, so it takes the same path as the mouse.

The dropdowns float under their triggers because EVG has overlay surfaces: Content is still the Menu’s child, and layout takes it out of the parent’s flow, finds the anchor among its own siblings and moves it and its subtree there. A submenu is a Menu like any other — there is no submenu case in the demo. A surface near an edge flips to the other side of its anchor and slides along the edge to stay on the page. The toolbar’s italic and underlined buttons are missing for an unrelated reason: EVG has no font-style and no text-decoration.