Open viridia opened 1 year ago
@nicoburns this feels like a feature we should implement in Taffy, and then expose in Bevy. Do you agree?
@nicoburns this feels like a feature we should implement in Taffy, and then expose in Bevy. Do you agree?
You might not need to. The root element (that is, any UI element that doesn't have a parent) already has this behavior; perhaps all you need to do is layout the element as if it had no parent.
I think this can be implemented quite easily in Bevy itself. The proposal makes a reasonable argument as to why it would be useful I guess. I'm not sure about the name, scrolling is something we are planning to implement and there is a PR #8104 though it hasn't seen much progress lately. Regardless, feels like we should be able to come up with something more descriptive than Fixed
.
PositionType::Origin
?
Other possible names:
PositionType::Root
PositionType::Window
I like PositionType::Window
quite a lot: it's very explicit about what it's positioned relative to.
Root
seems like it might be confusing but Window
seems alright. Maybe it doesn't quite fit when rendering to texture but that's probably not a problem.
I like
PositionType::Window
quite a lot: it's very explicit about what it's positioned relative to.
Coming from CSS / Tailwind, Fixed
seems more logical to me as it's often used in modals and other web-based "popups. It also seems to fit in with the rest of the variant names.
Looking at the variants, Absolute
and Relative
make sense but Window
in the context of those is a bit unclear. Whereas Fixed
has the implication of "this does not move" and would be familiar to people coming from CSS backgrounds.
I'm somewhat new to Rust and just getting into Bevy, so I am considering this as a good first issue to take and contribute!
That sounds great! Link this issue in that PR and we'll give you some reviews :)
Hello where to fix
BTW, just to be clear - the reason I chose the word "fixed" is because:
PositionType
enum is clearly inspired by the CSS position
attribute.position
, the fixed
value is the one that most closely matches the behavior we want. (Some options, like sticky
and static
, are meaningless in the context of Bevy.)In other words, web developers will know exactly what it means. Non-web developers will have to learn what it means :)
@UkoeHB @nicoburns Some additional thoughts on implementation. There are two obvious approaches:
This raises some questions:
Position::Fixed
as proposed doesn't affect the inheritance of TargetCamera
or any other inherited rendering attributes, so we'd be rendering on the same surface as the ui ancestors, with the same surface dimensions.TargetCamera
component, which would impact this calculation, but this also would logically impact vh and vw length calculations as well - see next bullet point. However, for MVP we really don't need to consider the case of overriding TargetCamera
, but it can be something considered for the future.Both options seem fine to me.
Wearing my taffy
maintainer hat, I'd prefer the former solution if everything else is equal. I think it's cleaner, and this is functionality that all of our consumers could benefit from.
What problem does this solve or what need does it fill?
For modal dialogs and popup menus, it is helpful to be able to position an element relative to the window rather than its parent element.
What solution would you like?
Currently the UI
PositionType
enum supports two types of positioning:PositionType::Absolute
andPositionType::Relative
which correspond to the CSS propertiesposition: absolute
andposition: relative
. This proposal adds a third choice,PositionType::Fixed
which positions elements relative to the window, and which also corresponds to the CSS attribute of that name. In other words, the element's parent position is ignored, and instead its layout is considered as if its parent was the same coordinates and dimensions as the window.Note: the semantics of "fixed" as proposed here are slightly different than the meaning of the CSS property - a "fixed" element in CSS is one that never scrolls, and is always relative to the viewport. Since Bevy doesn't have scrolling, the difference is moot.
What alternative(s) have you considered?
For something like a modal dialog or popup menu, it's possible to work around this by creating a completely separate view hierarchy for the overlay element, and then using state variables to control the opening and closing of it.
However, this approach has a drawback, which means that you can no longer use event bubbling to communicate between the dialogue and the code that invoked it. (I know Bevy doesn't have bubbling yet, but bevy_eventlistener does, and I believe bubbling is a planned feature).
Particularly for popup menus, the logic for positioning a menu requires placing the menu in absolute window coordinates (often limiting the menu size or switching sides depending on the available space), but still communicating with the anchor element (such as the menu button) as if it were a child element. (This also requires knowing the coordinates of the anchor in absolute window coordinates, but that's a different problem).
Dialogues which represent major "game modes" are often root-level components and thus don't require this; however contextual dialogues which are triggered by some other UI element (such as a combo box) are often implemented as children of that element; requiring the dialogue to be a root involves additional boilerplate.
Additional context
Frameworks such as React and Solid also provide a feature known as "portals" which allow sub-components to render elements that are located at the root of the DOM but still communicate with their parents as though they were children. This feature covers some of the same use cases.