Skip to content

Decoupling Bolt components

Rémy Denton edited this page Aug 12, 2022 · 1 revision

As a general rule, Bolt components should be decoupled from one another. This is a general computer science architecture principle: tightly coupled code is harder to update and re-use. Further reading:

What NOT to do

An example of coupling in Bolt happens when you create a component that includes another within its twig source template, like this:

<bolt-blockquote>
  {% if logo %}
    {% include '@bolt-components-logo/logo.twig' with logo only %}
  {% endif %}
  ...
</bolt-blockquote>

The only way for a user to use this pattern in a valid way is to match the logo schema withing their blockquote usage, like this:

{% include '@bolt-components-blockquote/blockquote.twig' with {
  logo: {
    src: '/cowboy.jpg',
    alt: 'Yeehaw',
  }
} only %}

What you've done here is couple the schemas together, such that the blockquote schema specifies an implicit sub array that matches the logo component's schema. If you ever make updates to logo, you need to check blockquote to be sure it still works (and vice versa). The more components are connected together like this, the worse the tangle gets.

Additionally, in Drupal, the logo and blockquote often get rendered separately (for example, using different paragraph types). But if you wire them together in Bolt, Drupal developers may have to deconstruct the renderable logo to format data in the specific way that blockquote needs. Extra work, extra mess, not good.

What to do instead

The better architecture is to leave a place for the logo within blockquote, but remain agnostic as to what it contains, like this:

<bolt-blockquote>
  {% if logo %}
    {{ logo }}
  {% endif %}
  ...
</bolt-blockquote>

That way, when it comes time for end users to consume your pattern, they can render the logo however they want. For example, it could be this:

{% set logo %}
  {% include '@bolt-components-logo/logo.twig' with {
    src: '/cowboy.jpg',
    alt: 'Yeehaw',
  } only %}
{% endset %}
{% include '@bolt-components-blockquote/blockquote.twig' with {
  logo: logo,
} only %}

or it could be this:

{% set logo %}
  {% include '@bolt-elements-image/image.twig' with {
    src: '/cowboy.jpg',
    alt: 'Yeehaw',
  } only %}
{% endset %}
{% include '@bolt-components-blockquote/blockquote.twig' with {
  logo: logo,
} only %}

or it could be this:

{% include '@bolt-components-blockquote/blockquote.twig' with {
  logo: '<img src="/cowboy.jpg"> alt="Yeehaw"',
} only %}

There are even other ways you might do this in Drupal (e.g. creating a render array for logo in preprocessing). The point is, if you support a single logo variable, it doesn't matter as long as it's renderable. You have decoupled the blockquote and logo patterns making them both easier to update and re-use.

Clone this wiki locally