bevyengine / bevyengine/bevy

Stepper Widget

Open
#25,706 0 comments 0 reactions 0 assignees View on GitHub
A-UI C-Feature D-Complex S-Needs-Design
Dominant language
Rust
Stars
48.2k
Forks
4.8k
Avg merge
3d 22h
Merged PRs (30d)
161

Description

I'm considering adding a `Stepper` widget to bevy_ui_widgets. This is a widget mainly used in console games, but it can also be useful in examples if we do a feathers version. (For example, we could use it to control which gltf scene is displayed).

The stepper is simply a button with two arrows, increment and decrement. It's like a slider, but without the draggable thumb.

The stepper widget is unopinionated about how the value is displayed: it could be a number, or it could be a word. An example of the latter would be a game difficulty stepper, which displays easy / normal / veteran / hardcore / insanity. (I can even envision an animated version in which the old word slides out and the new word slides in.)

While the stepper does respond to mouse clicks, it's main purpose is to be driven by the keyboard, or if available, a gamepad. For example, the D-Pad inputs could be used to increment or decrement the stepper.

## Open Question

Currently the `Slider` widget only supports `f32`. FeathersNumberInput takes a much more complex route, and supports `i32`, `i64`, `f32`, and `f64` through the use of enum variants. That's fine for feathers, which isn't intended to be a lightweight solution.

The stepper needs to support at least `i32` and `f32`; The "game difficulty" use case is an example of the former, and "dead zone adjust" is an example of the latter.

One solution would be to migrate the feathers `NumberInputValue` into bevy_ui_widgets. One concern I have about this is small platforms like GBA which might not have i64 support, in which case we'd be generating extra code that never gets used, bloating the binary size. `NumberInputValue` does a lot of its internal calculations in f64 (like `.offset_by` and `.scale_by`, and while this is fine for an editor, a console game in which there's a fixed memory budget may want something slimmer.

It would also mean that Stepper was inconsistent with Slider (unless we update Slider too).

A variant of this would be to replace `NumberInputValue`'s enum implementation with a trait-based generic, so that apps could choose which number types they wanted to support.

Another approach would be to make Stepper generic; this would also require making its plugin and all of its observers generic too. Going too far down this road leads to a combinatorial explosion of observers. Like, do we really want `Stepper` to be part of `DefaultPlugins`?

This, too, is inconsistent with the way the other widgets behave.

A third option is to go with a "pure MVC" approach, and not have the stepper manage the value at all - that is, it only generates increment / decrement events and leaves the mutation and clamping of the value up to the app/model. However, this also has problems: first, it means that the app would also be responsible for updating the a11y information, which violates our "a11y is the path of least resistance" principle. Second, this also is inconsistent with how the other widgets work.

A final alternative is to have explicitly two different steppers: `StepperI32` and `StepperF32`.

@alice-i-cecile @kfc35 @ickshonpe

Contributor guide

Open the contributing guide

Research direction

Start by reviewing the existing Slider widget and FeathersNumberInput implementation, then compare their value-handling, plugin, observer, keyboard, gamepad, and accessibility behavior against the proposed Stepper. Before implementation, resolve the open question of supported numeric types and whether the widget should manage values or emit increment/decrement events; done is a documented design and an agreed implementation scope.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
frontend, game-dev
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.