Drupal Planet

PatternLab: Your Clients Don't Need a Science Lesson

Mark.ie Loves Patternlab

Let's revisit my recent post and see if we can come up with more user-friendly names for PatternLab items.

My Approach to PatternLab recently got quite an amount of discussion on Slack and other places about PatternLab and naming conventions, especially the line "Clients do not want a science lesson". In that I set out my current naming convention like so:

  • Basic Elements
  • Site Blocks
  • Building Blocks
  • Content
  • Sample Pages

While generally appreciated, some people criticised it for being too Drupal-centred. What happens if your client doesn't want to use Drupal? What happens if you want to use the same PatternLab instance for an app on Android or iOS? Good questions, and they got me thinking more. A number of people on Slack recently have been asking about what naming conventions besides the atoms > molecules > organisms one people have been using.

I had a verrrrry long chat (over 3 hours) with some developers from outside of my work place to see what what naming convention(s) might make sense, be easy for clients to understand, and allow enough scale to be used outside of Drupal. Here's what we came up with:

  • Utilities
    • Items such as utility classes like .visually-hidden or .padding-top
  • Base
    • Items such as colours and fonts
  • Elements
    • Low level elements such as headings, paragraphs, basic lists
  • Components
    • High definition components such as a teaser view mode, an embedded video component, a list of teasers
  • Layouts
    • General layout classes for the different page designs - with sidebar, without sidebar, etc
  • Mock-ups
    • Rendered 'pages' or other UI interfaces
    • We shied away from 'Pages' here because not everything might be a page, such as a login screen on an iPhone app

I'm quite happy with those naming conventions and think I might start porting some of them to my work at Annertech. (Oh, and by the way, if you want to get really good Drupal developers to work on your website, we're available for hire - contact us!)

 

Join the "Something nice ..." newsletter

The full title is "Something nice, something quirky, something else".

I send an email once a week with something nice, something quirky, and something else that I think is interesting (all with a web development theme, of course).

My Approach to PatternLab?

Mark.ie Loves Patternlab

I'm sometimes asked for an overview of my general approach to PatternLab. Simple: put everything for each component in the same directory!

When working with PatternLab, which I use for all my Drupal themes, including the theme for this website, I don’t use the full atomic approach. I don't use the approach of atoms > molecules > organisms > etc. I’m sure many people seriously disagree with me for that ( I do think it's a very clever concept). Instead I’ve renamed things to match the language we use with our clients.

I tried talking about atoms and molecules to some clients and their eyes glazed over. Clients do not want a science lesson. They do not want to be told that we are going to take two of these atoms, and mix them with one of these atom, and eventually we'll have water. No, they want to know what their final website is going to look like. When I changed the conversation and started talking about ‘Building Blocks’ (what we call our Drupal paragraph types), site blocks (Drupal's search block, branding block), display types (Drupal's view modes such as teaser, search result), etc, they immediately understood. Then we started hearing things like, "Oh, so we can create a page by adding a number of different building blocks?" and "I see, so the search results page is made up of a group of pages using the 'Search Result' display type?". And my response, "Yes!". You see, we are using plain English to ease with understanding.

Another aspect of my approach that I really like is that _everything_ for each of my components is within the same directory. For example, if it’s a nested paragraph component such as an accordion (so we need a paragraph type called 'Accordion' and one called 'Accordion Item') each template and css and js and readme and json and yaml is all in the same folder. That means when I want to reuse one in another project, I don’t need to remember what sub-particles (atoms/molecules) are used to create the organism. It also means my CSS is scoped to that specific component and doesn’t bleed out of it, so making changes or adding new features is very easy, you just scope the new component's CSS to it, so it won't affect other previously-created components.

Now the top bar of my PatternLab that used to say Atoms | Molecules | Organisms, etc has tabs for:

  • Base
    • Colours
    • Spacing
    • Breakpoints
  • Basic Elements
    • Headings
    • Paragraphs
    • Lists
  • Site Blocks (Drupal Blocks)
    • Search Block
    • Login Block
    • Branding Block
  • Building Blocks (Paragraph Types)
    • Accordion
    • Image with Text
    • Video
  • Content
    • Display Types (View Modes)
      • Teaser
      • Card
      • Search Result
    • Lists (Views)
      • Blog
      • Search Results
    • Content Types
      • Basic Page
      • Blog
      • Event
  • Page Sections (Regions)
    • Header
    • Footer
    • Sidebar
  • Sample Pages
    • Homepage
    • Blog Listing Page
    • Blog Node

After that, I have Backstop.js set up to regression test all of these, so each time I create a new component I can quickly run the visual regression tests and check that nothing has broken. Since all my CSS/JS is scoped to each individual component, it's rare if something is.

Join the "Something nice ..." newsletter

The full title is "Something nice, something quirky, something else".

I send an email once a week with something nice, something quirky, and something else that I think is interesting (all with a web development theme, of course).

Showing Fields in a Referenced Node Depending on the Value of a Boolean in a Paragraph Bundle

Show Fields in Node Reference Depending on Boolean Value

Mission: you have 2 fields in a Drupal paragraph bundle, one a node reference field and one a boolean field. Show certain fields in the referenced node depending on the value of the boolean field.

That's a question that popped up today in the DrupalTwig Slack. Here's my response, which I implemented a version of recently.  (In that particular case, we had an 'Event' content type with fields for 'address', 'phone number', etc and also a reference field for 'Amenity'. If the fields were filled in in the event content type, they were to be presented, but if they were left blank on the event content type, we had to pull in the corresponding fields for address, phone number, etc from the referenced amenity.) Anyway, my response:

{# Check the value of the boolean field #}
{% if paragraph.field_boolean.value === 'on' %}
  {# Just render the title of the referenced node #}
  {{ paragraph.field_reference.0.entity.label }}
{% else %}
  {# Render the title and the image field #}
  {{ paragraph.field_reference.0.entity.label }}
  <img src="{{ file_url(paragraph.field_reference.0.entity.field_image.url) }}" alt="{{ paragraph.field_reference.0.entity.field_image.url }}">
{% endif %}

{# Ensure that the cache contexts can bubble up by rendering the {{ content }} variable #}
{{ content|without('field_boolean', 'field_reference') }}

Just for clarity - variables in that code snippet are simply made up off the top of my head (this is what happens when answering questions on Slack). I'm sure I have things slightly wrong and you'll need to play with them to get them to work correctly.

Also, the reason for the cache contexts bit? Say thanks to Lee Rowlands from Previous Next for his blog post Ensuring Drupal 8 Block Cache Tags bubble up to the Page

Join the "Something nice ..." newsletter

The full title is "Something nice, something quirky, something else".

I send an email once a week with something nice, something quirky, and something else that I think is interesting (all with a web development theme, of course).

Adding {{ attributes }} to a Drupal PatternLab Theme

Drupal PatternLab Attributes Error

Ever gotten this error: User error: “attributes” is an invalid render array key? Here's what I do to get around it. If you've a better solution, let me know.

When building PatternLab-based Drupal themes, I try to get the Twig in PatternLab to match what I expect from Drupal. So, if I know Drupal has a line like this in its node.html.twig:

<article{{ attributes.addClass(classes) }}>

I want to be able to put the same thing into my PatternLab template - even though I am not going to use the {{ attributes }} in PatternLab. This means then I can simply let the Drupal template extend from the PatternLab one and not need to worry about anything.

However, when you do this, you will often get an error to say "attributes” is an invalid render array key. How do I get that error message to go away? Simple - I just add attributes to my Pattern's .yml file, like so:

attributes:
  Attribute():
    class:

Note: to use this, you need to have the plugin-data-transform by @aleksip (thanks to Aleksip for pointing this out to me on Slack). This can be added to your composer.json require-dev section:

"aleksip/plugin-data-transform": "^1.0.0",

The data.json File

You can do this for each individual pattern, but then you might get an error somewhere else talking about "title_attributes” is an invalid render array key. To get around all these errors, I simply add these items globally to the default data.json file, like so:

  "attributes": {
    "Attribute()": {
      "class": []
    }
  },
  "content_attributes": {
    "Attribute()": {
      "class": []
    }
  },
  "title_attributes": {
    "Attribute()": {
      "class": []
    }
  },
  "rows": {
    "Attribute()": {
      "class": []
    }
  },
  "teaser": {
    "Attribute()": {
      "class": []
    }
  }

The PatternLab Teaser Twig File

Taking the teaser view mode as an example, here's what my PatternLab twig file looks like:

{%
set classes = [
  'node',
  'node--type-' ~ node.bundle|clean_class,
  node.isPromoted ? 'node--promoted',
  node.isSticky ? 'node--sticky',
  not node.isPublished ? 'node--unpublished',
  view_mode ? 'node--view-mode-' ~ view_mode|clean_class,
]
%}
<article{{ attributes.addClass(classes) }}>

  {% if display_submitted %}
    <footer class="node__meta">
      <div class="node__meta--item node__meta--published">Published: {{ node.created.value|date("D d M Y") }}</div>
    </footer>
  {% endif %}

  {{ title_prefix }}
    <h2{{ title_attributes.addClass('node__title') }}>
      <a href="{{ url }}" rel="bookmark">{{ label }}</a>
    </h2>
  {{ title_suffix }}

  {{ content.field_intro }}

</article>

The PatternLab yml (or json) File

Here's the corresponding .yml (or .json) file:

node:
  bundle: article
  isPublished: true
  created:
    value: 1511941986
  changed:
    value: 1512127363

view_mode: teaser

display_submitted: true

label: 'A Blog Post by Mark Conroy, all about PatternLab and Drupal'

content:
  field_intro: <div class="field--name-field-listing-snippet"><p>Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit. Curabitur blandit tempus porttitor. Sed posuere consectetur est at lobortis. Maecenas faucibus mollis interdum.</p></div>

The Rendered HTML in PatternLab

This will then print our html like so (notice, no attributes):

<article class="node node--type-article node--view-mode-teaser">

      <footer class="node__meta">
      <div class="node__meta--item node__meta--published">Published: Wed 29 Nov 2017</div>
    </footer>
 
 
    <h2 class="node__title">
      <a href="http://example.com" rel="bookmark">A Blog Post by Mark Conroy, all about PatternLab and Drupal</a>
    </h2>

  <div class="field--name-field-listing-snippet"><p>Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit. Curabitur blandit tempus porttitor. Sed posuere consectetur est at lobortis. Maecenas faucibus mollis interdum.</p></div>

</article>

The Drupal Template File

Next, my node--teaser.html.twig file is as follows (just one line):

{% extends '@content/01-display-types/teaser/teaser.twig' %}

The Rendered Drupal HTML

And that renders html like so (notice, we have attributes that Drupal will use):

<article data-history-node-id="40" data-quickedit-entity-id="node/40" role="article" class="contextual-region node node--type-article node--promoted node--view-mode-full" about="/blog/web-development/add-slider-your-website-if-you-do-not-want-your-visitors-see-your-content" typeof="schema:Article" data-quickedit-entity-instance-id="0">

      ...

</article>

Full disclosure, I came up with this idea about a year ago after seeing something similar in the Bear Skin theme.

You can see this in action on my PatternLab's teaser pattern.

Join the "Something nice ..." newsletter

The full title is "Something nice, something quirky, something else".

I send an email once a week with something nice, something quirky, and something else that I think is interesting (all with a web development theme, of course).

Out of the Box has just been Committed to Drupal Core 8.6.x

Screenshot of part of the homepage of the demo_umami profile

After two years of planning, discussing, and (eventually) coding, the "Out of the Box" initiative has just been committed to Drupal Core.

One of the things most often requested of Drupal has been a better experience "Out of the Box", so that when a new users installs it they see something more positive than a message saying "You have not created any frontpage content yet".

To that end, a strategic initiative called the "Out of the Box Initiative" was set up. I was a member of that team. What we sought to do over the past two years was create a website for a (fictional) publishing company. We decided upon the name "Umami" for a food publishing company, publishing articles and recipes. We went through the full web design process - user stories, validation, requirements gathering, wireframes, design, development ... up to creating what we called the "MEGA Patch". And then submitted about 50 versions of it.

This week we hoped our work would be committed to Drupal 8.5.0-alpha1, but we just missed that deadline. Instead, we had a meeting with the product owners last night to have the final "Needs Product Owners Review" tag removed from the "Create experimental installation profile" issue. Here's the video of that demonstration and meeting:

The referenced media source is missing and needs to be re-embedded.

Following that meeting, the tag was removed and our code was committed to Drupal 8.6.x. This means you'll see it shipping in Drupal in September at the latest, but we hope to get the final beta blockers fixed to have it backported to 8.5.0-beta. If you'd like to help squash some of the bugs, follow these "Out of the Box" issues. Here's the tweet from @webchick (THANKS!) announcing it.

So, what is in this commit?

This commit brings a new installation profile to Drupal. The profile is called "Umami" and has a corresponding "Umami" theme. It creates three content types - basic page, article, and recipe. It has listing pages for articles and recipes, some promotional blocks, a homepage, contact form, and search page. It is a fully-featured (small) website built using only (stable) Drupal core modules.

We are not using experimental modules such as content moderation, layout builder, media, etc. Once they are stable, we hope to bring them into the "Out of the Box" experience as well.

If you'd like to install it, try this link on SimplyTest.me.

 

Join the "Something nice ..." newsletter

The full title is "Something nice, something quirky, something else".

I send an email once a week with something nice, something quirky, and something else that I think is interesting (all with a web development theme, of course).

Integrating a Drupal Text with Image Paragraph Bundle with Patternlab

PatternLab Image with Text Component

Let's get to grips with having a text with image paragraph bundle set up with PatternLab, including having options for left/right for the image/text.

It's a fairly common design pattern for clients to request - upload an image, place text beside it, and choose whether we have the image on the left with the text on the right or vice versa. You can see my PatternLab version of it here.

PatternLab Image with Text Component

 

Okay, first off, in my twig file, I have the following:

{%
set classes = [
  'image-with-text',
  'layout-contained',
  paragraph.field_p_it_alignment.value,
]
%}

<div class="image-with-text__bg image-with-text__bg--{{ paragraph.field_p_it_style.value }}">
  <div{{ attributes.addClass(classes) }}>

    <div class="image-with-text__image">
      {{ content.field_p_it_image }}
    </div>

    <div class="padding image-with-text__text">
      {{ content.field_p_it_text }}
    </div>

  </div>
</div>

The only thing that is anyway special here is the paragraph.* variables. I have named them like so because this is what Drupal is going to give me back (since the machine name of those fields is p_it_alignment (I namespace all my entity fields with the first letter of the entity type - in this case the name stands for Paragraph Image (with) Text Alignment). This then allows me to have options in PatternLab for alignment and background style (light/dark). To achieve this, I have the following in my pattern's .yml file:

paragraph:
  field_p_it_alignment:
    value: left
  field_p_it_style:
    value: light

And in my image-with-text~right.yml file, I just need to override those variables like so:

paragraph:
  field_p_it_alignment:
    value: right

Following that, I have variables named content.field_p_it_image and content.field_p_it_text. Again, these are deliberately named like so, because this is what Drupal will give us back after I create a field with those machine names. Again and again, I try to keep my pattern variables in PatternLab the same as what I will get back from Drupal so when I come to adding the Drupal template, it's just one line of code to say "Hi Drupal template, you'll find the code for this file over here!". So, you can decide in PatternLab what the machine name for the Drupal fields is going to be and then get your site-builders to create fields with matching names, or you can ask your site-builders what machine names are being used in Drupal and then use those in PatternLab.

In my pattern's .yml file, I then set those variables like this:

content:
  field_p_it_text: '<h2>A Short Heading</h2><p>Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus.</p>'
  field_p_it_image: '<img src="http://placeimg.com/600/600/nature">'

Finally, in our paragraph--image-with-text.html.twig file we have just one line of code:

{% extends "@building-blocks/image-with-text/image-with-text.twig" %}

You can probably guess what the sass looks like:

.image-with-text {
    display: flex;
    &.left {
      flex-direction: row;
    }
    &.right {
      flex-direction: row-reverse;
    }
}

The images with text above is an example of this pattern in use on a Drupal website.

 

Join the "Something nice ..." newsletter

The full title is "Something nice, something quirky, something else".

I send an email once a week with something nice, something quirky, and something else that I think is interesting (all with a web development theme, of course).

Integrating a Simple Drupal Text Paragraph Bundle with Patternlab

PatternLab Text Building Block Example

This is the first post in a series about how to integrate Drupal with PatternLab. In this first blog post, we'll look at a simple text paragraph bundle, which just has one field: text (formatted, long).

I see a lot of blog posts and talks around about the benefits of using component-based design, about how we should use design in the browser principles to present designs to our clients, about how styleguides are the best way to have sustainable frontends. I've even written some and given many presentations about it myself. What I don't see a lot of is blog posts about how to actually do it.

So, here's how to (or at least how I) integrate my PatternLab theme (it's based on the Phase 2 PatternLab Drupal theme) with a simple paragraph type.

PatternLab

Create a pattern - you can put it wherever your setup says it should go. Paragraph bundles are probably molecules, but I'm not sure how you set up yours. In my case, I have hacked PatternLab and created a folder called "Building Blocks" - this is where all my paragraph bundles go (and then I also have a "Building Blocks" field in each content type - more about my set up in another blog post.

Call the pattern something meaningful - in this case, I call mine "Text". Next, we write the Twig for the text pattern. This can be as simple as this:

{%
set classes = [
  "text"
]
%}

<div{{ attributes.addClass(classes) }}>
    {{ content }}
</div>

Then in my corresponding text.yml or text.json file, I put in some sample content, like so (I like yml):

content: >
  <h2>This is a Level 2 Heading</h2>
  <p>This is a paragraph of text followed by a list. Sed posuere consectetur est at lobortis. <strong>This is strong</strong> while <em>this is emphasised</em> Morbi leo risus, porta ac consectetur ac, vestibulum at eros. Aenean lacinia bibendum nulla sed consectetur. Curabitur blandit tempus porttitor. Integer posuere erat a ante venenatis dapibus posuere velit aliquet. Vestibulum id ligula porta felis euismod semper.</p>
  <ul>
    <li>A text item in a list</li>
    <li>Another text item</li>
    <ul>
      <li>A sub-item</li>
      <li>Another sub-item</li>
    </ul>
    <li>A third item in a list</li>
  </ul>
  <h3>This is a Level 3 Heading</h3>
  <p>Followed by some more text. <a href="#">This is a link</a> sed posuere consectetur est at lobortis. Morbi leo risus, porta ac consectetur ac, vestibulum at eros. Aenean lacinia bibendum nulla sed consectetur. Curabitur blandit tempus porttitor. Integer posuere erat a ante venenatis dapibus posuere velit aliquet. Vestibulum id ligula porta felis euismod semper.</p>

Drupal

Finally, in my Drupal paragraph--text.html.twig file, I extend the above PatternLab file, like so:

{% extends "@building-blocks/text/text.twig" %}

Yes, there is only one line of code in that file.

Some Explanation

Why do I call my variable {{ content }}? Simple, I know that the default variable in Drupal's paragraph module to print the contents of the paragraph is {{ content }}, so if I give my pattern in PatternLab the same variable name, I won't have to worry about matching any variables. I do not need to do something like this:

{% include '@building-blocks/text/text.twig' with {
  content: text
  }
%}

This will become much clearer when we work with more complex paragraph types in later blog posts.

You can see an example of this pattern in PatternLab here, and the text you are currently reading is an example of it in use in a Drupal template. Simple, eh?

Join the "Something nice ..." newsletter

The full title is "Something nice, something quirky, something else".

I send an email once a week with something nice, something quirky, and something else that I think is interesting (all with a web development theme, of course).

Adding Tokens for Metatag Image Fields when using Drupal Media Entity

Metatag Fields set correctly using Media Entity

Metatag cannot directly extract an image url from a media field referenced by another entity.

I upgraded my site from Drupal 7 to Drupal 8 this week (yes, that's why it's running on Bartik - a PatternLab developed theme will be installed in time).

This morning I enabled the Metagtag module and set some defaults for page title, description, image, etc. The help notes on the image metatag field says "An image associated with this page, for use as a thumbnail in social networks and other services. This will be able to extract the URL from an image field." This is true, except in my case, all the image fields on the site use the Media Entity module, so they are entity reference fields rather than image fields.

When I put in a token of [node:field_main_image], the result in the outputted metatags was:

<meta property="og:image:url" content="Mark Conroy | DrupalCon Dublin 2017" />

In that case, "Mark Conroy | DrupalCon Dublin 2017" is the name of the referenced media. I needed to output the image field of the referenced media.

After a little trial and error, I came up with this:

[node:field_main_image:entity:field_m_image_image]

which outputs:

<meta property="og:image:secure_url" content="https://mark.ie/sites/default/files/media/images/2017-10/mark_presenting_1.jpg" />

In this case, "field_main_image" is the name of the image field on my content type, and "field_m_image_image" is the name of the image field on my image media bundle.

If you wish to output a specific image style, you can append :default:url to the token like so:

[node:field_main_image:entity:field_m_image_image:default:url]

or

[node:field_main_image:entity:field_m_image_image:large:url]

To use the image media item's alt tag for your Twitter alt tag, you can do this:
 

[node:field_main_image:entity:field_m_image_image:alt]

I hope that helps!

Join the "Something nice ..." newsletter

The full title is "Something nice, something quirky, something else".

I send an email once a week with something nice, something quirky, and something else that I think is interesting (all with a web development theme, of course).

Drupal Camp Dublin is Next Week - Last Chance for Tickets

Mark Conroy | DrupalCon Dublin 2017

Seems like just yesterday since we held DrupalCon in Dublin, now we're back with our annual Drupal Camp Dublin.

This year's Drupal Camp Dublin has a great line up of speakers from Ireland and abroad, covering such topics as:

  • Building multi-lingual, multi-region websites (Stella Power)
  • Working as a developer with attention-deficit disorder - add (Levi Govaerts)
  • Planning for disruptions (Jochen Lillich)
  • Migrating from Drupal 4 to 5 to 6 to 7 to 8 (Alan Burke)
  • Automating deployments (Luis Rodriguez)
  • Working webform and commerce and paragraphs and display suites and more (Chandeep Khosa)
  • Live debugging a site that's giving issues (Anthony Lindsay)
  • Stop estimating, start forecasting (Mike King)
  • Deploy with Fabric, and test driven development (Oliver Davies)
  • Design in the Browser (yours truly, me, Mark Conroy)
  • Teaching web development at third level (Ruairi O'Reilly)
  • The QA process (Daniel Shaw)
  • Getting started with Docker (Ed Crompton)
  • The new theme coming to Drupal core (Mark Conroy)

And then there's some socials, and our Drupal Ireland AGM, and at least one other talk not announced yet, and ... you get the idea.

The full schedule is available on our website. There are some tickets left (only €20), get them before they are all gone.

Join the "Something nice ..." newsletter

The full title is "Something nice, something quirky, something else".

I send an email once a week with something nice, something quirky, and something else that I think is interesting (all with a web development theme, of course).

A (simple) Plan for Everyone to Get a Free T-Shirt at DrupalCon

You know you want a t-shirt at DrupalCon Vienna, right? I do. read on...

At this year's DrupalCon in Vienna, the Drupal Association will only be providing 'free' t-shirts to people who purchase an early bird ticket (not exactly 'free' when the ticket costs almost €500) - a position I don't agree with (if you can't afford to give a t-shirt in a welcome pack when charging €500 a ticket, there seems to be something drastically wrong with your business model).

After a tweet last night of me sporting a Druid.fi t-shirt that I received at DrupalCon Dublin, I got thinking: how can we do something to make sure everyone gets a free t-shirt? Then I thought, 'why not provide our own'? Heaven knows we all have loads of them.

So, here's the plan. Everyone brings a Drupal-related t-shirt to DrupalCon. It could be one from your company, one from a previous DrupalCon (I've never been to an non-European one so would like one from somewhere else in the world), one from your local DrupalCamp, a DevDays t-shirt, etc. Then, after the Driesnote, while we are all getting into position for the group photo you give that t-shirt to someone of a similar size to you, and they give you they one they brought (if they brought one). Feel free to bring more than one t-shirt to cover those who don't bring any (it might be some people's first Drupal event).

Oh, and by the way, my size is 'medium'!

Join the "Something nice ..." newsletter

The full title is "Something nice, something quirky, something else".

I send an email once a week with something nice, something quirky, and something else that I think is interesting (all with a web development theme, of course).