<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: FrontendTeam</title>
    <description>The latest articles on DEV Community by FrontendTeam (@frontendteam).</description>
    <link>https://dev.to/frontendteam</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F828204%2Fde827056-7ba9-47ad-9f47-7830262baf51.png</url>
      <title>DEV Community: FrontendTeam</title>
      <link>https://dev.to/frontendteam</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/frontendteam"/>
    <language>en</language>
    <item>
      <title>How to develop a web component using tailwind: a modern starter kit (vite, tailwind, lit element, SCSS)</title>
      <dc:creator>FrontendTeam</dc:creator>
      <pubDate>Thu, 27 Oct 2022 07:06:25 +0000</pubDate>
      <link>https://dev.to/frontendteam/how-to-develop-a-web-component-using-tailwind-a-modern-starter-kit-vite-tailwind-lit-element-scss-455c</link>
      <guid>https://dev.to/frontendteam/how-to-develop-a-web-component-using-tailwind-a-modern-starter-kit-vite-tailwind-lit-element-scss-455c</guid>
      <description>&lt;h2&gt;
  
  
  No crap, show me the tailwind web components starter kit
&lt;/h2&gt;

&lt;p&gt;First of all, if you don't mind about the details, here is the repo of the starter kit:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/butopen/web-components-tailwind-starter-kit"&gt;https://github.com/butopen/web-components-tailwind-starter-kit&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you mind, then keep reading :-)&lt;/p&gt;

&lt;h2&gt;
  
  
  Some intro
&lt;/h2&gt;

&lt;p&gt;For the first release of Browserbot, our open source project to delegate tests for web apps, &lt;br&gt;
we want to give devs a frontend API to easily create new systems &lt;strong&gt;without having to reinvent &lt;br&gt;
the frontend parts each time&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;When developing a frontend API, you should consider:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the framework devs love: &lt;strong&gt;Angular&lt;/strong&gt;, &lt;strong&gt;React&lt;/strong&gt;, &lt;strong&gt;Vue&lt;/strong&gt;, &lt;strong&gt;Svelte&lt;/strong&gt;, ...&lt;/li&gt;
&lt;li&gt;how to make it simple to &lt;strong&gt;integrate&lt;/strong&gt; a component&lt;/li&gt;
&lt;li&gt;how to &lt;strong&gt;keep the effort to understand the component dynamics at minimum&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you plan to release your own custom frontend components and make the devs use them &lt;strong&gt;like a html tag&lt;/strong&gt;, &lt;br&gt;
web components are the way to go.&lt;/p&gt;

&lt;p&gt;Unfortunately web components are a raw tech: a technology with a lot of potential, but for some reason never upgraded in the last 6 years.&lt;/p&gt;

&lt;p&gt;And here we are: we mixed some ingredients to improve the developer experience:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;using &lt;strong&gt;lit element&lt;/strong&gt; for a higher level api over web components&lt;/li&gt;
&lt;li&gt;using &lt;strong&gt;typescript&lt;/strong&gt; to prevent stupid errors&lt;/li&gt;
&lt;li&gt;using &lt;strong&gt;scss&lt;/strong&gt; for the styles to better scale our CSS&lt;/li&gt;
&lt;li&gt;integrate &lt;strong&gt;vite&lt;/strong&gt; for a quick development process&lt;/li&gt;
&lt;li&gt;integrate &lt;strong&gt;tailwind&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this post you'll find a cool &lt;strong&gt;starter kit to develop web components&lt;/strong&gt; with all these frontend technologies inside.&lt;/p&gt;
&lt;h2&gt;
  
  
  How to write a web component with tailwind and the starter kit
&lt;/h2&gt;

&lt;p&gt;You can find the kit at this open source repo:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/butopen/web-components-tailwind-starter-kit"&gt;https://github.com/butopen/web-components-tailwind-starter-kit&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To create a new web component, here is a sample code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;customElement&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;property&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lit/decorators.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;TailwindElement&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../shared/tailwind.element&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./test.component.scss&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// #1&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;customElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;test-component&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;TestComponent&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;TailwindElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// #2&lt;/span&gt;

  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;property&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;World&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;html&lt;/span&gt;&lt;span class="s2"&gt;`
      &amp;lt;p&amp;gt;
        Hello,
        &amp;lt;b&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/b&amp;gt;
        !
      &amp;lt;/p&amp;gt;
      &amp;lt;button class="bg-blue-200 text-yellow-200 p-2 rounded-full text-2xl"&amp;gt;Hello world!&amp;lt;/button&amp;gt;
    `&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is based on the &lt;a href="https://lit.dev/docs/"&gt;lit element&lt;/a&gt; technology: if you wrote a lit component before, you'll find it familiar.&lt;/p&gt;

&lt;p&gt;The only difference to a standard &lt;em&gt;LitElement&lt;/em&gt; is that:&lt;br&gt;
1) You must import your styles from a separate file. And this is good for two reasons:&lt;br&gt;
    - it separates the CSS from the logic&lt;br&gt;
    - you can decide to use CSS or SCSS&lt;br&gt;
2) the component class extends a &lt;em&gt;TailwindElement&lt;/em&gt; rather than a LitElement&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;TailwindElement&lt;/em&gt; extends the &lt;em&gt;LitElmement&lt;/em&gt; (see below) and adds the logic to integrate tailwind and your styles.&lt;/p&gt;

&lt;h2&gt;
  
  
  Get started with the starter kit
&lt;/h2&gt;

&lt;p&gt;To run the project:&lt;br&gt;
1) &lt;code&gt;pnpm install&lt;/code&gt; (only the first time)&lt;br&gt;
2) &lt;code&gt;pnpm start&lt;/code&gt; to run the server&lt;br&gt;
3) to develop the library, run &lt;code&gt;pnpm build&lt;/code&gt; and copy the static assets where you need them.&lt;/p&gt;

&lt;p&gt;You may clone the repo (&lt;a href="https://github.com/butopen/web-components-tailwind-starter-kit"&gt;https://github.com/butopen/web-components-tailwind-starter-kit&lt;/a&gt;) and start developing your components by looking at the &lt;em&gt;test.component&lt;/em&gt; as reference.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use the Tailwind class in your own code without the starter kit
&lt;/h2&gt;

&lt;p&gt;As an alternative, and if you like to have control over every piece, do the following:&lt;/p&gt;

&lt;p&gt;1) copy the files in the shared folder:&lt;br&gt;
    - &lt;em&gt;tailwind.element.ts&lt;/em&gt; extends LitElement by adding the tailwind support&lt;br&gt;
    - &lt;em&gt;tailwind.global.css&lt;/em&gt; includes tha Tailwind base classes into each component&lt;br&gt;
    - &lt;em&gt;globals.d.ts&lt;/em&gt; is used to avoid TypeScript errors whe nimporting CSS/Scss files in typescript files&lt;br&gt;
2) copy the &lt;em&gt;package.json&lt;/em&gt; or just its devDependencies into your own &lt;em&gt;package.json&lt;/em&gt;  (&lt;strong&gt;this starter kit has no dependencies&lt;/strong&gt;)&lt;br&gt;
3) copy &lt;em&gt;postcss.config.js&lt;/em&gt;, &lt;em&gt;tailwind.config.js&lt;/em&gt; and &lt;em&gt;tsconfig.js&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That's all.&lt;/p&gt;

&lt;h2&gt;
  
  
  Show me the pieces
&lt;/h2&gt;

&lt;p&gt;If you want to understand how it works:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the &lt;strong&gt;package.json&lt;/strong&gt; integrates these technologies:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"autoprefixer"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^10.4.12"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"postcss"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^8.4.18"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"lit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^2.4.0"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"tailwindcss"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^3.2.0"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"typescript"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^4.8.4"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"vite"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^3.1.8"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"sass"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^1.55.0"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;vite&lt;/strong&gt; does almost all the work&lt;/li&gt;
&lt;li&gt;to integrate tailwind, the most important file is in &lt;em&gt;src/shared/tailwind.element.ts&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;LitElement&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;unsafeCSS&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;lit&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./tailwind.global.css&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tailwindElement&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;unsafeCSS&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;TailwindElement&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;LitElement&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

        &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="nx"&gt;styles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;tailwindElement&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;unsafeCSS&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;)];&lt;/span&gt;

    &lt;span class="p"&gt;};&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It extends a &lt;em&gt;LitElement&lt;/em&gt; class at runtime and adds the tailwind support.&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;style&lt;/em&gt; variable comes from your component, where it is imported from an external CSS (or SCSS) file.&lt;/p&gt;

&lt;p&gt;Then it is combined with the default tailwind classes.&lt;/p&gt;

&lt;p&gt;If you add more components, the common parts are reused.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who uses it?
&lt;/h2&gt;

&lt;p&gt;We developed this starter kit to implement a web session player for our open source SaaS &lt;a href="https://browserbot.io/"&gt;browserbot&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you want to contribute or share soem thoughts, just get in touch with us.&lt;/p&gt;

&lt;p&gt;Enjoy.&lt;/p&gt;

&lt;h2&gt;
  
  
  Some more details about web components
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What are web components
&lt;/h3&gt;

&lt;p&gt;Web components are an html technology to share common fronted logic/ui without worrying about the framework &lt;br&gt;
you're using. The goal is to create your own custom HTML tags.&lt;/p&gt;

&lt;p&gt;So you end up having a &lt;code&gt;&amp;lt;maps&amp;gt;&lt;/code&gt; component, or a &lt;code&gt;&amp;lt;pdf-viewer&amp;gt;&lt;/code&gt; component. Just embed a JS script in the page, &lt;br&gt;
and start using that tag as if it was a native one. &lt;/p&gt;

&lt;p&gt;Is it easy to develop a web component? Not much. Our frontend team made it easier. &lt;/p&gt;

&lt;h3&gt;
  
  
  Why integrating tailwind in a webcomponent is difficult
&lt;/h3&gt;

&lt;p&gt;Tailwind is a wonderful technology to speed up the css part of the frontend development. And wehen I say speed up... trust me: we're talking about an order of magnitude less time to reach the desired aspect of our ui.&lt;br&gt;
Because of how tailwind works, web components do not play well with tailwind since they do not see css classes from outside.&lt;/p&gt;

&lt;p&gt;Web components have this concept of total isolation: they will not tell you how things work inside. Just have fate and trust it.&lt;/p&gt;

&lt;p&gt;So in order to support tailwind, we need to find a way to inject the classes inside.&lt;/p&gt;

&lt;p&gt;Spoiler: we found it and we kept it so simple that you'll not even notice the difference to pure lit elements.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to keep the developer experience high when integrating web components and tailwind
&lt;/h3&gt;

&lt;p&gt;Devs writing web components rarely write them using the custom elements raw technology.&lt;/p&gt;

&lt;p&gt;Some use Stencil, some use Lit, some use Svelte.&lt;/p&gt;

&lt;p&gt;For this project we decided to go for Lit.&lt;/p&gt;

&lt;p&gt;Writing a web component in Lit is like writing a typescript class plus some decorators.&lt;/p&gt;

&lt;p&gt;That experience should not change: integrating tailwind should not break this behavior.&lt;/p&gt;

&lt;h2&gt;
  
  
  Well done!
&lt;/h2&gt;

&lt;p&gt;That's all. For more posts remember to subscribe to our newsletter :-)&lt;/p&gt;

</description>
      <category>tailwindcss</category>
      <category>vite</category>
      <category>webcomponents</category>
    </item>
    <item>
      <title>How to handle input keyup events after the user stops typing - Svelte actions and debouncing</title>
      <dc:creator>FrontendTeam</dc:creator>
      <pubDate>Fri, 29 Apr 2022 13:36:13 +0000</pubDate>
      <link>https://dev.to/frontendteam/how-to-handle-input-keyup-events-after-the-user-stops-typing-svelte-actions-and-debouncing-47cn</link>
      <guid>https://dev.to/frontendteam/how-to-handle-input-keyup-events-after-the-user-stops-typing-svelte-actions-and-debouncing-47cn</guid>
      <description>&lt;h2&gt;
  
  
  Why we should implement a custom event in Svelte?
&lt;/h2&gt;

&lt;h4&gt;
  
  
  The problem
&lt;/h4&gt;

&lt;p&gt;I already know that when you need to handle some validation on text inputs, then you do it on keyup events.&lt;/p&gt;

&lt;p&gt;And that is ok. Or not? &lt;/p&gt;

&lt;p&gt;Actually, if the user types fast, you would like to call a function only when he/she stops typing.&lt;/p&gt;

&lt;p&gt;So you start to think about &lt;em&gt;setTimeout&lt;/em&gt; or &lt;em&gt;setInterval&lt;/em&gt; strategies to implement.&lt;/p&gt;

&lt;p&gt;Well, you should know that there is a more abstract technique, called &lt;strong&gt;debounce&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;But if you're using svelte, you should not implement debounce everytime you need this behaviour: &lt;strong&gt;svelte &lt;em&gt;actions&lt;/em&gt; let you extend any HTML element with common logic&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;And in this post we will see how to add a custom event to the input, to handle the use case above.&lt;/p&gt;

&lt;p&gt;But let's proceed step by step.&lt;/p&gt;

&lt;h4&gt;
  
  
  Input Validation
&lt;/h4&gt;

&lt;p&gt;When working with inputs, &lt;strong&gt;validation&lt;/strong&gt; is mandatory: it is necessary to perform some checks when the user stops typing, and not every time a key is pressed.&lt;/p&gt;

&lt;p&gt;We want to have a tool to attach this behaviour easily to our inputs everytime.&lt;/p&gt;

&lt;h4&gt;
  
  
  Autocomplete components
&lt;/h4&gt;

&lt;p&gt;The same behavior is also useful in &lt;strong&gt;autocomplete components&lt;/strong&gt;, where an action must be performed to decide which elements to show: if I execute it at each keypress I could soon block the system, especially if the action involves an &lt;strong&gt;asynchronous call&lt;/strong&gt; to an endpoint. &lt;/p&gt;

&lt;p&gt;The solution is to perform the action only when the user stops typing.&lt;/p&gt;

&lt;p&gt;In this frontend pill we will see just how to elegantly implement this functionality using &lt;strong&gt;Svelte actions&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  How the developer will consume a custom Svelte event
&lt;/h2&gt;

&lt;p&gt;As always, before implementing the "on stop typing" custom event, let's imagine the easiest way for the developer to consume it.&lt;/p&gt;

&lt;p&gt;In Svelte, the syntax to add event listener to an input tag is as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt;
      &lt;span class="na"&gt;on:stopTyping=&lt;/span&gt;&lt;span class="s"&gt;{onStopTyping}&lt;/span&gt;
      &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt;
      &lt;span class="na"&gt;bind:value=&lt;/span&gt;&lt;span class="s"&gt;{name}&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;em&gt;stopTyping&lt;/em&gt; event does not exist, so we need to implement it. Using an action:&lt;/p&gt;

&lt;p&gt;The result will be as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt;
      &lt;span class="na"&gt;use:stopTyping&lt;/span&gt;
      &lt;span class="na"&gt;on:stopTyping=&lt;/span&gt;&lt;span class="s"&gt;{onStopTyping}&lt;/span&gt;
      &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt;
      &lt;span class="na"&gt;bind:value=&lt;/span&gt;&lt;span class="s"&gt;{name}&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's then see how to implement the &lt;em&gt;stopTyping&lt;/em&gt; action. &lt;/p&gt;

&lt;h2&gt;
  
  
  How to implement a custom event in Svelte to reuse on any HTML element
&lt;/h2&gt;

&lt;p&gt;In Svelte there is the concept of &lt;em&gt;actions&lt;/em&gt;, a syntax keyword to &lt;strong&gt;extend native HTML elements with new functionality&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;To use an action, we add an attribute, &lt;em&gt;use&lt;/em&gt;, and the function that will take care of the custom behavior (&lt;em&gt;on stop typing&lt;/em&gt; in our case).&lt;/p&gt;

&lt;p&gt;&lt;b&gt;NOTE&lt;/b&gt;&lt;br&gt;
&lt;br&gt;&lt;br&gt;
Before explaining how this works, just one important note: actions only work on native HTML tags and not on Svelte components. At least for now.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to apply the &lt;em&gt;use&lt;/em&gt; directive in Svelte
&lt;/h3&gt;

&lt;p&gt;The Svelte &lt;em&gt;use&lt;/em&gt; directive is a kind of attribute on a HTML element that specifies a function.&lt;/p&gt;

&lt;p&gt;The function, also called action in this context, takes the referring node as input.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;aCustomAction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// some logic&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;destroy&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="c1"&gt;// (optional) some logic on destroy &lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The function returns an object with one method: &lt;em&gt;destroy&lt;/em&gt;. It is optional, and it is called when the component is destroyed.&lt;/p&gt;

&lt;p&gt;In Svelte an action can also add some behaviour based on some &lt;strong&gt;extra parameters&lt;/strong&gt; that we can pass to the function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;aCustomAction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;param1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// some logic&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;update&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="c1"&gt;// (optional) some logic executed when param1 gets updated &lt;/span&gt;
        &lt;span class="nx"&gt;destroy&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;em&gt;update&lt;/em&gt; method will be executed when the param1 changes. It is optional.&lt;/p&gt;

&lt;h2&gt;
  
  
  The &lt;em&gt;onStopTyping&lt;/em&gt; action
&lt;/h2&gt;

&lt;p&gt;In this pill we will see how to implement the stop typing action. &lt;/p&gt;

&lt;p&gt;Two key points:&lt;br&gt;
1) it has to be &lt;strong&gt;used on HTML inputs&lt;/strong&gt;&lt;br&gt;
2) it will &lt;strong&gt;fire an event only when the user stops typing&lt;/strong&gt; on that input&lt;/p&gt;

&lt;p&gt;The function is simple:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;stopTyping&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleKeyup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;debounce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;KeyboardEvent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// (1) the debounce logic&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// (2) restrict the event to the only referring node &lt;/span&gt;
            &lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dispatchEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;CustomEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;stopTyping&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// (3) fire the event&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// (4) add a generic keyup event&lt;/span&gt;
    &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;keyup&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;handleKeyup&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;destroy&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// (5) cleanup on destroy&lt;/span&gt;
            &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;removeEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;keyup&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;handleKeyup&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's go step by step.&lt;/p&gt;

&lt;p&gt;First of all, we register the &lt;code&gt;keyup&lt;/code&gt; event &lt;em&gt;(4)&lt;/em&gt; (and cleanup it on destroy to avoid memory leaks at &lt;em&gt;(5)&lt;/em&gt; ).&lt;/p&gt;

&lt;p&gt;The interesting parts are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;fire the custom event at &lt;em&gt;(3)&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;make sure the stopTyping event is fired only once when the user does not write for half a second (at &lt;em&gt;(1)&lt;/em&gt;) &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To make sure that a function is only runned once after the user stops typing, we make use of the &lt;em&gt;debounce function&lt;/em&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  How does the debounce function work?
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;debounce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;inputFunction&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;timeToWaitBeforeFiringInMs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;timer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;clearTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;timer&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;timer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;inputFunction&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;apply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nx"&gt;timeToWaitBeforeFiringInMs&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Above, you can find the implementation of the &lt;em&gt;dobounce function&lt;/em&gt; in javascript.&lt;/p&gt;

&lt;p&gt;It is used to &lt;strong&gt;execute a function only once&lt;/strong&gt; if called multiple times within a constrained time interval.  &lt;/p&gt;

&lt;p&gt;The &lt;em&gt;debounce function&lt;/em&gt; takes a function as argument and returns a new function (that will replace the original one we passed as input).&lt;/p&gt;

&lt;p&gt;Other use cases of the debounce function:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;on mouse move, if we want to know when the user stops moving the mouse&lt;/li&gt;
&lt;li&gt;on multiple mouse click, to react only after the last click&lt;/li&gt;
&lt;li&gt;when using websockets, to execute an action only after a burst of packets arrive&lt;/li&gt;
&lt;li&gt;when collecting multiple information packs, to pass to them to the backend only once every X seconds&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How to consume the onStopTyping event action in Svelte
&lt;/h2&gt;

&lt;p&gt;To use the function above on our inputs, we just need to import it in our Svelte component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;
&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
    &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;stopTyping&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../shared/on-stop-typing.event&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;thefrontendteam&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;onStopTyping&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// do something with name&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt;
      &lt;span class="na"&gt;use:stopTyping&lt;/span&gt;
      &lt;span class="na"&gt;on:stopTyping=&lt;/span&gt;&lt;span class="s"&gt;{onStopTyping}&lt;/span&gt;
      &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt;
      &lt;span class="na"&gt;bind:value=&lt;/span&gt;&lt;span class="s"&gt;{name}&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Well done!
&lt;/h2&gt;

&lt;p&gt;That's all. For more pills remember to subscribe to our newsletter :-)&lt;/p&gt;

</description>
      <category>svelte</category>
      <category>keyup</category>
      <category>event</category>
    </item>
    <item>
      <title>How to create a stepper atomic component using pure css and tailwind</title>
      <dc:creator>FrontendTeam</dc:creator>
      <pubDate>Tue, 19 Apr 2022 17:05:49 +0000</pubDate>
      <link>https://dev.to/frontendteam/how-to-create-a-stepper-atomic-component-using-pure-css-and-tailwind-1o3e</link>
      <guid>https://dev.to/frontendteam/how-to-create-a-stepper-atomic-component-using-pure-css-and-tailwind-1o3e</guid>
      <description>&lt;p&gt;In this &lt;a href="https://thefrontendteam.com/pills/"&gt;frontend pill&lt;/a&gt; we are going to create a &lt;br&gt;
stepper atomic component in pure css. &lt;/p&gt;

&lt;p&gt;We needed it in our design system to complete the onboard wizard at ssonext.com (WIP).&lt;/p&gt;

&lt;p&gt;This would be the result:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8Vk5zxzH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thefrontendteam.com/pills/stepper-pure-css-atomic-component-tailwind/stepper-component-butopen-design-system.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8Vk5zxzH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thefrontendteam.com/pills/stepper-pure-css-atomic-component-tailwind/stepper-component-butopen-design-system.png" alt="The Stepper component in the Butopen Design System" width="469" height="399"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Before writing the code (that is few lines, really) let's imagine the best way for the &lt;br&gt;
developer to consume this component.&lt;/p&gt;
&lt;h2&gt;
  
  
  What is the best way to consume a stepper atomic component in pure css
&lt;/h2&gt;

&lt;p&gt;Since the componet is in pure CSS, the developer expects to have some classes &lt;br&gt;
to create the component.&lt;/p&gt;

&lt;p&gt;There are two conditions that we must respect to maximize the developer experience:&lt;br&gt;
1) Minimize the number of tags necessary to create the stepper;&lt;br&gt;
2) Use only CSS: no javscript at all&lt;/p&gt;

&lt;p&gt;When making a stepper, the only thing that will be present is the stepper title:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;Step 1: do something&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;Step 2: almost done&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;Step 3: done!&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then we have to decide how to indicate the &lt;em&gt;state&lt;/em&gt; of the step: "&lt;strong&gt;&lt;em&gt;to do&lt;/em&gt;&lt;/strong&gt;"? "&lt;em&gt;&lt;strong&gt;active&lt;/strong&gt;&lt;/em&gt;"? "&lt;em&gt;&lt;strong&gt;done&lt;/strong&gt;&lt;/em&gt;"?&lt;/p&gt;

&lt;p&gt;Each state could be a class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"todo"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Step 1: do something&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"active"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Step 2: almost done&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"done"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Step 3: done!&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The problem with the code above is that &lt;em&gt;&lt;strong&gt;active&lt;/strong&gt;&lt;/em&gt; is a very common CSS class, so it is better &lt;br&gt;
to be more specific and use classes with detailed names. &lt;/p&gt;

&lt;p&gt;So we end up with the following classes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;'bo-step-done'&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        STEP 1
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;'bo-step-active'&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        STEP 2
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;'bo-step-todo'&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        STEP 3
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Simple and compact. Now it's time to translate the code above to this css atomic component:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8Vk5zxzH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thefrontendteam.com/pills/stepper-pure-css-atomic-component-tailwind/stepper-component-butopen-design-system.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8Vk5zxzH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thefrontendteam.com/pills/stepper-pure-css-atomic-component-tailwind/stepper-component-butopen-design-system.png" alt="The Stepper component in the Butopen Design System" width="469" height="399"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  How to implement a stepper component in SCSS + TailwindCSS
&lt;/h2&gt;

&lt;p&gt;To implement our stepper atomic component, remember that we want to use &lt;strong&gt;pure css&lt;/strong&gt;: so &lt;strong&gt;no javascript&lt;/strong&gt; at all.&lt;/p&gt;

&lt;p&gt;The developer should also be able to implement the stepper using only &lt;strong&gt;one html tag&lt;/strong&gt; (Developer experience: keep the number of tags to a minimum possible).&lt;/p&gt;
&lt;h3&gt;
  
  
  Drawing the step circle
&lt;/h3&gt;

&lt;p&gt;To draw the circle, we use the following tailwind classes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@apply&lt;/span&gt; &lt;span class="n"&gt;h-6&lt;/span&gt; &lt;span class="n"&gt;w-6&lt;/span&gt; &lt;span class="n"&gt;rounded-full&lt;/span&gt; &lt;span class="n"&gt;border-2&lt;/span&gt; &lt;span class="n"&gt;border-bop&lt;/span&gt; &lt;span class="n"&gt;bg-bop&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;rounded-full&lt;/code&gt; combined with &lt;code&gt;bg-bop&lt;/code&gt; will make a circle shape using the main color (the &lt;code&gt;-bop&lt;/code&gt; color... see the note below).&lt;/p&gt;

&lt;p&gt;Why a &lt;code&gt;border-2&lt;/code&gt;? Because we will customize it later for the specific state.&lt;/p&gt;




&lt;p&gt;&lt;b&gt;Note&lt;/b&gt; &lt;br&gt;&lt;br&gt;
The &lt;code&gt;-bop&lt;/code&gt; color in &lt;code&gt;bg-bop&lt;/code&gt; and &lt;code&gt;border-bop&lt;/code&gt; refers to the primary butopen color. You can use &lt;br&gt;
&lt;code&gt;-red-600&lt;/code&gt; or &lt;code&gt;-green-500&lt;/code&gt;... it's your choice. &lt;br&gt;
&lt;br&gt;&lt;br&gt;
The good thing of the ButOpen primary color is that &lt;br&gt;
it is a CSS 3 variable so the color can be customized at runtime using a root style (1) or using javascript (2)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kDihcwO3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thefrontendteam.com/pills/stepper-pure-css-atomic-component-tailwind/img.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kDihcwO3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thefrontendteam.com/pills/stepper-pure-css-atomic-component-tailwind/img.png" alt="customize css color tailwind butopen design system" width="880" height="335"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;The empty circle will extend the filled circle, but using the &lt;code&gt;@apply bg-white&lt;/code&gt; class. &lt;/p&gt;

&lt;p&gt;We will see how in a moment.&lt;/p&gt;

&lt;h4&gt;
  
  
  Circle position
&lt;/h4&gt;

&lt;p&gt;The circle will be positioned at the center of the step height, so we'll add these tailwind classes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;flex&lt;/span&gt; &lt;span class="nt"&gt;items-center&lt;/span&gt; &lt;span class="nt"&gt;justify-center&lt;/span&gt; &lt;span class="nt"&gt;absolute&lt;/span&gt; &lt;span class="nt"&gt;top-0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Circle icons
&lt;/h4&gt;

&lt;p&gt;Since we want to have pure css, we had three choices for the icons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;base64 image data url in css (e.g. using this online tool: &lt;a href="https://www.cssportal.com/image-to-data/"&gt;https://www.cssportal.com/image-to-data/&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;SVG data url in css (e.g. using this online tool: &lt;a href="https://yoksel.github.io/url-encoder/"&gt;https://yoksel.github.io/url-encoder/&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;UTF8 icons (e.g. here: &lt;a href="https://www.utf8icons.com/"&gt;https://www.utf8icons.com/&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We are lucky enough to have these icons available in UTF-8:&lt;/p&gt;

&lt;p&gt;The check icon in pure CSS: &lt;strong&gt;✓&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The bullet icon in pure CSS: &lt;strong&gt;•&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Drawing the step vertical line
&lt;/h3&gt;

&lt;p&gt;The vertical line will be an empty element with a border. &lt;/p&gt;

&lt;p&gt;We can use the following tailwind classes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@apply&lt;/span&gt; &lt;span class="nb"&gt;block&lt;/span&gt; &lt;span class="n"&gt;h-full&lt;/span&gt; &lt;span class="n"&gt;w-0&lt;/span&gt;&lt;span class="m"&gt;.5&lt;/span&gt; &lt;span class="n"&gt;border&lt;/span&gt; &lt;span class="n"&gt;border-gray-300&lt;/span&gt; &lt;span class="nb"&gt;absolute&lt;/span&gt; &lt;span class="n"&gt;top-0&lt;/span&gt; &lt;span class="n"&gt;-left-4&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;block h-full w-0.5 border border-gray-300&lt;/code&gt; classes will draw the vertical line.&lt;/p&gt;

&lt;p&gt;The last three classes are used to position the element relative to the parent.&lt;/p&gt;

&lt;h3&gt;
  
  
  Let the developer use a single &lt;code&gt;div&lt;/code&gt; tag to implement the step
&lt;/h3&gt;

&lt;p&gt;We want the developer to implement the stepper using:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a &lt;em&gt;single tag&lt;/em&gt; &lt;/li&gt;
&lt;li&gt;and a &lt;em&gt;single class&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So we use the &lt;em&gt;after&lt;/em&gt; and &lt;em&gt;before&lt;/em&gt; CSS pseudo classes.&lt;/p&gt;

&lt;p&gt;The CSS (SCSS syntax) of the base step is as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scss"&gt;&lt;code&gt;&lt;span class="nc"&gt;._bo-step&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// the text&lt;/span&gt;
  &lt;span class="k"&gt;@apply&lt;/span&gt; &lt;span class="nt"&gt;relative&lt;/span&gt; &lt;span class="nt"&gt;ml-8&lt;/span&gt; &lt;span class="nt"&gt;pb-8&lt;/span&gt; &lt;span class="nt"&gt;pt-0&lt;/span&gt;&lt;span class="nc"&gt;.5&lt;/span&gt; &lt;span class="nt"&gt;pl-2&lt;/span&gt; &lt;span class="nt"&gt;text-sm&lt;/span&gt; &lt;span class="nt"&gt;font-bold&lt;/span&gt; &lt;span class="nt"&gt;text-gray-500&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// the vertical line&lt;/span&gt;
  &lt;span class="k"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nd"&gt;:before&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;@apply&lt;/span&gt; &lt;span class="nt"&gt;absolute&lt;/span&gt; &lt;span class="nt"&gt;top-0&lt;/span&gt; &lt;span class="nt"&gt;-left-4&lt;/span&gt; &lt;span class="nt"&gt;block&lt;/span&gt; &lt;span class="nt"&gt;h-full&lt;/span&gt; &lt;span class="nt"&gt;w-0&lt;/span&gt;&lt;span class="nc"&gt;.5&lt;/span&gt; &lt;span class="nt"&gt;border&lt;/span&gt; &lt;span class="nt"&gt;border-gray-300&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// the icon&lt;/span&gt;
  &lt;span class="k"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nd"&gt;:after&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;@apply&lt;/span&gt; &lt;span class="nt"&gt;absolute&lt;/span&gt; &lt;span class="nt"&gt;top-0&lt;/span&gt; &lt;span class="nt"&gt;flex&lt;/span&gt; &lt;span class="nt"&gt;h-6&lt;/span&gt; &lt;span class="nt"&gt;w-6&lt;/span&gt; &lt;span class="nt"&gt;items-center&lt;/span&gt; &lt;span class="nt"&gt;justify-center&lt;/span&gt; &lt;span class="nt"&gt;rounded-full&lt;/span&gt; &lt;span class="nt"&gt;border-2&lt;/span&gt; &lt;span class="nt"&gt;border-bop&lt;/span&gt; &lt;span class="nt"&gt;bg-bop&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;-1&lt;/span&gt;&lt;span class="mi"&gt;.7rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will be our base CSS structure for the &lt;em&gt;step&lt;/em&gt; pure CSS atomic component. &lt;/p&gt;

&lt;p&gt;Note that I added a small underscore for the name of the class (&lt;code&gt;_bo-step&lt;/code&gt;) since &lt;strong&gt;I do not want the developer to use this class directly&lt;/strong&gt;. &lt;br&gt;
It's like a &lt;em&gt;"private" class&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Having this base structure, we can easily define each &lt;em&gt;step status&lt;/em&gt; by customizing some parts:&lt;/p&gt;

&lt;p&gt;Look at the result:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8Vk5zxzH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thefrontendteam.com/pills/stepper-pure-css-atomic-component-tailwind/stepper-component-butopen-design-system.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8Vk5zxzH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thefrontendteam.com/pills/stepper-pure-css-atomic-component-tailwind/stepper-component-butopen-design-system.png" alt="The Stepper component in the Butopen Design System" width="469" height="399"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;DONE&lt;/strong&gt; step will have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a vertical line using the main color&lt;/li&gt;
&lt;li&gt;a check icon (white color)&lt;/li&gt;
&lt;li&gt;a filled circle (main color)
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scss"&gt;&lt;code&gt;
&lt;span class="nc"&gt;.bo-step-done&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;@extend&lt;/span&gt; &lt;span class="nc"&gt;._bo-step&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nd"&gt;:before&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;@apply&lt;/span&gt; &lt;span class="nt"&gt;border-bop&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nd"&gt;:after&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"✓"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;@apply&lt;/span&gt; &lt;span class="nt"&gt;text-sm&lt;/span&gt; &lt;span class="nt"&gt;font-black&lt;/span&gt; &lt;span class="nt"&gt;text-white&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With &lt;code&gt;@extend&lt;/code&gt; we extend the base CSS structure. &lt;/p&gt;

&lt;p&gt;Then we override the border color (from gray to primary) by specifying the new tailwind classes in the &lt;code&gt;&amp;amp;:before&lt;/code&gt; section.&lt;/p&gt;

&lt;p&gt;The same in the &lt;code&gt;&amp;amp;:after&lt;/code&gt; section: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;content: "✓"&lt;/code&gt; for check icon&lt;/li&gt;
&lt;li&gt;some tailwind font rules to make the check icon white (remember it is a UTF8 text). &lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;The &lt;strong&gt;ACTIVE&lt;/strong&gt; and &lt;strong&gt;TODO&lt;/strong&gt; steps are similar.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;ACTIVE&lt;/strong&gt; step will have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a vertical line using the main color&lt;/li&gt;
&lt;li&gt;a bullet icon (main color)&lt;/li&gt;
&lt;li&gt;a white circle with a main color border
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scss"&gt;&lt;code&gt;&lt;span class="nc"&gt;.bo-step-active&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;@extend&lt;/span&gt; &lt;span class="nc"&gt;._bo-step&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;@apply&lt;/span&gt; &lt;span class="nt"&gt;text-bop&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nd"&gt;:after&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"•"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;@apply&lt;/span&gt; &lt;span class="nt"&gt;bg-white&lt;/span&gt; &lt;span class="nt"&gt;pb-1&lt;/span&gt; &lt;span class="nt"&gt;text-lg&lt;/span&gt; &lt;span class="nt"&gt;font-black&lt;/span&gt; &lt;span class="nt"&gt;text-bop&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;strong&gt;TODO&lt;/strong&gt; step will have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a gray vertical line&lt;/li&gt;
&lt;li&gt;no icon&lt;/li&gt;
&lt;li&gt;a white background and a gray border for the circle
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight scss"&gt;&lt;code&gt;&lt;span class="nc"&gt;.bo-step-todo&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;@extend&lt;/span&gt; &lt;span class="nc"&gt;._bo-step&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nd"&gt;:after&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;@apply&lt;/span&gt; &lt;span class="nt"&gt;rounded-full&lt;/span&gt; &lt;span class="nt"&gt;border-gray-300&lt;/span&gt; &lt;span class="nt"&gt;bg-white&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nd"&gt;:last-child&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nd"&gt;:before&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;@apply&lt;/span&gt; &lt;span class="nt"&gt;border-transparent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Complete ButOpen Design System
&lt;/h2&gt;

&lt;p&gt;This component is now part of the &lt;em&gt;ButOpen Design System&lt;/em&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;it's &lt;strong&gt;open source&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;it's made in &lt;strong&gt;pure css&lt;/strong&gt; (SCSS+TailwindCSS)
&lt;/li&gt;
&lt;li&gt;it's easy to consume and integrate into any frontend framework&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can find it here: &lt;a href="https://github.com/butopen/butopen-design-system"&gt;https://github.com/butopen/butopen-design-system&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>css</category>
      <category>opensource</category>
      <category>design</category>
    </item>
    <item>
      <title>How to create a new component in svelte using a template - svelte component scaffolding and boilerplate</title>
      <dc:creator>FrontendTeam</dc:creator>
      <pubDate>Tue, 12 Apr 2022 17:07:19 +0000</pubDate>
      <link>https://dev.to/frontendteam/how-to-create-a-new-component-in-svelte-using-a-template-svelte-component-scaffolding-and-boilerplate-2el</link>
      <guid>https://dev.to/frontendteam/how-to-create-a-new-component-in-svelte-using-a-template-svelte-component-scaffolding-and-boilerplate-2el</guid>
      <description>&lt;h2&gt;
  
  
  Why
&lt;/h2&gt;

&lt;p&gt;Creating new components is probably one of the things you do most in svelte.&lt;/p&gt;

&lt;p&gt;And to maximize the developer experience, you must automate every task that you do often.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It's not just to save time, but also to avoid repetitive tasks that annoy and distract us developer.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Here we'll learn hot to create your customized component template once and use it everytime.&lt;/p&gt;

&lt;h2&gt;
  
  
  How
&lt;/h2&gt;

&lt;p&gt;So imagine to write this command:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npx t6e $name.svelte src/components name=my-component&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;and get the component as you would have written it, ready into the &lt;code&gt;src/component&lt;/code&gt; folder.&lt;/p&gt;

&lt;p&gt;It's easy:&lt;/p&gt;

&lt;p&gt;1) Create the template. Here you can find the one we use into our &lt;em&gt;svelte&lt;/em&gt; projects:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;script lang="ts"&amp;gt;
  import { createEventDispatcher } from 'svelte';
  import { writable } from 'svelte/store';
  const dispatch = createEventDispatcher();

  const store = writable({
    hello: ""
  });


&amp;lt;/script&amp;gt;

&amp;lt;div class="$name"&amp;gt;
    {$store.hello}
&amp;lt;/div&amp;gt;

&amp;lt;style lang="scss"&amp;gt;
    .$name {
        @apply block
    }
&amp;lt;/style&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;2) name it &lt;code&gt;$name.svelte&lt;/code&gt; and put it in a &lt;code&gt;templates&lt;/code&gt; folder&lt;/p&gt;

&lt;p&gt;3) to create your component, run &lt;/p&gt;

&lt;p&gt;&lt;code&gt;npx t6e templates/$name.svelte src/components name=counter&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;4) you're done. A new fresh component was save in the &lt;code&gt;src/components/counter.svelte&lt;/code&gt;: &lt;br&gt;
&lt;code&gt;$name&lt;/code&gt; was replaced by &lt;code&gt;counter&lt;/code&gt; in both the &lt;strong&gt;file name&lt;/strong&gt; and the &lt;strong&gt;file content&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;You can now re-use that template for all your components, saving hours every month.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is t6e?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;T6e&lt;/strong&gt; is an open source scaffolder, boilerplater or put simply it lets you &lt;br&gt;
create any file based on your custom templates.&lt;/p&gt;

&lt;p&gt;We created a template for svelte above, but you can create any template and reuse it as you like with this &lt;br&gt;
small open-source tool provided by us at &lt;a href="https://butopen.com"&gt;butopen&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can find &lt;strong&gt;t6e&lt;/strong&gt; here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/butopen/t6e"&gt;https://github.com/butopen/t6e&lt;/a&gt;&lt;/p&gt;

</description>
      <category>frontend</category>
      <category>tailwindcss</category>
      <category>svelte</category>
      <category>dx</category>
    </item>
    <item>
      <title>Why your frontend team is wasting hours every day without a design system</title>
      <dc:creator>FrontendTeam</dc:creator>
      <pubDate>Wed, 16 Mar 2022 15:22:43 +0000</pubDate>
      <link>https://dev.to/frontendteam/why-your-frontend-team-is-wasting-hours-every-day-without-a-design-system-195c</link>
      <guid>https://dev.to/frontendteam/why-your-frontend-team-is-wasting-hours-every-day-without-a-design-system-195c</guid>
      <description>&lt;h2&gt;
  
  
  A frontend team without a design system
&lt;/h2&gt;

&lt;p&gt;We develop frontend systems every day. We know it well: if you have to remember how to style a button, you will miss something: padding, margin, colors, background, font... &lt;strong&gt;you cannot remember all the CSS rules&lt;/strong&gt;, I know.&lt;/p&gt;

&lt;p&gt;And I assure you: many companies work this way. You have to play “treasure hunt” and look for the CSS rules of the button hidden somewhere in the code.&lt;/p&gt;

&lt;p&gt;We are talking about the old “copy/paste”, and it is scary even to write about it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The button monsters list
&lt;/h2&gt;

&lt;p&gt;Do you know what happens with &lt;em&gt;word of mouth&lt;/em&gt;? At each step, a few pieces are lost or a few sentences are misreported.&lt;/p&gt;

&lt;p&gt;Without a design system, we have the same problem: each time you miss something new &lt;strong&gt;design monsters emerge&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;the link button monster&lt;/strong&gt;, where there was a metamorphosis between the button and the link
&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F84snc9k7hhgjf73wkiid.png" alt="the link button monster"&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The “slimer” button monster&lt;/strong&gt;, where padding got lost somewhere&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvwf33n8q8n7nmp67u3la.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvwf33n8q8n7nmp67u3la.png" alt="The “slimer” button monster"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;the "guess riddle" button monster&lt;/strong&gt; (no need to rage further)&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyf19jl73jk7zkqgen3uy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyf19jl73jk7zkqgen3uy.png" alt="the "&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;the serious button monster&lt;/strong&gt;, except for the missing typography… but which dev cares about typography?&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcgw5naxz4mmjr2seilv9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcgw5naxz4mmjr2seilv9.png" alt="the serious button monster"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;the Cupid button monster&lt;/strong&gt;, in which the text and the icon want to stick together forever&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgyxeojxn6kdxvskkvnbs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgyxeojxn6kdxvskkvnbs.png" alt="the Cupid button monster"&gt;&lt;/a&gt;&lt;br&gt;
)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;the Neanderthal button monster&lt;/strong&gt;, the basic one, when you give up (which is not even the ugliest, except that it is at the mercy of the browser)&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsbe0ie7h37e9j6mn7tos.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsbe0ie7h37e9j6mn7tos.png" alt="the Neanderthal button monster"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And we’re frontend devs, we know that something is wrong. But it is not the focus of the feature we are implementing, so it’s not important right now. &lt;strong&gt;Which means that it’s not important ever.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A simple CSS class would be enough to establish the style of the button once and for all.&lt;/p&gt;

&lt;p&gt;And we are talking about buttons; I know many of you will say: &lt;em&gt;"but I already manage buttons with a class"&lt;/em&gt;.&lt;br&gt;
Good! great job.&lt;br&gt;
But do you do it for everything related to the frontend?&lt;br&gt;
Because if sometimes, somewhere, you have doubts about which margin/padding/font size to use, then there is still a problem.&lt;/p&gt;

&lt;p&gt;CSS classes are the first step. Then you need to structure the project in a better way.&lt;/p&gt;

&lt;p&gt;And today, finally, there is a method that allows you to solve everything with elegance: &lt;strong&gt;the design system&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why you are wasting time without a design system and the “rosetta stone” of the frontend teams
&lt;/h2&gt;

&lt;p&gt;When developing a software product, there are two important goals:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;maximizing efficiency&lt;/strong&gt;: trying to get there without wasting time&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;minimizing bugs&lt;/strong&gt;: minimizing the possibility of errors&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Many teams are involved in the process: &lt;strong&gt;the dev team&lt;/strong&gt;, &lt;strong&gt;the design team&lt;/strong&gt;, &lt;strong&gt;the UX team&lt;/strong&gt;, and so on.&lt;/p&gt;

&lt;p&gt;Devs and designers speak a different language, devs and UXs speak a different language.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2ckh30ujf2kaoq78admk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2ckh30ujf2kaoq78admk.png" alt="dev vs world"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The design system is like a &lt;em&gt;“rosetta stone”&lt;/em&gt;: a very powerful tool shared between designers and developers.&lt;/p&gt;

&lt;p&gt;They both love it as it simplifies and speeds up the work on both sides.&lt;/p&gt;

&lt;p&gt;With a well-done design system, we will be able to cover points 1 and 2 mentioned above and much more.&lt;/p&gt;

&lt;h2&gt;
  
  
  How the design and developer teams can benefit from a a design system?
&lt;/h2&gt;

&lt;p&gt;A design system is a tool that has two faces:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;on the designer side, it is a set of mockup components, which the designer has produced and which he uses and reuses to create more complex designs&lt;/li&gt;
&lt;li&gt;for developers, it is a set of developed components, ready to use in their projects&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There is a one-to-one correspondence between the design components and the developed components.&lt;/p&gt;

&lt;h3&gt;
  
  
  Let's understand it better with an example: buttons
&lt;/h3&gt;

&lt;p&gt;Speaking of buttons, on the design side I could have the button in 3 sizes (small, medium, large) and 2 variants (filled, outline). The main color, the color of the text, the borders, the shadows are all defined.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft1ganu0fe5muhstiqgcb.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft1ganu0fe5muhstiqgcb.jpg" alt="buttons in a design system"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On the developer side, I will have the same button component. Size variants will always be 3 and often specified with 3 CSS classes. The color, corners, or shading will be defined once and for all in the component.&lt;/p&gt;

&lt;p&gt;Since the rules of the button are now fixed on the designer and developer side, two interesting things happen:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;when a button is needed, the designer does not have to draw a rectangle and specify the colors every time: he has it available in the design system library (&lt;a href="https://www.figma.com/" rel="noopener noreferrer"&gt;Figma&lt;/a&gt; has a specific function for the components of the design system and it is easy to &lt;a href="https://uxdesign.cc/simple-reusable-design-system-in-figma-a3a01236a7e3" rel="noopener noreferrer"&gt;define your design system into a library&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;the developer will reuse the component of the developed design system, without the possibility of leaving out “unimportant nuances” while developing a feature in which the button is secondary. In particular, the colors, the shadows, the roundings, etc. have already been defined and will be reused.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Designers and developers cannot make a mistake implementing the button: what to do and how to do it are set in stone by the design system. Since everything has already been said on the button, you shouldn't waste time discussing it or thinking about it.&lt;/p&gt;

&lt;p&gt;On the developer side, there is also no possibility to create graphic bugs. And when we deal with more sophisticated components, even functional bugs will disappear because the design system is solid and stable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The design system is the foundation of our projects.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We maximized effectiveness since we focused on the feature only, not the components. And we minimized bugs since we do not have to rewrite these components again.&lt;/p&gt;

&lt;h2&gt;
  
  
  The 5 characteristics of a well-done design system
&lt;/h2&gt;

&lt;p&gt;We (The Frontend Team) focused on these goals when designing the design system:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Easy to &lt;strong&gt;reuse&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Easy to &lt;strong&gt;integrate&lt;/strong&gt; into all frontend frameworks&lt;/li&gt;
&lt;li&gt;Easy to &lt;strong&gt;extend&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;With a high &lt;strong&gt;developer experience&lt;/strong&gt; in place&lt;/li&gt;
&lt;li&gt;Easy to &lt;strong&gt;test&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With these goals in mind the frontend team made a choice: use &lt;strong&gt;Tailwind&lt;/strong&gt; and &lt;strong&gt;Scss&lt;/strong&gt; to develop &lt;strong&gt;a pure CSS framework-agnostic design system&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why a pure CSS framework-agnostic design system
&lt;/h2&gt;

&lt;p&gt;We tried to build a design system for a specific framework, in Angular.&lt;/p&gt;

&lt;p&gt;Then we needed to have a Svelte version. &lt;/p&gt;

&lt;p&gt;So we thought it should be multi-framework, should we re-implement it?&lt;/p&gt;

&lt;p&gt;What if we develop our design system using a multi-purpose framework? like Stencil or mitosis?&lt;/p&gt;

&lt;p&gt;We opted for Stencil, which in theory exports web components for all frameworks. &lt;/p&gt;

&lt;p&gt;In theory. Because the result is a poor developer experience for any framework.&lt;/p&gt;

&lt;p&gt;I wrote more about this here: &lt;a href="https://www.butopen.com/blog/why-a-pure-css-tailwind-design-system/" rel="noopener noreferrer"&gt;Pure CSS design system in tailwind VS web components, angular, react, vue, svelte&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So finally we decided to build a pure CSS design system.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are the components of a design system?
&lt;/h2&gt;

&lt;p&gt;Here is a list (far from being complete) of components that should be part of a design system.&lt;/p&gt;

&lt;p&gt;In the next posts we will discuss how to implement each of them.&lt;/p&gt;

&lt;h3&gt;
  
  
  Theme
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Colors&lt;/li&gt;
&lt;li&gt;Text sizes and typography&lt;/li&gt;
&lt;li&gt;Spaces&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Atomic components
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Card&lt;/li&gt;
&lt;li&gt;Mini-card&lt;/li&gt;
&lt;li&gt;Badges&lt;/li&gt;
&lt;li&gt;Icon badges&lt;/li&gt;
&lt;li&gt;Buttons&lt;/li&gt;
&lt;li&gt;Icon&lt;/li&gt;
&lt;li&gt;Divider&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Boxes
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;warning&lt;/li&gt;
&lt;li&gt;success&lt;/li&gt;
&lt;li&gt;error&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Form components
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Field labels (vertical and horizontal)&lt;/li&gt;
&lt;li&gt;Input (text, numbers, dates)&lt;/li&gt;
&lt;li&gt;Input from / to&lt;/li&gt;
&lt;li&gt;Input time&lt;/li&gt;
&lt;li&gt;Select&lt;/li&gt;
&lt;li&gt;Textarea&lt;/li&gt;
&lt;li&gt;Checkbox&lt;/li&gt;
&lt;li&gt;Switch&lt;/li&gt;
&lt;li&gt;Radio&lt;/li&gt;
&lt;li&gt;Multi-tag&lt;/li&gt;
&lt;li&gt;Error / validation messages&lt;/li&gt;
&lt;li&gt;File upload&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Tables
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Basic table styles&lt;/li&gt;
&lt;li&gt;Pagination&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Components with logic
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Tabs&lt;/li&gt;
&lt;li&gt;Autocomplete&lt;/li&gt;
&lt;li&gt;Modal&lt;/li&gt;
&lt;li&gt;Popup with a Tooltip&lt;/li&gt;
&lt;li&gt;Header (Desktop and mobile)&lt;/li&gt;
&lt;li&gt;Horizontal container&lt;/li&gt;
&lt;li&gt;Section expand / collapse&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Singleton components
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Notification&lt;/li&gt;
&lt;li&gt;Loading (full-screen and inline)&lt;/li&gt;
&lt;li&gt;Global errors&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We will see how to develop each component and keep the design system super-easy to consume, integrate, debug and customize.&lt;/p&gt;

&lt;p&gt;Finally, our mission is to make the world a better place… for frontend teams. So our design system is open source and available on GitHub: &lt;a href="https://github.com/butopen/butopen-design-system" rel="noopener noreferrer"&gt;https://github.com/butopen/butopen-design-system&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Stay tuned.&lt;/p&gt;

&lt;p&gt;Originally published at &lt;a href="https://thefrontendteam.com/blog/design-system-what-is-save-hours-how-to-implement-frontend/" rel="noopener noreferrer"&gt;https://thefrontendteam.com/blog/design-system-what-is-save-hours-how-to-implement-frontend/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>designsystem</category>
      <category>frontend</category>
      <category>webdev</category>
      <category>tailwindcss</category>
    </item>
  </channel>
</rss>
