Upgrade Your Drupal Skills

We trained 1,000+ Drupal Developers over the last decade.

See Advanced Courses NAH, I know Enough

Lessons Learned: Component Based Design with Paragraphs

Parent Feed: 

At the 2017 Bay Area Drupal Camp (BADCamp), Senior Drupal Developer, Anthony Simone, presented 'Lessons Learned: Component Based Design with Paragraphs' to a packed auditorium. Watch his presentation here. 

The ideas of Atomic Design and component based design allow one to create an established structure within which a large scale front end project can be built. The CMS space hasn’t always been the most friendly toward implementing these types of patterns. Whether it’s difficulty in creating a content architecture that models your front end design system within Drupal or the feeling of lack of control over generated markup, it can feel like an uphill battle.

The Paragraphs module gives us the tools to create much more well defined and structured component based architectures upon which modular front end systems can be built. The Paragraphs module, however, comes with no rules. As a site architect and front end developer, you must decide how to implement Paragraphs. There is definitely a lot of room for flexibility in implementation, but there are many best practices that can be followed to allow for a very clean, scalable, and extendable front end design system to be built within Drupal 8.

The goals of this session will be the following:

  • Review the basic concepts and benefits of component based design
  • Discuss the paragraphs module and how to create an implementation based on a well defined content architecture 
  • Explore some Drupal best practices that allow for a successful component based design system implementation

Transcript

ANTHONY SIMONE: 

Today we are going to talk about component based architecture in Drupal, specifically with the paragraphs module. My name is Anthony Simone and I am a Senior Developer based out of a digital agency in Denver called Elevated Third. Here are the goals for the talk:

First we are going to go over Atomic Design principles in general and component based architecture.  We’ll then discuss component based design within the context of Drupal.  Then we’ll examine a few patterns for successfully implementing the paragraphs module specifically for component-based design.  Finally, we will review the tools and best practices for theming and frontend execution of your design system.  

So design systems in general is where we are starting.  What is a design system? An easy way to think about it can be the deliverables that the UX team designs and that are sent to the client.  This includes wireframes, design mockups, PSD, illustrator files and user stories.  But really the design system is more than that; it starts with the UX/UI intention and the user experience travels through what that looks like with wires or designs and then eventually out into the application.  So essentially, your project and how the user actually interacts with your project.  So the design system is kind of the entire presentation of your web project.  It’s more than just the single deliverable asset.

Atomic design is a design principle created by Brad Frost that describes one way to think about and build component-based architecture.  There’s a lot of great literature put out by him by a lot of people about it so we’re just going to touch on a couple quick concepts.  One is that you need to create very well-defined components.  We’re going to use the word component a lot throughout the talk and use it interchangeably with the word paragraph, but very well defined components are very important.  Two- is to start with the smallest pieces possible, the very smallest implements.  Third is Implementing these components consistently and regularly across your project.  And lastly, you want to take these small pieces and use them as building blocks to make larger ones and improve constructability and reuse of the components.  

Here is a little video from the patent website which is an implementation of Atomic design and a great tool to use to build design systems.  It just goes through the website’s ideas on Atomic design.  You have your atoms, your smallest pieces so the actual labels, the actual inputs, the actual button.  They’re all individual components.  It goes together to make their form, you can put that form inside cutter and then you have your layout right here.  So as you can see the important thing here is that we’re defining each of the smallest possible things; your individual input, your button, and your label are all different components.

So this idea of Atomic design, there are some things in Drupal right now and in drupal 7 that already use this pattern.  More specifically entities and view modes.  Entities are basically the basis of all content architecture within Drupal.  An entity is a collection of fields and then a view mode is a presentation of those fields.  So that’s a definition of a component.  You can have a lot of view modes of an entity that might handle the presentation of those fields in a different way but the same way every time you use that view mode.  Fields and field formatters are pretty similar.  You have a field that has a type and it collects data and then it presents that data in a handful of different ways defined by the field formatter.  Lastly we have the paragraph modules which are essentially another way to handle custom entities in a modular pattern within Drupal.

When you’re thinking about implementing a design system, you have a set of items that you need to go through.  Initially you have your intention; what are the goals of the design system regarding user interaction and user flows.  This intention typically goes hand-in-hand with the deliverables to the clients including user stories, wireframes, and designs.  Then you take those intentions and turn them into a structure or foundation to be used in your application, in our case Drupal.  This structure step includes content architecture, data architecture, and site building which are all part of the middle stage.  You then need to execute on the design system and bring it to life.  The theming, implementation, presentation and make it look, behave, and interact the way it was originally intended to by the wires and designs.  When thinking about this process, the middle step, the content and data architecture, is the glue that holds the concepts and mockups together with the final build and implementation of the project.  

Who is responsible for this content architecture step? Is it IA/UX?  Is it backend or frontend?  This question moves us into the types of content.  We have structured content, which is the typical event that are described by the fields.  There is a date field, time field, maybe multiple instances of the event, categories, speakers, sponsors, etc.  The event is defined by its fields that creates the item.  Then we have unstructured content in which the content isn’t really modeling anything, right, the old school style might just be a big ole blue zooming on a page or a free-for-all where you can do whatever you want with it.  Now that we have a lot more tools, that approach isn’t really Ok anymore.  It’s not accessible to the end-user or client admin, who is typically on the non-technical side with most of the projects we do.  So we have the idea of unstructured content which is a little bit of a misnomer because to build some system around creating and maintaining unstructured content you really need a lot of structure.  Especially in a CMS and a tool like Drupal, you need a lot of data mining around that so you content adamant can go in and build complex pieces and complex assemblies of all these atomic components in a very easy and non-technical way.  

So what’s required for implementing component-based design in Drupal specifically?  The first thing is structure, you need to have a system that handles structure very well.  Unstructured content is left to handle on your own, including field groups, field collections, paragraphs, panels, custom entities, etc.  All in all, components based design requires defined structure.  

The second requirement is controllable markup.  As a frontend developer, you want to be able to control your markup patterns at all times.  These patterns also need to be consistent and easily repeatable, which Drupal 8 allows us to do more efficiently than Drupal 7.  You also want to render view modes of content/entities all the time.  That can go with your paragraph bundles, any of your node content types.  Rendering in Drupal, the view mode in essence is a component so if you’re always rendering view modes of entities you’re always going to have easy access to data and easy control over templates.  

The third requirement is your SASS framework (or whatever CSS you are using) and theming structure.  All of the well planned and well thought out data architecture isn’t going to be useful if your implementation is a mess or if your implementation doesn’t leverage all of that component-based design.  Implementing strict selector targeting patterns is really important, that way your components will stay modular, strongly leveraging your preprocessor, Sass, or whichever you use.  This will help you do complex targeting and selecting with easy mix-ins and workarounds which will really help you adhere to this requirement.  

Going back to whose responsibility is the design system?  I would say it is the frontend developers responsibility, which might be a bit of a controversial statement.  The frontend developer is a bit of a loose term, especially is the Drupal community.  It is hard to work with Drupal as a frontend developer without learning at least some PHP knowledge.  Essentially we’re building a design system.  We’re not architecting abstract data models but we’re architecting a content system.  Since the frontend developer is responsible for implementing it, it also makes sense for them to be responsible for architecting, designing, and translating it from requirements, user stories, and wireframes into implementation as well.  If you’re working on a team of 15 or a team of 2, the frontend developer needs to be involved in the process at all points and not just at the end when it’s time to theme.  

So now I’ll get into paragraph modules.  *brings up visual of a website* So this is just a components-based page.  Every horizontal slice is a component and there’s a lot of nested pieces on the inside.  Up here I have a little widget that outlines where the components and paragraph bundles are.  Red is the top level, yellow is the second level, and blue is the third.  

So jumping into the paragraphs module.  Just so we’re all on the same page, it’s essentially a wrapper around a custom entity.  You have a custom entity that you can create arbitrary bundles that lets you field them and place anywhere on the site.  It’s not too different from just your content types or your node types in which you field them and implement them in a handful of different ways.  

Because there are really no rules about using this module, it’s very flexible but also means you really have to consider your implementation.  You have an opportunity to create a very well structured design system and content architecture that is going to be able to model what you want to present and display on your Drupal site.  You also have the opportunity to create something enormous and complicated and not straightforward.  I will be very difficult to manage.  

Let’s get into creating your component framework and well defined paragraphs.  A lot of the following things are some methods that have worked well for me and my company but there are multiple ways to do this.  We’ve iterated over many many times and these sorts of patterns have been helpful to us to maintain existing projects.  So I’ve said this a lot, but a design system requires well-defined components.  When we’re creating our paragraph components, we really want to be clear about the intentions and responsibilities of a single component.  Using these definitions then helps you to determine when you have new feature requests and whether or not you are building a new component or extending an existing one.  How does this component compare to what’s already been designed and how does it fit into my architecture?  You have to make your own rules, and then you have to follow them!

I generally would recommend creating some type of hierarchy and naming paragraph bundles according to that.  The paragraph module right now doesn’t really have the idea of paragraph types, you just make your own bundles.  A really easy way to do this is to use keywords that group your paragraphs.  A lot of ones we’ve used in the past are simple, compound, layout, slideshow, summary; things that generally group them by behaviors.  You then create a role for what that behavior looks like and this will end up giving you a clean organization of all your components.  For my three examples on screen; Simple would mean that the component has a lightweight group of fields with little opinion about how it’s used, and very often is used as a nested component.  Compound has a little more opinion about the structure and layout, and there is often more composition.  Layout would be a highly opinionated structure or functionality tied to a component, and is rarely nested inside other components.  

Compound - Media bar is an example of some content with a little more opinion.  This one’s responsibility is to handle the display of a piece of media along with a piece of content.  The media could be an image or some sort of interactive video and the other half of the page could be any type of content.  

Layout Tabs is going to be something pretty complicated.  So this whole tabs representation can be handled by a component but this is very complex and has a lot of functionality behind it, which makes it a layout.  Whatever your prefix grouping words are for your project are going to depend on a lot of things; how many component will you have? How much granularity will you need? What will they look like? This all varies from project to project.

This gets us into naming, which is very important because we are creating a taxonomy to talk about this design system with multiple departments including design, developers, admin, etc.  Just like how we want to implement patterns with our components, we want to implement patterns with our naming.  Those grouping terms are describing patterns and you want to use terms consistently to create patterns (card, bar, callout, teaser, etc).  Whatever terms you think are appropriate but just make sure you are using them in the same way across your design system.  You also want to name based off intention rather than exact functionality.  ‘Content Bar’ would better describe the purpose of a component rather than ‘Two column ⅔ width no header’. 

When you’re actually building your paragraphs, there are two pieces of the puzzle which are the bundles and the fields.  The field is the implementation.  It has the delta or number of components allowed, types of bundles allowed, a dn functionality (i.e. slider, gallery).  Your paragraph bundles are the definition, the markup, the styles.  It is the responsibility and intention of the component and they own the structure and also have all of the content fields.  

Now we’re going to take this basic landing page and go through what it looks like in terms of paragraph bundles and paragraph fields.  It’s fairly simple, at the top you have your simple content which is essentially an introductory paragraph.  At the bottom we have a content bar paragraph component that has four simple content components inside of it; 4 nested components inside of its parent compound content bar.  In the middle we have our media bar with a simple image on the left and a simple image on the right nested inside.  

If we look at the same page from an implementation (fields) point of view, we start with our landing page or node which has field_p content and all of our top level paragraph components are inside of that field.  Our compound content bar at the bottom needs a paragraph field to implement what types of paragraphs that can go inside of that.  In this case, that field might have a delta of 4 and can only have simple card items.  If we go back to our middle component, the media bar, that component will have two paragraph fields.  The image on the right would be called field_p_media_item with a delta of one simple image component.  Down the road you would be able to add a new bundle that describes a video or a bundle that describes an interactive feature.  
    
So components really can be used for anything.  Some of these include sliders, galleries, tabs, accordions, interactive features, custom view displays, curated content with custom queries.  They’re just an entity so they can hold almost any responsibility.  

Now that we’ve gone through the architectural implementation of the paragraphs module, we’ll get into theming patterns.  The whole point of components is that they’re modular and that they have an identity.  Drupal is already very good at creating identities for your content, for example entity types and view modes.  Isolating your theming to that identity is very helpful because when it comes to your components, that’s the top level wrapper for you component.  
    
Components are self contained so if you set some strict patterns about theming and targeting that component wrapper, then it doesn’t matter how you implement your components because they will behave the same.  Whether it’s placed on our landing page via a field on a node or placed in a block, they will behave the same.  The paragraphs previewer module is a nice tool to use to isolate your component’s context.  

You want to isolate your theming to your component wrappers ALL the time.  This forces you to think “where is the responsibility for this style coming from?”  So we have a our paragraph bundle name wrapper and pretty much all styles for that paragraph should go inside this wrapper.  If there’s something you need to do that goes outside of that wrapper, you have to think to yourself where is the responsibility coming from?  The component?  A relationship? The implementation?  Context? 

We’ll now go through a few specific examples of theming that come up a lot.  You might start with some base styles if we’re looking at our landing page in which we have field P content and every paragraph has some margin between it and you can take advantage of collapsing margins.  Then you might need to implement a paragraph with a background color so for that single paragraph, you can take advantage of saas to remove the margin on the parent component, add padding to a child wrapper, and add background color.  Do all of these theme styles that are related to that feature within your paragraph bundle type wrapper.  

Contextual Styles.  You will have a lot of instances where theming paragraph components has something to do with their neighbor or what they’re nested inside of or where they’re placed.  These are all different types of contextual styles that are very important and they can be handled in similar ways depending on where their source is coming from.  The idea of contextual styles is that you need to have two neighboring components that interact with each other.  On the left side the top one is supposed to be a darker grey and the bottom area is supposed to be white. We have margins or padding giving those two a break since their colors are different.  On the right side they both have the grey background so you really want to collapse that margin because the margin should always be 60 pixels and if you had the two different paddings next to each other you would get 120 pixel space.  

Another contextual style is nested components.  Here we have our simple content component and when it’s nested inside of a media bar the title should be orange.  We can have this style inside of our simple content component bar component wrapper and again use the parent selector to add those styles that we need contextually.  

We’re no going to run through a couple more complex scenarios that using paragraph components are pretty helpful for.  We looked at tabs briefly before but let's take a deeper dive.  So we have our our Layout - Horizontal tabs component.  This might have fields like field title, field description, and then a field p tabs which contains all of our tab components.  And then an individual tab is essentially what we have here which is going to be a compound tab component and all of its fields might include tab title, icon, content title, or content description.  That inner part could also be our simple content component and we might have more leveraging paragraphs there as well.  You can also take advantage of view modes of your paragraph, so that way you can have your view mode tab button.  In your preprocessor or your template or wherever you are creating all the markup that’s necessary for the tab functionality, you just render your tab button view mode or render my tab content view mode.  And If you’re using the UI to put fields in different places, that’s just going to place those new fields wherever they need to be.  
Summary/custom view gives the content admin more power and control over referenced content displays.  You should field a paragraph to accept user input and model these rules in whatever ways you need.  Gives you a flexible custom view component.  
    
You can also create a super link field so instead of using field link you would use field P link and then do things like have a normal link and fild download link on the same field.  You could also even have a video modal.  
    
You can also do an interactive flip card component that has content on the front and on the back in which you can leverage paragraph fields to have what the content is on the fron be choosable and dynamic based on that field.  The full width background image vs. the copy is all handled in the nested component that you’re placing.  So say that image needs to change to a background image sometimes, you can just add a new component, let that component be selectable as the front of the flip card.  So it’s easy to extend and add new component with fields and definitions of itself.  

We’re almost running out of time so I just wanted to quickly make a note about nested paragraphs.  You can see if you use some of these things or a handful of them together, you can get deeply nested in the paragraph hole.  It’s not bad to nest paragraphs and I don’t think it’s bad to nest them deeply, but I think you have to have a very good reason to especially if you’re going four deep or more.  But if you look at the idea of layout - tabs, it requires a certain amount of nesting and then you might have a slideshow in front of that and then one of the items in the slideshow has a flexible link field.  In this case you’re getting pretty deep, but each of those has an intention regarding why you’re going there.  You have to balance flexibility along with admin usability and the requirements so there’s not always a single solution.  

Building in this way and thinking in this way gives very reasonable, extendable, and modular projects.  The most important thing about this architecture is that it’s very easy to maintain and very easy to extend and build features within a projects 6-18 months afterwards because of how isolated all of the styles, architecture, and functionality is. 
 

Original Post: 

About Drupal Sun

Drupal Sun is an Evolving Web project. It allows you to:

  • Do full-text search on all the articles in Drupal Planet (thanks to Apache Solr)
  • Facet based on tags, author, or feed
  • Flip through articles quickly (with j/k or arrow keys) to find what you're interested in
  • View the entire article text inline, or in the context of the site where it was created

See the blog post at Evolving Web

Evolving Web