Using React + Lucid to Create a BEM Accordion

Edmund Reed
3 min readMay 27, 2019

--

Full disclosure: I am the author of Lucid and this article is intended to promote the tool

BEM is a great concept; arising as a CSS naming convention its philosophies can apply to any structured UI. Even if you don’t use CSS (and instead, for example, use JavaScript for styles), there are still benefits to thinking about your UI in terms of blocks, elements and modifiers.

This article will look at rendering a BEM accordion focusing on the resulting markup, ignoring any functionality, as the goal of this article is to focus on the synergy between the markup and the styling (jump to the end of this article to see how to add functionality using React hooks). Assuming you are using CSS for styling, a primitive BEM accordion using vanilla React may look something like:

View a live demo of the final Accordion

This would render something like the following HTML:

…meaning it could now be styled with normal BEM CSS. There’s nothing particularly wrong with the JSX example, but at scale the repetition of keywords like ‘accordion’ could quickly become cumbersome. This is why Lucid was created; with Lucid the Accordion React component could be reduced to:

…letting Lucid handle all the work when it comes to generating the class names. Projects which use BEM extensively will find themselves repeating keywords such as Block and Element names quite often, increasing WETness and reducing things like maintainability.

This is just a basic example to set the scene; Lucid is very flexible and can handle modifiers, nested blocks and sub-elements (in case you wanted accordion__panel__title instead of accordion__title, for example).

Sign me up!

First step is to get Lucid installed:

npm install --save @onenexus/lucid

…and then import the required HOCs:

import { Module as Block, Component as Element } from 'lucid';

The final step is to tell the environment to use the BEM preset (as it’s not the default convention for Lucid; Lucid refers to Blocks as “Modules”, and Elements as “Components”):

window.Synergy = {
modifierGlue: '--',
componentGlue: '__',
multipleClasses: true
}

…this will ensure that when using the imported <Block> and <Element> components they will render with the correct BEM syntax. And that’s it! The example code will now work. Happy coding 😎

Checkout the Lucid Wiki for full documentation

What about functionality?

This article has just looked at generating BEM markup using React/Lucid in order to facilitate styling for projects which use BEM. From here, actually getting it to “work” can be done in several ways.

Using Hooks

The best way to handle functionality when using React is by using React’s state. The best way to utilise state with React is by using React Hooks (specifically the useState hook).

This works by adding the visible modifier to the panel element when the title element is clicked, so as long as your CSS has something like:

.accordion__panel .accordion__content {
display: none;
}
.accordion__panel--visible .accordion__content {
display: block;
}

…then it’s good to go. Thanks for reading!

--

--

Edmund Reed

Design Systems Architect 🎨 UI•UX designer & developer 💻 I take front-end thought experiments too far 🧪 @valtech 💙