- Issue created by @tim.plunkett
- 🇦🇺Australia larowlan 🇦🇺🏝.au GMT+10
There's now a default content import API in core that handles files (courtesy of recipe API) we could make use of that
- 🇧🇪Belgium wim leers Ghent 🇧🇪🇪🇺
#3: except it doesn't really handle files. @Felix worked on a PoC at https://git.drupalcode.org/project/experience_builder/-/commit/8ecc46f91... — there the managed file is captured in the config itself and recreated on the destination, by using purely the existing config management infrastructure
The issue description is clearly huge in scope. We should narrow this down to multiple config entity types. Hence making this a meta. Subtasks I propose:
- Start with a new config entity type that "decorates" an SDC — only SDCs with such a decorating config entity should be exposed in XB.
xb.component.*
? - Make it fully validatable + ensure valid config dependencies (on the module providing the SDC), and test that using a
ConfigEntityValidationTestBase
subclass - Once that exists, allow specifying such a component with a value already assigned to a prop — for example a default image, using parts of the PoC MR's code.
- Once that exists, allow specifying whether such a default value is actually fixed — meaning that the user can't change it. For example: a consistent "Christmas hero" component that can be placed in a bunch of places with fixed content. — @lauriii to confirm this is a goal for XB, @Wim thinks he remembers this.
- Next: … TBD
- Start with a new config entity type that "decorates" an SDC — only SDCs with such a decorating config entity should be exposed in XB.
- 🇫🇮Finland lauriii Finland
Where and/or how would the
xb.component.*
configuration be created for the Experience Builder components? From DX perspective, it seems ideal that a developer could complete the user story listed in 📌 "Developer-created components": mark which SDCs should be exposed in XB Fixed within code. Can we achieve that with the proposed solution?Once that exists, allow specifying whether such a default value is actually fixed — meaning that the user can't change it. For example: a consistent "Christmas hero" component that can be placed in a bunch of places with fixed content. — @lauriii to confirm this is a goal for XB, @Wim thinks he remembers this.
There are several related user needs:
- As a content creator, I want to create components with static values I can reuse across the site. For example, follow us on social media component which should always have the same content and design regardless of where it's being displayed.
- As a builder, I want to create components where some of the values are static and some of them can be filled by content creators. For example, a card with a button, where the button text should always be the same, e.g. "Read more".
- 🇧🇪Belgium wim leers Ghent 🇧🇪🇪🇺
- 🇫🇮Finland lauriii Finland
#6: That's interesting! I think the user stories we have talked about are:
- As a front-end developer, I want to have an easy way to expose components from code within the Experience Builder because I want to minimize the time I need to spend to learn a new platform.
- As a content creator, I want to be able to use components to build pages from a list of components which has been curated for the context of the site I'm working with so that I don't have to browse through long list of irrelevant options.
- As a builder, I want to be able to control which components are available within the Experience Builder so that the content creators are displayed a curated list of components in the Experience Builder.
This indicates that there should be some aspect of customizability per-site. However, how I was thinking about this was so that a front-end developer could expose a component directly within the Experience Builder, but a builder could revert that decision by hiding the component in the UI.
- 🇬🇧United Kingdom catch
However, how I was thinking about this was so that a front-end developer could expose a component directly within the Experience Builder, but a builder could revert that decision by hiding the component in the UI.
This feels like it could be very error prone.
e.g. A contrib module adds a new SDC in a new release. It is very similar to a custom SDC that a site already has (maybe even has an identical label).
Site owner/development team does not notice the new SDC in the list in layout builder until after it's deployed to production.
Content editors start using the new SDC, either intentionally, or mistakenly because it's similar to another one.
Once this is discovered, the site owner/dev team now needs to audit all recent content for the new SDC, convert it to the other one, before they can hide it from the UI again.vs.
New SDC goes into an 'available SDCs' list somewhere, and is explicitly enabled by the site owner - now it gets reviewed before anyone starts using it instead of afterwards when it's too late.
For developers, a 'drush sdc:layout-enable' command or similar could skip having to go into the UI.
- 🇧🇪Belgium wim leers Ghent 🇧🇪🇪🇺
- 🇦🇺Australia larowlan 🇦🇺🏝.au GMT+10
What catch is saying is also the same as the equivalent LB ✨ Add the notion of a 'configured layout builder block' to solve a number of content-editor and performance pain points Active - opt-in instead of firehose++
- 🇧🇪Belgium wim leers Ghent 🇧🇪🇪🇺
🌱 [META] Configuration management: define needed config entity types Active landed. Next up: 📌 Add ::calculateDependencies() to ComponentTreeItem Active , which is a small next task to unblock the much bigger ✨ Allow specifying default props values when opting an SDC in for XB Fixed .
- 🇧🇪Belgium wim leers Ghent 🇧🇪🇪🇺
Diagram WIP, more tomorrow: #3454677-8: [PP-1] Diagram tying the product requirements + decisions together → .
- 🇫🇮Finland lauriii Finland
The current approach for the config entities goes somewhat against the SDC principle which is that everything related to the component should be in a single directory. This way you can move the SDC from a system to another, without having to chase down for additional files outside the SDC. Also, as a frontend developer you know that if you need to make changes to a component, you can always find the underlying code in that directory. It might not be possible to have everything in the
*.component.yml
, but having a*.experience_builder.yml
file there would still be better than storing it in config outside the component.What comes to opting-in components, I agree with the general sentiment from @larowlan and @catch that there needs to be a way to curate the components exposed to the page builder. What I'm not convinced is that we should require opt-in on component by component basis. I believe an ideal experience would be something in between a fire-hose and opting in on component by component based. In my mind, that ideal DX would allow exposing components directly from code, without requiring a step in the UI. I believe we should try to enable this while avoiding the fire-hose problem.
So what if we introduce a concept of categories and tags? This way builder could select either specific components, tags or categories that they want to expose for the content creators. We probably need the concept of categories anyway, in order to group components in the UI.
By default there would be one category for elements. Rest of the components would be listed as untagged components. Ideally components themselves could specify their category; for no-code components this is in the UI and for code components this is in code. This way sites can choose what is the level on which they want to decide which components can be used by content creators, and you could get rid of the additional step.
This approach does not have to be specific to choosing which components to allow in the page builder. Individual components need to be able to specify restricted slots too, where they define which components are allowed for that slot. The restricted slots may also want to be able to use tags and/or categories for defining the allowed components. This way the slots become more flexible, because for example in the case that a design system has multiple CTA components, you could allow all different CTA components to be used in a certain slot without having to specify them one by one.
I proposed this (without as much detail) in 📌 Clarify "components" vs "elements" vs "patterns" Active and @Wim Leers posted some concerns:
The only way around it I see is generating such a config entity automatically for every discovered SDC
I'm curious why we'd require a config entity per SDC? I understand that no-code components require a config entity, but why code components require that too?
A) accept that every SDC ends up in an "untagged" bucket by default and hence we can overwhelm content creators, and allow specifying a tag after the fact
The untagged bucket might be displayed by default, but most sites would end up disabling it after they've decided how they'd like to restrict components that are available in the page builder.
B) accept that some SDCs may fail to generate a reasonable preview and can hence confuse content creators, and allow specifying a default value after the fact
We can probably accept the lack of default values especially given that we can control the starting point ourselves. We can also either come up with ways to generate the default values ourself (i.e. static default values), or by defining some ways to nudge component authors to define them e.g. within development tooling.
C) accept the field type + widget suggested by #3452497: [MR Only] Edit any component prop, powered by a new FieldForComponentSuggester service, which will power the JS UI as the default, and allow editing after the fact
I'm not entirely convinced that requiring manual widget selection makes sense for components. Maybe there should be a way to manually override the widget when the one automatically selected doesn't make sense, but I'd imagine this is something that we can automate to large extent for components by setting sensible defaults.
- 🇬🇧United Kingdom catch
So what if we introduce a concept of categories and tags? This way builder could select either specific components, tags or categories that they want to expose for the content creators. We probably need the concept of categories anyway, in order to group components in the UI.
How would that work in the following situation:
- A site builder includes components from the 'image gallery' tag but not the 'image sliders' tag.
- A content editor uses a component, provided in code from a contrib module, from within the 'image gallery' tag.
- The contrib module providing this component realises it's mis-tagged the component, and changes its tag from 'image gallery' to 'image slider'.
Now the component is no longer allowed, but there is content using it.
- 🇬🇧United Kingdom catch
Re #15 that sounds very unpredictable. It could also go the other way - you opt-out of a tag, then a component moves tag in a contrib module update, and you don't pick it up during QA then suddenly the component is available on production.
Or you opt-in to the image gallery tag, and a contrib module adds an entirely new image gallery component which you don't want, which you now have to opt out of individually.
- 🇧🇪Belgium wim leers Ghent 🇧🇪🇪🇺
#14:
Now the component is no longer allowed, but there is content using it.
Exactly. That's another reason config is important. Even if we'd be auto-creating that config. Because the config allows us to use the entire config import/export system and dependency system to detect and prevent accidental breakage.
I disagree with @lauriii's premise in #15.
@catch wrote the more disastrous example I was thinking of in #16 👍🙏
The only way I see out of this is to auto-create this "Component" (name TBD) config entity for each discovered SDC, so that the Site Builder doesn't have to do anything to allow advanced Content Creators to use arbitrary components.
For the reasons cited in #16, there MUST be a triaging ability for the Site Builder to ensure the UX for the Content Creator expected by the Site Builder. Simpler sites may choose not to need this at all. Huge sites with thorough QA may not need it either — in either of those, there might be no Site Builder triaging.
But for many sites, there would be. - 🇧🇪Belgium wim leers Ghent 🇧🇪🇪🇺
Another reason I think we need a config entity: the need to tie SDCs to design tokens — which @ckrina is exploring.
- 🇫🇮Finland lauriii Finland
Re #16 I'm wondering if we are overestimating the complexity involved with components in relation to modules. Components (at least ones used via XB, with the exception of elements) would generally not be shipped by modules. This is because components must include both markup and CSS because they are self-contained. For this reason, components are usually specific to a design system, and therefore not shipped by modules.
I agree that using categories and tags comes with some downsides because you lose some control. Maintaining components one by one for every slot that exists in the system just sounds like a terrible experience. You could still do it if you want to, but you would not be forced to do it.
The only way I see out of this is to auto-create this "Component" (name TBD) config entity for each discovered SDC, so that the Site Builder doesn't have to do anything to allow advanced Content Creators to use arbitrary components.
But this would still violate the single directory principle. If we break that principle, it makes it harder to maintain components as well as to share them between sites. Ideally we could do something like https://wordpress.org/patterns/ with SDCs. Requiring additional steps besides copy pasting the directory adds friction to this process.
- 🇧🇪Belgium wim leers Ghent 🇧🇪🇪🇺
But this would still violate the single directory principle.
How? If it's auto-generated, it doesn't matter?
makes it harder to maintain components as well as to share them between sites
Two sites may want to use the same component but make different data structure choices. One site might be using Drupal core's Media, another might be using just the Image field, and yet another might be using a DAM.
They could all be sharing the same components, but the way they choose to populate the components' props might be different.
Requiring additional steps besides copy pasting the directory adds friction to this process.
If a copy/pasted SDC uses a SDC prop shape already in use on the site, then there would be zero friction. This will be the case most of the time.
Captured this as
- 🛑 (Would address @lauriii's concerns at #3444424-13: [META] Configuration management: define needed config entity types → , but merits further discussion — the product requirements are contradictory on this front. ⚠️) ✨ Allow specifying default props values when opting an SDC in for XB Fixed specified a default field type + default widget + default value for each component. Flip that around: gather all unique SDC prop shapes, and ask a default field type+widget+value for those. Then, subsequently, we could auto-generate component config entities for all available SDCs. The component config entities could still be valuable to deviate from the default for a particular component.
at 🌱 [META] Early phase back-end work coordination Active 👍
- 🇬🇧United Kingdom catch
Components (at least ones used via XB, with the exception of elements)
What does 'with the exception of elements' mean?
- 🇫🇮Finland lauriii Finland
Elements are low level components that are agnostic to design; e.g. paragraph, container, image, columns, and so on. These are the building blocks for building no-code components. Given that these are design system agnostic, they would be like shipped by modules.
- 🇬🇧United Kingdom catch
These are the building blocks for building no-code components.
OK that makes sense, so essentially components that are so low-level that need zero or very limited CSS.
Given that, even if it turns out to be the case that modules don't ship higher-level components that often, it seems quite likely that recipes could be shipping low-code components, and depending on granularity/redundancy that could still result in things being available that site builders need to exclude.
- 🇧🇪Belgium wim leers Ghent 🇧🇪🇪🇺
📌 "Developer-created components": mark which SDCs should be exposed in XB Fixed introduced the
Component
config entity. Details documented in https://git.drupalcode.org/project/experience_builder/-/blob/0.x/docs/co...📌 Introduce an XB `PageTemplate` config entity Active is working to introduce the
PageTemplate
config entity. It will update the aforementioned docs. - 🇧🇪Belgium wim leers Ghent 🇧🇪🇪🇺
📌 Introduce a `Pattern` config entity Active will introduce the
Pattern
config entity type. - 🇧🇪Belgium wim leers Ghent 🇧🇪🇪🇺
📌 Introduce an XB `PageTemplate` config entity Active is in ⇒ unpostponed #3479643: #3479643-8: Introduce a `Pattern` config entity → .
And … 📌 HTTP API to read+write PageTemplate and Pattern config entities Active is very far along too!
I'll create an implementation issue for 🌱 [later phase] [META] 7. Content type templates — aka "default layouts" — affects the tree+props data model Active , with a description/outline of how I think this can work similar to what I did for #3479643.
- 🇧🇪Belgium wim leers Ghent 🇧🇪🇪🇺
📌 HTTP API to read+write PageTemplate and Pattern config entities Active is in!
Next up: 📌 Introduce a `Pattern` config entity Active .