The molecule helper allows us to create shared components that are genuinely reusable (since each molecule is only created once and included everywhere it’s used). Including molecules this way:

  • Allows us to keep templates DRYer
  • Avoids the possibility that different instances of the same molecule have been tweaked in place and diverged (which makes it harder to modify existing molecules with confidence)
  • Makes handling BEM modifier names easy (since molecule generates these for us based on the molecule name)
  • Makes it much easier to replace or update a component across the entire UI
  • Encourages us to think more holistically about each molecule: what variants it has and how it will be used

How to use it

= molecule('feedback-message', variant: 'success', content: { message: "You've changed your email address." })

molecule is in many ways similar in usage to render. It takes the name of a molecule (which should correspond to the name of a partial in views/shared/molecules) and a content argument, which expects a hash of keys and values to pass to the molecule.

Optionally, you may also specify a variant argument, which takes a string or array (if you’d like multiple modifiers), and which is used to create appropriate BEM modifier classes. eg. the above example would add a m-feedback-message--success class to the molecule.

Molecules may also receive captured block content. This can be more convenient / readable than passing everything through as content, especially when you’d like to pass in larger blocks of content (such as longer text, or content that has its own internal markup structure).

For example:

= molecule('billboard-new', variant: ['inverse'], content: { icon: "shared/svg_icons/subject_categories/science_engineering_and_maths_courses" }) do
    Science, Engineering & Maths Courses
    Whether you want to brush up on basic science and numeracy skills or master
    advanced topics like robotics and forensics, our online maths, engineering
    and science courses will help. Broaden your mind and build your STEM
    knowledge with top universities.

Creating a new shared molecule

There are a few things to bear in mind when creating a molecule partial to work with the molecule helper:

  • It should live in views/shared/molecules
  • The BEM modifier classes are passed through as molecule_classes(so you’ll need to add {class: molecule_classes} to the root element of the molecule)
  • Captured block content is passed through as captured_content
  • Fields passed through via the content argument are available as, eg. content.message in the partial.
  • content is forgiving of undefined values (they will be nil), so you can use simple conditionals

Here’s a simple (made up) example molecule partial for reference:

.m-media{class: molecule_classes}
    - if content.icon.present?
        = render content.icon
      = content.text || captured_content