<?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: psborul</title>
    <description>The latest articles on DEV Community by psborul (@psborul).</description>
    <link>https://dev.to/psborul</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%2F374078%2Fcd56934c-254d-4b45-aca6-fac0cd472b97.jpeg</url>
      <title>DEV Community: psborul</title>
      <link>https://dev.to/psborul</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/psborul"/>
    <language>en</language>
    <item>
      <title>Storybook and custom “dynamic template” addon creation, with Vue and Vuetify</title>
      <dc:creator>psborul</dc:creator>
      <pubDate>Sun, 26 Apr 2020 15:23:10 +0000</pubDate>
      <link>https://dev.to/psborul/storybook-and-custom-dynamic-template-addon-creation-with-vue-and-vuetify-jec</link>
      <guid>https://dev.to/psborul/storybook-and-custom-dynamic-template-addon-creation-with-vue-and-vuetify-jec</guid>
      <description>&lt;p&gt;Hello everyone, let’s start by understanding what problem we are solving.&lt;br&gt;
Every hour in the world, development teams grow. When a new member joins, the first step is onboarding to the project, and it takes a lot of time. Therefore, today we will reduce this time and the second goal is to improve developers communications with designers and managers.&lt;/p&gt;

&lt;p&gt;// Time is the most valuable thing a man can spend. — Theophrastus.&lt;/p&gt;

&lt;p&gt;As a result, we will have such functionality in our Storybook:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;See how component looks like&lt;/li&gt;
&lt;li&gt;Interact with component options&lt;/li&gt;
&lt;li&gt;Get component template, depending on selected options
There are many ready-made solutions for the first two points, which cannot be said for the third. I didn’t find any examples, so we need to write it ourselves. Let’s start.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;// During all installations we will select default options.&lt;/p&gt;

&lt;p&gt;If u don’t have an existing Vue.js project, let’s install it using the Vue CLI, the name of the project is up to you, i named it “dynamic-template-addon”&lt;/p&gt;

&lt;p&gt;$ vue create dynamic-template-addon&lt;/p&gt;

&lt;p&gt;Next, install Vuetify in our project&lt;/p&gt;

&lt;p&gt;$ vue add vuetify&lt;/p&gt;

&lt;p&gt;Then we need to install the Storybook, since we are using Vuetify, let’s get vue-cli-plugin-vuetify-storybook from their official repository&lt;/p&gt;

&lt;p&gt;$ vue add vuetify-storybook&lt;/p&gt;

&lt;p&gt;We also need to install js-beautify, so that the formatting of the template will lie on it’s shoulders. The entire list of settings and additional information is here, later we will return to this&lt;/p&gt;

&lt;p&gt;$ npm install js-beautify&lt;/p&gt;

&lt;p&gt;Now we can work with our Storybook, but before we start, let’s shorten the launch command a bit, we can do this in package.json file&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--IxRL04mI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/hpmenasg5mn4r0qo6ph9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IxRL04mI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/hpmenasg5mn4r0qo6ph9.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Today we look at an example of a date picker component, based on Vuetify. So let’s get started.&lt;/p&gt;

&lt;p&gt;// Talk is cheap. Show me the code. — Linus Torvalds.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Remove unnecessary components and settings, leave the most basic&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--GmfCb_B6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/4nlzttcr5a78022cn8m9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GmfCb_B6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/4nlzttcr5a78022cn8m9.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create DatePicker.vue file in our components folder.&lt;br&gt;
As a result, we will have an textfield, by clicking on it a menu with a calendar will open. After choosing a date, our menu will close and it will be written in the textfield.&lt;br&gt;
Also in the component we have such props:&lt;br&gt;
~ label — sets textfield label;&lt;br&gt;
~ value — it’s the date value, that we want to update using our component;&lt;br&gt;
~ filled — applies the alternate filled textfield style;&lt;br&gt;
~ type — determines the type of the picker — date for date picker, month for month picker;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You can get more information about Vuetify component modifiers in the official documentation&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bmwp7EEF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/83w9zjagdenzh94wonue.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bmwp7EEF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/83w9zjagdenzh94wonue.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Import our DatePicker component into App.vue file and create “date” property, which we will pass into it. Also add some styles, so as not to be nervous, when we open it all in the browser&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KAZckXWR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/kyxujwohurevrk1g8ypr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KAZckXWR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/kyxujwohurevrk1g8ypr.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Good, we are done with our component template, so let’s write a cool stories about it.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Delete the utils folder, because we will use a different approach, than Vuetify offers us;&lt;/li&gt;
&lt;li&gt;Rename the file example.stories.js to datePicker.stories.js in the stories folder (config.js file contains regular expression, that collects all the files in this folder with the stories.js extension);&lt;/li&gt;
&lt;li&gt;Write stories in datePicker.stories.js file&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let’s go through each point of this file:&lt;br&gt;
~ Import of Storybook Addon Knobs;&lt;/p&gt;

&lt;p&gt;// Storybook Addon Knobs enable the user to interact with the component, allowing to edit props dynamically using the Storybook UI. You can dive deeper in official documentation.&lt;/p&gt;

&lt;p&gt;~ Defined the name that will be shown in the list of all components of our Storybook;&lt;br&gt;
~ Import of DatePicker component;&lt;br&gt;
~ Written stories (we have two stories to select the date and month)&lt;/p&gt;

&lt;p&gt;// Each story is a single state of your component.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--VbA_wUWd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ovyjbfgp5f8rxt60yosf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VbA_wUWd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ovyjbfgp5f8rxt60yosf.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we can run Storybook:&lt;/p&gt;

&lt;p&gt;$ npm run storybook&lt;/p&gt;

&lt;p&gt;But there are two problems:&lt;br&gt;
~ Our template shows props as variables, not values;&lt;br&gt;
~ Props aren’t hidden, if they are equal to default values&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hwWnNMsA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ic8cl847g4mfqbygo46z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hwWnNMsA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ic8cl847g4mfqbygo46z.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s fix it, because we want, after choosing the options we need, just copy the component and use it right way.&lt;/p&gt;

&lt;p&gt;We have to edit decorator.js file in addon-show-vue-markup folder.&lt;/p&gt;

&lt;p&gt;~ EVENT_ID —name of event that our panel will listen;&lt;br&gt;
~ story — define our story instance;&lt;br&gt;
~ template, components — template and components of our story;&lt;br&gt;
~ storyValues — the value of props, that were selected in the knobs tab;&lt;br&gt;
~ defaultValue — in our options we have an object “props”, but there is a bug, and when we change the value of props with knob — default value changes to a new one, so we must take the default value of the props from the component instance;&lt;br&gt;
~ We have only one way to change the template with a regular expression, it is very short and easy;&lt;br&gt;
~ Next we loop in “storyValues” and check, if the current value is default, we don’t want to add it to the template, and also don’t forget, that when value type is boolean or object, we must add a colon to it;&lt;br&gt;
~ After all the code, add s hint, that the developer can bind the property to the component using v-model directive;&lt;br&gt;
~ “I tried so hard” — in the end, add settings to beautify-js&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--f4kPCSHh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/mi0az58q9bbl3n09j1et.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--f4kPCSHh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/mi0az58q9bbl3n09j1et.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;// A few words about register.js file — In the Storybook we can’t create addon with Vue.js, because it must be React component, we can only hope that this will be fixed in the future&lt;/p&gt;

&lt;p&gt;That’s all, now we have dynamic-template-addon, which implements all the functionality we need.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7SZJ6_XD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/wi2c3wm75mez5le781zw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7SZJ6_XD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/wi2c3wm75mez5le781zw.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Github with source code - &lt;a href="https://github.com/psborul/dynamic-template-addon"&gt;https://github.com/psborul/dynamic-template-addon&lt;/a&gt;&lt;br&gt;
Thanks for reading.&lt;br&gt;
See you next time!&lt;/p&gt;

</description>
      <category>vue</category>
      <category>vuetify</category>
      <category>storybook</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
