Introduction
In the ever-evolving landscape of web development, creating a custom Drupal theme has become a multifaceted endeavor that demands a more sophisticated approach than in the past. The integration of modern build tools such as Gulp, Grunt, and Webpack has revolutionized the way developers automate repetitive tasks associated with front-end development. These tasks include, but are not limited to, compiling and minifying code, compressing images, and linting code. The emergence of Atomic Web Design has further complicated the process, as developers are now required to build components that necessitate a comprehensive style guide or design system to effectively showcase and maintain these elements.
As a response to these challenges, our team at Drusphere Web Development embarked on a journey to explore and implement a more contemporary and robust design system within our multi-site Drupal environment. Our previous experience with Patternlab, a design system we had successfully utilized for nearly a decade, provided us with valuable insights but also highlighted the need for a transition to a more modern solution. With a small but dedicated team, we embraced the challenge of migrating to a new design system that could better meet our evolving requirements.
Enter Storybook
After conducting extensive research on various design system options, we identified Storybook as the most suitable choice for our needs. With a decade of development under its belt, Storybook has matured into a popular tool within the Drupal ecosystem, boasting a vibrant community and a rich array of plugins that enhance its core functionality. This alignment with the principles of Drupal and its active community made Storybook an appealing candidate for our project.
The recent advancements in Storybook, particularly the introduction of Single Directory Components (SDC) and the Storybook module for Drupal, further solidified our interest. We recognized the potential for these tools to streamline our front-end development processes. However, due to specific technical limitations and our unique requirements, we opted to create a standalone integration of Storybook 8, allowing us to tailor the environment to our needs.
Our Process and Requirements
In selecting Storybook, we undertook a rigorous research and testing process to ensure that it would not only address our immediate challenges but also serve as a sustainable long-term solution. During this evaluation, we explored several alternatives, including Emulsify and Gesso, which are excellent options for those seeking a ready-to-use design system. Our decision-making process was guided by several key requirements that we deemed essential for a successful migration.
The first requirement was to minimize the refactoring of existing components. We had a substantial library of components built within the last year, and the last thing we wanted was to undergo a complete rebuild simply due to a change in our design system.
Secondly, we aimed to establish a new front-end build workflow. While we had relied on Gulp for its efficiency, we recognized the need to explore other tools that could enhance our workflow. After careful consideration, we discovered ViteJS, a next-generation front-end tooling solution that promised to deliver exceptional speed and an expanding ecosystem.
Lastly, we sought to eliminate Sass from our workflow in favor of PostCSS. The advancements in CSS have made it possible to achieve many of the functionalities previously reliant on preprocessors like Sass. By adopting plain CSS in conjunction with PostCSS, we aimed to streamline our development process and reduce the number of dependencies.
Through this case study, we will outline the steps we took to build a new Drupal theme using Storybook and ViteJS, highlighting the essential components of our approach and the lessons learned along the way.
Elevate your digital presence with Drusphere's AI-driven Drupal solutions—let's innovate together! Schedule your free consultation today
Building a Custom Drupal Theme: The Evolving Landscape
Creating a custom Drupal theme has become increasingly intricate in recent years. Unlike in the past, where themes could be built with minimal tooling, today's development environment often necessitates the use of build tools such as Gulp, Grunt, or Webpack. These tools automate repetitive tasks that are essential for front-end development, including compiling and minifying code, compressing images, and linting code. The advent of Atomic Web Design has further complicated matters, as developers are now required to create components that are accompanied by a style guide or design system to effectively showcase and maintain these components. One such design system that has served me well for nearly a decade is Patternlab.
Patternlab has been my go-to design system in all my Drupal projects, and it has also been the preferred choice at my workplace. However, as part of our ongoing development efforts, I was tasked with migrating to a different design system. Our small team was eager to embrace this challenge, seeking a more modern and robust solution suitable for our large multi-site Drupal environment.
Enter Storybook
After evaluating various design systems, we found that Storybook emerged as the most fitting option for our needs. The reasons for this choice were twofold: first, Storybook has been around for about a decade and has matured significantly during that time. Second, it has gained immense popularity within the Drupal ecosystem. Much like Drupal, Storybook boasts an active community and a robust ecosystem of plugins that extend its core functionalities.
With the recent release of Single Directory Components (SDC) and the new Storybook module, the prospects for enhancing Drupal front-end development look promising. However, due to specific technical limitations and requirements, we were unable to utilize SDC or the Storybook module in our case. Instead, we opted to build our environment from the ground up, integrating Storybook 8 as a standalone solution.
INFO: At the time of our implementation, TwigJS lacked the ability to resolve SDC's namespace. Fortunately, this issue has since been addressed, and utilizing SDC should now be feasible with this custom setup, although I have not personally tested it to confirm.
Our Process and Requirements
Choosing Storybook involved a thorough research and testing process to ensure that it would not only address our immediate challenges but also serve as a long-term solution. We explored several alternatives, including Emulsify and Gesso, both of which are excellent options for those seeking a ready-to-use system. Our requirements for a new design system were specific and non-negotiable:
1. No Components Refactoring
The foremost requirement was to migrate our existing components from Patternlab to the new design system with minimal refactoring. Given that we had developed a substantial number of components over the past year, we wanted to avoid the cumbersome task of rebuilding them simply because we were transitioning to a new system.
2. A New Front-end Build Workflow
For a long time, I had relied on Gulp as my front-end build tool due to its efficiency in handling various tasks. Our Drupal project also utilized Gulp, but during this migration, we sought to explore other options that could potentially enhance our workflow. Webpack was an obvious contender, but upon further investigation, we discovered ViteJS, which positions itself as "The Next Generation Frontend Tooling". ViteJS lives up to its reputation of being "blazing fast", and its growing ecosystem made it the clear choice for our project.
3. No More Sass in Favor of PostCSS
In recent years, CSS has evolved significantly, enabling developers to accomplish many tasks that previously required Sass or similar preprocessors. By eliminating Sass from our workflow, we also removed numerous node dependencies associated with it. Our goal was to implement plain CSS alongside PostCSS, and one of the advantages of using Vite is its built-in support for PostCSS processing without needing additional plugins or dependencies. However, for more advanced PostCSS processing, some external dependencies may still be necessary.
Building a New Drupal Theme with Storybook
Now, let’s outline the steps for creating the foundation of your new Drupal theme using ViteJS and Storybook. This overview will highlight the most critical aspects related to Drupal. If you already have an existing theme, be sure to adjust the instructions accordingly.
1. Setup Storybook with ViteJS
ViteJS
- Navigate to your Drupal project's theme directory (e.g.,
/web/themes/custom/
). - Run the following command:
npm create vite@latest storybook
- Select your desired framework when prompted; for our project, we chose React.
- When asked for the project variant, we selected JavaScript.
Upon completion, you will have a basic Vite project set up.
Storybook
- Ensure your system is running NodeJS version 18 or higher.
- Inside the newly created theme, run this command:
npx storybook@latest init --type react
- After the installation finishes, you will have a new Storybook instance running.
- If Storybook does not start automatically, initiate it with:
npm run storybook
TwigJS
Twig templates are typically rendered server-side with TwigPHP to produce HTML in Drupal. However, since Storybook is a JavaScript tool, we need to integrate TwigJS, the JavaScript equivalent of TwigPHP, to ensure Storybook can interpret Twig files. To install the necessary dependencies for this integration:
- If Storybook is still running, press Ctrl + C to stop it.
- Run the following command:
npm i -D vite-plugin-twig-drupal html-react-parser twig-drupal-filters @modyfi/vite-plugin-yaml
- vite-plugin-twig-drupal: This plugin transforms Twig files into JavaScript functions for use in Storybook, allowing it to understand Twig syntax.
- twig-drupal-filters: Provides the TwigJS implementation of various Twig functions and filters.
- html-react-parser: Essential for parsing HTML into React elements.
- @modyfi/vite-plugin-yaml: Converts YAML files into JavaScript objects, useful for passing data to React components.
ViteJS Configuration
Update your vite.config.js file to utilize the newly installed extensions and configure the namespaces for your components.
import { defineConfig } from "vite"
import yml from '@modyfi/vite-plugin-yaml';
import twig from 'vite-plugin-twig-drupal';
import { join } from "node:path"
export default defineConfig({
plugins: [
twig({
namespaces: {
components: join(__dirname, "./src/components"),
// Additional namespaces can be added here.
},
}),
// Enables Storybook to read data from YAML files.
yml(),
],
})
Storybook Configuration
Storybook comes with two primary configuration files: main.js and preview.js, located within the .storybook directory. These files are crucial for configuring the location of your components and handling Drupal filters.
- In the .storybook/main.js file, update the stories array as follows:
stories: [
"../src/components/**/*.mdx",
"../src/components/**/*.stories.@(js|jsx|mjs|ts|tsx)",
],
- In the .storybook/preview.js file, make the following updates:
/** @type { import('@storybook/react').Preview } */
import Twig from 'twig';
import drupalFilters from 'twig-drupal-filters';
function setupFilters(twig) {
twig.cache();
drupalFilters(twig);
return twig;
}
setupFilters(Twig);
const preview = {
parameters: {
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/i,
},
},
},
};
export default preview;
Creating the Components Directory
- If Storybook is still running, press Ctrl + C to stop it.
- Create a new components directory inside the src directory. Alternatively, you can rename the existing stories directory to components.
Creating Your First Component
With the current setup in place, we can start building components. Let’s begin with a simple title component to test our configuration.
- Create a new directory called title inside src/components.
- Within the title directory, create two files: title.yml and title.twig.
Writing the Code
- In title.yml, add the following content:
---
level: 2
modifier: 'title'
text: 'Welcome to your new Drupal theme with Storybook!'
url: 'https://mariohernandez.io'
- In title.twig, include the following code:
<h{{ level|default(2) }}{% if modifier %} class="{{ modifier }}"{% endif %}>
{% if url %}
<a href="{{ url }}">{{ text }}</a>
{% else %}
<span>{{ text }}</span>
{% endif %}
</h{{ level|default(2) }}>
This simple title component will display a heading based on the provided parameters. The level key allows us to specify the heading level (e.g., h1, h2, h3), while the modifier key permits the addition of a modifier class. The url key is useful for linking the title to another page or component.
At this point, the title component is not visible in Storybook. To display each component as a story, we need to create a special file named component-name.stories.jsx.
- Create a file called title.stories.jsx inside the title directory.
- In the stories file, add the following code:
/**
* Import the `html-react-parser` extension to parse HTML into React.
*/
import parse from 'html-react-parser';
/**
* Import the component's markup (Twig), data schema (YAML), and any styles or JS it may require.
*/
import title from './title.twig';
import data from './title.yml';
/**
* Define a default configuration for the component. These settings will be inherited by all stories of the component.
* `component` is an arbitrary name assigned to the default configuration.
* `title` determines the location and name of the story in Storybook's sidebar.
* `render` uses the parser extension to render the component's HTML to React.
* `args` uses the variables defined in title.yml as React arguments.
*/
const component = {
title: 'Components/Title',
render: (args) => parse(title(args)),
args: { ...data },
};
/**
* Export the Title and render it in Storybook as a Story.
* The `name` key allows you to assign a name to each story of the component.
*/
export const TitleElement = {
name: 'Title',
};
/**
* Finally, export the default object, `component`. This step is required by Storybook/React.
*/
export default component;
- If Storybook is running, you should now see the title story. If not, start Storybook with:
npm run storybook
With Storybook running, the title component should display correctly. The controls at the bottom of the title will allow you to adjust the values of each field dynamically.
Starting with the simplest component, the title, demonstrates how Storybook, aided by the extensions we installed, can effectively interpret Twig. The good news is that this approach is scalable; it works just as well for more complex components, and the React code remains largely unchanged even for larger components.
In the next blog post, we will delve into creating more intricate components that incorporate smaller components and add Drupal-related configurations to our theme. This will enable us to utilize the theme within a Drupal site. Stay tuned! If you're interested in accessing the complete code from this post, you can download it below.
Resources
In Closing
Reaching this milestone was a collaborative effort, and I would like to express my gratitude to Chaz Chumley, a Senior Software Engineer, who played a significant role in the configuration discussed in this post. Additionally, I appreciate the insights from the Emulsify and Gesso teams, whose guidance was invaluable during our research phase.
I hope this article proves helpful. Should you have any questions or need assistance in your journey to create a Storybook-friendly Drupal theme, please feel free to reach out.
Elevate your digital presence with Drusphere's AI-driven Drupal solutions today!
Conclusion
In summary, the process of building a custom Drupal theme has evolved significantly, necessitating the use of modern tools and methodologies to streamline development. The transition from traditional design systems to more contemporary frameworks like Storybook reflects a broader trend in web development, where efficiency and scalability are paramount. This article has explored the journey of migrating from Patternlab to Storybook, highlighting the challenges and considerations involved in selecting a suitable design system for a multi-site Drupal environment.
Our exploration of Storybook revealed its robust capabilities and advantages, particularly its active community and extensive ecosystem of plugins. Despite facing technical limitations that prevented us from utilizing the Single Directory Components (SDC) and the Storybook module initially, we successfully integrated Storybook 8 into our workflow. This choice was driven by a thorough research process, ensuring that the selected design system would not only address our immediate needs but also serve as a sustainable long-term solution.
We outlined several key requirements that guided our decision-making, including the necessity for minimal component refactoring, the adoption of a new front-end build workflow, and the transition from Sass to PostCSS. These requirements underscored our commitment to maintaining efficiency while modernizing our development practices. By opting for ViteJS as our build tool, we embraced a faster and more versatile solution, ultimately enhancing our overall workflow.
As we detailed the steps involved in setting up Storybook with ViteJS and creating our first components, it became clear that the integration of these tools offers a streamlined approach to component development. The simplicity of building a title component served as a foundation for more complex components, demonstrating the flexibility and power of Storybook in managing Drupal themes. The journey does not end here; future articles will delve deeper into integrating these components with Drupal and expanding our theme's capabilities.
Finally, this endeavor was a collaborative effort, and I would like to express my gratitude to my team members and the communities surrounding Emulsify and Gesso for their invaluable support. The insights gained from this research have been instrumental in paving the way for a more efficient and effective development process. Should you have any questions or require assistance in your own journey toward creating a Storybook-friendly Drupal theme, please feel free to reach out.
Consult with an expert for free.