Define component negotiation and replacement for SDC

Created on 12 October 2022, about 2 years ago
Updated 4 March 2023, almost 2 years ago

Let's discuss the details around component negotiation and the ergonomics around component replacement.

Extracted from the parent issue ✨ Single directory components in core Active .

Component negotiation

Including a component in a Twig template looks like this:

{{ include('my-component', {
  prop1: content.field_foo
}) }}

When Drupal encounters this it will search for all the components with a machine name 'my-component'. The negotiation will choose the component with the following priority rules.

  1. The component is in the active theme.
  2. The component is in one of the base themes of the active theme. The closer in the inheritance chain, the more priority.
  3. The component is in a module.

This intentionally matches the priority rules used for templates sharing the same name.

If the developer wants to skip the negotiation step, they can include the provider in the template name:

{{ include('olivero:my-component', {
  prop1: content.field_foo
}) }}

Component replacement

Themes and modules can replace components provided by other themes and modules.

Themes can replace a component by copy & paste of the original component in a location that has higher priority (see Component negotiation). Themes can replace components provided either by modules or by themes which they extend.

Modules can replace components provided by other modules by copy & paste of the original component and explicitly stating it with the "replaces" property in the component definition file (my-component.component.yml). Example, the node module wants to replace "my-component" originally provided by system. node/templates/components/foo/bar/my-component/my-component.component.yml needs to contain: replaces: 'system:my-component'

Additional considerations

We decided against always prefixing components with the provider. This will better reflect the developer's decision of embedding a component leveraging the negotiation rules. Adding the provider in front will have the effect of including the component as defined in the specified provider.

We thought it would be confusing to allow writing {{ include('system:my-component') }} yet render the my-component as defined in a sub-theme of Olivero, so we decided against it.

No prefix when including/embedding means "let the negotiation decide the component to render". Adding the prefix will skip negotiation entirely.

πŸ“Œ Task
Status

Fixed

Version

10.1 ✨

Component
RenderΒ  β†’

Last updated about 8 hours ago

Created by

e0ipso Can Picafort

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

Production build 0.71.5 2024