Repository: AmbientRun/Ambient
File: shared_crates/ui/src/scroll_area.rs (Rust)

Code before:
                .with(width(), inner_size.x)
        }
        ScrollAreaSizing::FitParentWidth => {
            UIBase
                .el()
                .init_default(children())
                .children(vec![
                    // TODO: For some reason it didn't work to set the translation on self.0 directly, so had to introduce a Flow in between
                    Flow(vec![inner]).el().with_default(fit_horizontal_parent()).with(translation(), vec3(0., scroll, 0.)),
                ])
                .with_default(layout_width_to_children())
        }
    }
}


/// A scroll box view that can be used to scroll its child with a scroll bar.
#[element_component]
pub fn ScrollBoxView(
    hooks: &mut Hooks,
    /// Width of the scroll area
    min_width: f32,
    /// Height of the scroll area
    min_height: f32,
    /// Distance of scrolling in y axis
    scroll_height: f32,
    /// The child element
    inner: Element,
) -> Element {
    let (scroll, set_scroll) = hooks.use_state(0.);
    let (ratio, _set_ratio) = hooks.use_state_with(|world| {
        let r = world.resource(window_scale_factor()).clone();
        r as f32
    });

    let mouse_over_count = hooks.use_ref_with(|_| 0);
    hooks.use_runtime_message::<messages::WindowMouseWheel>({
        to_owned![mouse_over_count];
        move |_world, event| {
            if *mouse_over_count.lock() == 0 {
                return;
            };
            let delta = event.delta;
            let mouse_pos = scroll + if event.pixels { delta.y } else { delta.y * 20. };
            set_scroll(mouse_pos.clamp(-scroll_height, 0.));
        }
    });

    let bar_height = min_height / (min_height + scroll_height) * min_height;
    let offset = scroll / scroll_height * (min_height - bar_height);
    let id = hooks.use_ref_with(|_| None);

Review comment (suggestion):
Scroll height should be automatically measured internally. Use the `MeasureSize` component on the inner content. You can also see how it's done in the ScrollArea component

Code after:
        to_owned![id, mouse_over_count, set_outer_width];
        move |world| {
            if let Some(id) = *id.lock() {
                let number = world.get(id, mouse_over()).unwrap_or(0);
                *mouse_over_count.lock() = number;
                let canvas_local_to_world = world.get(id, local_to_world()).unwrap();
                let (_, _, pos_world) = Mat4::to_scale_rotation_translation(&canvas_local_to_world);
                set_canvas_offset(vec2(pos_world.x, pos_world.y));
                let w = world.get(id, width());
                let h = world.get(id, height());
                // outer size is mainly for the scroll bar
                if let Ok(w) = w {
                    set_outer_width(w);
                }
                if let Ok(h) = h {
                    set_outer_height(h);
                }
            }
        }
    });
    hooks.use_runtime_message::<messages::WindowMouseWheel>({
        to_owned![mouse_over_count];
        move |_world, event| {
            if *mouse_over_count.lock() == 0 {
                return;
            };
            let delta = event.delta;
            let mouse_pos = scroll + if event.pixels { delta.y } else { delta.y * 20. };
            set_scroll(mouse_pos.clamp(-scroll_height, 0.0));
        }
    });

    let canvas = UIBase::el()
        .on_spawned({
            to_owned![id];
            move |_world, canvas_id, _| {
                *id.lock() = Some(canvas_id);
            }
        })
        .init(mouse_pickable_min(), Vec3::ZERO)
        .init(mouse_pickable_max(), Vec3::ZERO)
        .init_default(children())
        .children(vec![
            // TODO: For some reason it didn't work to set the translation on self.0 directly, so had to introduce a Flow in between
            MeasureSize::el(
                {
                    let flow = Flow(vec![inner])
                        .el()
                        .with_default(fit_vertical_children())
                        .with_default(fit_horizontal_parent())
                        .with(scissors_recursive(), {