Active
Project:
Drupal Canvas
Version:
1.x-dev
Component:
Component sources
Priority:
Major
Category:
Plan
Assigned:
Unassigned
Reporter:
Created:
13 Jun 2024 at 23:06 UTC
Updated:
15 Oct 2025 at 12:12 UTC
Jump to comment: Most recent
At the moment the component config entity (introduced in #3444417: "Developer-created components": mark which SDCs should be exposed in XB, being refined in subsequent issues) is tightly coupled to an SDC but it feels like we need to support other things - like blocks (views, menus). Making this pluggable could also mean a bridge for paragraphs users.
Make the "component" config entity and data model support other component types (does that even make sense as a name?).
| "Component type"/"Renderable"/… NAME TBD | Inputs | Required context | Input UI | Has slots or not? | Issue |
|---|---|---|---|---|---|
SDC (no plugin interface because zero PHP logic, plugin manager: \Drupal\Core\Theme\ComponentPluginManager) |
props | Depending on PropSource: no context needed, or host entity needed |
Shape-matched field types + widgets, current PoC: #3452497: [MR Only] Edit any component prop, powered by a new FieldForComponentSuggester service, which will power the JS UI | ✅ | N/A |
| Nuxt (TBD) | props | same as SDCs | probably same as with SDCs (shape-matched form) | ✅ | #3520666: Prototype rendering JavaScript components with Nuxt |
Block (BlockPluginInterface) |
block settings | None (although blocks themselves can react to context using Context API) | each block plugin's form Details/concerns: #3462241-8: [PP-1] Decorate the SDC plugin manager and allow components defined in code |
❌ | #3475584: Add support for Blocks as Components |
Layout (LayoutInterface) |
❌ | None (although layouts themselves can react to context using Context API) | some layout plugins have a settings form (thanks to composing with PluginFormInterface) |
✅ | #3483307: New `ComponentSource`: `Layout`, to allow for a Layout Builder-to-Canvas migration |
Paragraphs (TBD Interface) |
Fields | TBD | TBD | ✅ [Paragraphs can be nested] | #3517216: New `ComponentSource`: `ParagraphType`, to allow for a Paragraphs-to-Canvas migration |
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #2
pdureau commented"tightly bundled to an SDC" may be the issue here.
As much as I like SDC components, they are UI / design thingies not CMS / building thingies. It is better to manipulate blocks & layout plugins, not directly SDC components, and some of them (I hope most of them) will be direct conversion from SDC components.
I have already posted this image in an other issue where I warned about the coupling risk for the project:
https://www.drupal.org/project/experience_builder/issues/3454173#comment...
Not everything in a design system is a component
Let's look a bit forward. On our way to extends the design systems coverage of Drupal, we will meet other UI "artefacts" which are renderable in HTML, but which are not UI components.
2 examples:
{#type: "icon", "#iconset": "foo", "#icon": "bar" }with optional settingsWe are only at the beginning of our design system journey. Do we want to introduce a specific tight coupling for each design artefact? Or do we want to manipulate known CMS objects without caring about where they from in the design implementation?
Comment #3
wim leers@lauriii wrote in Slack that he also images layout plugins become available in XB. But that's not listed in the product requirements. It is sort of implied by
39. Layout Builder migrationthough.@lauriii, I'm curious if you could provide more color/context than what you said in Drupal Slack (which will be nearly impossible to find later anyway)? 🙏
@pdureau I'm confused why you bring "icons" into this discussion. That seems to be a much lower level thing — a design system artifact as you described it a few weeks ago. Do you consider that "another component type"? 🤔 (@lauriii can probably help clarify this too.)
Comment #4
lauriii@pdureau I would imagine this issue is to remove that tight coupling so that we can have other concepts like Blocks exposed in the Experience Builder. 😊 This was documented in the product requirements with the following user story:
@Wim Leers We don't have a separate product requirement for layout components. We discussed them as part of the default design system and style guide discussion. What we discussed was that by default, Experience Builder would provide a single section/grid component which can be configured into different shapes. The grid system itself including columns, gutters, container options (i.e. fluid vs fixed) is configured in the style guide. This component is mainly targeted at the builder persona, which they could use to configure into different shapes as patterns and no-code components.
Exposing Layout Plugins themselves as @Wim Leers guessed has more to do with legacy support. We could discover there are valid use cases for Layout Plugins in this new paradigm but I'm not aware of any at the moment.
Comment #5
wim leersI don't remember discussing this. Where is that written? 🤔
@lauriii: Which component types do you currently think to make sense?
Everyone: please add to the table I just added to the issue summary! 🙏
Comment #6
wim leersTo be able to use field formatters in XB, we could go with either Layout Builder's block-centric approach (
\Drupal\layout_builder\Plugin\Block\FieldBlock) or just use field formatters directly (which would still allow for an easy upgrade path) and should help UX/performance scalability challenges (see #3365551: Add the notion of a 'configured layout builder block' to solve a number of content-editor and performance pain points).Comment #7
wim leersTo achieve the great UX that XB aims for, including "direct manipulation" of visible pieces (see #3453690: [META] Real-time preview: supporting back-end infrastructure) without imposing additional work on the component developer (regardless of "component type", name TBD), it is necessary to be able to automatically infer which (Twig) template input connects to which component input (for SDC: "props").
For example: for
sdc_test:my-ctaSDC, that would mean that the visible part of its templateconnects to the
textprop.That requires connecting the component's template's AST (see #3453690-10: [META] Real-time preview: supporting back-end infrastructure) to the component's inputs. For an SDC this is fairly straightforward.
This may not be possible (or relevant!) for all component types though: For e.g. a block it may not be possible to do that: the
SystemMenuBlockblock plugin only accepts settings for defining how/what subset of the menu to render, so none of the "component's inputs" are directly visible in the template.Comment #8
wim leersWhile working on this + #3444424: [META] Configuration management: define needed config entity types, I stumbled upon an aspect in the product requirements that is confusing, so opened an issue to get a clarification from @lauriii, the product owner: #3455036: Clarify "components" vs "elements" vs "patterns".
Comment #9
larowlanComment #10
larowlanI'm working on some API design here to allow us to support these things
Comment #12
larowlanI've scaffolded some rough code to break the coupling between SDC and components into the branch as follows:
Adds two new plugin types as follows:
Component source plugin
This decouples the component config entity and component tree from SDC components.
There's a SingleDirectoryComponent implementation that all the existing logic moves to
Adds two additional implementations as follows:
Paves the way for:
Component storage plugin
Decouples the component tree loading from the component tree field.
There's an implementation for ComponentTreeItem that holds the existing logic
Starts to scaffold a layout builder version in a sub-module that in could possible be a BC layer for layout builder (I'll keep going on this).
Also opens door to:
Comment #13
effulgentsia commentedIf I'm reading this right, this MR introduces the concept of a "component", that can contain props and slots, but is decoupled from SDCs, and therefore can forward those props and slots to a different source plugin, such as blocks and layouts. What does this enable or make better than what you'd be able to achieve by implementing a "block" SDC or "layout" SDC that performs that forwarding? If we already have the concept of SDCs, why introduce yet another concept of a "component"?
#2 gives some examples of where
propsandslotsmight be an insufficient data model, but I'm not clear how this MR resolves that.I guess from my perspective, what's important about SDCs isn't the SD part (though that part is nice for ergonomics) but the props and slots part.
Comment #14
larowlan@effulgentsia can you elaborate some more on how we could achieve that?
The SDC plugin manager is not like other plugin manager in core in that it doesn't support derivatives OR fire an alter hook.
This means there is no way to dynamically declare SDC plugins/components. This is by design, looking in the comments in the manager it says only directory based components are supported. If that's the case then the only way we could make SDC components for blocks would be to manually create them. This would mean something like twig tweak's `drupal_block` function in core. This effectively makes these components hidden from site builders. The other alternative is we swap out the plugin manager and add support for dynamic plugins. (There's also a third option, dynamically write components to disk, but that won't work on secure hosting where the file system is read-only outside the files folders - e.g. skpr amongst others). That's even before we start thinking about theme-builder created components.
Another approach is to flip the script and make blocks the canonical thing - we have prior art for blocks that wrap SDC (sdc blocks, component blocks modules) but blocks don't support slots, so they're out.
Layouts do support slots and props - but it feels like forcing a round peg in a square hole.
Hence this approach - a new component definition interface and repository. It means we can have components from things other than SDC folders on disk.
Comment #15
effulgentsia commentedOh right, I forgot about that. I think what we should do then is either:
Then hopefully whichever of the above we choose can make its way into core eventually.
The pro of #1 is that modules that have already begun to standardize on SDCs, like https://www.drupal.org/project/sdc_display, can work without change with not-on-disk components.
I guess the con of #1 is then the "SD" part of the "SDC" name becomes less accurate.
I'm concerned about XB defining its own component concept, and a bunch of other modules each defining their own component concept. What I prefer about #1 is that the SDC concept is already in core and has the shape we want (except perhaps if @pdureau's comment #2 is foreshadowing that XB will need to work with components that need things that can't be cleanly represented with props and slots, but I'm not clear yet on how those specific examples will relate to XB).
Comment #16
larowlanI think my preference would be to add support in core for programmatically declared components.
I'll open an issue for it.
Comment #17
wim leersI intend to review @larowlan's MR first thing on Monday :)
Comment #18
wim leersNote that I do not think this is in the critical path for #3454094: Milestone 0.1.0: Experience Builder Demo, but it would be awesome if we can get this in place before then for sure — we'll need it for #3455753: Milestone 0.2.0: Early preview, because without it the data model would be very much incomplete.
Comment #19
wim leersI had to focus on other things today. (#3452512: Add component instance edit form to contextual panel is a major step forward. #3450586-26: [META] Back-end Kanban issue tracker is now conveying again what needs to happen in the short term.)
I'll review tomorrow. Sorry for the delay.
Comment #20
larowlan@Wim Leers I think we should have a chat about this first. I think there's a quite a few things in it that could be split out on their own. There's also some changes needed in relation to discussion with @effulgentsia above.
Tried messaging on slack to arrange a call.
Comment #21
wim leersAbout to meet with @larowlan — but wanted to make sure I processed everything said on this issue ahead of our meeting in a few minutes 😊
@effulgentsia in #13 and @larowlan in #14: Variable # of slots (the "grids" example provided by @pdureau in #2) is a limitation of SDCs. It's also something that @lauriii has identified as one of the biggest risks of this project: the fact that we don't have a full sense yet of what missing features and technical limitations in Single-Directory Components that XB needs resolved. We know about:
@larowlan in #14: we have a PoC branch (built by @tedbow: https://git.drupalcode.org/project/experience_builder/-/blob/research_sd...) that decorates the existing SDC plugin manager, to prove that XB could add support for "config-defined SDCs" (in addition to the default of "code/directory-defined SDCs")
— @effulgentsia in #15
I'm less concerned about this consequence: every "non-directory SDC" could be converted into an SDC, exported, if you will. That's actually a literal product requirement of Experience Builder:
63. Shared components's user story says exactly that!@larowlan in #16: Did you already open that issue? Related issues I could find: #3390980: Make SDC extensible, #3394901: No matter what I do, I can't swap the class of the SDC plugin
Comment #22
wim leers@larowlan just walked me through the changes in the MR attached to this issue. He identified 5 areas, each of which can be split into their own issue/MR:
Componentconfig entity based on the ID (this was an intentionally simplistic choice in #3444417: "Developer-created components": mark which SDCs should be exposed in XB), to both allow >1 config per component (not sure about this, because @lauriii IIRC indicated there should only be one set of default values per component, I can see both sides) as well as allowing non-SDC "components"ComponentSourceInterfaceand friends, and in particular theBlockComponentcomponent source plugin for a very interesting example). @larowlan was interested/glad to see the PoC branch I linked in #21, and we concluded that for now we'd replace theplugin.manager.sdcservice in XB (so: choosing #15.1, not #15.2 as in the current MR), but we eventually would want to see that in core. But ahead of it (hopefully) being in core (which would need the support from SDC maintainer @e0ipso), it'd make sense to validate that in contrib.So: the concrete implementation in the current MR would change to become more akin to what's in the PoC branch, but the concepts in the MR would remain.
SdcController::layout()(seeComponentLeaf(Interface)and friends) would make the tree structure better defined, and would unblock a Just-in-Time approach of loading e.g. Layout Builder into the Experience Builder UI, which in turn enables a smooth, gradual adoption/transition from Layout Builder to Experience Builder.LayoutBuilderSectionComponentTreeStorage), which is how the JIT loading becomes possible (using . Besides transitioning from Layout Builder, it would also enable the use case of defining multiple component trees (one per view mode — by makingComponentFieldTreeStorageaware of the render context).Componentconfig entity defined for every component, because when JIT-loading the component tree from a Layout Builder field (seeComponentDefinitionRepository, those config entities would not exist. This is exactly the direction we were already going in with #3461499: Support complex SDC prop shapes: introduce (Storable)PropShape to compute field type storage settings: that too is working towards makingComponentconfig entities optional.We didn't delve into the concrete implementation details of any of these, but they all would represent significant steps forward towards meeting the product requirements.
I'm super excited about the changes @larowlan is proposing here. Especially because in every of the 5 areas, he's bringing in relevant pieces of his vast real-world experience with Layout Builder, wanting to avoid the scalability problems he experienced there. 🙏🙏🥳🚀
(For example, we also discussed the need for per-slot restrictions on which components would be allowed, which is possible in Layout Builder using https://www.drupal.org/project/layout_builder_restrictions, but that module has scalability issues — through no fault of its own — because the "tags" are not built in, resulting in hundreds of lines of YAML in
third_party_settings😳. That validates @lauriii's thinking to make that an inherent part — see #21.4. Related: #3459088: Every XB `Component` config entity should have a `category` property.)Comment #23
wim leers@larowlan will be creating concrete issues for the 5 areas mentioned in #22 😊🥳
Comment #24
wim leersClarifying issue status: conveying that @larowlan is working on next steps 😊
Comment #25
wim leersFinally fully caught up on everything that happened in the issue queue since June 20 noon — you opened #3456064: [PP-1] Experiment: Adapt existing layout builder storage model instead of starting fresh just as I'd left for vacation. 😄
I think the draft MR here (https://git.drupalcode.org/project/experience_builder/-/merge_requests/68 is essentially a subsequent concrete iteration of the proposal over at #3456064, @larowlan?
Comment #28
larowlanCreated those issues and a bonus one as children of this one.
I need to do some security team tasks tomorrow, but if I get through those I'll start on some of these as well.
Used the pnx²b 😉 tag and flagged with colleagues as well.
Comment #29
wim leersThe issue summary needs to be expanded with at least Layout Plugins, probably also Paragraphs?
I took a stab at expanding it with:
LayoutInterfaceMore needed.
Comment #30
wim leersInteresting observation: the first column are all existing plugin types, but one is more special than others…
Comment #31
wim leersTying this to my detailed analysis for Blocks at #3462241-8: [PP-1] Decorate the SDC plugin manager and allow components defined in code.
Comment #32
wim leersFYI: #3379725: Make Block config entities fully validatable landed July 22, which means supporting Blocks in XB is much more feasible now. IMHO XB should support only block plugins whose config schema is fully validatable, because only then can we be confident that a block placed in an XB component tree will work reliably (prior to that, a block plugin's block settings is quite often just … a dumping ground).
Comment #33
wim leersIMHO #3469609: Prepare for multiple component types: ComponentTreeStructure should contain Component config entity IDs, not SDC IDs is the inevitable first step — regardless of whether we do #3469610: Prepare for multiple component types: prefix Component config entity IDs with `sdc` or not. Together with @abhisekmazumdar, I got that to green, so … consider this officially started 🤓
Comment #34
longwaveAfter reviewing the IS and considering the comments and code provided here, I think @larowlan's approach is valid.
We could try to repurpose SDCs so they can wrap blocks or layouts, but this doesn't conceptually appear to be the right thing to do - SDCs are self contained single directory components by definition, so expanding them with features beyond is scope creep.
We could try to use blocks everywhere and wrap SDCs in blocks, but then we run into the slots issue, and would have to extend blocks so they support slots in some way.
What we are trying to do here is map props/values and slots/components into (at least) three things that are conceptually different (SDCs, blocks, layouts). This is effectively a translation layer and as such should be entirely standalone from the sources and targets of the translation; therefore I think this is the correct direction for this problem.
Also re #2 and the mention of icons, #3471494: Add an icon management API is a future proposal but eventually we could end up with icons as yet another component type alongside SDCs and blocks?
Comment #35
pdureau commentedThat is the way to go in my opinion. You can have a look on UI Patterns 2 implementation:
Which slots issue? Blocks doesn't have to knows about slots themselves, they just have to wrap a component which will know about slots.
Using the Render API, everything is supposed to nest nicely:
If the proposal is accepted, icons will be another render element which will also be nestable in slots:
And a data structure usable in props:
This proposal was already tested in projects and we already know it will fit perfectly with SDC components, and anything leveraging the Render API.
Comment #36
wim leersThe first step towards decoupling XB from SDC just landed: #3469609: Prepare for multiple component types: ComponentTreeStructure should contain Component config entity IDs, not SDC IDs. 🥳
@pdureau in #35
Interesting! I suspect you're looking at blocks through a very particular lens here: as a mechanism for rendering. (Although you'd still have to do extra work to avoid the
block.html.twigwrapping markup to appear around every SDC.) Because:vs
is a contradiction from an Experience Builder point of view AFAICT 😅
The reason blocks not knowing about slots being a problem is because we're talking about what the right abstraction layer would be for XB to deal with all components the same way, regardless of component type/source (SDC, Block, Layout …). Since blocks don't have slots, they are unable to decorate/wrap SDCs and still provide access to critical information.
Comment #37
f.mazeikis commentedComment #38
f.mazeikis commentedI've created #3475584 to start working on "Blocks as Components" requirement. It's based on @larowan work started in MR68 (closed). It's limited scope, focusing only on blocks for now and using the "Component Source Plugin" approach, as per #12.
Comment #39
wim leersAnother step landed: #3469610: Prepare for multiple component types: prefix Component config entity IDs with `sdc`. Component config entity IDs are now present in the client-side data model, instead of SDC plugin IDs. Next up: #3475584: Add support for Blocks as Components.
Comment #40
kristen poltagging for findability
Comment #41
kristen polWe discussed this a couple of days ago at
#3516536: XB migration meeting 31 March 2025 8:30pm to 9:30pm UTC
and at DrupalCon Altanta.
Can we explicitly add Paragraphs to the issue summary list at this point?
Comment #42
wim leers#41: feel free to do so :) Consider this issue summary basically a wiki! 😄
Comment #43
wim leersLinking the relevant issue from the table.
Comment #44
kristen polAdd Paragraphs to list in issue summary, but with TBD placeholders as we are sorting things out.
I suppose we need a Layout Blocks item as well per @larowlan's slides but I'll check with him.
Comment #45
deviantintegral commentedHas there been any discussion about node types as components? This could be a 100% in-core case of doing something like embedding an upcoming event on a landing page, or the little-bit-out-of-core scenario like using Rabbit Hole on content types for a form of microcontent.
Comment #46
longwave@deviantintegral I haven't tested this at all but given that we support blocks as components, perhaps you just need https://www.drupal.org/project/entity_block in order to embed any entity as a component?
Comment #47
penyaskito@deviantintegral @longwave Gave a quick try to that and _mostly_ worked after fixing the entity_block schema so its blocks settings are FullyValidatable. The UI showed up, there were some issues on storing the component but I'm pretty sure that is not a big effort to fix, and probably all effort in entity_block module itself.
Comment #48
wim leers#46 & #47: wow, very cool! :D
Comment #49
wim leers@fago started experimenting with Nuxt components at #3520666: Prototype rendering JavaScript components with Nuxt, so adding that here for discoverability :)
Comment #50
balintbrewsWe also have these two awesome POCs:
Comment #51
fagoAdding some more details about the Nuxt/Vue component source plugin.
I have not started working on the component-source part yet, but what Nuxt is going to need is basically a "JavaScript component plugin with externally bundled JS". So this might be something we can develop generally and make usable with multiple JavaScript frameworks with little glue to invoke the components correctly, or shipping a base-class that easy easy to extend with the glue.
Comment #52
nagwani commentedAfter discussing this with @lauri, I am removing the stable blocker tag.
Comment #53
wim leersThat aligns with #3520484-76: [META] Production-ready ComponentSource plugins 👍
But to convey the ecosystem importance of this, tagging 😊
Comment #55
kristen polHaha... this definitely shouldn't be assigned to me anymore :)
I've poked and prodded Lee & Daniel (on Layout Builder) and Sascha (on Paragraphs) a bunch but they have had other priorities... [no judgment!]
Wim set to "post-stable priority" so hoping these can move forward soon :)
Comment #56
kristen polLee's plan for Layout Builder in Slack:
https://drupal.slack.com/docs/T06GX3JTS/F09JNG8K317