Missteps, Learnings, and Success
Video: Youtube
Slides: https://wheatpenny.github.io/D8-component-theming/
Download theme: componenttheme.zip
“The world needs more people who are two days into learning something writing about the problems of people who are one day in.”-- Patrick McKenzie
(Highlighted folders and files of our Drupal 8 component-based theme)
We're going to reach these goals with component theming in Drupal 8.
These goals are great, but why even bother? This is a lot of effort and something brand new to learn.
Make changes to exactly the part of the site you want.
Those changes roll out in a predictable manner.
Two CSS properties walk into a bar. A barstool in an entirely different bar falls over.
Bundles of HTML, CSS, and JS that can be moved around the site and remain CONSISTENT and PREDICTABLE
(CONTENT HERE)
(CAPTION HERE)
Pattern Lab owns a template that Drupal imports. Drupal inserts content and displays the markup.
.paragraphs-code {
clear: both;
padding: 0 0 20px 20px;
border-left: #f7951d 2px solid;
margin-left: 0;
}
@media (min-width: 1250px) {
.paragraphs-code {
padding-left: 40px;
margin-left: -40px;
}
}
.paragraphs-code__code {
background-color: #f2f2f2;
overflow: scroll;
}
.paragraphs-code__caption {
color: #7a7a7a;
border-bottom: 1px solid #f2f2f2;
padding-bottom: 5px;
}
.paragraphs-code__text {
margin-bottom: 0;
}
Pattern Lab generates this CSS, and the Drupal theme imports this CSS file.
The deliverable we are using to define client acceptance in the browser.
The design system I chose to implement a front end style guide.
Display code examples in my writing posts.
Understand that there is a need for a component.
Create the component in Pattern Lab.
npm run new
https://github.com/phase2/pattern-lab-starter
<{{ element ?: "figure" }} class="paragraphs-code">
{{ code }}
{% if caption %}
{{ caption }}
{% endif %}
{{ element ?: "figure" }}>
Twig markup
.paragraphs-code {
clear: both;
padding: 0 0 $spacing--l $spacing--l;
border-left: $c-code-border 2px solid;
margin-left: 0;
@include breakpoint($bp--xxlarge) {
padding-left: $spacing--l*2;
margin-left: -$spacing--l*2;
}
&__code {
background-color: $c-code-bg;
overflow: scroll;
}
&__caption {
color: $c-byline-color;
border-bottom: 1px solid $c-byline-border;
padding-bottom: $spacing--sm;
}
&__text {
margin-bottom: 0;
}
}
SCSS file
{
"code": "drup(){cd /var/www/$1/sites/default/ (cdd && git pull && drush updatedb)}",
"caption": "This example shows how to automate your startup environment."
}
JSON file
Test your pattern in the browser!
Build functionality in Drupal
Figure out template name in Drupal
Pull component Twig template into Drupal theme.
{% embed "@molecules/paragraphs-code.twig"
with {
"code": content.field_figure_code|field_value,
"caption": content.field_figure_caption|field_value
}
%}
{% endembed %}
paragraph--paragraphs-code.html.twig
Drupal modules that allows editors to create small, movable chunks of content. Replaces a big Body field.
Generates the final CSS file
Makes BEM naming structure easier to implement.
Block, Element, Modifier. CSS naming convention
HTML templating engine in D8. Replaces PHPTemplate in D7.
Comes from node.js. It's a package manager. YOU DON'T NEED TO BE AN EXPERT HERE...just have to get it installed.
Show Images in Writing Posts
Understand that there is a need for a component. (system thinking)
Create the component in Pattern Lab.
<{{ element ?: "figure" }} class="paragraphs-image{% if styleModifier %} paragraphs-image--{{ styleModifier }}{% endif %}">
{% block img %}
{% include "@atoms/_img.twig" %}
{% endblock %}
{% if byline %}
Image courtesy {{ byline }}
{% endif %}
{% if caption %}
{{ caption }}
{% endif %}
{{ element ?: "figure" }}>
Twig markup
.paragraphs-image {
clear: both;
margin-left: 0;
margin-right: 0;
margin-bottom: $spacing--l*2;
display: table;
// styleModifier: left
&--left {
float: none;
margin-left: auto;
margin-right: auto;
@include breakpoint($bp--large) {
float: left;
margin: 0 $spacing--l $spacing--l 0;
max-width: 600px;
}
@include breakpoint($bp--xlarge) {
//margin: 0 $spacing--l $spacing--l -05%;
max-width: 700px;
}
@include breakpoint($bp--xxxlarge) {
margin: 0 $spacing--l $spacing--l -15% ;
}
}
// styleModifier: right
&--right {
float: none;
margin-left: auto;
margin-right: auto;
@include breakpoint($bp--large) {
float: right;
margin: 0 0 $spacing--l $spacing--l;
max-width: 600px;
}
@include breakpoint($bp--xlarge) {
//margin: 0 -05% $spacing--l $spacing--l;
max-width: 700px;
}
@include breakpoint($bp--xxxlarge) {
margin: 0 -15% $spacing--l $spacing--l;
}
}
// styleModifier: hero
&--hero {
margin-left: auto;
margin-right: auto;
}
&__image {
position: relative;
float: left;
img {
display: block;
width: 100%;
}
}
&__byline {
position: absolute;
bottom: 0;
right: 0;
@include knockout;
// styleModifier: hero
.paragraphs-image--hero & {
@include breakpoint($bp--xxlarge) {
transform: rotate(90deg);
transform-origin: 100% 100%;
}
}
// styleModifier: left
.paragraphs-image--left & {
@include breakpoint($bp--xxlarge) {
left: inherit;
right: auto;
transform: rotate(270deg);
transform-origin: 0 100%;
}
}
// styleModifier: right
.paragraphs-image--right & {
@include breakpoint($bp--xxlarge) {
transform: rotate(90deg);
transform-origin: 100% 100%;
}
}
}
&__caption {
color: $c-byline-color;
border-bottom: 1px solid $c-byline-border;
padding-bottom: $spacing--sm;
clear: both;
display: table-caption;
caption-side: bottom;
}
&__text {
margin-bottom: 0;
}
}
SCSS file
{
"img": "http://placehold.it/1000x400",
"byline": "Freddy Foto",
"bylineurl": "https://www.example.com",
"caption": "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud "
}
JSON file
/**
* Implements hook_preprocess_HOOK() for paragraph--paragraphs-image.html.twig.
*/
function patternlab_preprocess_paragraph__paragraphs_image(&$variables) {
$paragraph = $variables['paragraph'];
// Get the value of the image style and add it as a class on the image field.
$display_image = $paragraph->get('field_figure_position')->value;
$variables['display_image'] = $display_image;
}
Theme function: place in themename.theme
{% embed "@molecules/01-paragraphs-image.twig"
with {
"byline": content.field_figure_byline.0["#title"],
"bylineurl": content.field_figure_byline.0["#url"],
"caption": content.field_figure_caption|field_value,
"styleModifier": display_image
}
%}
{% block img %}
{{ content.field_figure_image|field_value }}
{% endblock %}
{% endembed %}
paragraph--paragraphs-image.html.twig
Show Cards in Views
Understand that there is a need for a component. (system thinking)
Create the component in Pattern Lab.
<{{ element ?: "div" }} class="writing-card{% if styleModifier %} writing-card--{{ styleModifier }}{% endif %}">
{% block img %}
{% include "@atoms/_img.twig" %}
{% endblock %}
{% if title %}{{ title }}
{% endif %}
{% if body %}
{{ body }}
{% endif %}
{{ element ?: "div" }}>
Twig markup
.writing-card {
position: relative;
//styleModifier: hero
&--hero {
margin-bottom: $spacing--l*2;
}
&__caption {
border-top: $spacing--l/4 solid $c-writing-card-caption-border;
border-bottom: $spacing--l/4 solid $c-writing-card-caption-border;
// styleModifier: hero
.writing-card--hero & {
border-top: $spacing--l/4 solid $c-writing-card--hero-caption-border;
border-bottom: $spacing--l/4 solid $c-writing-card--hero-caption-border;
position: relative;
@include breakpoint($bp--medium) {
position: absolute;
bottom: 0;
width: 100%;
}
}
}
&__title {
@include knockout;
background-color: $c-writing-card-caption-bg;
font-weight: normal;
margin-top: 0;
margin-bottom: 0;
}
&__body {
@include knockout;
background-color: $c-writing-card-caption-bg;
font-style: italic;
}
&__text {
margin-bottom: 0;
}
}
SCSS file
{
"img": "http://placehold.it/650x250",
"url": "http://www.example.com",
"title": "The Cobbler's Children: Pattern Lab and being your own client"
}
JSON file
Test your pattern in the browser!
Build functionality in Drupal
Structure > Display Modes > View Modes
Add View Modes for content.
Configure for each content type:
Structure > [Content Type] > Manage Display
Enable under "Custom Display Settings."
Figure out template name in Drupal
Pull component Twig template into Drupal theme.
Each View Mode gets a Drupal template, but they all use the same component.
{% embed "@molecules/01-writing-card.twig"
with {
"url": url,
"title": label,
"body": content.field_card_blurb|field_value
}
%}
{% block img %}
{{ content.field_card_image|field_value }}
{% endblock %}
{% endembed %}
node--writing--card.html.twig
{% embed "@molecules/01-writing-card.twig"
with {
"url": url,
"title": label,
"body": content.field_card_blurb|field_value,
"styleModifier": "hero"
}
%}
{% block img %}
{{ content.field_card_image|field_value }}
{% endblock %}
{% endembed %}
node--writing--card-hero.html.twig
{% embed "@molecules/01-writing-card.twig"
with {
"url": url,
"title": label,
"body": content.field_card_blurb|field_value
}
%}
{% block img %}
{{ content.field_card_image|field_value }}
{% endblock %}
{% endembed %}
node--writing--card-text-only.html.twig
What were my wrong assumptions?
Drupal would be my test area for real content.
Real content in Pattern Lab. Take the time to do this!
Exceptionally important if your front end style guide is not perfectly in sync with the live site. You need to see if your ideas actually work!
I wanted to provide every template Drupal would use.
I used blocks in Twig heavily to create replaceable sections.
I thought that I would be theming a lot of views with fields.
I themed view modes that were then used in views.
Yes
Yes
No, not yet
Learn and contribute at the same time!
I've learned a ton here. People are very helpful as long as you put in the effort.
Use SCSS formatting!
There is an extensive list of additional resources at the bottom of this page.