<?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: Alexey Pavlov</title>
    <description>The latest articles on DEV Community by Alexey Pavlov (@alpavlove_9).</description>
    <link>https://dev.to/alpavlove_9</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%2F182709%2Fbdf11f24-116d-4d41-bbff-3266711b292b.jpg</url>
      <title>DEV Community: Alexey Pavlov</title>
      <link>https://dev.to/alpavlove_9</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/alpavlove_9"/>
    <language>en</language>
    <item>
      <title>How to deploy and publish to NPM your own React Components library</title>
      <dc:creator>Alexey Pavlov</dc:creator>
      <pubDate>Thu, 08 Sep 2022 04:08:06 +0000</pubDate>
      <link>https://dev.to/alpavlove_9/how-to-deploy-and-publish-to-npm-your-own-react-components-library-h1</link>
      <guid>https://dev.to/alpavlove_9/how-to-deploy-and-publish-to-npm-your-own-react-components-library-h1</guid>
      <description>&lt;h2&gt;
  
  
  Deploy Storybook to GitHub Pages
&lt;/h2&gt;

&lt;p&gt;Now we are going to deploy Storybook to &lt;a href="https://pages.github.com/"&gt;GitHub Pages&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For that we create a new branch "gh-pages" in our repo.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hVUYjy2a--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cf114fbffuzkwzymrqkg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hVUYjy2a--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cf114fbffuzkwzymrqkg.png" alt="Image description" width="880" height="359"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then go to &lt;em&gt;settings&lt;/em&gt; -&amp;gt; &lt;em&gt;pages&lt;/em&gt; and we can find there a link for Storybook. If "gh-pages" branch wasn't chosen automatically, do it manually.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NLyKeWqk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/igsev7lp4hkqh4nat952.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NLyKeWqk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/igsev7lp4hkqh4nat952.png" alt="Image description" width="880" height="581"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For Storybook deploy, we will use &lt;a href="https://github.com/JamesIves/github-pages-deploy-action"&gt;github-pages-deploy-action&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Create a new workflow file &lt;code&gt;storybook.yml&lt;/code&gt; in the &lt;code&gt;workflows&lt;/code&gt; folder and past code below. The workflow starts for every &lt;code&gt;push&lt;/code&gt; that contain changes in &lt;code&gt;storybook&lt;/code&gt; or &lt;code&gt;src&lt;/code&gt; directories.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Let's push it to GitHub and check that it works. For that, we need to do some changes in any file &lt;code&gt;storybook&lt;/code&gt; or &lt;code&gt;src&lt;/code&gt; directories and push it. Go to &lt;em&gt;GitHub repo _-&amp;gt; _actions&lt;/em&gt; and check the workflow. When it finishes, we can open a live Storybook page using the link we noticed before (&lt;em&gt;settings&lt;/em&gt; -&amp;gt; &lt;em&gt;pages&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wQU6YLBz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a3yx6wkol254qqlzafvx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wQU6YLBz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a3yx6wkol254qqlzafvx.png" alt="Image description" width="880" height="321"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Storybook for my project is located &lt;a href="https://alpavlove.github.io/fancy-ui-reat-lib/?path=/story/button--default"&gt;here&lt;/a&gt; &lt;br&gt;
All project files you can find in my &lt;a href="https://github.com/alpavlove/fancy-ui-reat-lib"&gt;GitHub repo&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Publish a package to NPM
&lt;/h2&gt;

&lt;p&gt;I suggest you to use &lt;a href="https://semantic-release.gitbook.io/semantic-release/"&gt;semantic-release&lt;/a&gt; - fully automated version management and package publishing. It makes the process of publishing super easy.&lt;/p&gt;

&lt;p&gt;To start, run this command in your project directory. It will set up semantic-release for your project.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx semantic-release-cli setup
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It will ask us some questions, to answer that, you need to be already signed up in &lt;a href="https://www.npmjs.com/"&gt;npm&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What is your npm registry? (I left this field by default)&lt;/li&gt;
&lt;li&gt;What is your npm username? (use your personal username)&lt;/li&gt;
&lt;li&gt;What is your npm password? (use your personal password)&lt;/li&gt;
&lt;li&gt;What is your NPM two-factor authentication code?&lt;/li&gt;
&lt;li&gt;Provide a GitHub Personal Access Token (follow instructions bellow to create it)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TNvlqBrw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/btfcd4x9cgvuj5yff3op.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TNvlqBrw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/btfcd4x9cgvuj5yff3op.png" alt="Image description" width="880" height="142"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To create a GitHub Personal Access Token go to &lt;a href="https://github.com/settings/tokens/new"&gt;this page &lt;/a&gt;, add name to your token, click first checkboxes group (repo) and click "generate token" button. Copy it and paste to terminal.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--eE6iQDMi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jzpu1kxc0qty3ub0xfra.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--eE6iQDMi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jzpu1kxc0qty3ub0xfra.png" alt="Image description" width="880" height="630"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2BNcp4C6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4nak732y7cw4jvzgzpw6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2BNcp4C6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4nak732y7cw4jvzgzpw6.png" alt="Image description" width="880" height="71"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then the script offers us some CI for choosing. Chose "GitHub Actions"&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9urpyZa1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c8swzwftkdodt2tc5bgo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9urpyZa1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c8swzwftkdodt2tc5bgo.png" alt="Image description" width="880" height="147"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After that, we create a &lt;code&gt;release.yml&lt;/code&gt; workflow to release the library. Go to semantic-release &lt;a href="https://semantic-release.gitbook.io/semantic-release/recipes/ci-configurations/github-actions"&gt;docs&lt;/a&gt; and copy this code for a new workflow&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;name: Release
on:
  push:
    branches:
      - master
jobs:
  release:
    name: Release
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v2
        with:
          fetch-depth: 0
      - name: Setup Node.js
        uses: actions/setup-node@v2
        with:
          node-version: 'lts/*'
      - name: Install dependencies
        run: npm ci
      - name: Release
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
        run: npx semantic-release
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In my project, I will only change a command to install dependencies for a command I already use in other workflows&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;      - name: Install deps and build (with cache)
        uses: bahmutov/npm-install@v1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;instead of&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;      - name: Install dependencies
        run: npm ci
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then run&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And push changes to GitHub repo.&lt;/p&gt;

&lt;p&gt;Important notice! You can publish only a package with unique name for NPM registry. Be sure a name you are using in &lt;code&gt;package.json&lt;/code&gt; &lt;code&gt;name&lt;/code&gt; field in unique.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--U4hWiD_t--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jc3sgn6phldk0snv8j0t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--U4hWiD_t--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jc3sgn6phldk0snv8j0t.png" alt="Image description" width="880" height="34"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After workflow finishes, you will be able to find your package on NPM.&lt;/p&gt;

&lt;p&gt;One more benefit of using semantic-release, you can use commit message to choose a &lt;a href="https://semantic-release.gitbook.io/semantic-release/#commit-message-format"&gt;release type&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--uJEJx11Q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7gkklggo8aixu8fduibf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--uJEJx11Q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7gkklggo8aixu8fduibf.png" alt="Image description" width="880" height="488"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hope you find this article useful and will easily deploy and push your package to NPM!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>react</category>
      <category>tutorial</category>
      <category>programming</category>
    </item>
    <item>
      <title>How to test your own React Components library</title>
      <dc:creator>Alexey Pavlov</dc:creator>
      <pubDate>Mon, 22 Aug 2022 07:39:31 +0000</pubDate>
      <link>https://dev.to/alpavlove_9/how-to-test-your-own-react-components-library-3ob4</link>
      <guid>https://dev.to/alpavlove_9/how-to-test-your-own-react-components-library-3ob4</guid>
      <description>&lt;p&gt;We are going to test the components library, that we have created in &lt;a href="https://dev.to/pavlov/how-to-create-your-own-react-components-library-2764"&gt;this article&lt;/a&gt;. We have the &lt;code&gt;Button&lt;/code&gt; component for testing.&lt;/p&gt;

&lt;p&gt;We will use &lt;a href="https://testing-library.com/docs/react-testing-library/intro/" rel="noopener noreferrer"&gt;React Testing Library&lt;/a&gt;. To install it, run this script&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn add -D @testing-library/react
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  If you use CSS files
&lt;/h2&gt;

&lt;p&gt;As you may know from a previous article, we use a CSS file to add styles to our button, but &lt;code&gt;Jest&lt;/code&gt; can't handle such files by default and tests will fail. To run tests, we need to mock CSS files first. &lt;/p&gt;

&lt;p&gt;To do that, add a &lt;code&gt;jest.config.js&lt;/code&gt; file to the root of your project and paste a code below, it says that all CSS files should be handled by &lt;code&gt;identity-obj-proxy&lt;/code&gt; library&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;module.exports = {
  moduleNameMapper: {
    '\\.(css)$': 'identity-obj-proxy',
  },
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;and run&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn add -D identity-obj-proxy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Well, now we can start writing tests&lt;/p&gt;
&lt;h2&gt;
  
  
  Writing tests
&lt;/h2&gt;

&lt;p&gt;Firstly, we have to decide that exactly we want to test. Let's check if the button is rendered correctly in different states and if it is clickable/not clickable. So we create a template and comment that we don't need for now.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;For the first test, we need to import a &lt;code&gt;render&lt;/code&gt; function from React Testing Library. We will check if default button has a primary variant. There are few ways to do it. For the first one, we need a function of searching element in the screen, let's import an object &lt;code&gt;screen&lt;/code&gt;, that contains the function we need. &lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;The next one is to test a success variant. Let's have a look at another way of implementing such test. We will find our button by &lt;code&gt;querySelector&lt;/code&gt; function. &lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h2&gt;
  
  
  Snapshot test
&lt;/h2&gt;

&lt;p&gt;For disabled button state, let's use a snapshot test - the third way of implementing this type of tests. For that, we need an &lt;code&gt;asFragment&lt;/code&gt; function, that we get from &lt;code&gt;render&lt;/code&gt;.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;After running the test, &lt;code&gt;Jest&lt;/code&gt; will generate a snapshot and paste it to our test as a &lt;code&gt;toMatchInlineSnapshot&lt;/code&gt; function argument:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Next time we will run the test, &lt;code&gt;Jest&lt;/code&gt; will compare a result of &lt;code&gt;asFragment&lt;/code&gt; function with this snapshot. Every time we create a new snapshot, we need to check that it meets our expectations.&lt;/p&gt;

&lt;p&gt;Move on, now we will check if button is clickable. For that, we will mock &lt;code&gt;onClick&lt;/code&gt; function and pass it to our button, then, emulate on button click with &lt;code&gt;fireEvent.click&lt;/code&gt;. In the end, check that click was done, and it was done 1 time. &lt;/p&gt;

&lt;p&gt;For testing a disabled button state, we will do the same, but use &lt;code&gt;expect().not.toHaveBeenCalled()&lt;/code&gt; to be sure that click wasn't done. See example below:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;I will run all tests one more time to be sure that all is fine&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%2Fx9wp3ely6vz8n62vyf7l.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%2Fx9wp3ely6vz8n62vyf7l.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Good, I pushed it to my GitHub. You can find all tests &lt;a href="https://github.com/alpavlove/fancy-ui-reat-lib/blob/master/test/Button.test.tsx" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the &lt;a href="https://dev.to/pavlov/how-to-deploy-and-publish-to-npm-your-own-react-components-library-h1"&gt;next article&lt;/a&gt;, we will deploy storybook to GitHub pages.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>react</category>
      <category>tutorial</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How to create your own React Components library</title>
      <dc:creator>Alexey Pavlov</dc:creator>
      <pubDate>Thu, 18 Aug 2022 12:15:00 +0000</pubDate>
      <link>https://dev.to/alpavlove_9/how-to-create-your-own-react-components-library-2764</link>
      <guid>https://dev.to/alpavlove_9/how-to-create-your-own-react-components-library-2764</guid>
      <description>&lt;p&gt;Are you curious about how to create your own components library on React + Typescript?&lt;/p&gt;

&lt;p&gt;In this set of articles we will go through such aspects as: setup project structure, writing a small component, testing, connecting to storybook, deploying project to GitHub Pages and pushing a package to NPM. Let's start by setting up a project!&lt;/p&gt;

&lt;h2&gt;
  
  
  Set up
&lt;/h2&gt;

&lt;p&gt;We will use a &lt;a href="https://tsdx.io/" rel="noopener noreferrer"&gt;TSDX library&lt;/a&gt; - this tool is something similar to create-react-app, but for creating components library. It allows as to initialize a project immediately with already set up bundler, Rollup with Typescript supporting, testing with Jest, code formatter, Prettier and Storybook.&lt;/p&gt;

&lt;p&gt;To start, run this command in your terminal with your library name&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx tsdx create fancy-react-lib
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Choose a template &lt;code&gt;react-with-storybook&lt;/code&gt; - it is a React package with necessary development dependencies and @types installed, with &lt;a href="https://storybook.js.org/" rel="noopener noreferrer"&gt;React Storybook&lt;/a&gt; already setup as well&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%2Flhoyu6vv5tvmlwkoxnjg.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%2Flhoyu6vv5tvmlwkoxnjg.png" alt="Choose a TSDX template"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we can open a generated project and browse the structure. The first folder is &lt;code&gt;GitHub workflows&lt;/code&gt;. The First of them - &lt;code&gt;main.yml&lt;/code&gt;, it runs linting, tests and builds the project. The main goal is to check that the project is building successfully in different operating systems and node versions. Some dependencies require &lt;code&gt;node&lt;/code&gt; version 14 and upper, so let's update this part of the file:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    strategy:
      matrix:
        node: ['14.x', '16.x']
        os: [ubuntu-latest, windows-latest, macOS-latest]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The next - &lt;code&gt;size.yml&lt;/code&gt;. It uses action &lt;code&gt;size-limit&lt;/code&gt; to get a final bundle size and push it to pull request. Also, it rejects a pull request if the size is higher than the limit, that was mentioned in &lt;code&gt;package.json&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  "size-limit": [
    {
      "path": "dist/react-super-library.cjs.production.min.js",
      "limit": "10 KB"
    },
    {
      "path": "dist/react-super-library.esm.js",
      "limit": "10 KB"
    }
  ],
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;We also have next folders in our project:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;storybook&lt;/li&gt;
&lt;li&gt;example (it is a playground, but we will use storybook for these purposes)&lt;/li&gt;
&lt;li&gt;src (we will place our components here)&lt;/li&gt;
&lt;li&gt;stories (here will be our stories for storybook)&lt;/li&gt;
&lt;li&gt;test&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In general, this is all that we need to know about the project structure. Now we can init a git repository and push it to GitHub.&lt;/p&gt;

&lt;p&gt;It's time to create the first piece of code!&lt;/p&gt;
&lt;h2&gt;
  
  
  Creating a component
&lt;/h2&gt;

&lt;p&gt;Let's start with the button component.&lt;/p&gt;

&lt;p&gt;Create a &lt;code&gt;Button&lt;/code&gt; folder in &lt;code&gt;src&lt;/code&gt;, then create a &lt;code&gt;Button.tsx&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;Nothing complicated, just standard HTML &lt;code&gt;button&lt;/code&gt; and several props: onClick, children (ReactNode - it is a type including React Element, string, number, whatever), isDisabled, variant (to use different styles, let's start with &lt;code&gt;primary&lt;/code&gt; and &lt;code&gt;success&lt;/code&gt; variants). &lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;h2&gt;
  
  
  Styling
&lt;/h2&gt;

&lt;p&gt;You can use any approach to adding &lt;code&gt;CSS styles&lt;/code&gt;, that you like. I will show the easiest way - just add a CSS file for our component. Create a &lt;code&gt;Button.css&lt;/code&gt; in &lt;code&gt;src/Button&lt;/code&gt; folder and paste styles below&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;We want bundler to provide styles as separate CSS file, for that we need to change Rollup settings bit. &lt;/p&gt;

&lt;p&gt;Run this command and follow &lt;a href="https://tsdx.io/customization#rollup" rel="noopener noreferrer"&gt;TSDX customization &lt;/a&gt;instructions&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn add -D postcss rollup-plugin-postcss autoprefixer cssnano

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

&lt;/div&gt;


&lt;p&gt;Create a &lt;code&gt;tsdx.config.js&lt;/code&gt; file in the root directory and past this code&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;h2&gt;
  
  
  Storybook
&lt;/h2&gt;

&lt;p&gt;Let's create a story for our button! We already have a default story in the &lt;code&gt;stories&lt;/code&gt; folder, so we can create the same one. Create a new file &lt;code&gt;Button.stories.tsx&lt;/code&gt; in &lt;code&gt;storybook&lt;/code&gt; folder&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;To build storybook locally, run this command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; yarn storybook
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The last but not least, let's export the Button component in  src/index.js file - the entry point of our package.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export * from './Button/Button'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cool! We can check that storybook is working.&lt;/p&gt;

&lt;p&gt;Hope it was helpful. The project files you can find also in a &lt;a href="https://github.com/alpavlove/fancy-ui-reat-lib" rel="noopener noreferrer"&gt;GitHub repo&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>tutorial</category>
      <category>typescript</category>
      <category>react</category>
    </item>
    <item>
      <title>Svelte app: create Loading Overlay component using svelte/motion</title>
      <dc:creator>Alexey Pavlov</dc:creator>
      <pubDate>Thu, 26 May 2022 06:26:05 +0000</pubDate>
      <link>https://dev.to/alpavlove_9/svelte-app-create-loading-overlay-component-using-sveltemotion-5jp</link>
      <guid>https://dev.to/alpavlove_9/svelte-app-create-loading-overlay-component-using-sveltemotion-5jp</guid>
      <description>&lt;p&gt;For one of my projects, I needed to create a loading overlay component to hide the app until the loading is complete. In this article, I want to share how I did it.&lt;/p&gt;

&lt;p&gt;First, let's sketch out the HTML and CSS markup. This is quite simple. I create a block, position it fixed, stretch it to full-screen size, and centre its content. Notice how we use the svg gradient to fill the text with different colours.&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;"overlay"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;svg&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"115"&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;"32"&lt;/span&gt; &lt;span class="na"&gt;viewBox=&lt;/span&gt;&lt;span class="s"&gt;"0 0 78 32"&lt;/span&gt; &lt;span class="na"&gt;xmlns=&lt;/span&gt;&lt;span class="s"&gt;"http://www.w3.org/2000/svg"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;defs&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;linearGradient&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"filler"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;stop&lt;/span&gt; &lt;span class="na"&gt;offset=&lt;/span&gt;&lt;span class="s"&gt;"50%"&lt;/span&gt; &lt;span class="na"&gt;stop-color=&lt;/span&gt;&lt;span class="s"&gt;"#ff006e"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;stop&lt;/span&gt; &lt;span class="na"&gt;offset=&lt;/span&gt;&lt;span class="s"&gt;"50%"&lt;/span&gt; &lt;span class="na"&gt;stop-color=&lt;/span&gt;&lt;span class="s"&gt;"white"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/linearGradient&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/defs&amp;gt;&lt;/span&gt;

        &lt;span class="nt"&gt;&amp;lt;text&lt;/span&gt; &lt;span class="na"&gt;x=&lt;/span&gt;&lt;span class="s"&gt;"0"&lt;/span&gt; &lt;span class="na"&gt;y=&lt;/span&gt;&lt;span class="s"&gt;"24px"&lt;/span&gt; &lt;span class="na"&gt;fill=&lt;/span&gt;&lt;span class="s"&gt;"url(#filler)"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Loading...&lt;span class="nt"&gt;&amp;lt;/text&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/svg&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
  &lt;span class="nc"&gt;.overlay&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;fixed&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;right&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&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;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;z-index&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10001&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;align-items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;justify-content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#3a86ff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;font-family&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;"Arial"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;sans-serif&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1.375rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;iframe src="https://codesandbox.io/embed/1ypl81"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Cool. We are done with the markup. Now let's move on to animation. To do this, we will use standard Svelte tools. Using &lt;a href="https://svelte.dev/docs#run-time-svelte-motion-tweened"&gt;&lt;code&gt;tweened&lt;/code&gt;&lt;/a&gt; from &lt;code&gt;svelte/motion&lt;/code&gt; we create a &lt;code&gt;progress&lt;/code&gt; variable and use its value in the svg gradient.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;progress&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;tweened&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;easing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;linear&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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;linearGradient&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"filler"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;stop&lt;/span&gt; &lt;span class="na"&gt;offset=&lt;/span&gt;&lt;span class="s"&gt;{`${$progress}%`}&lt;/span&gt; &lt;span class="na"&gt;stop-color=&lt;/span&gt;&lt;span class="s"&gt;"#ff006e"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;stop&lt;/span&gt; &lt;span class="na"&gt;offset=&lt;/span&gt;&lt;span class="s"&gt;{`${$progress}%`}&lt;/span&gt; &lt;span class="na"&gt;stop-color=&lt;/span&gt;&lt;span class="s"&gt;"white"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/linearGradient&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, let's create &lt;code&gt;animate&lt;/code&gt; function that we will call when the component mounts. We make this function recursive so that the animation continues indefinitely. Like any other recursive function, it must have an exit point. Therefore, in order to avoid memory leaks, we make sure that the execution of the function ends when the component instance is destroyed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;destroyed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&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;animate&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&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;destroyed&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="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;animate&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;onMount&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;animate&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;

  &lt;span class="nx"&gt;onDestroy&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;destroyed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;iframe src="https://codesandbox.io/embed/fg3881"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Fine. Our component already looks good. Now we will improve the resulting animation by making it two-stage, where in the first stage we paint over the white text with pink, and vice versa, in stage number 2 we paint over the pink text with white. To do this, we will create a &lt;code&gt;writable&lt;/code&gt; store with a boolean value that we will use to indicate the current stage of the animation. With each call of the &lt;code&gt;animate&lt;/code&gt; function, we will change this value to the opposite.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isFirstStage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;writable&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;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;animate&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&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;destroyed&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="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;width&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="nx"&gt;isFirstStage&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="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;animate&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;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;linearGradient&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"filler"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;stop&lt;/span&gt; &lt;span class="na"&gt;offset=&lt;/span&gt;&lt;span class="s"&gt;{`${$progress}%`}&lt;/span&gt; &lt;span class="na"&gt;stop-color=&lt;/span&gt;&lt;span class="s"&gt;{$isFirstStage&lt;/span&gt; &lt;span class="err"&gt;?&lt;/span&gt; &lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="na"&gt;#ff006e&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt; &lt;span class="na"&gt;:&lt;/span&gt; &lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="na"&gt;white&lt;/span&gt;&lt;span class="err"&gt;'}&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;stop&lt;/span&gt; &lt;span class="na"&gt;offset=&lt;/span&gt;&lt;span class="s"&gt;{`${$progress}%`}&lt;/span&gt; &lt;span class="na"&gt;stop-color=&lt;/span&gt;&lt;span class="s"&gt;{$isFirstStage&lt;/span&gt; &lt;span class="err"&gt;?&lt;/span&gt; &lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="na"&gt;white&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt; &lt;span class="na"&gt;:&lt;/span&gt; &lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="na"&gt;#ff006e&lt;/span&gt;&lt;span class="err"&gt;'}&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/linearGradient&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;iframe src="https://codesandbox.io/embed/tpk15e"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;So, we are done with the loading indicator component itself. Now let's imagine that there can be several components that use our indicator. We could render our overlay in each of them, but let's better refine our approach and create functionality that will allow us to render the indicator once and provide functions for turning the indicator on and off. To do this, we will create another &lt;code&gt;writable&lt;/code&gt; store, which will contain requests to display the indicator. The indicator itself will be rendered as long as there is at least one request left in the store.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&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;writable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;derived&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;svelte/store&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;nanoid&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;nanoid&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;const&lt;/span&gt; &lt;span class="nx"&gt;loadingOverlayQueue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;writable&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;function&lt;/span&gt; &lt;span class="nx"&gt;showLoadingOverlay&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;newRequestId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;nanoid&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="nx"&gt;loadingOverlayQueue&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="nx"&gt;currentValue&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;currentValue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;newRequestId&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;newRequestId&lt;/span&gt;&lt;span class="p"&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;function&lt;/span&gt; &lt;span class="nx"&gt;hideLoadingOverlay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;requestId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;loadingOverlayQueue&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="nx"&gt;currentValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="nx"&gt;currentValue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;requestId&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="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isLoadingOverlayShown&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;derived&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;loadingOverlayQueue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;iframe src="https://codesandbox.io/embed/8zvtuu"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Now, all done. We've created an original animated loading indicator in a few easy steps. The source code can be found on &lt;a href="https://github.com/alpavlove/svelte-loading-overlay"&gt;my GitHub&lt;/a&gt;. Do you enjoy working with svelte?&lt;/p&gt;

</description>
      <category>svelte</category>
      <category>javascript</category>
      <category>tutorial</category>
      <category>frontend</category>
    </item>
  </channel>
</rss>
