Grid alignment ergonomics pitfall
- Dominant language
- Rust
- Stars
- 48.2k
- Forks
- 4.8k
- Avg merge
- 3d 22h
- Merged PRs (30d)
- 161
Description
I want to spawn a grid with two columns, one right-aligned and one left-aligned. This is a very common use case, e.g. for a [credits screen](https://github.com/TheBevyFlock/bevy_new_2d/blob/d5c50ea75d712d9b5f91de061d634f399723d841/src/screens/credits.rs#L48) or [settings menu](https://github.com/TheBevyFlock/bevy_new_2d/blob/d5c50ea75d712d9b5f91de061d634f399723d841/src/screens/settings.rs#L31). The recommended approach in CSS is to use selectors and style cascading to overwrite _only_ the `justify-self` property on the appropriate grid items:
```css
.grid > :nth-child(2) {
justify-self: end;
}
```
However, this does not translate to Bevy, where properties live in a monolithic `Node` component with no support for selectors or style cascading. You have to set the properties manually on spawn instead:
```rust
fn grid() -> impl Bundle {
(
Node { display: Display::Grid, ..default() },
children![
(Node { justify-self: JustifySelf::End, ..default() }, ...),
(Node { justify-self: JustifySelf::Start, ..default() }, ...),
(Node { justify-self: JustifySelf::End, ..default() }, ...),
(Node { justify-self: JustifySelf::Start, ..default() }, ...),
],
)
}
```
Unfortunately, this approach destroys reusability, because there's no way to do something like this:
```rust
fn grid() -> impl Bundle {
(
Node { display: Display::Grid, ..default() },
children![
widget::label(...).with_justify_self(JustifySelf::End),
widget::button(...).with_justify_self(JustifySelf::Start),
widget::container(...).with_justify_self(JustifySelf::End),
widget::color_picker(...).with_justify_self(JustifySelf::Start),
],
)
}
```
And even if you could, this type of code is a major pain to tweak (e.g. add a column, change a column's alignment, rearrange grid items, etc.). Plus, if you make changes like spawning or despawning grid items after the initial spawn, the column alignment will break.
To fix these issues, you could define a custom `GridAlignment { rows: Vec, columns: Vec }` component and a system to keep grid items in sync.
However, this leads to another problem: Between template tracks and explicit grid placement, how can you determine which rows/columns a grid item spans? Luckily this is already solved internally by `taffy`, and the computed information is [provided](https://github.com/DioxusLabs/taffy/pull/772) -- but Bevy doesn't expose this yet.
Contributor guide
Assessment
This issue has not been assessed yet.