Composable Widgets

Hi there, I’m wondering if there’s been any discussion around a composable layer above the widget API. I believe the vast majority of UI elements can be built with a relatively short list of components, stacks & callbacks - rectangles, circles, text, on_drag, on_hover etc.

Curious to know people’s thoughts - I think a composable API might be very nice to have in iced!

Yes! I opened a discussion about a widget composition API a while ago, but didn’t end up bearing much fruit.

I believe I probably wasn’t thinking low-level enough. I think this should be a layer below the widget API.

1 Like

Thinking a bit more about it, I believe it could be on top of the Widget API and leverage generics to avoid any kind of overhead.

Will explore soon some more!

1 Like

Oh, nice! I read through that discussion, my thoughts might be in the same vein.

My ideas on this came from reading the discussion around animation. If I remember correctly, one of the troubles with adding animation was that every widget is responsible for it’s own (relatively low level) rendering. The way to add new capabilities (such as interpolation) was to update every single widget.

Based on that - I think an API that provides a set of fundamental units could allow things to scale differently. Any capabilities added to the units could inherently be available to the widget which composes them.

The quick and dirty implementation I was messing around with was a widget that takes a set of “unit” elements like a stack would, draws them, & optionally handles some callbacks like ‘on_hover’ or ‘on_press’.

The definition of a custom widget with this approach looks something like this

    ComposedWidget::new(state, move |s| -> Element<'a, Message, Renderer> {
        rect(31., 31.)
            .corner_radius(4.)
            .fill_color(s.hovered.interpolating(
                    Color::from_rgb(0., 0., 0.7),
                    Color::from_rgb(0.5, 0.5, 1.),
                    time(),
                ),
            )
            .into()
    })
    .on_press( // message )
    .on_hover( // message )

This kind of thing would likely need Z stacks to work very well, & I’m not sure what kind of issues pop up on the layout side.