Skip to content
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 114 additions & 0 deletions src/content/posts/2025/my-sdc-workflow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
---
title: My Single Directory Components Workflow
description: A walkthrough of the workflow I used to build a custom Drupal theme that relies heavily on Single Directory Components
author: Brian
date: 2025-01-18
tags:
- drupal
---

Recently I've been working on my first honest to God Drupal theme in years after primarily building decoupled front ends. This also proved to be the first time I could really put [Single Directory Components](https://www.drupal.org/docs/develop/theming-drupal/using-single-directory-components) (SDCs) to the test, after following along with development and experimenting in small side projects. I found pretty quickly that SDCs offered a bridge to the component based workflow I was familiar with that felt pretty comfortable. Further more, as my workflow established itself, an interesting pattern emerged around progressive enhancement and custom elements.

### Initial Prototyping

When possible, I prefer to do initial prototyping outside of Drupal. This often allows front end work to proceed before the back end functionality it depends on has been implemented. It also allows me to work in a lighter weight environment, and to focus on the design and user experience without the constraints of a CMS.

My current tool of choice for this is [Astro](https://astro.build/). But maybe for you it is [Storybook](https://storybook.js.org/), or a simple HTML file. The important thing is that it is a familiar environment that allows you to iterate as quickly as possible. And ideally this should also be something that you can easily deploy somewhere for others to see and provide early feedback.

At this point, I also include a few libraries or frameworks that I know I'll be using in the final build. For many, this might be something like adding [Tailwind](https://tailwindcss.com/). For me, I currently lean on the following in custom Drupal themes:

- [Pico](https://picocss.com/) - a minimal CSS framework based on semantic HTML.
- [Open Props](https://open-props.style/) - pre-packaged CSS variables for common design tokens.

With that out of the way, pour over your design and identify the reusable components that you'll need to build.

I won't get too deep into the Astro worflow, but in general you have your HTML, CSS, Props, etc which you'll find translate to your SDCs nicely.

### Component Scaffolding

When I identified a component that I needed to build, I'd start by creating the simplest possible representation of it as a single directory component. First I'd create a `component.yml` file in the `components` directory of my theme. The simplest possible version would be.

```yml
# components/header/header.component.yml
name: Header
props:
type: object
properties: {}
```

That's a component with no props or slots, so basically not a component at all. But it exists, which is still a small victory.

We can take the step of adding some obvious slots since we're here:

```yml
# components/header/header.component.yml
name: Header
props:
type: object
properties: {}
slots:
logo:
title: Logo
description: Site logo
content:
title: Content
description: Header content
```

Those slots are quite broad, but in my work with SDCs thus far I've found that using Drupal's markup where you can is usually a good idea. So often start with broad slots and narrow them down as needed. We'll also see in a bit how drastically altering markup for things like images or menus often isn't necessary.

At this point, I'd add a bare bones twig template to start getting something on the screen. But this is also where I found myself bringing a little more flavor from my framework component workflow to Drupal.

### I Want My Cool Custom Tag

If I was using a framework like React, I'd create my header component and be off to the races. Something like:

```jsx
// Header.js
import React from "react";

export const Header = ({ logo, content }) => (
<header>
<div>{logo}</div>
<div>{content}</div>
</header>
);
```

And then I'd have a `<Header>` component that I could import and use anywhere in my app.

Single Directory Components end up getting close to that.

```twig
{# components/header/header.html.twig #}
<header>
{% block logo %}{%endblock%}
{% block content %}{%endblock%}
</header>
```

And then I'd use it in a template like:

```twig
{# templates/page.html.twig #}
{% embed 'mytheme:header' %}
{% block logo %}{# my logo markup #}{% endblock %}
{% block content %}
{# my content markup - {{page.header}} for example #}
{% endblock %}
{% endembed %}
```

That's nice, but I found that combining this with custom elements was a great way to get a little closer to the React experience, and also had some nice side effects.

### TAC CSS Methodology

...

### HTML Web Components

...

### One WYSIWG-Related Catch

Using custom elements in CKEditor is tricky. Or maybe I just don't know how to do it.