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

Layout components: standardize API approach #43085

Open
ciampo opened this issue Aug 9, 2022 · 7 comments
Open

Layout components: standardize API approach #43085

ciampo opened this issue Aug 9, 2022 · 7 comments
Labels
[Package] Components /packages/components [Type] Discussion For issues that are high-level and not yet ready to implement.

Comments

@ciampo
Copy link
Contributor

ciampo commented Aug 9, 2022

Context

This issue applies to layout-based components in the @wordpress/components package:

After a couple of recent conversation around these layout components (example, example), I had a look at the state of layout components, here's a few observations:

  • These components are meant to be a utility for implementing the majority of layouts in a declarative way, without the need for custom styles
  • The components currently expose a mix of high-level and low-level props through their APIs:
    • lower-level props are basically exact mirrors of a CSS property, although they don't always have the same exact name as the CSS property (e.g. justify instead of justifyContent, etc..)
    • higher-level "abstract" props are usually shortcuts for setting multiple CSS props at the same time (e.g. alignment), or for setting a specific complex value (like proposed here), or for supporting a more advanced version of the same CSS property (e.g. gap)
  • As a developer with good knowledge of the CSS grid and flexbox specs, I often find it harder to use these components than to write CSS styles myself. The mix of higher and lower level props and the lack of exact 1:1 matching between lower level props and the CSS counterpart often mean that I can't easily achieve the layout that I have in mind with these components, without some trial & error.
  • I'm also not sure about high-level properties using the ResponsiveValue type (e.g. columns for Grid) (see convo)

Solution(s) proposed

Grid and Flex as low-level layout components

One potential solution is to treat Flex and Grid as low-level components, and make sure that they only expose low-level props that are named exactly like the CSS properties.

Pros of this approach:

  • Flex and Grid would be much more predictable to use, while still allowing the maximum flexibility to their consumers
  • HStack and VStack could be seen as high-level components, a sort of "preset" of the Flex component — which means that we could even decide to expose high-level props (and only a few low-level props from Flex, if non at all)

Cons of this approach:

  • Flex and Grid's utility would mostly be in their declarative approach — by removing high-level props, the consumer would basically need to specify the same styles via props
  • We'd need to decide how much of the flexbox and grid specs we want to expose: should we be aiming at exposing only a few selected CSS props? How do we decide which ones?
  • We'd likely need to be maintaining/updating/enriching these components as the CSS specs are updated (some properties even get deprecated/renamed). For example, would we need to support the Subgrid spec too ?

My opinion

Personally, I am 100% convinced that lower-level and higher-level props should not be exposed within the same component. But I'm not convinced that we should be exposing components that merely expose CSS props via React props either, as it feels to me a poor tradeoff (arbitrary decisions, potentially high maintenance, but low convenience as the consumer may as well just write CSS directly).

A potential solution could be to expose only high-level layout components that can be used to cover the majority of the cases: HStack and VStack already exist, and I believe that they could cover 99% of cases where flexbox is needed (for more complex needs, the consumer may directly implement they custom layout). We could think about creating similar high-level components for the CSS Grid layout?

More in general, as we rework these components, regardless of the solution adopted, we should:

  • Introduce more examples showcasing how to achieve a few different layouts
  • Assess if our defaults are sensible
@ciampo
Copy link
Contributor Author

ciampo commented Aug 9, 2022

cc @mirka @chad1008 and a few devs who have been recently working often with the @wordpress/components package @aaronrobertshaw @andrewserong @talldan @ntsekouras

@ciampo ciampo added [Package] Components /packages/components [Type] Discussion For issues that are high-level and not yet ready to implement. labels Aug 9, 2022
@aaronrobertshaw
Copy link
Contributor

Thanks for putting this issue together here along with your thoughtful analysis. You make some great points.

Personally, I am 100% convinced that lower-level and higher-level props should not be exposed within the same component.

Agreed.

But I'm not convinced that we should be exposing components that merely expose CSS props via React props either

Same. Further to the list of concerns raised, another small con might be given the low convenience factor, we'd get a real mix of approaches using the low-level component or DIY. Could this impede defining a best practice or lead to greater potential for styling inconsistencies?

A potential solution could be to expose only high-level layout components that can be used to cover the majority of the cases

For the cases not covered, would there be any benefit to providing some style mixins to achieve other layouts that might not warrant a dedicated component?

We could think about creating similar high-level components for the CSS Grid layout?

I'd like to see us explore some high-level grid components. Happy to help here if we all decide to go down this path.

@mirka
Copy link
Member

mirka commented Aug 10, 2022

A potential solution could be to expose only high-level layout components that can be used to cover the majority of the cases: HStack and VStack already exist, and I believe that they could cover 99% of cases where flexbox is needed (for more complex needs, the consumer may directly implement they custom layout)

I like this. There are multiple times where I've reached for Flex when I could've just used HStack/VStack, because my brain just instinctively thought "flex" 🙈 I don't think I've ever actually needed Flex.

We could think about creating similar high-level components for the CSS Grid layout?

In this vein, as I work on #39358 I'm wondering if we should have a high-level layout component specifically for sidebar controls. It would be nice to have an easy way to maintain layout consistency between ToolsPanel, Global Styles, and custom Inspector controls injected by blocks.

@ciampo
Copy link
Contributor Author

ciampo commented Aug 10, 2022

Thank you for your replies, @aaronrobertshaw and @mirka ! It looks like we may be converging towards this proposed solution:

A potential solution could be to expose only high-level layout components that can be used to cover the majority of the cases: HStack and VStack already exist, and I believe that they could cover 99% of cases where a flexbox layout is needed (for more complex needs, the consumer may directly implement they custom layout). We could think about creating similar high-level components for the CSS Grid layout?

I'll try to answer to the remaining questions that you both asked.

@aaronrobertshaw:

Further to the list of concerns raised, another small con might be given the low convenience factor, we'd get a real mix of approaches using the low-level component or DIY. Could this impede defining a best practice or lead to greater potential for styling inconsistencies?

I believe that's a risk that is there with or without our low-level components, unfortunately — and it's also something that would happen outside of the components package. But if we believe that our set of high-level components would cover the majority of use cases, then hopefully that will be already a good start.

For the cases not covered, would there be any benefit to providing some style mixins to achieve other layouts that might not warrant a dedicated component?

I'm not sure — after all, if a preset "high level" component doesn't cut it, there's a chance that mixins won't either. With regards to which high-level components we should publish (and which properties they offer), I would start with a small set of components / features, ad add more components/features as we encounter layout "challenge" that are frequent enough.

I'd like to see us explore some high-level grid components. Happy to help here if we all decide to go down this path.

Absolutely! I think a good start may be to go through the current usage of Grid and Flex:

  • For the cases where Flex is used, we should try to replace it with HStack or VStack.
  • For the cases where Grid is used, we should prepare a census of the layouts that the component is used for, and try to prepare a list of high-level components to satisty these challenges.

@mirka:

In this vein, as I work on #39358 I'm wondering if we should have a high-level layout component specifically for sidebar controls. It would be nice to have an easy way to maintain layout consistency between ToolsPanel, Global Styles, and custom Inspector controls injected by blocks.

I'd be very interested to see what such a high-level component may look like

@andrewserong
Copy link
Contributor

Apologies for the late reply, and thanks for the discussion here!

I often find it harder to use these components than to write CSS styles myself

I've found this working with Flex, too, and also agree that exposing the lower and higher level props in the one component creates a lot of confusion.

It looks like we may be converging towards this proposed solution:

Consolidating around a few high level components sounds good to me. For cases where these high level components aren't appropriate for someone's use case, would we then encourage folks to use their own flex or grid CSS styling particular to the component they're writing (perhaps attached to View components) over using Flex directly?

@ciampo
Copy link
Contributor Author

ciampo commented Aug 16, 2022

would we then encourage folks to use their own flex or grid CSS styling particular to the component they're writing (perhaps attached to View components) over using Flex directly?

I think so, mainly because (as explained more in details above) that currently using Flex doesn't really bring any advantages over using straight CSS props (although this is not yet a decision set in stone and we should be assessing all what's been discussed in details)

@ciampo
Copy link
Contributor Author

ciampo commented Sep 19, 2024

In the context of #59418, I'd like to resume this conversation.

Talking to @mirka , we feel that Flex and Grid are not a useful abstraction to maintain, given how CSS flexbox and grid layouts have now gotten wide browser support.

Regarding HStack and VStack, we still think that they could be useful utilities to keep around, but we see issues with their API layers:

  • they do not reflect the latest changes in the CSS specs;
  • they apply abstractions that over-complicate the code, and move away from logical properties (eg. alignment prop);
  • they are too generic, and allow consumers to implement bad practices (like reversing flex order);
  • they have default properties that are not the same as the CSS default values for flexbox layouts (ie. non-zero gap, non-start alignments, etc)

For this reason, we're considering to deprecate HStack and VStack and replace them with a new version.

While we're in the process, we're also considering deprecating Spacer, as it offers little value and has issues with its APIs similar to the ones described above for HStack and VStack.

Finally, we don't see much of a need for ZStack, and therefore we're considering deprecating it without a replacement.


Proposal recap:

  • Deprecate Flex, Grid, ZStack => replace with ad-hoc solution using CSS directly;
  • Deprecate HStack and VStack, replace with a v2 that is more focused on typical high-level usecases, and more aligned with the CSS flexbox spec

(cc @WordPress/gutenberg-components )

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Package] Components /packages/components [Type] Discussion For issues that are high-level and not yet ready to implement.
Projects
None yet
Development

No branches or pull requests

4 participants