First of three steps agreed with Iris for getting scrolling out of the list and into `Scroll`, so that `.scrollable()` is the one way anything in iris scrolls. docs/IRIS_TODO.md's "In progress" block carries the whole plan and the decisions behind it; this step is the rename and the direction. `List` -> `LazySpan`, and it moves in beside `Span` under `widget/position/`. It is what `Span` is -- a sequence of children along an axis -- laid out lazily from an anchor instead of eagerly from the start, and the name says the one thing that matters about it. It also stops colliding with `BlockKind::List` in the markdown code. `ListRow` -> `LazyItem`; `RowKey` keeps its name, since rows are the vocabulary in transcript-ui. `Axis` -> `Dir`, with the sign meaning what it means in `Span`: which end of the box item 0 sits at. **That is a different question from which end the view is pinned to**, and conflating them would stand a transcript on its head -- its oldest message is item 0 and sits at the top (`Dir::DOWN`) while the view clings to the bottom. So the pin is its own constructor argument, `LazySpan::new(dir, at_end)`, spelled the same way as `Scroll::new`'s. Making `Dir::UP` real rather than nominal is most of the diff. The walk now works entirely in direction-relative pixels from the leading edge -- `Edge::Top`/`Bottom` are `Leading`/`Trailing`, `Placement` likewise, and `RowExtent`'s fields and every local are `lead`/`trail` -- with two places converting: `abs_region`, which flips the box for `Sign::Neg`, and `flip_pos`, which converts the screen-space positions the public helpers speak in (`note_tap`, `key_at`, `extent`, all fed by pointer events) into the walk's space. Without the second, a reversed span would hit-test at the mirror of where it drew. `a_dir_up_span_grows_upward_from_item_zero` asserts on where each row was **actually drawn** (`UiRenderState::active`), not on `extents`: the first version of it read `extent()` and passed with `abs_region`'s flip deleted -- checking the bookkeeping against itself while every row painted at the mirror of where it belonged. It now fails with the flip removed (row 2 at 80..100 instead of 0..20), which is the check that matters. Verified: cargo fmt --check, clippy --workspace --all-targets clean, cargo test --workspace green (21 suites), including the phone-shaped fixture tests. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
iris
My experimental attempt at a rust ui library (also my first ui library).
It's currently designed around using retained data structures (widgets), rather than diffing generated trees from data like xilem or iced. This is an experiment and I'm not sure if it's a good idea or not.
Examples are in examples, eg. cargo run --example tabs.
Goals, in general order:
- does what I want it to (text, images, video, animations)
- very easy to use ignoring ergonomic ref counting
- reasonably fast / efficient (a lot faster than electron, save battery life, try to beat iced and xilem)
dev details
not targeting web rn cause wanna use actual nice gpu features & entire point of this is to make desktop apps / not need a web browser
general ideas trynna use rn / experiment with:
- retained mode
- specifically designed around wgpu so there's no translation
- postfix functions for most things to prevent unreadable indentation (going very well)
- events can be done directly where you draw the widgets
- almost no macros in user code & actual LSP typechecking (variadic generics if you can hear me please save us)
- relative anchor + absolute offset coord system (+ "rest" / leftover during widget layout)
- single threaded ui & pass context around to make non async usage straightforward (pretty unsure about this)
- widgets store outside of the actual rendering so they can be moved around and swapped easily (unsure about this but seems to work good for now)
under heavy initial development so not gonna try to explain status, maybe check TODO for that; sizable chance it gets a rewrite once I know everything I need and what seems to work best
it's called iris because it's the structure around what you actually want to display and colorful