Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Split UI Style into multiple components #5511

Open
Weibye opened this issue Jul 31, 2022 · 5 comments
Open

Split UI Style into multiple components #5511

Weibye opened this issue Jul 31, 2022 · 5 comments
Labels
A-UI Graphical user interfaces, styles, layouts, and widgets C-Usability A targeted quality-of-life change that makes Bevy easier to use

Comments

@Weibye
Copy link
Contributor

Weibye commented Jul 31, 2022

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
@Weibye Weibye added A-UI Graphical user interfaces, styles, layouts, and widgets C-Usability A targeted quality-of-life change that makes Bevy easier to use labels Jul 31, 2022
@Nilirad
Copy link
Contributor

Nilirad commented Jul 31, 2022

I would suggest spending some time in component design, instead of blindly convert each field into a component.

@alice-i-cecile
Copy link
Member

Strongly in favor; I think this would help make accessing and defining this information much easier. Some bikeshedding:

  1. DisplayComponent etc -> Display. Just expose the raw value, and use taffy::Display when we need to differentiate.
  2. UiStyleQuery This should probably be FlexboxLayoutQuery or something, to better communicate scope.
  3. "Add the UiStyleBundle to the UiNodeBundles": this will be controversial; I think we should just add the components individually.

Archetype invariants is definitely the right tool to ensure cohesion. It should be ready soon.

@alice-i-cecile
Copy link
Member

I would suggest spending some time in component design, instead of blindly convert each field into a component.

Proposed split:

  1. Boundaries: margin + border + padding
  2. UiSize: size, min size and max_size
  3. TextDirection: direction
  4. LayoutStrategy: display
  5. FlexboxLayout: everything else

@Weibye Weibye added this to UI Jul 31, 2022
@Weibye Weibye moved this to Todo in UI Jul 31, 2022
@Nilirad
Copy link
Contributor

Nilirad commented Jul 31, 2022

Not sure if in-topic, but I think it would be good UX to have font weight/style and text decoration as their own components:

  • Underline (as or with an enum with Normal, Dotted, Wavy, etc variants)
  • Overline
  • LineThrough
  • Bold
  • Italic

@alice-i-cecile
Copy link
Member

Definitely agree, but for now we should just split the layout-relevant bits.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-UI Graphical user interfaces, styles, layouts, and widgets C-Usability A targeted quality-of-life change that makes Bevy easier to use
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants