Skip to content

Split UI Style into multiple components #5511

@Weibye

Description

@Weibye

What problem does this solve or what need does it fill?

  • The UI Style component is rather monolithic could benefit from being split into multiple components.
  • This would allow more granular access to the various style elements on the UI.
  • I think it could improve ergonomics around modifying existing UI like animation, hover effects, showing or hiding UI ++.
  • I suspect the UX around creating UI would more or less be the same but it could unlock other approaches to improve that problem area

I want to gather some feedback on the validity / usefulness of doing so before we'll mark this as "ready-for-implementation" or close it out if it turns out to not be a good idea.

This is what it looks like today:

pub struct Style {
    /// Whether to arrange this node and its children with flexbox layout
    ///
    /// If this is set to [`Display::None`], this node will be collapsed.
    pub display: Display,
    /// Whether to arrange this node relative to other nodes, or positioned absolutely
    pub position_type: PositionType,
    /// Which direction the content of this node should go
    pub direction: Direction,
    /// Whether to use column or row layout
    pub flex_direction: FlexDirection,
    /// How to wrap nodes
    pub flex_wrap: FlexWrap,
    /// How items are aligned according to the cross axis
    pub align_items: AlignItems,
    /// Like align_items but for only this item
    pub align_self: AlignSelf,
    /// How to align each line, only applies if flex_wrap is set to
    /// [`FlexWrap::Wrap`] and there are multiple lines of items
    pub align_content: AlignContent,
    /// How items align according to the main axis
    pub justify_content: JustifyContent,
    /// The position of the node as described by its Rect
    pub position: UiRect<Val>,
    /// The margin of the node
    pub margin: UiRect<Val>,
    /// The padding of the node
    pub padding: UiRect<Val>,
    /// The border of the node
    pub border: UiRect<Val>,
    /// Defines how much a flexbox item should grow if there's space available
    pub flex_grow: f32,
    /// How to shrink if there's not enough space available
    pub flex_shrink: f32,
    /// The initial size of the item
    pub flex_basis: Val,
    /// The size of the flexbox
    pub size: Size<Val>,
    /// The minimum size of the flexbox
    pub min_size: Size<Val>,
    /// The maximum size of the flexbox
    pub max_size: Size<Val>,
    /// The aspect ratio of the flexbox
    pub aspect_ratio: Option<f32>,
    /// How to handle overflow
    pub overflow: Overflow,
}

What solution would you like?

  • Split the Style component into the following:
    • DisplayComponent
    • PositionTypeComponent
    • DirectionComponent
    • FlexDirectionComponent
    • FlexWrapComponent
    • AlignItemsComponent
    • AlignSelfComponent
    • AlignContentComponent
    • JustifyContentComponent
    • PositionComponent
    • MarginComponent
    • PaddingComponent
    • BorderComponent
    • FlexGrowComponent
    • FlexShrinkComponent
    • FlexBasisComponent
    • SizeComponent
    • MinSizeComponent
    • MaxSizeComponent
    • AspectRatioComponent
    • OverflowComponent
  • Implement a UiStyleQuery that queries for all of these components
  • Create a UiStyleBundle containing all of these components
  • Add the UiStyleBundle to the UiNodeBundles
  • We need some mechanism to ensure all UI nodes always have all style-components present or the node would be invalid and the app should panic or produce error
  • sixfold on discord mentioned that these components should all share the same Style-trait which would be a marker trait to start with but could be extended going forward

Open to suggestions on naming, I'm not sure how useful calling them FooComponent when they also #[derive(Component)]
If some of these components are always used together, it might make sense to merge them instead of having everything be separate.

What alternative(s) have you considered?

Leave Style as is.
We are going to need more ergonomic ways of interacting with UI overall, this addresses a tiny part of it but there could be other designs that makes more sense.

Additional context

  • @TheRawMeatball's work on ui4
  • Consensus has been reached to make windows become entities + components: Windows as entities #4530
    • This means splitting up the existing Window struct into multiple separate components
    • Details can be seen here on how this looks: Windows as Entities #4947
    • The use-case here is slightly different so I'm not 100% certain all the arguments for that use-case can be applied here as well

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-UIGraphical user interfaces, styles, layouts, and widgetsC-UsabilityA targeted quality-of-life change that makes Bevy easier to use

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions