Thank you! This MR became super simple as a result. Marking as RTBC because of that.
Should this have been marked as fixed given that the MR was merged?
Looks great! Could we refine this further so that when you edit a folder, nothing in the left panel flickers / moves around?
Minor feedback; why is the icon disappearing when you are typing a new name? The pattern from other tools like Figma, MacOS Finder, etc is that the text should not move and the icon should remain so it feels as if you're editing the text 'inline'.
Awesome! Could we also allow renaming a folder by double clicking it? If it's not easy, we can open a follow-up for that.
The contextual link should be only visible when the node is being rendered with the content template, which currently requires that the content template must be published. If it's difficult to achieve this, I think we should just descope this since this was not part of the original scope of this issue and isn't as important as having the other entry points for content templates.
Is there a specific reasons why you couldn't use Canvas Pages for this instead of creating overrides of one off content types?
Promoting this to a critical since this is a common use case resulting in a WSOD.
Limiting the automatic updating to the three scenarios from #21 📌 [later phase] When the field type for a PropShape changes, the Content Creator must be able to upgrade Postponed is not sufficient. The scenarios that require developer-provided update paths would create a significant burden for component authors. It shouldn't be on them to provide migration paths for changes to props.
We need to be able to handle all scenarios for prop and slot modifications. This is already the case for content modeling outside of Canvas components in Drupal, including Blocks. When you change field configuration for Blocks and other fieldable entities, it's reflected everywhere that entity is used without requiring manual upgrade path. We should match that experience.
The way that the shortcut module works today is really confusing and would require us to rethink how it works. Because of that, it's fine to move the module to contrib. It would be great to work on a new version of the module (maybe in contrib) that focuses in allowing users to customize the navigation for themselves.
I think this is great now! Thank you so much @benjifisher, @rkoller, and @dww, as well as everyone else who has worked on this!
I'm agnostic to whether we should use Content Moderation or not. I believe that in future, Content Moderation and Workspaces will converge. Integrating Canvas with Workspaces is a high priority meaning it's something we'd do likely some time in 2026. Because of that, we should implement this in a way that 1) minimizes any friction for us to integrate with Workspaces 2) keeps implementing this as simple as possible. I don't know how using Content Moderation impacts that.
I got a +1 from @ckrina in https://drupal.slack.com/archives/C079NQPQUEN/p1766215827620139 on this. We will have to make some improvements to the UX in 📌 Allow user to add display modes from respective field UI's. Needs work to start slowly getting rid of the separate display modes UI.
I’ve updated the table to display the description and I’ve shortened the help text.
All of the tests are now passing! Changes were mostly related to updating the tests to use the new URL for the default display mode.
I think it would make sense to commit this as is and add various improvements like being able to modify the available view modes in a follow-up.
Moving to needs review on the high level approach. The MR will fail inevitably at this point since I haven't updated any of the tests.
I was working on #3483304 ✨ Allow disabling a route for a bundle and adding additional routes for view modes other than 'full' Postponed and realized there's overlap with this issue. I don't think we should introduce the concept of locked view modes. For micro-content we'd want users to be able to delete the Full view mode entirely.
Given that, here's a proposal:
1. Copy "Default" display to "Full" display for existing sites
For BC, provide an update hook that copies core.entity_view_display.*.default configs to *.full when a Full display doesn't already exist.
2. Stop creating "Default" display for new content types
New content types would only get a "Full" display — no "Default" at all. This means new sites and new content types are immediately on the new structure with no legacy baggage.
3. Make "Default" display deletable
Allow existing sites to delete their "Default" displays once they've confirmed it's no longer being used. This lets sites migrate at their own pace.
4. Introduce internal fallback rendering (code-only, not config)
When a requested view mode has no "Default" display, render a warning message with a link to create/enable the missing view mode. This is purely code (i.e. no config entity, no view mode in dropdowns or exports).
Something like:
The view mode 'card' is not configured for this entity type.
[Link to create it]
With these changes, deprecation becomes simpler since new installs never have "default" to begin with:
- 11.x: Copy default→full for existing, stop creating default for new bundles, allow deletion, update UI to show Full as primary
- 12.x: Remove Default from Manage Display UI entirely
- 13.x: Remove "default" view display support from config loading
Given the complexity of the ideal experience described here, I think we can remove the option to mark draft as archived. In that scenario, we should not display either publish or archive as an option for draft content.
For the use case of abandoning draft pages that are no longer needed, users can either delete the draft entirely or leave it in draft status by not publishing it. Not perfect, but a reasonable compromise that keeps the implementation simpler.
I've already spoke to two different organizations who won't adopt Canvas due to lack of Content Moderation support for pages and their compliance requirements. I am also in the camp who believes content moderation and workspaces are not exclusive, so we still have to consider content moderation.
That's true today. However, I personally believe we can achieve requirements that users of both modules have with a single solution.
Adding some additional perspective to what Gábor shared.
The reason behind this proposal is a broader strategy shift in how we're thinking about Drupal core versus the ecosystem. Previously, the thinking was that Drupal core should provide turnkey solutions for all common CMS needs. In practice, this approach hasn't served users as well as we'd hoped because core solutions have ended up competing with more capable contrib alternatives. When users eventually need capabilities that core doesn't provide, they face a migration to the contrib solution. Making the contrib solutions easy to adopt and getting users to adopt them from the beginning would put users on a better path from day one.
This isn't a statement that Drupal doesn't need the search module. It's a question of where that functionality belongs. The criteria we're using is whether something is a foundational capability that contrib needs to extend and integrate with, or a baseline expectation that doesn't face significant competition from contrib because core already handles it well. I don't think the search module fits these criteria.
The usage data supports this too. Looking at modules enabled in Standard profile, search has the second-lowest adoption at 60.5% ( #3158669-49: [Policy] By default deprecate non-experimental modules that are used by less 5% of sites before the next major version → ), only announcements feed is lower. For comparison, most Standard modules sit above 80%. This suggests users are actively choosing to disable core search, likely because they're replacing it with Search API or not using search at all.
I understand the instinct that "a CMS should ship with search", but I'd reframe that as "a CMS should make it easy to have good search". Ideally, we'd have a powerful search capability that's as easy to set up as core search is today. Convergence between Search API and the search module would be wonderful, but that's unlikely to happen while search remains in core with its current constraints. Moving search to contrib might actually create more space for that kind of evolution.
For users who don't want the full Drupal CMS package, the Drupal CMS Search recipe can be applied to any Drupal site independently. This provides a pre-configured Search API setup without requiring adoption of Drupal CMS as a whole.
I definitely considered adding tailwind_merge() as part of this module! I just didn't have the chance to do that yet. I might do that some time soon when I work on Mercury again but would also be happy to review a MR in case that you want to work on this. 😊
I think there may be some confusion here. When a page is in Draft state, the "Publish page" option should not be visible in the dropdown at all.
For draft pages, the available action should be "Archive". This allows users to archive a page that has never been published. Archiving a draft means the content won't be published when changes are reviewed/published; it essentially shelves the draft.
To clarify the expected behavior:
Draft page (never published):
- "Publish page" option: Not visible
- "Archive" option: Visible → page will remain unpublished when changes are published
Published page:
- "Publish page" option: Not visible
- "Archive" option: Visible → unpublishes the page when the changes are published
Archived page:
- "Publish page" option: Visible → publishes the page when changes are published
- "Archive" option: Invisible
I believe this was the behavior in an earlier version of the MR but has since changed. We should revert to that previous behavior. The workflow diagram should also be updated to show that Draft → Archived is a valid transition.
This should be tied into the default content template. I don't think we should provide the link if the default content template isn't built in Canvas. Given that the link should take you always to edit the default content template, I don't think there is impact from having other content templates other than making sure that the logic has been implemented correctly to determine the visibility of the link based on the default content template.
What are the next steps on this issue? It would be great to get this committed early in the release cycle.
Thanks for the workflow video! A couple of clarifications:
The workflow should allow going directly from Draft to Archived. There are valid use cases where a user might want to archive a draft page without ever publishing it first (e.g., a page that was started but is no longer needed, or content that was created speculatively and then abandoned). Forcing users to publish first just to archive seems unnecessarily restrictive.
Can we confirm the expected behavior for the publishing flow? When you have a draft page and go through "Review changes" → "Publish", this action should publish the page directly. There shouldn't be a separate/explicit "publish" step required before you can use the standard publish flow. In other words: Draft → Review changes → Publish should result in a published page. It should not require Draft → (explicit publish action) → Review changes → Publish which is what I see in the video in #19 ✨ Create ability to unpublish Canvas page Needs work .
Could you update the workflow diagram to reflect these cases?
SDCs already allow using the group property:
https://www.drupal.org/docs/develop/theming-drupal/using-single-director... →
which is what it should match against. We haven't defined how we'd reference those which is an interesting question given that groups don't have a machine readable name defined today.
I believe we discussed at some that tags is something we we'd likely want to support (and it's supported by UI Patterns already). However, if it's something we'd, we'd do it in a later issue.
I'm trying to understand how are you determining what becomes available for translators in In ConfigTranslationAddForm and ConfigTranslationEditForm. Are you for example going to allow translating all data using TextfieldWidget or is there a selection that happens at a certain point by someone to determine what gets translated? Or are you making everything available for translation and letting the translator decide which data should be translated?
+1 for minItems and maxItems. This seems like a minor revision of what we have agreed. Most likely it only takes a simple search and replace at this point since it doesn't seem anyone has released anything where the old keys are being used. If that's the case, let's go ahead with it.
What's needed for this to be committed other than updating the MR to account for ^?
What are you planning to use for determining which props should be translated? Asking because it might be good for us to coordinate on this so that we could provide a good experience for people who are using both Canvas and Display Builder.
This issue assumes we need to distinguish between archived and unpublished pages. Currently they both have status = 0, only difference is draft pages have never been published
That would be ideal but we should not implement this at the cost of making the future Workspaces integration significantly more complicated.
Do we want to avoid adding extra field store, to allow distinguishing between draft and archive? We may want avoid this if we eventually want to still use Workspaces.
We are planning to work on Workspaces support in 2026 so we should avoid making the migration to Workspaces significantly more complicated than it's today. Are there drawbacks with the Views solution that we should be aware of because you're generically claiming that it might be better to go with the alternative approach? I assume we want to prioritize easy migration to Workspaces over whatever that is but it might be good to document the downsides explicitly.
Thank you for closing the duplicate issue @dcam!
I believe that the complexity introduced here will make it harder to move the functionality to a render element. It's something we can consider but maybe that's something we should do after we have landed this issue initially? The MR is already introducing this as a widget for the link field meaning that this is not tightly coupled with Menu Link Content. If you look at the MR, all Menu Link Content does is enable the widget.
FWIW, I've simplified the help text here because the current text is very long. Ideally the autocomplete widget should be able to help with the different use cases mentioned in the help text, but I don't think it needs to block this issue.
Fixing tags to track all remaining blockers under stable blocker tag.
Is there a technical reason for this approach, or is it intended to improve the user experience? The current behavior doesn't feel intuitive to me.
I'd expect that uploading components and making changes to them wouldn't cause any "side effects". This could even lead into awkward situations because you could have one user uploading changes via CLI and another user making changes in the code editor.
It seems more reasonable that there's differences in the compiled output when user has explicitly unchecked the option to upload global CSS.
Always use the local global.css file for building, but allow controlling whether the global.css file gets uploaded.
What happens if I push components from my local environment but skip uploading the updated global.css, and then make changes in the code editor?
I don’t think that behavior quite makes sense. We should either display the fields as we usually do for references or not display it at all. I think it makes sense to allow two levels of references but I think for now we could say we don’t support referenced beyond that to avoid infinite recursion.
Refactor JsComponent::rewriteExampleUrl to catch this exception gracefully. Instead of a fatal error that blocks the UI, it should log a clear error (identifying the specific Component and Prop) or handle the invalid URL safely so the editor can still load.
Instead of catching this one specific exception, is there any chance we could implement a more generic fix that would work for different types of exceptions that could be caused by components? This is something that was supposed to be prevented as part of 🌱 [META] Robust component instance error handling Active but I guess something about this is different than what was handled in the issues there.
Thank you! Tested manually and works great.
I noticed that for some reason the workspaces toggle doesn't always open the panel on the top but links to the page. 🤔 That seemed to be a pre-existing issue so maybe something we should work on in a separate issue?
+1 for marking Navigation stable and for the follow-ups to utilize it by default in the install profiles and to deprecate the old toolbar.
On Slack, @catch pointed out that this could be a blocker for 📌 Mark Navigation as a stable module Active . I personally think it's fine for us to mark the module stable and commit this whenever it's ready. That said, this is a pretty nasty DX bug so it would be good to get this fixed sooner rather than later.
I did pretty extensive manual testing of the MR as well as a high level code review. @pameeela has been doing testing on this too. I checked the change records and they look good too.
Thank you for the feedback @dead_arm! 🙏 I've incorporated your feedback regarding the clarification on the field cardinality being a limit for the number of values. I've also worked with @ckrina to remove the "Details" column and move it to the first column which is now named as "Field", since it contains field label, machine name, as well as some of the details. I've added a screenshot to the issue summary.
I re-read the changes in the MR and the changes still make sense. I approved suggestions from Pam – they were all related to grammar and didn't change the content of the change in any way.
Thank you @mark_fullmer for pushing this forward! I think the acceptance criteria and testing against those is a good idea. Looking at the failures, I think we should merge this to 11.x even thought this is not passing all of the acceptance criteria. Working on this issue with 300+ comments and commits is a really expensive way to address these issues. We should open follow-ups for the failures and solve them that way before 11.4.0. I think that's fine especially given that this is a completely new feature.
For some reason I still don't see optional or required media images as an option to map to an image prop in Canvas. I've tried clearing caches. Am I missing some other steps to be able to use this?
I'm second guessing myself from before by wondering if we should just automatically update all instances when the page is being edited. I'm not sure what the benefit of the 'Update to latest version' would be given that we would still render the component using the latest version. The only reason this could make sense is that if fields are removed, you could at least copy the values and move them somewhere. However, given that you wouldn't know what's being changed, it doesn't seem all that useful. If we wanted to solve for that, maybe we need a way to access stale data that was attached to a component before? It seems like that could be an incremental addition we would add at a later point.
Cross posted with #30.
Can we just remove the link description text either here or in a follow-up? I don't think that belongs in the description.
Does this issue make it possible to link media images and videos with the image and video prop from Canvas?
I could have swore that issue existed and spent a while trying to look for it 🙈
I've defined some time back the mappings I believe we should be supporting in https://docs.google.com/spreadsheets/d/1aBasy3o7Z0OGRig2Xfd1_EInA2UsSgLO.... I've started creating issues for these:
- ✨ Allow linking lists to `type: string` props Active
- ✨ Allow linking unformatted text to formatted text props Active
- ✨ Allow linking telephone field to `type: string` and URL prop Active
- ✨ Allow linking email to `type: string` and URL props Active
Should we create a new meta issue for these or should we keep collecting them here?
Exactly, the problem is that the attributes from that list get added to the <a> element and not the <li>. There's a way to add attributes from preprocess but not from the render array that's constructing the list.
I've added couple more fields that we should consider as irrelevant.
User Status field you may want to use if you're building a content template for the user entity – so let's not get rid of that.
I don't see "this component prop needs an image URL" as a common use case – >99% of the time you would just use image upload / media library for that use case. I don't think this is something we should support in the code editor.
x-allowed-schemes: [http, https] doesn't seem sufficient because as I pointed out, there are many valid use cases for links that are using protocols other than those two.
The scope of this issue is both props and slots but it looks like the issue summary is only talking about props. Adding the 'Needs issue summary update' tag to expand the proposed solution to include slots.
never allowing prop shapes to be changed, unless there's zero instances
I think we should allow this to be done. Prop data will be either converted to the new prop type (when possible) or deleted (when conversion is not possible) when component with the changed prop type is loaded.
I don't really see a strong reason to why we'd have to provide a ton of flexibility to configure this especially in the UI for creating props. That would be relevant if you're implementing business logic related to handling the link but implementing that in your component doesn't seem like the right place. Even the current settings don't really make sense in my mind and they are confusing; I had opened before ✨ Allow mixing internal and external URLs Active . Since then we've changed the labels but I'm not sure I'd be able to explain the difference between the options still without looking into the implementation and referring to JSON Schema docs.
I think we should focus the default link prop to what's allowed by href attribute, i.e. what's defined in https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/a#href. Based on that URLs must be absolute (start with http:, https:, mailto:, sms:, or tel: and have a hostname) or site relative (/page/123) or a hash (#something).
#20.1I think with the improved labels it would have made sense to me what was being offered there. FWIW, I was testing this with code components so maybe the prop type in code components should be setting stronger restrictions for the stream wrapper URL to not be offered?
#20.2: Will add it there 👍
#20.3: I see. 👍 I don't think the current solution of displaying the URL outside of the entity is perfect but I'm not convinced it's bad enough to warrant significant rework. It's a bit strange when you see both levels there but people will probably just figure it out.
Testing this and this is definitely a really nice improvement already! A bit of feedback / questions:
-
Images seem to introduce some interesting. It looks like we could map the image to "image" but there's also URI and root-relative URL. What's the difference between these different mappings? -
This might be something for a follow-up but I don't think we should be exposing the author of the file entity in the UI at all. - Why does the URL show up on the second level, i.e. Authored by => URL, and not on the third level inside the entity, i.e. Authored by => User => URL?
Depth/level of indirection for suggested entity URLs: I think you mean only URLs for the entities referenced directly by the host entity? So, for example, assuming we're looking at the content template for some Node bundle:
- suggest URL to the author (User) of a Node (1 reference), but NOT URL to the user picture of the author (User) of the Node (2 references)
- suggest URL to the "primary topic" (Term) of a Node (1 reference), but NOT URL to the "resident expert" (User) of a "primary topic" (Term) of a Node (2 references)
Or did you really want the entity URL to be available at every one of those levels? (Which your phrasing seems to imply.)
I would expect this to inherit our existing limitations for level of depth, i.e. the link should be available for all of the entity references that are accessible there. So if user can map an image field to a user picture, they should be able to map a link field to the user pictures URL. Same is true for the resident expert for the primary topic.
If the answer to the above is "yes, every level", then what about the levels you previously asked to omit? You requested in #3547598: Refine API response with DynamicPropSource suggestions to provide better UX that we hide/omit the "intermediary Files", which also means linking to it becomes harder. Or did you want for a media entity both the "media item canonical URL" and "media item image file canonical URL" to be surfaced?
For images this is already working as expected. It doesn't look like mapping to media references is working yet but I would expect that it should be possible to link to the media item image file canonical URL.
Speaking of that: what do you expect the labels to become? No guidance existed for this in #3545859: Add a `host-entity-url` prop source for linking to the host entity (because it landed with zero product requirements or design), so I did the simplest possible thing that would clearly need to be improved later: I labeled it Canonical absolute URL — because it's factually true, and because it'd guarantee that we'd improve it later. But if many such suggestions would start appearing, then it'd become a problem, doubly so if to the prior point you'd answer that you expect both suggestions (which would appear as siblings) to get a unique label.
Could we just call it URL and Slug? They should not appear as siblings; they should appear under a child menu. For example, Image => URL or Authored by => URL.
Let's just omit revision_log_message. The two other examples have valid use cases i.e. displaying the author who had edited the node and when it was edited. I checked again and didn't see any other values we would have to omit.
We will be adding the option to update component instances in 📌 [later phase] When the field type for a PropShape changes, the Content Creator must be able to upgrade Postponed which we are prioritizing next after this. It seems that it will solve this issue. Given that we will be working on that soon, I don't think we have to figure out UX & implement a stopgap for this here. This certainly isn't perfect but to me it seems that this is a step forward.
Describe the props/slots for developers
I believe this is best achieved by using inline comments, which is supported in YAML. This wouldn't make it easy to display the developer focused comments in the UI but that seems like an acceptable trade-off.
Describe the props/slots for LLM for better usage in Canvas AI
There's still some work to define what exactly is needed by LLMs to effectively use components. The current thinking is that there needs to be more context than just description of props. While we could use the descriptions for this, the need to have more context is suggesting that will require something new regardless. See this for an example of what's being explored in the XB Metadata module: https://github.com/salsadigitalauorg/xb_metadata/blob/develop/web/themes.... Because of that, it seems safe to assume this will live elsewhere.
We had a client who wanted to be able to edit all fields/content type description, in case of a misuse, so those descriptions became content with a module we built.
That seems like a valid use case but doesn't seem like something we must provide as part of the core functionality. The goal is to allow the component.yml file include all of the necessary pieces for the component to be used in Drupal Canvas, making the components portable between projects. Editorial help texts is an important part of it. Maybe in future there could be a module that allows overriding this information, similar to what the Canvas AI module is doing.
A prop may not be of type "object" unless it has a $ref defined.
There's two related issues already for this:
- 🐛 References must not be required to guess props' JSON schema Active
- 📌 [PP-1] Support `{type: object, …}` prop shapes that require *multiple* field types Postponed
Required props must have examples and/or default
This would be resolved by 🐛 DX & authoring experience: for SDC+code components, the example is treated as the default, may not be desirable Active
Canvas always requires schema, even for theme components.
This one is still remaining without an issue. Let's repurpose this issue for this?