Adding a ‘thousands’ separator to ChartJS’s Y axis and tooltips

I learned the toLocaleString() method for adding thousands separators from this Github issue (

These options in your options config will add a thousands separator to your tooltips and yAxes.

options: {
  tooltips: {
    callbacks: {
      label: function(tooltipItems, data) {
        return data.labels[tooltipItems.index] + ": " + data.datasets[0].data[tooltipItems.index].toLocaleString();
  scales: {
    yAxes: [{
      ticks: {
        beginAtZero: false,
        callback: function(value, index, values) {
          return value.toLocaleString();

Drupal 7: Implementing designs & patterns using Paragraphs

I know the sun is setting on Drupal 7, but I think it’s still got a few good years left and someone may find this useful.

Design systems and pattern libraries are all the rage now. If you’re on Drupal 7 and using Paragraphs, you may be wondering how you can go about implementing patterns into Drupal for editors or your site builders to take advantage of.

Here’s the end result of the blog post:

I’m not going to get into what CSS I used, but in this post I’ll walk through my process and share some insights of what I learned along the way in regards to implementing the Paragraphs.

Start with a concept

Internally, we use Adobe XD to prototype ideas. A designer on our team analyzed different higher ed sites to come up with common patterns that seem to show up. She then documented those components in an XD document along with some variations.

I took those concepts and built out some pages using different combinations of components and their variations. I got some quick feedback from the team and we decided that I should begin implementing the patterns.

Break down the concept

Try to find common patterns that can act as your Paragraphs container. This ideally should be done after the concept is complete, but you may find that you need to make a couple passes at this.

You can do this on a whiteboard or a piece of paper or within a graphics program or prototyping tool. Doing this could save you a little time. I tried to break it down in my head and ran into some issues that probably could’ve been avoided.

In discussing the components with other people, questions about how similar one component was to another lead me down a path where I realized where I had 2 components, I could actually get away with only 1 component with a variation option (more on that later, but I used the Classy Paragraphs module)

Getting it into Drupal

For this example I’m going to implement 3 Paragraphs types (components) including the ability to choose some options when utilize the components to introduce variety.

  • Full width section container (full_width_section_container)
    • Background options (field_background_options)
      • Image
      • Green
      • Gold
      • Light gray
    • Spacing options (field_spacing_options)
      • Add vertical margin
      • Add margin top
      • Add margin bottom
    • Background image (field_oz_media)
    • Full width content (field_full_width_content)

  • Small feature (a component that is just an image with text to the side of it and buttons if desired)
    • Title (field_title)
    • Image/Video (field_oz_media)
    • Text (field_accompanying_text)
    • Buttons (field_buttons)
    • Variations (field_variations)
      • Center
      • Move right
      • Image on right

  • Button (button)
    • Title
    • URL
    • Variations (field_variations)
      • Green
      • Light
      • Arrow

Once you get your components broken down into a format like is shown above, it’s just a matter of clicking a few buttons within Drupal to create the Paragraphs types.

Reminder: Make sure you go to “Manage Display” and hide all the labels

Protip: Use the fences module to remove Drupal 7’s plethora of divs (divitis)

Protip: Use the classy paragraphs module to easily provided a dropdown list that can be used to add classes for use in your $classes array in .tpl.php files.

Add logic within a custom module

I made a module called “paragraphs_pages” to store the logic and templates of the components.

function paragraphs_pages_classy_paragraphs_list_options($options, $field, $instance) {
    if ($instance['field_name'] === 'field_background_options') {
        $options['bg-lg'] = t('Light gray background (soft)');
        $options['bg-gr'] = t('Green background (strong)');
        $options['bg-ye'] = t('Gold background (loud)');

    if ($instance['field_name'] === 'field_spacing_options') {
        $options['mv5'] = t('Add vertical margin');
        $options['mb5'] = t('Add margin bottom');
        $options['mt5'] = t('Add margin top');

    if ($instance['field_name'] === 'field_variations') {
        if ($instance['bundle'] === 'small_feature') {
            $options['center'] = t('Center text');
            $options['right'] = t('Right side');
            $options['img-right'] = t('Image on right side');
        if ($instance['bundle'] === 'button') {
            $options['btn-green'] = t('Green');
            $options['btn-white'] = t('Light');
            $options['btn-arrow'] = t('Text with arrow');

    return $options;

 * Implements hook_theme().
function paragraphs_pages_theme($existing, $type, $theme, $path) {
    $theme = array();
    $theme['paragraphs_item__small_feature'] = array(
        'render element' => 'content',
        'base hook' => 'entity',
        'template' => 'paragraphs-item--small-feature',
        'path' => drupal_get_path('module', 'paragraphs_pages') . '/templates',
    $theme['paragraphs_item__full_width_section_container'] = array(
        'render element' => 'content',
        'base hook' => 'entity',
        'template' => 'paragraphs-item--full-width-section-container',
        'path' => drupal_get_path('module', 'paragraphs_pages') . '/templates',
    $theme['paragraphs_item__button'] = array(
        'render element' => 'content',
        'base hook' => 'entity',
        'template' => 'paragraphs-item--button',
        'path' => drupal_get_path('module', 'paragraphs_pages') . '/templates',
    return $theme;

For the hook_classy_paragraphs_list_options() that the classy paragraphs module provides, I check to see what the field name of the classlist is and provide options that can be selected. If you’d like a UI for this, check out classy paragraphs ui module.

If I want the variations to differ based on what Paragraphs type is being used, I can check the bundle before setting the options, as shown above.

For the hook_theme() implementation, you’ll see that I am telling Drupal to use custom templates for our paragraph types that reside within the ‘paragraphs_pages’ custom module folder.

A template implementation example

<?php $bg = (isset($content['field_oz_media'])) ? "filter-darken cover" : ""; ?>
<?php if (isset($content['field_oz_media'])): ?>
  <?php $imgurl = file_create_url($content['field_oz_media'][0]['#item']['uri']); ?>
  <?php hide($content['field_oz_media']); ?>
<?php endif; ?>

<?php if ($bg === ""): ?>
  <div class="pv5 <?php print $classes; ?>"<?php print $attributes; ?>>
    <?php print render($content); ?>
<?php else: ?>
  <div class="pv5 <?php print $bg . " " . $classes; ?>"<?php print $attributes; ?> style="background-image: url('<?php print $imgurl; ?>')">
    <div class="relative z-1">
      <?php print render($content); ?>
<?php endif; ?>
<?php if (isset($content['field_oz_media'])): ?>
  <?php $classes .= " has-media"; ?>

  <div class="small-feature <?php print $classes; ?>">
    <div class="the-media">
      <?php print render($content['field_oz_media']); ?>
    <div class="small-feature__content">
      <h3><?php print render($content['field_title']); ?></h3>
      <?php print render($content['field_accompanying_text']); ?>
      <?php print render($content['field_buttons']); ?>

<?php else: ?>

  <div class="small-feature <?php print $classes; ?>">
    <div class="small-feature__content">
      <h3><?php print render($content['field_title']); ?></h3>
      <?php print render($content['field_accompanying_text']); ?>
      <?php print render($content['field_buttons']); ?>

<?php endif; ?>

I know it isn’t best practice to put any logic within a tpl.php file but hey, it got the job done.

Most of the classes that I’m using are provided by Tachyons. I find that this framework allows me to rapidly get my components 90% complete. I would highly recommend taking a look at that for quickly building components.

Wrapping up

That is the meat of how to implement some components that can be put into Paragraphs for site builders and editors to create awesome looking, consistent pages using components. Adding just a few variations can help create a large number of combinations of components to create many different looking pages that all have a shared style.

Challenges of getting into a ‘deep work’ state

Read Cal Newport’s book Deep Work for a refreshing take on the state of our minds in the 21st century. Also, the following video is a must watch if you think that social media could be impacting your attention span.

I’ve been noticing more and more lately how social media use has an effect on my attention span and I don’t like what I’m noticing.

I’m a freelance web developer in the evenings and I help businesses and organizations manage their web sites and other miscellaneous IT needs. I typically set aside 10 hours a week for freelance work so I need to make it count when I do sit down to work.

Starting to really notice a problem

Lately, during my freelance hours I’ve been noticing that when I come up across a problem that is not a quick and simple fix, my mind says “I’m outta here” and I have a reflex to jump to Twitter, reddit, or some other information junk food.

When I say reflex, I mean it in the most literal sense. An action that is performed as a response to a stimulus and without conscious thought. When a hard problem or situation that requires some deep thinking comes up, I can see this happening and it’s quite troubling.

I’ve always had love-hate relationships with social media (constantly quitting and rejoining). I think it’s time to cut the fat in some ways and remove all social media that isn’t being used as a means to serve some personal or professional goal (similar to how Cal Newport talks about it in Deep Work).

The information buffet line that social media serves up is rewiring us in a bad way. We run away from hard problems instead of coming at them head on. The sense of pleasure and accomplishment of sticking with a problem and seeing it through until it is solved has been replaced with the cheap, shallow gratification that social media offers us.

Social media companies want us to be consumers for life, constantly consuming the information on their platforms so they can aggregate data on us and sell it to advertisers. And we’re giving up one of our most valuable assets in the process: our time and attention.

I’ll end this rant by saying that I think the biggest challenge to entering a deep work state is social media. I struggle with my own social media usage and boundaries and I’m sure other people do as well.

The second biggest challenge is the sheer amount of notifications we all receive now from all of our devices. We all need to give ourselves some time to think and reflect once in a while.

I think as a society we need to take a look at what we’re doing as we could be heading down a path where significantly less people in the future will be capable of complex thought.

If you are a current social media user and have no problem controlling your attention span, kudos! Leave a comment, I’d love to hear how you do it.

Scene from the movie “Idiocracy” where many people are incapable of thinking things through.

Using utility classes (like Tachyons) on a Drupal 7 project

We all want to move quickly to create awesome interfaces right? Well, if you’re on Drupal 7, you know that it isn’t exactly the best system to quickly make great front end interfaces with.

I’ve recently found that using Panels/Panelizer and the Tachyons’ spacing classes, I can crank out interfaces very quickly. This is beautiful to me because before I would have to work locally to write/compile CSS, then push it up through dev and staging before I see a style change on production.

Further, every time I’d write a CSS change, it was typically a spacing issue (something like):

.component {
  padding-left: 2rem;
  margin-bottom: 4rem;

This is a big waste of time in my opinion because I’m essentially bloating my CSS with writing lots of the same spacing properties.

Instead of doing this, why not use a Tachyons-style approach and have a bunch of utility classes in your CSS that can be used to tweak spacing on the fly within Panels/Panelizer.

Panel pane configuration options after you click “Customize this page”

In fact, with a recent update of Panels, they’ve put a CSS button right on each pane so you don’t have to go into the styles menu to add them! This is perfect for quickly applying spacing classes.

There are a lot of other major benefits from using these small utility classes in production, but thought I’d share one use case that has saved me a lot of time!

Happy New Year

Happy New Year to all my family, friends, acquaintances, co-workers, people I have done business with (and anyone else not covered by those categories).

May your 2018 be filled with not only the completion of personal and professional goals, but with contentment with who you are and where you are in this life.

2017 year end review

2017 marked the first year in our new home. We got it (mostly) decorated and have loved having guests over to enjoy some dinner, games and conversation.

My dog, Nugget
In 2017, we got our first puppy. He was about 6 months old when we got him and has been quite a handful!

This post is one of my favorites to write every year because it allows me to look back on the year and evaluate what I’ve learned and determine where I’ve made progress.

Design systems

This is the year that I spent a lot of time reading and working on a design system. I’ve spent a bit of time thinking about the challenges in implementing and maintaining a design system, and even wrote a few blog posts about design systems.

Jeremy Keith linked to one of my blog posts, calling out my Venn diagram as similar to how he thinks about how design system, pattern libraries, and style guides all fit together. This simple thing was a huge boost to my confidence as it sent a signal to me that I’m thinking about these things the right way.

I feel as if we made significant progress in our organization to implement a system of components. However, an unseen (yet ultimately positive) circumstance arose that temporarily halted progress on the design system, which was an accessibility complaint.

After this holiday vacation, one of my top priorities is going to be completing a design system that we can build on for years to come.


I crammed so much accessibility knowledge into my head this year because of a complaint we had filed against us by OCR (Office of Civil Rights), which claimed that our website was inaccessible.

While the situation was at times stressful, in hindsight I view it as an incredibly positive experience for a lot of reasons:

  • Definitely “leveled-up” my accessibility skills a LOT
  • Created a sense of urgency and importance about the topic within our organization
  • Offered opportunity to revisit old processes and policies to ensure people understand accessibility
  • Got me out of my comfort zone and gave a couple accessibility workshops on campus
  • Again, got me out of my comfort zone to be involved and contribute to in a campus-wide accessibility working group

As part of our organization’s commitment to accessibility, I was sent to WebAIM training in beautiful Logan, Utah. The training was highly valuable as it clarified a lot of the misconceptions I had about accessibility and solidified my understanding of when to use ARIA attributes vs HTML5 elements when it comes to accessible markup.

Templating languages

While working on design systems, I’ve experimented with a lot of templating languages. These are a delight to use because they fit in perfectly with component based design and allow for rapid front-end prototyping. Throughout the year I stumbled on 3 different templating languages that I got the opportunity to play with.

Pug — Thanks to CodePen, I’ve learned how Pug templating works. CodePen’s new Projects feature is an amazing tool to use when prototyping.

Twig — At work, the current version of our pattern library is in PatternLab which uses Twig to template components. This has allowed me to learn the ins and outs of Twig and get up to speed with it quickly. It is such a good fit because as our organization eyes moving to Drupal 8, learning Twig will prove to be a good investment of time.

Handlebars — I use to build certain custom designed, special projects which use Handlebars to template out partials and layouts.

Governance and policy

This isn’t a technical achievement, but it’s note-worthy nonetheless. While sometimes I wish I could focus on the tech part of my job 100% of the time, it is necessary to be competent in writing and communicating in order to be truly effective and successful in your career.

This year marked the first time I’ve taken a serious look into governance policies, which our organization sorely needs. I like to think I helped get the ball rolling on that initiative by creating some drafts of policy documents that I shared with my superiors who see the policies as a necessity are now using their status to get buy-in and carry the project across the finish line.


The most important design principle: Be inclusive

I’ve made some previous posts about design systems, which are all the rage in 2017. We are still working through the creation of one at my organization. One of the core parts of design systems are principles.

These principles ideally shape the future of design for an organization. The most important thing that I keep coming back to when thinking about how to create interfaces is to be inclusive.

Be inclusive

This is the most important design principle you can have as an organization. Convincing people that it is important can take a lot of work and often times you will be fighting an existing culture that says “If it works on my computer then its good.” A lot of people don’t stop to consider all the other ways people can be accessing their site/content.

What does that mean?

If your creative team is well versed in inclusive design principles, then it’s easy: Hand over design authority to your creative team. Are you reaching as many people as you can? If your superiors look at your creative team as tools that will do what they say and create what they want then it is incredibly difficult to design inclusively.

The problem with this approach is that often times the stakeholders who are “driving the bus” so to speak, are not well versed in performance, accessibility, and usability — all three of these areas are vital to being inclusive.


It’s nice that the site works on your high speed, wired internet connection, but how does it perform with spotty WiFi or on 3G speeds? Are you able to access the site in these situations?


I think this is what a lot of people think of when talking about being inclusive. Is your site designed and developed in a way that takes into account WCAG 2.0 (the de-facto standard for accessibility guidelines)? Complying with these guidelines helps everyone, not just those with disabilities. Microsoft has done a phenomenal job at explaining that disabilities are not personal health conditions, but rather mismatched human interactions.


Usability is closely related to performance and accessibility. If the site isn’t performant and accessible then it isn’t usable. On top of that, ensure your site is following agreed upon UI patterns to ensure a consistent experience across your site.

This is not a complete or exhaustive list by any means but it seems to me that keeping these three areas in mind will go a long way in ensuring that your site is inclusive.

Using different template (tpl.php) files for a specific content type in Drupal 7

Use case

In one of our sites, we post email communications that were sent out as all-campus announcements on our website.

The problem is, our basic web template does not look like an email template.

So I thought, “I wonder if I could just load a separate set of tpl.php files based on the content type.” Spoiler alert: I could.

I wanted a solution that didn’t require hacking my original theme. I wanted to leave the current theme untouched and simply provide new html.tpl.php and page.tpl.php for this specific content type (presidential_email).

Start with Features

This step is technically optional. If you don’t have a local or dev environment then you don’t need to package your content type in a feature. But for those of us who have to push code through dev -> stg -> prod, features is the best route so you don’t have to rebuild the content type on each environment.

Create your content type in your local environment. Add fields to your liking. Now export that content type using Features.

I typically use the “Generate Feature” functionality under Advanced Options, but you can do whatever you want. Generate Feature allows me to write the code directly where I want to. In this case, it was sites/all/modules/custom.

Fire up your code editor and add your hooks

Go to your sites/all/modules/custom directory and you should see a folder in the path you specified with your content type exported into a Features module.

Add your hooks to your modulename.module file to really get cookin’!


In your hook_theme implementation, you want to specify the new tpl files you want to use. In my case, I want this module to override html.tpl.php and page.tpl.php for the presidential_email content type.

 * Implements hook_theme().
function presidential_email_theme($existing, $type, $theme, $path) {
    $theme = array();
    $theme['html__presidential_email'] = array(
        'render element' => 'content',
        'base hook' => 'node',
        'template' => 'html--presidential-email',
        'path' => drupal_get_path('module', 'presidential_email') . '/templates',
    $theme['page__presidential_email'] = array(
        'render element' => 'content',
        'base hook' => 'node',
        'template' => 'page--presidential-email',
        'path' => drupal_get_path('module', 'presidential_email') . '/templates',
    return $theme;

Create your templates folder and files
In your created module folder, add a templates folder. The above functions are telling Drupal to look in yourmodule/templates for html–presidential-email.tpl.php and page–presidential-email.tpl.php.


Depending on your use case, this could be optional. In my case, I didn’t want ANY of the typical CSS to be loaded because I wanted to use inline styles created by the MailChimp template. To achieve this, my hook_css_alter looked something like this:

 * Implements hook_css_alter().
function presidential_email_css_alter(&$css) {
    $node = menu_get_object();
    if ($node && $node->type == 'presidential_email' ) {
        foreach ($css as $k => $v) {
            if (!strpos($k, "navbar")) {

Essentially, this code checks to see if the current node is a ‘presidential_email’ and then loops through all the CSS files, unsetting them all unless it’s necessary for the navbar (I still want it to look presentable while logged in).

hook_preprocess_html and hook_preprocess_page

Last but certainly not least, this method only works if you have auto-generated template suggestions based on node type. For instance, consider my template_preprocess_html and template_preprocess_page functions (replace template with your theme name).

You could also put these in your .module file changing ‘template’ in the function name to your module name.

 * Implements template_preprocess_html().
function template_preprocess_html(&$vars) {
    $node = menu_get_object();
    if ($node && $node->nid) {
        $vars['theme_hook_suggestions'][] = 'html__' . $node->type;

 * Implements template_preprocess_page().
function template_preprocess_page(&$variables) {
    if (isset($variables['node']->type)) {
        $nodetype = $variables['node']->type;
        $variables['theme_hook_suggestions'][] = 'page__' . $nodetype;

I wrote these at different times in my Drupal career but they do the trick. A content type of “presidential_email” will now produce template suggestions for html–presidential-email.tpl.php and page–presidential-email.tpl.php.

With this in place, the module will now load templates in the module’s template folder when the presidential_email content type is being displayed. Worked well for my simple use case!