<?xml-stylesheet href="/pretty-feed-v2.xsl" type="text/xsl"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Trys Mudford's Blog</title>
    <link>https://www.trysmudford.com/tags/eleventy/</link>
    <description>Posts, thoughts, links and photos from Trys</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-us</language>
    <lastBuildDate>Mon, 16 May 2022 00:00:00 +0000</lastBuildDate>
    <atom:link href="https://www.trysmudford.com/blog/index.xml" rel="self" type="application/rss+xml"/>
    
    <item>
      <title>Building a design system with Eleventy</title>
      <link>https://www.trysmudford.com/blog/eleventy-design-system/</link>
      <pubDate>Mon, 16 May 2022 00:00:00 +0000</pubDate>
      
      <guid>https://www.trysmudford.com/blog/eleventy-design-system/</guid>
      <description><![CDATA[
<p>One of the standout projects while working at <a href="https://www.clearleft.com">Clearleft</a> was collaborating with Malvern Panalytical to build the foundations of <a href="https://brand.malvernpanalytical.com/">their design system</a>. Four tech stacks within the business dictated that this system would centre around CSS, rather than language-driven component markup.</p>
<p>This decision gave us freedom to pick the most flexible stack for the design system, not forcing our hand to choose an off-the-shelf platform with specific language/framework support. Furthermore, we wanted a system that was beyond a component library; a true design system that could be used to articulate and accommodate brand, content and wider design standards.</p>
<p>Eleventy was the obvious candidate. Generating &ldquo;pages from data&rdquo; was the most compelling feature, and add to that the flexibility in templating and the rapid build times, there really was no other stack that came close.</p>
<p>Taking inspiration from <a href="https://fractal.build/">Fractal</a>; a project born from design systems projects at Clearleft, I wanted to build this system around component &ldquo;context&rdquo;. Context is a fancy word for the data that gets passed to a component to render it, and it allows you to render a component, and any number of variants by providing different data.</p>
<p>Mixed with the <a href="/blog/encapsulated-11ty-components/">encapsulated macro pattern</a>, we can demonstrate these  components with ease, and with a consistent interface.</p>
<h2 id="demo-design-system">Demo design system</h2>
<p>I&rsquo;ve created a <a href="https://eleventy-design-system.netlify.app/">demonstration design system</a> to articulate how this can work in practice. Feel free to fork <a href="https://github.com/trys/eleventy-design-system/">the repository</a> and tweak to your heart&rsquo;s content.</p>
<a href="https://eleventy-design-system.netlify.app/" class="button">Demo Design System</a>

<h3 id="screenshots-from-the-system">Screenshots from the system</h3>
<figure>
  <img src="/images/blog/e-ds-1.jpg">
  <figcaption>A button component within the system</figcaption>
</figure>
<figure>
  <img src="/images/blog/e-ds-5.jpg">
  <figcaption>A simple example of a variant: a button with a different background</figcaption>
</figure>
<figure>
  <img src="/images/blog/e-ds-2.jpg">
  <figcaption>The generated `.html` code for the button</figcaption>
</figure>
<figure>
  <img src="/images/blog/e-ds-3.jpg">
  <figcaption>The component macro and the context data passed to it</figcaption>
</figure>
<figure>
  <img src="/images/blog/e-ds-6.jpg">
  <figcaption>A quotation component rendered in a centred, limited-width preview</figcaption>
</figure>
<h2 id="how-it-works">How it works</h2>
<p>There are three key files in this design system (the links below go to the files in the repository on GitHub):</p>
<ol>
<li><a href="https://github.com/trys/eleventy-design-system/blob/main/src/_includes/components/button/button.config.js"><code>_includes/components/**/*.config.js</code></a></li>
<li><a href="https://github.com/trys/eleventy-design-system/blob/main/src/_data/components.js"><code>_data/components.js</code></a></li>
<li><a href="https://github.com/trys/eleventy-design-system/blob/main/src/components-full-pages.njk"><code>components-full-pages.njk</code></a></li>
</ol>
<h3 id="key-file-1-_includescomponentsconfigjshttpsgithubcomtryseleventy-design-systemblobmainsrc_includescomponentsbuttonbuttonconfigjs">Key file 1: <a href="https://github.com/trys/eleventy-design-system/blob/main/src/_includes/components/button/button.config.js">_includes/components/**/*.config.js</a></h3>
<p>A config file is what flags each component to the design system. Here&rsquo;s an example configuration for the quote component rendered in the screenshots above:</p>
<div class="highlight"><pre class="chroma"><code class="language-js" data-lang="js"><span class="nx">module</span><span class="p">.</span><span class="nx">exports</span> <span class="o">=</span> <span class="p">{</span>
  <span class="nx">title</span><span class="o">:</span> <span class="s1">&#39;Quote&#39;</span><span class="p">,</span>
  <span class="nx">context</span><span class="o">:</span> <span class="p">{</span>
    <span class="nx">body</span><span class="o">:</span> <span class="s1">&#39;&lt;p&gt;Maecenas sed diam eget risus varius blandit...&lt;/p&gt;&#39;</span><span class="p">,</span>
    <span class="nx">citation</span><span class="o">:</span> <span class="s1">&#39;Trys Mudford, Design Engineer&#39;</span>
  <span class="p">},</span>
  <span class="nx">preview</span><span class="o">:</span> <span class="s1">&#39;wrapper&#39;</span>
<span class="p">}</span>
</code></pre></div><p>The <code>title</code> field is used in the sidebar menu. The <code>context</code> object is the data that&rsquo;s passed into the component at the time of rendering. The <code>preview</code> field references the file that should be used to render the component. Most components are rendered in a full-width wrapper, but it can be useful to pop the component into a more realistically limited-width, or multi-column wrapper.</p>
<p>Now we&rsquo;ve got this data format, it&rsquo;s trivial to create variants of it. Here&rsquo;s the button configuration:</p>
<div class="highlight"><pre class="chroma"><code class="language-js" data-lang="js"><span class="nx">module</span><span class="p">.</span><span class="nx">exports</span> <span class="o">=</span> <span class="p">{</span>
  <span class="nx">title</span><span class="o">:</span> <span class="s1">&#39;Button&#39;</span><span class="p">,</span>
  <span class="nx">context</span><span class="o">:</span> <span class="p">{</span>
    <span class="nx">label</span><span class="o">:</span> <span class="s1">&#39;Hello&#39;</span><span class="p">,</span>
  <span class="p">},</span>
  <span class="nx">variants</span><span class="o">:</span> <span class="p">[</span>
    <span class="p">{</span>
      <span class="nx">title</span><span class="o">:</span> <span class="s1">&#39;Different label&#39;</span><span class="p">,</span>
      <span class="nx">context</span><span class="o">:</span> <span class="p">{</span>
        <span class="nx">label</span><span class="o">:</span> <span class="s1">&#39;Hello, world&#39;</span>
      <span class="p">}</span>
    <span class="p">},</span>
    <span class="p">{</span>
      <span class="nx">title</span><span class="o">:</span> <span class="s1">&#39;Blue background&#39;</span><span class="p">,</span>
      <span class="nx">context</span><span class="o">:</span> <span class="p">{</span>
        <span class="nx">colour</span><span class="o">:</span> <span class="s1">&#39;blue&#39;</span>
      <span class="p">}</span>
    <span class="p">},</span>
  <span class="p">]</span>
<span class="p">}</span>
</code></pre></div><p>You&rsquo;ll see the <code>variants</code> field format is a repeat of the parent component, but in an array, with only the differences in data from the parent passed in. In this case, either a different <code>label</code>, or a <code>colour</code> parameter. These pieces of data are then available within the component <code>params</code> variable to adapt to accordingly.</p>
<div class="highlight"><pre class="chroma"><code class="language-twig" data-lang="twig"><span class="c">{# button.njk #}</span><span class="x">
</span><span class="x"></span><span class="cp">{%</span>- <span class="k">set</span> <span class="nv">classNames</span> <span class="o">=</span> <span class="s2">&#34;c-button&#34;</span> -<span class="cp">%}</span><span class="x">
</span><span class="x">
</span><span class="x"></span><span class="cp">{%</span>- <span class="k">if</span> <span class="nv">params.colour</span> -<span class="cp">%}</span><span class="x">
</span><span class="x">  </span><span class="cp">{%</span> <span class="k">set</span> <span class="nv">classNames</span> <span class="o">=</span> <span class="nv">classNames</span> <span class="o">+</span> <span class="s2">&#34; c-button--&#34;</span> <span class="o">+</span> <span class="nv">params.colour</span> <span class="cp">%}</span><span class="x">
</span><span class="x"></span><span class="cp">{%</span> <span class="k">endif</span> -<span class="cp">%}</span><span class="x">
</span><span class="x">
</span><span class="x">&lt;button type=&#34;</span><span class="cp">{{</span> <span class="nv">params.type</span> <span class="k">or</span> <span class="s1">&#39;button&#39;</span> <span class="cp">}}</span><span class="x">&#34; class=&#34;</span><span class="cp">{{</span> <span class="nv">classNames</span> <span class="cp">}}</span><span class="x">&#34;&gt;
</span><span class="x">  </span><span class="cp">{{</span> <span class="nv">params.label</span> <span class="cp">}}</span><span class="x">
</span><span class="x">&lt;/button&gt;
</span></code></pre></div><h3 id="key-file-2-_datacomponentsjshttpsgithubcomtryseleventy-design-systemblobmainsrc_datacomponentsjs">Key file 2: <a href="https://github.com/trys/eleventy-design-system/blob/main/src/_data/components.js">_data/components.js</a></h3>
<p>JavaScript files in the <code>_data</code> folder are called at build time by Eleventy, to provide global data to templates. Usually, this would be used for API calls, gathering content before generating the website. But we can perform other asynchronous actions in this space, namely, reading from the file system:</p>
<div class="highlight"><pre class="chroma"><code class="language-js" data-lang="js"><span class="nx">module</span><span class="p">.</span><span class="nx">exports</span> <span class="o">=</span> <span class="kr">async</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
  <span class="c1">// Pull in all the config files
</span><span class="c1"></span>  <span class="kr">const</span> <span class="nx">modules</span> <span class="o">=</span> <span class="kr">await</span> <span class="nx">requireGlob</span><span class="p">(</span><span class="s1">&#39;../_includes/**/*.config.js&#39;</span><span class="p">,</span> <span class="p">{</span>
    <span class="nx">reducer</span><span class="p">,</span>
    <span class="nx">bustCache</span><span class="o">:</span> <span class="kc">true</span>
  <span class="p">});</span>

  <span class="c1">// Convert the components into our required format
</span><span class="c1"></span>  <span class="kr">const</span> <span class="nx">componentGroups</span> <span class="o">=</span> <span class="nx">modules</span><span class="p">.</span><span class="nx">components</span>
    <span class="p">.</span><span class="nx">map</span><span class="p">(</span><span class="nx">convertComponent</span><span class="p">)</span>
    <span class="p">.</span><span class="nx">filter</span><span class="p">(</span><span class="nb">Boolean</span><span class="p">);</span>
  
  <span class="c1">// Return the components and the menu
</span><span class="c1"></span>  <span class="k">return</span> <span class="p">{</span>
    <span class="nx">components</span><span class="o">:</span> <span class="nx">componentGroups</span><span class="p">.</span><span class="nx">flat</span><span class="p">(),</span>
    <span class="nx">menu</span><span class="o">:</span> <span class="nx">prepareMenu</span><span class="p">(</span><span class="nx">componentGroups</span><span class="p">)</span>
  <span class="p">};</span>
<span class="p">}</span>
</code></pre></div><p>The function <code>convertComponent</code> moulds the data from <code>*.config.js</code> into a usable format:</p>
<div class="highlight"><pre class="chroma"><code class="language-js" data-lang="js"><span class="kd">function</span> <span class="nx">convertComponent</span><span class="p">(</span><span class="nx">component</span><span class="p">)</span> <span class="p">{</span>
  <span class="c1">// Extract variants from component and remove them
</span><span class="c1"></span>  <span class="kd">let</span> <span class="p">{</span> <span class="nx">variants</span> <span class="o">=</span> <span class="p">[]</span> <span class="p">}</span> <span class="o">=</span> <span class="nx">component</span><span class="p">;</span>
  <span class="k">delete</span> <span class="nx">component</span><span class="p">.</span><span class="nx">variants</span><span class="p">;</span>

  <span class="c1">// Back out if the component isn&#39;t valid
</span><span class="c1"></span>  <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">component</span> <span class="o">||</span> <span class="o">!</span><span class="nx">component</span><span class="p">.</span><span class="nx">title</span><span class="p">)</span> <span class="k">return</span> <span class="kc">null</span><span class="p">;</span>

  <span class="c1">// Set sensible defaults for previews &amp; slugs
</span><span class="c1"></span>  <span class="nx">component</span><span class="p">.</span><span class="nx">preview</span> <span class="o">=</span> <span class="nx">component</span><span class="p">.</span><span class="nx">preview</span> <span class="o">||</span> <span class="s1">&#39;default&#39;</span><span class="p">;</span>
  <span class="kr">const</span> <span class="nx">parentSlug</span> <span class="o">=</span> <span class="nx">component</span><span class="p">.</span><span class="nx">slug</span> <span class="o">||</span> <span class="nx">slugify</span><span class="p">(</span><span class="nx">component</span><span class="p">.</span><span class="nx">title</span><span class="p">.</span><span class="nx">toLowerCase</span><span class="p">());</span>
  
  <span class="c1">// Loop the variants, returning a merged combo of component, then variant
</span><span class="c1"></span>  <span class="nx">variants</span> <span class="o">=</span> <span class="nx">variants</span><span class="p">.</span><span class="nx">map</span><span class="p">(</span><span class="nx">variant</span> <span class="p">=&gt;</span> <span class="p">{</span>
    <span class="kr">const</span> <span class="nx">variantSlug</span> <span class="o">=</span> <span class="nx">slugify</span><span class="p">(</span><span class="nx">variant</span><span class="p">.</span><span class="nx">title</span><span class="p">.</span><span class="nx">toLowerCase</span><span class="p">());</span>
    <span class="kr">const</span> <span class="nx">preview</span> <span class="o">=</span> <span class="o">!!</span><span class="nx">variant</span><span class="p">.</span><span class="nx">preview</span> <span class="o">?</span> <span class="nx">variant</span><span class="p">.</span><span class="nx">preview</span> <span class="o">||</span> <span class="s1">&#39;default&#39;</span> <span class="o">:</span> <span class="nx">component</span><span class="p">.</span><span class="nx">preview</span> <span class="o">||</span> <span class="s1">&#39;default&#39;</span><span class="p">;</span>

    <span class="k">return</span> <span class="p">{</span>
      <span class="p">...</span><span class="nx">component</span><span class="p">,</span>
      <span class="p">...</span><span class="nx">variant</span><span class="p">,</span>
      <span class="nx">context</span><span class="o">:</span> <span class="p">{</span>
        <span class="p">...</span><span class="nx">component</span><span class="p">.</span><span class="nx">context</span><span class="p">,</span>
        <span class="p">...</span><span class="nx">variant</span><span class="p">.</span><span class="nx">context</span>
      <span class="p">},</span>
      <span class="nx">variant</span><span class="o">:</span> <span class="kc">true</span><span class="p">,</span>
      <span class="nx">preview</span><span class="p">,</span>
      <span class="nx">originalTitle</span><span class="o">:</span> <span class="nx">variant</span><span class="p">.</span><span class="nx">title</span><span class="p">,</span>
      <span class="nx">title</span><span class="o">:</span> <span class="sb">`</span><span class="si">${</span><span class="nx">component</span><span class="p">.</span><span class="nx">title</span><span class="si">}</span><span class="sb"> - </span><span class="si">${</span><span class="nx">variant</span><span class="p">.</span><span class="nx">title</span><span class="si">}</span><span class="sb">`</span><span class="p">,</span>
      <span class="nx">slug</span><span class="o">:</span> <span class="sb">`</span><span class="si">${</span><span class="nx">parentSlug</span><span class="si">}</span><span class="sb">-</span><span class="si">${</span><span class="nx">variantSlug</span><span class="si">}</span><span class="sb">`</span>
    <span class="p">}</span>
  <span class="p">});</span>
    
  <span class="c1">// Return the main component and any variants
</span><span class="c1"></span>  <span class="k">return</span> <span class="p">[</span>
    <span class="p">{</span>
      <span class="nx">slug</span><span class="o">:</span> <span class="nx">parentSlug</span><span class="p">,</span>
      <span class="p">...</span><span class="nx">component</span><span class="p">,</span>
    <span class="p">},</span>
    <span class="p">...</span><span class="nx">variants</span>
  <span class="p">]</span>
<span class="p">}</span>
</code></pre></div><p>So what we&rsquo;ve done here is gather up all the config files, and serve them as one massive global array for Eleventy to work with.</p>
<h3 id="key-file-3-components-full-pagesnjkhttpsgithubcomtryseleventy-design-systemblobmainsrccomponents-full-pagesnjk">Key file 3: <a href="https://github.com/trys/eleventy-design-system/blob/main/src/components-full-pages.njk">components-full-pages.njk</a></h3>
<p>This ingenious little template from Eleventy loops around the data we&rsquo;ve exposed in <code>components.components</code> (sorry, poor choice of variable naming there), and creates a page for every component <em>and</em> variant! It renders the component using the <code>{{ c() }}</code> macro, passing in the context, and it pops it within a preview wrapper.</p>
<div class="highlight"><pre class="chroma"><code class="language-twig" data-lang="twig"><span class="x">---
</span><span class="x">pagination:
</span><span class="x">    data: components.components
</span><span class="x">    size: 1
</span><span class="x">    alias: component
</span><span class="x">permalink: &#34;components/full/</span><span class="cp">{{</span> <span class="nv">component.slug</span> <span class="cp">}}</span><span class="x">/&#34;
</span><span class="x">title: &#39;Components&#39;
</span><span class="x">renderData:
</span><span class="x">  title: &#34;</span><span class="cp">{{</span> <span class="nv">component.title</span> <span class="cp">}}</span><span class="x">&#34;
</span><span class="x">---
</span><span class="x">
</span><span class="x"></span><span class="cp">{%</span> <span class="k">extends</span> <span class="s2">&#34;layout.njk&#34;</span> <span class="cp">%}</span><span class="x">
</span><span class="x">
</span><span class="x"></span><span class="cp">{%</span> <span class="k">block</span> <span class="nv">inner</span> <span class="cp">%}</span><span class="x">
</span><span class="x">  </span><span class="cp">{%</span> <span class="k">set</span> <span class="nv">comp</span> <span class="cp">%}</span><span class="x">
</span><span class="x">    </span><span class="cp">{{</span> <span class="nv">c</span><span class="o">(</span><span class="nv">component.name</span><span class="o">,</span> <span class="nv">component.context</span><span class="o">)</span> <span class="cp">}}</span><span class="x">
</span><span class="x">  </span><span class="cp">{%</span> <span class="k">endset</span> <span class="cp">%}</span><span class="x">
</span><span class="x">  </span><span class="cp">{%</span> <span class="k">include</span> <span class="s2">&#34;design-system/previews/preview-&#34;</span> <span class="o">+</span> <span class="nv">component.preview</span> <span class="o">+</span> <span class="s2">&#34;.njk&#34;</span> <span class="cp">%}</span><span class="x">
</span><span class="x"></span><span class="cp">{%</span> <span class="k">endblock</span> <span class="cp">%}</span><span class="x">
</span></code></pre></div><p>And that&rsquo;s it! Here&rsquo;s what it looks like:</p>
<p><img src="/images/blog/e-ds-4.jpg" alt=""></p>
<h2 id="designing-the-design-system">Designing the design system</h2>
<p>Hang on; you might be thinking, that looks pretty different to the earlier screenshots? Well yes, but that&rsquo;s for good reason. See, instead of rendering the component directly within a page in the design system, we render it on its own, and then include it via an <code>&lt;iframe&gt;</code>. This renders the component at the window size of the iframe, not at the size of the whole page. It&rsquo;s a subtle difference, but when you&rsquo;re working with viewport units or <a href="https://utopia.fyi">fluid type &amp; space</a>, it&rsquo;s an important distinction.</p>
<p>The solution is another <code>-pages.njk</code> <a href="https://github.com/trys/eleventy-design-system/blob/main/src/components-pages.njk">file</a>. It starts off in the same way as the previous template, reading in the <code>components.components</code> data and rendering a page for each component/variant. For each page, we then output some tabs for the various views we want for the component.</p>
<div class="highlight"><pre class="chroma"><code class="language-twig" data-lang="twig"><span class="c">{# components-pages.njk #}</span><span class="x">
</span><span class="x">---
</span><span class="x">pagination:
</span><span class="x">    data: components.components
</span><span class="x">    size: 1
</span><span class="x">    alias: component
</span><span class="x">permalink: &#34;components/</span><span class="cp">{{</span> <span class="nv">component.slug</span> <span class="cp">}}</span><span class="x">/&#34;
</span><span class="x">title: &#34;Components&#34;
</span><span class="x">sidebar: components
</span><span class="x">renderData:
</span><span class="x">  title: &#34;</span><span class="cp">{{</span> <span class="nv">component.title</span> <span class="cp">}}</span><span class="x">&#34;
</span><span class="x">---
</span><span class="x">
</span><span class="x"></span><span class="cp">{%</span> <span class="k">extends</span> <span class="s2">&#34;./_includes/design-system/library.njk&#34;</span> <span class="cp">%}</span><span class="x">
</span><span class="x">
</span><span class="x"></span><span class="cp">{%</span> <span class="k">from</span> <span class="s2">&#34;design-system/component.njk&#34;</span> <span class="nv">import</span> <span class="nv">code</span><span class="o">,</span> <span class="nv">context</span> <span class="cp">%}</span><span class="x">
</span><span class="x">
</span><span class="x"></span><span class="cp">{%</span> <span class="k">block</span> <span class="nv">content</span> <span class="cp">%}</span><span class="x">
</span><span class="x">  &lt;seven-minute-tabs class=&#34;ds-stretch&#34;&gt;
</span><span class="x">    &lt;ol role=&#34;tablist&#34; class=&#34;ds-tabs&#34; aria-label=&#34;What does this tab chooser do?&#34;&gt;
</span><span class="x">      &lt;li&gt;&lt;a class=&#34;ds-link&#34; href=&#34;#example-tab&#34; role=&#34;tab&#34;&gt;Demo&lt;/a&gt;&lt;/li&gt;
</span><span class="x">      &lt;li&gt;&lt;a class=&#34;ds-link&#34; href=&#34;#code-tab&#34; role=&#34;tab&#34;&gt;.html&lt;/a&gt;&lt;/li&gt;
</span><span class="x">      &lt;li&gt;&lt;a class=&#34;ds-link&#34; href=&#34;#context-tab&#34; role=&#34;tab&#34;&gt;.njk &amp; context&lt;/a&gt;&lt;/li&gt;
</span><span class="x">      &lt;li&gt;&lt;a class=&#34;ds-link&#34; href=&#34;/components/full/</span><span class="cp">{{</span> <span class="nv">component.slug</span> <span class="cp">}}</span><span class="x">&#34;&gt;Full Screen ↗&lt;/a&gt;&lt;/li&gt;
</span><span class="x">    &lt;/ol&gt;
</span><span class="x">
</span><span class="x">    &lt;div id=&#34;example-tab&#34; role=&#34;tabpanel&#34; class=&#34;ds-stretch&#34;&gt;
</span><span class="x">      &lt;div class=&#34;ds-frame ds-stretch&#34;&gt;
</span><span class="x">        &lt;iframe class=&#34;ds-stretch&#34; src=&#34;/components/full/</span><span class="cp">{{</span> <span class="nv">component.slug</span> <span class="cp">}}</span><span class="x">&#34; sandbox=&#34;allow-same-origin allow-scripts allow-forms allow-modals&#34; style=&#34;&#34; marginwidth=&#34;0&#34; marginheight=&#34;0&#34; frameborder=&#34;0&#34; vspace=&#34;0&#34; hspace=&#34;0&#34; scrolling=&#34;yes&#34;&gt;&lt;/iframe&gt;
</span><span class="x">      &lt;/div&gt;
</span><span class="x">    &lt;/div&gt;
</span><span class="x">
</span><span class="x">    &lt;div id=&#34;code-tab&#34; role=&#34;tabpanel&#34; class=&#34;ds-code ds-stretch&#34;&gt;
</span><span class="x">      </span><span class="cp">{{</span> <span class="nv">code</span><span class="o">(</span><span class="nv">component.name</span><span class="o">,</span> <span class="nv">component.context</span><span class="o">)</span> <span class="cp">}}</span><span class="x">
</span><span class="x">    &lt;/div&gt;
</span><span class="x">
</span><span class="x">    &lt;div id=&#34;context-tab&#34; role=&#34;tabpanel&#34; class=&#34;ds-code ds-stretch&#34;&gt;
</span><span class="x">      </span><span class="cp">{{</span> <span class="nv">context</span><span class="o">(</span><span class="nv">component.name</span><span class="o">,</span> <span class="nv">component.context</span><span class="o">)</span> <span class="cp">}}</span><span class="x">
</span><span class="x">    &lt;/div&gt;
</span><span class="x">  &lt;/seven-minute-tabs&gt;
</span><span class="x"></span><span class="cp">{%</span> <span class="k">endblock</span> <span class="cp">%}</span><span class="x">
</span></code></pre></div><p>In this case, I&rsquo;ve got a tab for the visual demo of the component (housing the aforementioned <code>&lt;iframe&gt;</code>), a view of the generated HTML, a print-out of the context in use for the variant, and an option to see the component full screen. But this is only the start, we can render markdown documentation, prop tables, version numbers, stability labels, links to Figma, or whatever else takes your fancy.</p>
<p>The beauty of the <code>*.config.js</code> format, is you can pop in whatever data you fancy, and it&rsquo;ll be available in this template. If your team has other requirements, you can easily adapt!</p>
<h3 id="styling-the-system">Styling the system</h3>
<p>The final part of this example is a <a href="https://github.com/trys/eleventy-design-system/blob/main/src/static/design-system/css/design-system.css">sprinkling of CSS</a> to give the design system some form, and a sidebar to render the list of components, and any other associated pages of documentation. In the past, I&rsquo;ve written about the <a href="/blog/design-foundations/">systemised foundations</a>, how to release the design system on NPM, and the decisions behind the CSS methodology, along with brand guidelines, tone of voice guides and anything else required to make this the home of digital design within a company.</p>
<p>You can get <em>really</em> meta, and use the components <em>within</em> the design system, to design the design system! If you&rsquo;ve already designed buttons &amp; tabs for your website, why generate another load of them for the system, right?!</p>
<p>If you have any questions on how this all works, or if you&rsquo;d be interested in how I&rsquo;d extend the system further, please <a href="https://www.twitter.com/trysmudford">pop me a tweet</a>.</p>
]]>
      </description>
    </item>
    
  </channel>
</rss>