tim.plunkett → credited lauriii → .
which are not supposed to have anything processable in them
Is there a concrete problem that you're anticipating?
We're using HTML comments because we don't want to rely on a specific attribute for this. The goal for Experience Builder is to provide an easy way for developers to expose their existing SDC. Requiring a specific attribute would make the integration harder because components would need to always have this attribute which isn't the case today based on what I've seen in design systems.
Attributes also have another challenge. We need to be able to identify all of the slots as well. This means that not only would we need to have the attributes in the wrapper, but also on wrappers for slots. This would add additional requirements for components (i.e. consistent display of wrappers + attributes for slots) which is not acceptable from DX perspective.
This is definitely solving a pain point that I've heard mentioned in many conversations with Drupal users. However, many of these sites are re-using media and it would be great if we could solve this in a way that doesn't get rid of the re-use media part. I think there are ways in which this could be solve so that we would have both.
This is not the only pain point that I've heard mentioned related to inserting media. Maybe we should do a more holistic design effort around how media gets referenced from content types to try to design something that could solve more of these problems at once? We don't have to implement all of these at once but having a north star design would be more likely to get us an overall better experience. It looks like some of these considerations are already being documented in 🌱 [Meta] Consider adopting Media Widgets as an experimental feature Active .
Here's a patch that contains all of the changes I made to be able to do the demo. It includes:
- Fix for 🐛 PHP warning on image props without examples Active
- 📌 Create back link in XB Active
- Disabling contextual links from the frontend
- Adding "Edit with XB" local task
lauriii → created an issue. See original summary → .
lauriii → created an issue. See original summary → .
Was supposed to mark as needs work.
wim leers → credited lauriii → .
UX wise this seems like a nice improvement! I asked review from @jessebaker on the solution.
Got a +1 from @larowlan on Slack that this is ready to merge.
This is not in scope for 0.2.0. Potentially not in scope for 1.0.0 but need to evaluate later.
#18: That description does not exactly match the use of the colors defined by design. Even though the root is close to a region, it doesn't cascade outside the current page. Therefore we should not be using green for the root as green is supposed to signify that changes inside that area cascade outside the current page.
Blue vs purple is supposed to signify components vs elements. We don't really have elements at this point so pretty much everything should be either purple or green.
Slots don't have their own color at the moment; they should inherit the color of their parent. In this case since we're using components, they should be purple.
Assigning to @wim leers because there's an open question to him in the MR.
For accessibility and consistency reasons (and others), it's important that the title (of a controller with some logic or of a content entity) is always rendered in the same place, using the same markup.
That's why I doubt the content entity's title can realistically become part of the content entity (template)'s component tree? 🤔
I don't think mandating this as a requirement matches well with real life requirements that sites have from design perspective. I agree that title has some nuance to it which makes it different from messages and the main.
Here are few example where it's easy to see there are many sites where there isn't a lot of consistency on how the title is displayed between pages:
discuss with @Lauriii the repercussions/design behind what things do/don’t go into the temp store. I think the consensus was that pretty much everything should always save to temp and be published in one action at a later point to avoid things like a pattern existing but it contains components that were never published.
Anything that would impact the live site should go through the temp store. I was originally thinking that maybe adding new sections wouldn't go through the temp store but there could be some interesting edge cases with that because someone might be creating a section using a component that only exists in the temp store. 🤔
Nice! This definitely makes creating pages from scratch feel more polished! Few refinements we could do in a follow-up:
- We should probably use blue color for the border instead of green because the green is supposed to be signifying global regions (i.e. change may have implications outside of the current page)
- Root seems a bit technical. How about just calling it "Page"?
- This is more of a UX challenge but documenting it here. The current blue background with drops doesn't make it super clear that this is the area where you're supposed to be dragging components in.
griffynh → credited lauriii → .
The UI + OpenAPI changes are minimal and @jessebaker and @wim leers have been active here so going ahead and merging this.
If so: do we want the same treatment for the page title (Drupal\Core\Block\TitleBlockPluginInterface) and messages (Drupal\Core\Block\MessagesBlockPluginInterface)?
99% of the time sites would display these foundational blocks in a region and there wouldn't be any complexity involved with it. However, there are some use cases where context is used so that the block could be displayed in a different region depending on the page.
The approach that I think would work here is to allow theme to decide a placement of a block. Once theme has decided on it's placement, it would not be available to be used in XB. This would particularly well for Drupal\Core\Block\MessagesBlockPluginInterface
and Drupal\Core\Block\MainContentBlockPluginInterface
. Maybe it doesn't even have to be generic since it's quite specific to these two blocks.
The outlier here is Drupal\Core\Block\TitleBlockPluginInterface
because in most scenarios, it would not make sense to display the title block for Pages and Nodes because the title would be defined either in content or the content type template. However, other controllers may need the title to be displayed. If we implemented the generic way for themes to place blocks, we could potentially fit the title use case there too without introducing conditionality for the placement by allowing the template to not render the variable when the title is not desired. Otherwise I guess for now we'd just allow users to place the title in case that it's something they'd need.
This is all really fascinating and brings me flashbacks from #2476947: Convert "title" page element into a block → .
The required label for a section is missing. Or are we saying that they should not have labels? 🤔 If so, happy to remove that from the server-side logic 👍
The API should enforce a label. We should prevent saving sections without a label.
Last paragraph of #6: the shape of the data uses the current client-side data model, which is not necessarily a good thing. See #3467954: Evolve XB UI's data model to allow non-SDC components' inputs, DynamicPropSource support, etc..
This is not necessarily urgent. I was hoping we could demo this at DrupalCon in case that this was really close to being done but it seems that it isn't the case. I'd be fine with us postponing this on 🐛 Some components cannot be used in XB because UI prevents SDC props being named `name` Active and re-evaluating closer to 0.2.0 if that hasn't been done.
NO error handling! 😅 The server side can return validation errors!
I wonder if this is covered by the global error handling? When I tested this, I was getting a fairly graceful handling of errors within the modal.
The global regions should not be editable by default when editing a page or node. The interaction that design defined for this is that users need to double click a global region, which opens up the region in a "focus mode" where user is now allowed to make changes to the global region. How this looks visually has been defined here: https://www.figma.com/design/Ps3m4APGHIILsBrm0Uj31N/Experience-Builder?n....
It is possible to place other blocks in the same region above or below the "main content" block.
I'm not convinced we would need to support this. This is easy enough to workaround by providing a "Above content" and "Below content" regions so I'm not convinced that we should convolute the UX to add support for this use case.
Let's start with that, but eventually, the main content block should be placeable in any region of the theme.
If we need this, this seems like a setting for the theme. This doesn't seem something that would have to be editable in XB. I'm not aware of common use cases that would require moving the main content block to another region after the initial theme setup.
Thank you @wim leers! Based on #28, it totally makes sense to do it in a different issue.
It looks like the XB preview is now showing global regions but the actual main content is slightly different between the real site and XB. Is there still an additional step needed to render the node content using the display mode? FWIW, if this is difficult to do, it would be fine to handle this in a follow-up issue.
XB:
Actual page:
We should display translations there but we need to determine how, because the design doesn't account for how translations are displayed in there (yet). I can think of at least two ways to display this:
- Each translation becomes it's own row
- Each row indicates which translations of the page has been changed
The designers suggested that the errors should have a have a link to the page where the error appears, and it should indeed focus the error that the user clicked. I think it's a good point that it might be beneficial to additionally highlight the pages that have errors in the list of pages. 👍
Warnings should also be displayed outside the preview. We could render them in a toast or a similar component.
It seems that the FE is already connected but I'm getting an error when trying to use this. This probably needs someone on the backend to debug this.
The error with a backtrace:
Error: Call to undefined method Drupal\Core\Config\Schema\Undefined::getIterator() in Drupal\Core\Entity\Plugin\DataType\ConfigEntityAdapter->getIterator() (line 74 of /var/www/html/drupal/core/lib/Drupal/Core/Entity/Plugin/DataType/ConfigEntityAdapter.php).
Backtrace
#0 /var/www/html/drupal/core/lib/Drupal/Core/TypedData/Validation/RecursiveContextualValidator.php(163): Drupal\Core\Entity\Plugin\DataType\ConfigEntityAdapter->getIterator()
#1 /var/www/html/drupal/core/lib/Drupal/Core/TypedData/Validation/RecursiveContextualValidator.php(106): Drupal\Core\TypedData\Validation\RecursiveContextualValidator->validateNode()
#2 /var/www/html/drupal/core/lib/Drupal/Core/TypedData/Validation/RecursiveValidator.php(93): Drupal\Core\TypedData\Validation\RecursiveContextualValidator->validate()
#3 /var/www/html/drupal/core/lib/Drupal/Core/TypedData/TypedData.php(132): Drupal\Core\TypedData\Validation\RecursiveValidator->validate()
#4 /var/www/html/drupal/modules/custom/experience_builder/src/Controller/ApiConfigControllers.php(106): Drupal\Core\TypedData\TypedData->validate()
#5 [internal function]: Drupal\experience_builder\Controller\ApiConfigControllers->post()
#6 /var/www/html/drupal/core/lib/Drupal/Core/EventSubscriber/EarlyRenderingControllerWrapperSubscriber.php(123): call_user_func_array()
#7 /var/www/html/drupal/core/lib/Drupal/Core/Render/Renderer.php(593): Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}()
#8 /var/www/html/drupal/core/lib/Drupal/Core/EventSubscriber/EarlyRenderingControllerWrapperSubscriber.php(121): Drupal\Core\Render\Renderer->executeInRenderContext()
#9 /var/www/html/drupal/core/lib/Drupal/Core/EventSubscriber/EarlyRenderingControllerWrapperSubscriber.php(97): Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->wrapControllerExecutionInRenderContext()
#10 /var/www/html/drupal/vendor/symfony/http-kernel/HttpKernel.php(183): Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}()
#11 /var/www/html/drupal/vendor/symfony/http-kernel/HttpKernel.php(76): Symfony\Component\HttpKernel\HttpKernel->handleRaw()
#12 /var/www/html/drupal/core/lib/Drupal/Core/StackMiddleware/Session.php(53): Symfony\Component\HttpKernel\HttpKernel->handle()
#13 /var/www/html/drupal/core/lib/Drupal/Core/StackMiddleware/KernelPreHandle.php(48): Drupal\Core\StackMiddleware\Session->handle()
#14 /var/www/html/drupal/core/lib/Drupal/Core/StackMiddleware/ContentLength.php(28): Drupal\Core\StackMiddleware\KernelPreHandle->handle()
#15 /var/www/html/drupal/core/modules/big_pipe/src/StackMiddleware/ContentLength.php(32): Drupal\Core\StackMiddleware\ContentLength->handle()
#16 /var/www/html/drupal/core/modules/page_cache/src/StackMiddleware/PageCache.php(116): Drupal\big_pipe\StackMiddleware\ContentLength->handle()
#17 /var/www/html/drupal/core/modules/page_cache/src/StackMiddleware/PageCache.php(90): Drupal\page_cache\StackMiddleware\PageCache->pass()
#18 /var/www/html/drupal/core/lib/Drupal/Core/StackMiddleware/ReverseProxyMiddleware.php(48): Drupal\page_cache\StackMiddleware\PageCache->handle()
#19 /var/www/html/drupal/core/lib/Drupal/Core/StackMiddleware/NegotiationMiddleware.php(51): Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle()
#20 /var/www/html/drupal/core/lib/Drupal/Core/StackMiddleware/AjaxPageState.php(36): Drupal\Core\StackMiddleware\NegotiationMiddleware->handle()
#21 /var/www/html/drupal/core/lib/Drupal/Core/StackMiddleware/StackedHttpKernel.php(51): Drupal\Core\StackMiddleware\AjaxPageState->handle()
#22 /var/www/html/drupal/core/lib/Drupal/Core/DrupalKernel.php(709): Drupal\Core\StackMiddleware\StackedHttpKernel->handle()
#23 /var/www/html/drupal/index.php(19): Drupal\Core\DrupalKernel->handle()
#24 {main}
Here's the request:
fetch("https://drupal-dev.ddev.site/xb/api/config/pattern", {
"headers": {
"accept": "*/*",
"accept-language": "en-US,en;q=0.9",
"content-type": "application/json",
"priority": "u=1, i",
"sec-ch-ua": "\"Google Chrome\";v=\"131\", \"Chromium\";v=\"131\", \"Not_A Brand\";v=\"24\"",
"sec-ch-ua-mobile": "?0",
"sec-ch-ua-platform": "\"macOS\"",
"sec-fetch-dest": "empty",
"sec-fetch-mode": "cors",
"sec-fetch-site": "same-origin"
},
"referrer": "https://drupal-dev.ddev.site/xb/node/1/editor/component/6e4aac04-cb0d-4431-87df-afaec573375a",
"referrerPolicy": "strict-origin-when-cross-origin",
"body": "{\"layout\":{\"nodeType\":\"root\",\"uuid\":\"root\",\"children\":[{\"children\":[{\"uuid\":\"6e4aac04-cb0d-4431-87df-afaec573375a-slot-column_one\",\"name\":\"column_one\",\"nodeType\":\"slot\",\"children\":[{\"children\":[],\"nodeType\":\"component\",\"type\":\"sdc.experience_builder.image\",\"uuid\":\"1b4b7c65-b356-4b22-abb9-d1bccaad4135\"}]},{\"uuid\":\"6e4aac04-cb0d-4431-87df-afaec573375a-slot-column_two\",\"name\":\"column_two\",\"nodeType\":\"slot\",\"children\":[{\"children\":[],\"nodeType\":\"component\",\"type\":\"sdc.experience_builder.heading\",\"uuid\":\"b1b626de-6653-453c-aa26-32e2a79c2c0e\"}]}],\"nodeType\":\"component\",\"type\":\"sdc.experience_builder.two_column\",\"uuid\":\"6e4aac04-cb0d-4431-87df-afaec573375a\"}]},\"model\":{\"6e4aac04-cb0d-4431-87df-afaec573375a\":{\"name\":\"Two Column\",\"width\":25},\"b1b626de-6653-453c-aa26-32e2a79c2c0e\":{\"name\":\"Heading\",\"text\":\"A heading element\",\"style\":\"primary\",\"element\":\"h1\"},\"1b4b7c65-b356-4b22-abb9-d1bccaad4135\":{\"name\":\"Image\",\"image\":{\"src\":\"https://placehold.co/600x400.png\",\"alt\":\"Boring placeholder\",\"width\":600,\"height\":400}}},\"name\":\"Two Column section\"}",
"method": "POST",
"mode": "cors",
"credentials": "include"
});
@larowlan Here's the correct Figma link: https://www.figma.com/design/Ps3m4APGHIILsBrm0Uj31N/Experience-Builder?n.... Updated the original link too.
It would be good to PoC that we can get the insert media to work before we further optimize the solution. This is the concern raised by @bnjmnm in #25. It seems that #28 outlines some steps that we know need to happen before we can get the insertion to work. Are there other steps that we know need to happen?
Proposal makes sense. Thank you @wim leers! 💯
FYI, I opened 📌 Improve server-side error handling Active to improve the error handling. I don't think we should render the error message in the rendered preview but instead there should be a specific interface in XB that handles them. It sounds like the JSON to HTML change might make that more challenging.
If there are multiple pages being published, what happens when some of them pass validation but others don't
How do we convey that to the user
This is demonstrated by this user flow: https://www.figma.com/design/1sj0mnVdLFdYihrkAhR43u/Experience-Builder-%.... Let me know if you want me to record a short video to walk through that since this is one of the more complex flows and it might be helpful.
What happens if we're publishing a large number of entities and we hit resource constraints - we likely don't want to reach for batch API here because the UX isn't on par with what XB is delivering
We can accept the scalability problems for this initial state. We'd probably publish at maximum 10-15 entities with the intermediate solution. We could probably accept even if it was just 5-10 but then we'd need to document it somewhere.
Do these scalability concerns exist with the Workspace based solution too? From design perspective, it seems that the current solution is good enough for now. It would probably be worth opening a spinoff issue to define in a bit more detail how we'd expect the panel to behave in this scenario.
XB won't use this directly (inside XB). This is simply partially driven by needs from Drupal CMS and XB to bring continuity between the Drupal UI and XB (by making changes to the Drupal UI).
That's a good question. I think it should be just the entity title/label since that's what we would be using for referring to the page else where.
The page title should update automatically as it's being changed.
This is currently missing test coverage and error handling. I guess it would be worth considering how extensive test coverage should we write, given that this is a temporary step.
The MR was missing few use statements which led into the CI failures. The fix was simple enough so I went ahead and merged this with the fixes.
This probably should have the same behavior as core's Toolbar: core/modules/toolbar/js/escapeAdmin.js.
The behavior cannot be exactly the same as escapeAdmin.js
because the admin UI could be linking to XB, and in that case we'd want to link user back to the page in the admin UI that they used to navigate to XB. Other than that, it could be the same as what's in Toolbar.
Thank you for picking this up @shyam_bhatt! I left some feedback on the MR
Let's close this one. We can deal with the rest in 📌 Allow saving component compositions as sections Postponed / follow-ups to that.
kristen pol → credited lauriii → .
Merged this based on @tedbow approval. I had to bypass the approvals because there wasn't approval from /src/Entity
code owner. We got review from @wim leers and this is adding a new entity type so it seems fine to bypass the approval there.
+1 for expanding this outside of Node in targeted follow-ups.
We still need this but isn't this pretty simple in the 0.2.0 scope because of 🌱 [Research] Landing page integration Active ?
I'm removing the Display Modes example from the issue summary since that is working by design. The remaining use cases are valid and should be addressed one way or another, either in core or by guiding how contrib modules should approach this.
Here's how I understand this issue. It seems that this problem is specific to the class attribute. It seems that the root cause to the problem is that ckeditor5_style
defines <$any-html5-element class>
as it's elements, which then triggers the validation if anyone tries to add a class attribute to a HTML5 element, because theoretically, they could add that using the style plugin. The plugin documents that the class
is dynamically restricted to a subset of class attributes, but this is not taken into account in the validation.
Requiring the use of the style plugin might be problematic because it a) requires someone to know and specify every class that may be used and it b) exposes them through the user interface (which might not be always desired). Because of this, people are specifying class as an attribute in the source editor plugin.
If this is a somewhat correct understanding of the problem, it seems that an ideal solution would be to special case the class attribute on the style plugin somehow. This way we could allow adding class attribute to elements even though it's an attribute that's supported by the style plugin.
It seems that #59 is proposing something pretty close to this. However, it seems to be adding a new syntax for this. I'm not sure that we need a new syntax for this; in my mind we would just special case the class attribute to not trigger this validation.
This is not so much about rendering PHP errors vs not. This was about where and how those errors should be rendered. For example, the error in the issue summary, is not even something that happens as part of the preview request, it happens on the component preview request. We should improve the error handling so that errors that happen during API requests, never end up in the preview.
Explaining Nodes as pages is already a simplification of the reality because they are not just pages. This is why we are already not calling them Pages, but Content in the product. I believe that for a non-technical user the easiest way to explain Nodes is by the purpose that a Content Type has in the specific site; e.g. product, product collection, event, blog, press release, etc. They may generate a page but often they are used for more than that. For example, a product could generate a page, but it could be also used for "micro-content" because you may want to create a list of products or embed a product as part of a blog post.
When you have a page that is not modeled (i.e. Basic Page), it is just a page because it provides only limited re-use. XB plans to separate this from the re-usable modeled content: 🌱 [Research] Landing page integration Active . Based on user interviews we conducted this spring, this maps well with the mental model that users have. Here's an anecdote from one of the interviews:
Interviewer:
You have this content type called page. What is that?
Participant:
That's actually the content type that I use the most. Whenever we have something that's got more like set structure, that's when we use a content type that is more kind of identified and clear. But whenever we have something that needs to be a little bit more flexible, we use the page. Page is much more bare bones than the more specific content types.
Many products like Webflow, Framer, Wix explain Nodes as CMS collections. I think this is a smart way of explaining modeled content to the site builder. It's communicating that unlike pages, modeled content is something that allows you to create lists besides being able to have a page. While their content modeling capabilities are more limited than what Drupal has, I believe that they do a better job at explaining their content modeling capabilities in relation to unmodeled content. I don't think we can adopt this quite as is because in Drupal you can create lists that combine multiple content types.
How does Block Content fit this thought process? Unlike Nodes, Block Content is for content that you would never want to display as a page or list for the end-user. It could be used for example for a hero that you want to display on multiple pages or a cookie banner. It would be rare for someone to create a page for a hero block or a list of hero blocks for other than administrative purposes.
This allows us to explain why for example Location should be a content type, and not a type of Block Content; because it's something that you may want to be able to list for the end-user, it's something that you may want to expose as a page. This helps explain why we need this change; to allow site builders to create modeled content without forcing them to have a canonical page for it.
It seems fine to raise the minimum requirement to the latest minor of Drupal 10 and 11 ^10.4 || ^11
to ^10.4 | ^11.1
.
I think we should go with the standard permission approach we've taken for entity types in core which as pointed out by #3 requires author/user for the entity. The permissions seem a bit more complex than what may be needed but we would have to go through some extensive thinking to deviate from the existing pattern.
I don't know what's the best way to store this but based on what we have in the designs, I'm anticipating we'd want to get following information:
- Who last changed a page (and when)
- Who created the page (and when)
- Who published the page (and when)
Would the author/user reference provide us what we need to provide this?
Clicked the merge because it looks like there's plenty of approvals there. 🚀
smustgrave → credited lauriii → .
Discussed this with @longwave and @jessebaker. We believe the extension_type
key is too narrow and doesn't account for other needs we have for these. Essentially what we need is information on what is the source of the "component". Potential sources are: Blocks, Theme Components, Module Components, Elements, and JavaScript components. Each of these sources then have categories within itself. Here's a visualization of that:
@ckrina is out until next Wednesday but we could reach out to her then. I have discussed this a while back with @ckrina on a high level.
Here's the latest design I've seen for this:
Essentially in this design there would be an Overview link that would allow user to navigate to the parent link. I don't think this a finalized design so we probably want to wait for input from here before we get too far on the implementation.
If in Core it sounds like maybe we need a mechanism either to opt in or opt out of having a direct access link. If opt in would need to update a lot of a contrib projects but at least that makes it a conscious decision. Perhaps a new attribute in menu link?
We could potentially automate that; the pages we don't want to display in the navigation are always rendered by \Drupal\system\Controller\SystemController
. It's a special controller designed to render menus. We would only want to link from the menu when the controller is something else, e.g. \Drupal\block\Controller\BlockListController
.
Core needs to provide direction for how to fix the Simple Blocks and Paragraphs examples from the issue summary. This might lead into change in either Core or these modules.
Ideally the fix for the Simple Blocks and Paragraphs would keep the Display mode use case intact because the Display mode example is as it is by design. This is where a contrib module could change the preference for the users that prefer a different behavior.
For context, it was decided earlier that access to the second level menus would be limited in the menu. This is due to the reason that Drupal Core uses those primarily to display the same information as what would be in the navigation but as a page. As a result, users would likely develop a pattern of not accessing those pages. The UX team did research to validate that the pages aren't considered to be useful.
The tricky bit is that there are some edge cases where the second level menu is actually useful. This is not great from UX perspective, because if the user has developed a pattern of not accessing the second level pages, they would have challenges to find these pages. The original plan was to provide an alternative affordance for this use case, to make it easy to differentiate between the two use cases so that users know when to expect something useful.
What is in the MR doesn't fulfill this. I think we need some direction from @ckrina on how we should handle this scenario.
It looks like feedback on MR has been addressed.
@mglaman The feedback has been getting more to the specifics so it's fine if you want to start work on this.
kristen pol → credited lauriii → .
I think XB should be built with node in mind from the start, otherwise we're losing functionality that we currently have with Layout Builder out of the box. Without node support, I think real world adoption will be slower and developers will have less confidence in adding XB to new sites.
We couldn't be early adoptors of this before it supports node, since we would need to run both Layout Builder and XB side-by-side, which doesn't feel worth it.
I understand that this is being built with the idea of rapid iteration and it's been said that supporting nodes out of the box will be done before the 1.0 release, it just feels like we should be fixing the node related issues as we go rather than kicking the can down the road and saying we'll figure it out later.
I personally don't think that the intent of the proposal is to kick the can down the road. We are actively working on making the node specific functionality to work. At the moment it looks like that we will have support for nodes without additional bundle fields before the end of the year.
I totally understand that Experience Builder will be only so useful until it can support structured content like nodes. I my mind, support for structured content is more than just being able to edit the field values within Experience Builder. Support for structured content includes also being able to build view modes using the field values in Experience Builder. Support for structured content is intended to be worked on early in 2025. This is to say that it's not something we're intending to leave last minute before the release.
This proposal allows us to start collecting feedback on a slice of Experience Builder before we get there, which should ultimately lead in a better product at the time of release. That said, this is not being done just for the short term gain. UX has identified that the basic page concept is somewhat distinct from the structured content and that at least in some UIs, that should be prioritized over other types of content. Here's an example of one screen for this:
This seems related to
📌
[later phase] Support matching `{type: array, …}` prop shapes
Postponed
. I wonder if we should add a new requirement for components; i.e. to not have type: array
properties?
This is also pointing another problem; we need a way for components to indicate if the component should be available for Experience Builder. I would not expect anyone to ever want to use the "Toolbar button" component in Experience Builder.
Moving to the Experience Builder queue since this seems like a problem most likely related to it.
Note: as can be seen in the component that has been linked in the issue summary, the property triggering the error is not required. In this case, the component props are valid as optional properties are allowed to not provide an example.
This is not an issue to fix the specific error. I opened 🐛 PHP warning on image props without examples Active for that. This issue is to improve the error handling, because I would not expect PHP errors from the small preview iframes to render in the preview canvas. I also would not expect errors to render inside the small preview iframes.
Tested this manually and the behavior seems fine. I agree it would be nice to make the interactions a bit smoother but I wonder if that should be left to a follow-up issue?
Maybe we should add some test coverage for this change?
lauriii → created an issue. See original summary → .
Would it be possible to provide a list of blocks that this impacts and what are the contexts they depend on? This would help me understand the impact of this and would make this more actionable for design.
Is there some existing UX for this in the Block module or Layout Builder?
Now, we can achieve that by having a config setting within XB for which node type is the one that "New page" creates, but the fact that user research led to designs that partition in this way leads me to wonder whether there's a real conceptual difference between un-modeled pages and modeled content, and whether creating a new entity type for un-modeled pages would help us both refine our understanding of that difference, and optimize various Drupal UIs accordingly.
From a content creators perspective, it's different from the rest of the content types because it doesn't come with a predefined template / structure. They are also more tied to the specific page that is being built (i.e., usually less or no additional view modes, not being displayed in lists, etc.). To a large extent, you could accomplish this with a content type, although it's not guaranteed to hold the same meaning across sites.
One related quote from a user interview earlier this year:
Interviewer: "You have this content type called page. What is that?"
Participant: "That's actually the content type that I use the most. Whenever we have something that's got more like set structure, that's when we use a content type that is more kind of identified and clear. But whenever we have something that needs to be a little bit more flexible, we use the page. Page is much more bare bones than the more specific content types."
Currently, Standard Profile provides that via the "Basic Page" content type, but does it actually make sense for "Basic Page" to be one content type among Article, Product, Event, JobPost, etc.? Or is the concept of "Basic Page" somehow special, different from those other content types? And would Drupal be easier to understand if we leaned in more into that specialness?
Whether we display the default page type as a content type impacts also users building the site. I don't have any user research suggesting one way or another on this.
My thinking on what makes sense here was shaped more by what the majority of the players in the market are doing. Having a default page type which could be used for one-off content, and modeled content for creating display templates that display the same content different ways (i.e., multiple pages or lists) is a fairly standard approach that many proprietary CMSs targeting non-enterprise sites have adopted. In Drupal, this becomes even easier to explain once we land ✨ Allow disabling a route for a bundle and adding additional routes for view modes other than 'full' Postponed and ✨ Support adding additional routes for view modes other than 'full' Active because it makes Nodes the central place for modeled content, not only for pages.
A key decision we need to make eventually is if we allow adding fields to the default page type or not. Some more complex sites use custom fields even for their landing pages, not to change the display but as meta information (e.g., tagging to build navigation views or to show related pages). Initially it's fine to not allow custom fields because for a simple site, we can define what are the fields needed to meet most use cases.
We can get at least a sense on what are the required capabilities because shipping with this type of content type is really common. For example, Rocketship comes with a page content type, Ignite comes with a page content type, and Wingsuit Kickstarter comes with a landing page content type. At minimum, we'd need to support meta tags and be able to exclude pages from search.
I discussed with @bostonjillian and @mglaman earlier today to find out if there are open questions we'd like to validate. In regards to displaying pages separately, we agreed that we didn't have open questions to be researched at this point around this. Most of the open questions I have are more around what it is we allow users to do to customize the default page type vs what we don't allow them to customize. We don't have all the answers and we may need to refactor this later but based on my discussion with @mglaman, at least he wasn't too concerned about the refactoring at this point (even if in the worst case we'd need to build a best effort upgrade path). Based on that, I'd be fine for us to proceed on this issue. We need to revisit this anyway, because regardless of the approach, we'd need to test the solution with the rest of the product later.
We also discussed the use case where users need to go from the default pages to modeled content. We discussed how challenging it would be to do this outside of very specific simple use cases since the default page type doesn't come with the fields the target content type would be likely to have. This would make any migration from the default page type to modeled content only so useful. We thought that given how many challenges there are with moving from a landing page to a modeled content, this use case would be better solved by focusing on educating users early on how to think about content modeling and why they should care.