gutenberg
gutenberg copied to clipboard
Layout components: standardize API approach
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 ofjustifyContent
, 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
)
- 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.
- 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
forGrid
) (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
andGrid
would be much more predictable to use, while still allowing the maximum flexibility to their consumers -
HStack
andVStack
could be seen as high-level components, a sort of "preset" of theFlex
component — which means that we could even decide to expose high-level props (and only a few low-level props fromFlex
, if non at all)
Cons of this approach:
-
Flex
andGrid
'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
cc @mirka @chad1008 and a few devs who have been recently working often with the @wordpress/components
package @aaronrobertshaw @andrewserong @talldan @ntsekouras
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.
A potential solution could be to expose only high-level layout components that can be used to cover the majority of the cases:
HStack
andVStack
already exist, and I believe that they could cover 99% of cases whereflexbox
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.
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
andVStack
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 withHStack
orVStack
. - 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 https://github.com/WordPress/gutenberg/issues/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
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?
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 usingFlex
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)