<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ Design Systems - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ Design Systems - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Sun, 24 May 2026 16:30:41 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/design-systems/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How to Move Figma Components to Penpot ]]>
                </title>
                <description>
                    <![CDATA[ Penpot is an open-source design tool for creating complete design systems. It is free, self-hostable, and allows multiple projects. Penpot supports reusable components and assets and allows files and libraries to be shared across projects. Penpot fil... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-recreate-figma-components-in-penpot/</link>
                <guid isPermaLink="false">67e48bc10d600bc3806ccf54</guid>
                
                    <category>
                        <![CDATA[ Design Systems ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Open Source ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Penpot ]]>
                    </category>
                
                    <category>
                        <![CDATA[ figma ]]>
                    </category>
                
                    <category>
                        <![CDATA[ components ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Fatuma Abdullahi ]]>
                </dc:creator>
                <pubDate>Wed, 26 Mar 2025 23:20:33 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1743028701920/ef200f8f-888d-4658-a5b0-ffa483edbdcf.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p><a target="_blank" href="https://penpot.app/">Penpot</a> is an open-source design tool for creating complete design systems. It is free, self-hostable, and allows multiple projects. Penpot supports reusable components and assets and allows files and libraries to be shared across projects. Penpot files can be exported in various formats to enhance collaboration.</p>
<p>Penpot designs directly translate to code that meets web standards, facilitating collaboration and hand-off between designers and developers.</p>
<p>This tutorial will walk you through recreating or moving existing <a target="_blank" href="https://www.figma.com/">Figma</a> components to Penpot. It will include a rundown of the Penpot tool and how to use it, a brief comparison of the two tools, and important resources.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-how-to-recreate-existing-figma-files-in-penpot">How to Recreate Existing Figma Files in Penpot</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-understanding-the-penpot-user-interface">Understanding the Penpot User Interface</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-understanding-penpot-layouts">Understanding Penpot Layouts</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-create-and-use-penpot-components">How to Create and Use Penpot Components</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-create-reusable-assets-in-penpot">How to Create Reusable Assets in Penpot</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-add-and-use-icons-in-penpot">How to Add and Use Icons in Penpot</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-figma-vs-penpot-my-experience">Figma Vs. Penpot - My experience</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-resources-and-notes">Resources and Notes</a></p>
</li>
</ul>
<h2 id="heading-how-to-recreate-existing-figma-files-in-penpot">How to Recreate Existing Figma Files in Penpot</h2>
<p>There are two ways to move or recreate existing Codex components from Figma to Penpot: By using the community-supported migration tool or by manually recreating the components and files.</p>
<h3 id="heading-using-the-community-supported-migration-plugin">Using the Community-Supported Migration Plugin</h3>
<p>You can use <a target="_blank" href="https://www.figma.com/community/plugin/1219369440655168734/penpot-exporter">this plugin</a> to move your Figma designs to Penpot. It is a straightforward way to migrate from Figma, especially if you have many components.</p>
<p>To do so, add it as a Figma plugin and find the option in the context menu. Then, click on the "Penpot Exporter" option to activate the plugin. The plugin will then create a zip file for your component and download it.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742571496007/da97ad1b-6939-4bb9-9000-6c367a711797.gif" alt="A screenrecording illustrating how to add and use the &quot;Penpot Exporter&quot; plugin." class="image--center mx-auto" width="800" height="450" loading="lazy"></p>
<p>Over in Penpot, in your Projects dashboard, click on the three dots context menu and select "Import Penpot files" to open a file picker window. Click on the zip file downloaded from Figma, and Penpot will create a new project with the same name as the zip file. This new project will contain your Figma component translated to the Penpot environment.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742571779644/1ebeb54d-ce27-4987-b630-f101a60ee8d3.gif" alt="An illustration of how to import files to Penpot" class="image--center mx-auto" width="800" height="450" loading="lazy"></p>
<p>Looking at the new component, you'll notice that the migration plugin correctly picks up any child components and typography variables while keeping things fairly organized. But it does not pick up color variables.</p>
<h3 id="heading-manually-recreating-figma-components">Manually Recreating Figma components</h3>
<p>Another way to move Figma components to Penpot is to recreate them manually. While this option is more tedious than the previous one, it gives you fine-tuned control over how the component looks, how the files are organized, and how the assets are carried over.</p>
<p>It is an excellent excuse to spruce up the existing components, especially if there are few. It is also a good exercise for first-time users to grasp Penpot.</p>
<p>To effectively move components using this method, you will need to understand how Penpot works. The following concepts will help make this process more efficient.</p>
<h2 id="heading-understanding-the-penpot-user-interface">Understanding the Penpot User Interface</h2>
<p>Penpot's UI is pretty similar to Figma's, except that Penpot defaults to Dark Mode. You have your controls on the right and your files, assets, and layers on the left, with a canvas in the middle.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742811019699/ea5336e3-50a7-4771-bfa6-07a225390320.png" alt="Alt: Screenshot of a Penpot UI with a left panel labeled &quot;Layers&quot; showing file structure, a central canvas labeled &quot;Canvas,&quot; and a right panel with various design tools and settings." class="image--center mx-auto" width="1600" height="620" loading="lazy"></p>
<p>Both have a toolbar that enables you to interact with the canvas. The toolbars have slightly different icons and names but have the same functionality. Notably, in Penpot, the Frame tool is called Board.</p>
<p>Penpot supports most of Figma's features, except for Design Tokens, which will be added soon.</p>
<h2 id="heading-understanding-penpot-layouts">Understanding Penpot Layouts</h2>
<p>Penpot supports Flex and Grid layouts. These layouts allow you to position items precisely and simplify creating fluid designs. For those familiar with CSS Grid and Flex, they work in the same way.</p>
<p>Flex layout allows you to organize the elements within a parent container, like a board or an encompassing shape, across one dimension, width, or height. It enables you to determine the spacing and positioning of the child elements via visual controls with labels on the right side panel.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742571904634/c8bf8fc0-79a7-415f-916b-42da7c881ed8.gif" alt="An illustration on how to use Penpot Flex Layout" class="image--center mx-auto" width="800" height="450" loading="lazy"></p>
<p>Grid layouts allow the same controls as Flex layouts but with the added flexibility of simultaneously spanning a child element across both dimensions. This makes Grid layouts quite helpful in creating complex and nuanced designs.</p>
<h2 id="heading-how-to-create-and-use-penpot-components">How to Create and Use Penpot Components</h2>
<p>Creating a component in Penpot is relatively straightforward. You select the elements that will make up the component, then right-click and click "Create component," turning your selection into a component.</p>
<p>Your new component will be available under the "Assets" tab on the left side panel. To use, drag it onto the canvas.</p>
<p>You can also create copies of the component. By default, the copies are tied to the main component, and any changes to the main will be reflected in all copies. You can override this by detaching the copies from the context menu.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742571991986/6dd4820b-0f3a-4d41-895d-cb9f5e7d4f52.gif" alt="A speedrun of how to create a Penpot Component" class="image--center mx-auto" width="800" height="450" loading="lazy"></p>
<h2 id="heading-how-to-create-reusable-assets-in-penpot">How to Create Reusable Assets in Penpot</h2>
<p>Penpot has three asset types: Typography, Colors, and Components, with <a target="_blank" href="https://penpot.app/collaboration/design-tokens">Penpot design tokens</a> coming very soon. Typography refers to information on font types and weights that make up text styles. Colors enable you to create and sort your repeated colors. Components refer to reusable design pieces and, in this context, include graphical items like icons and images.</p>
<p>To create a color or typography asset, click the "Assets" tab and the plus icon on the relevant accordion item. For color, it will open a color picker. Paste the hex value in the appropriate place, then save it. The color will show up in the accordion drop-down. You can click on it to give it a semantic name if desired.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742809861347/9ae3b0fb-798b-4363-ab90-873c18a16793.png" alt="Screenshot of a Penpot UI showing a color palette with hex codes, a color picker, and local library assets." class="image--center mx-auto" width="976" height="800" loading="lazy"></p>
<p>For typography, click on the plus icon at the relevant accordion. This will open a panel where you can specify the font, font weight, letter spacing, and line height. You can also change the asset's name after it's saved.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742810318737/daf0e24f-7c4a-4c00-bb73-ccca7575bcf5.png" alt="daf0e24f-7c4a-4c00-bb73-ccca7575bcf5" class="image--center mx-auto" width="443" height="400" loading="lazy"></p>
<h2 id="heading-how-to-add-and-use-icons-in-penpot">How to Add and Use Icons in Penpot</h2>
<p>You can add icon packs and libraries in Penpot from the Project dashboard. At the bottom of the page, a banner containing a list of commonly used libraries is displayed. These libraries usually include a few icon packs. You can scroll through to choose one or click on the explore more option at the end of the slider to open up the dedicated Penpot templates page.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742810534992/83b2eb72-4877-49b3-9d2e-02c37e0cb894.png" alt="Screenshot of Penpot UI's lower bottom showing &quot;Penpot - Design System v2.0&quot;, &quot;New Project 1&quot;, &quot;Avataaars&quot;, &quot;UX Notes&quot;, &quot;Whiteboarding Kit&quot;, &quot;Open Color Scheme&quot;, and &quot;Flex Layout Playground&quot;. A sidebar labeled &quot;Libraries &amp; Templates&quot; is visible on the right." class="image--center mx-auto" width="900" height="282" loading="lazy"></p>
<p>If you find a relevant library from the bottom banner, click the download icon. Penpot will prompt you to add the selected library. Once you accept it, it will be added to the "Libraries" menu item on the left side panel.</p>
<p>If you click through to the dedicated templates page, clicking the download icon will download a Penpot file. You can then drag it to the projects page, and it will also be available in the "Libraries" section of the projects page.</p>
<p>To use the libraries within your project file, click the "Assets" tab on the left side panel, then click the "Libraries" button below it. This will open a modal with all your libraries listed under "Shared Libraries."</p>
<p>Click on the plus icon on the ones you want to use in your project. This will link that library to your project and be available in the left side panel. You can then search for any particular icon from the search bar and drag it onto the canvas.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742571300138/3dbbc937-f727-4c03-987b-43ddb71b1608.gif" alt="A gif illustrating how to link and delink libraries in the Penpot User Interface" class="image--center mx-auto" width="800" height="450" loading="lazy"></p>
<p>To remove a library from your project, click on the libraries button. In the modal, under "libraries in this file," all used libraries are listed. Click on the link icon next to the library you want to remove. This will delink it and remove it from the side panel.</p>
<h2 id="heading-figma-vs-penpot-my-experience">Figma Vs. Penpot – My experience</h2>
<p>As a first-time user of Penpot and a long-term casual user of Figma, I noticed some differences and encountered some teething problems.</p>
<h3 id="heading-swapping-out-icons">Swapping Out Icons</h3>
<p>You can <a target="_blank" href="https://help.penpot.app/user-guide/components/#component-swap">swap out components</a> in Penpot! It's too bad that I discovered this after I had finished my first component migration.</p>
<h3 id="heading-renaming-files-and-folders">Renaming Files and Folders</h3>
<p>I struggled to find how to rename files and folders in Penpot. I kept looking for the shortcut or a menu item in the context menu. It turns out you have to double-click on the title to change it. You can rename files in the same way in Figma, but I just never did it like that.</p>
<h3 id="heading-adherence-to-web-standards">Adherence to Web Standards</h3>
<p>I was pleasantly surprised at the code quality that Penpot provides, along with your designs. It meets the <a target="_blank" href="https://www.w3.org/standards/">w3c standards</a>, but the HTML could be more <a target="_blank" href="https://web.dev/learn/html/semantic-html">semantic</a>.</p>
<h3 id="heading-penpot-design-system">Penpot Design System</h3>
<p>Penpot avails its <a target="_blank" href="https://community.penpot.app/t/pencil-the-penpot-design-system/7152">design system</a> along with lots of little libraries that help you understand how the tool works. This is very nice as it allows you to get a good understanding of design language and how to organize design systems.</p>
<h3 id="heading-limited-shape-options-in-the-toolbar">Limited Shape Options in the Toolbar</h3>
<p>The Penpot toolbar lacks essential shapes such as pen, arrow, and triangle. While you can recreate this with the path tool or use a library to import them, it is definitely something I missed that was readily available in Figma.</p>
<p>It took me a few tries to get comfortable with Penpot and in the end, I really liked it. Plus, its open-source nature makes it even more endearing.</p>
<h2 id="heading-resources-and-notes">Resources and Notes</h2>
<p>Using Penpot has a learning curve, even if you are familiar with other design tools like Figma. These resources can help you get up to speed faster and make you more efficient with Penpot.</p>
<ul>
<li><p><a target="_blank" href="https://www.youtube.com/live/64O8qi51Jqc?si=A6AVp1m8se3gl1ut">Penpot video on layouts</a></p>
</li>
<li><p><a target="_blank" href="https://www.youtube.com/live/aW0LNHLEI_Y?si=HATAWee8tH29Sgrq&amp;t=1604">Penpot live on design tokens</a></p>
</li>
<li><p><a target="_blank" href="https://help.penpot.app/user-guide/">Penpot documentation</a></p>
</li>
<li><p><a target="_blank" href="https://www.figma.com/community/plugin/1219369440655168734/penpot-exporter">Penpot migration plugin</a></p>
</li>
<li><p><a target="_blank" href="https://penpot.app/libraries-templates">Penpot templates and libraries</a></p>
</li>
<li><p><a target="_blank" href="https://penpot.app/blog/penpot-for-design-systems-101/">Penpot design systems</a></p>
</li>
</ul>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Use a Design System – a Case Study ]]>
                </title>
                <description>
                    <![CDATA[ You may have heard of, studied, or used a design system at some point in your coding career. But what role do design systems actually play in our projects? Why should we even bother to create or use them? In this guide, you'll be learning what design... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-use-a-design-system/</link>
                <guid isPermaLink="false">66d03a2edcbab93f8b58df8b</guid>
                
                    <category>
                        <![CDATA[ Design Systems ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Design ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Faith Olohijere ]]>
                </dc:creator>
                <pubDate>Tue, 17 Oct 2023 14:37:29 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/10/pexels-toa-heftiba-s-inca-1194420.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>You may have heard of, studied, or used a design system at some point in your coding career. But what role do design systems actually play in our projects? Why should we even bother to create or use them?</p>
<p>In this guide, you'll be learning what design systems are, why they're important, typical elements of a design system, and a practical example of how to implement a design system as a designer. Let's dive in!</p>
<h2 id="heading-what-is-a-design-system">What is a Design System?</h2>
<p>Design Systems are structured collections of reusable design components and elements. We use them to create a consistent and cohesive user experience across a range of products or services. </p>
<p>A design system is like a set of building blocks and rules for creating digital products like websites and apps. Design systems are made up of key elements like typography, color palette, icons, spacing and layout, and so on.</p>
<h3 id="heading-importance-and-purpose-of-a-design-system">Importance and purpose of a Design System</h3>
<p>Design systems are important for many reasons.</p>
<h4 id="heading-efficiency">Efficiency</h4>
<p>Design systems help you become more efficient. Because it's a collection of reusable components, it saves the time of producing new elements, and helps designers produce new features quickly in projects. It also serves as a productivity booster.</p>
<h4 id="heading-collaboration">Collaboration</h4>
<p>A team trying to build a product may consist of designers, developers, product managers, and others. The design system helps all members of the team make reference to the brand guidelines, no matter what they working on. It also helps to make sure everyone, including stakeholders, are involved in the design process, and facilitates collaboration.</p>
<h4 id="heading-consistency">Consistency</h4>
<p>Design systems ensure consistency in the user interface and user experience across various products and platforms. </p>
<p>We wouldn't want a scenario where a button design is inconsistent on different screens, would we? That's where the design system comes in. It helps our design assets and elements stay consistent, and it can always serve as a reference point.</p>
<h4 id="heading-scalability">Scalability</h4>
<p>Scalability here refers to the ability of the design system to grow and adapt to the changing needs of a project or an organization. </p>
<p>A crucial element of any design system is scalability. Design systems help in situations where the project might need to expand to accommodate different devices and platforms or when the team is expanding or when trying to accommodate new trends and practices.</p>
<h3 id="heading-how-design-systems-work">How Design Systems work</h3>
<p>To understand how a design system works, you just need to know the kinds of assets or components that make up the system and their roles. </p>
<p>A typical design system comprises of the following parts:</p>
<h4 id="heading-colours">Colours</h4>
<p>When you open a design system, one of the first things you'll see is a colour palette section. It's one of the most common elements in a design system. </p>
<p>Design systems define a set of of primary and secondary colours, as well as their various uses. This includes background colours, text colours, and so on.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/Rayna-46.png" alt="Image" width="600" height="400" loading="lazy">
<em>Colour palette section of Rayna UI design system</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/Rayna-47.png" alt="Image" width="600" height="400" loading="lazy">
<em>Colour palette section of Atlassian design system</em></p>
<h4 id="heading-typography">Typography</h4>
<p>Another typical element of a design system is typography. Every design system usually includes guidelines for typography, specifying fonts, font sizes, line height, and so on. </p>
<p>It may also define how typography is used for different content types like headings and body text, making sure they're accessible and legible for design use.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/Rayna-48.png" alt="Image" width="600" height="400" loading="lazy">
<em>Typography section of Google's Material Design</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/Rayna-49.png" alt="Image" width="600" height="400" loading="lazy">
<em>Typography section of Shopify's Polaris</em></p>
<h4 id="heading-icons">Icons</h4>
<p>Icons are very important when trying to give visual clues to your users. Design systems provide a set of standard icons and guidelines for their usage, ensuring they are recognizable and consistent.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/Rayna-50.png" alt="Image" width="600" height="400" loading="lazy">
<em>Iconography section of Atlassian design system</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/Rayna-57.png" alt="Image" width="600" height="400" loading="lazy">
<em>Iconography section of Google's Material Design</em></p>
<h4 id="heading-grid-and-spacing-styles">Grid and Spacing Styles</h4>
<p>A grid system helps establish a consistent structure for different components or pages. </p>
<p>Design systems provide spacing guidelines specifying margins, padding, and other layout-related rules to maintain alignment to create a visually pleasing and organized design. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/Rayna-51.png" alt="Image" width="600" height="400" loading="lazy">
<em>Grids and spacing styles section of Rayna UI design system</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/Rayna-53.png" alt="Image" width="600" height="400" loading="lazy">
<em>Spacing section of Atassian design system</em></p>
<h4 id="heading-documentation">Documentation</h4>
<p>Every well-structured design system has some form of documentation that usually explains how to use the elements and guidelines effectively. The documentation also helps designers and developers understand how to use and implement the design system.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/Rayna-54.png" alt="Image" width="600" height="400" loading="lazy">
<em>Documentation for button styles in the Rayna UI design system</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/Rayna-58.png" alt="Image" width="600" height="400" loading="lazy">
<em>Documentation for App icons on Apple's Human Interface Guidelines</em></p>
<h4 id="heading-ui-patterns-and-components">UI Patterns and Components</h4>
<p>UI patterns and components are the building blocks of a user interface. Design systems define UI patterns and components such as buttons, forms, modals, accordions, navigation bars, and so on, along with guidelines on how and when to use them.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/Rayna-59.png" alt="Image" width="600" height="400" loading="lazy">
<em>UI Components section of Shopify's Polaris</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/Rayna-60.png" alt="Image" width="600" height="400" loading="lazy">
<em>UI Patterns section of Aplles's Human Interface Guidelines</em></p>
<h4 id="heading-content-guidelines">Content Guidelines</h4>
<p>These cover how text and imagery is used in the user interface. They may specify tone, image use, and content hierarchy, ensuring that the content is consistent and aligns with the brand guidelines. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/Rayna-61.png" alt="Image" width="600" height="400" loading="lazy">
<em>Content guidelines section of Shopify's Polaris</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/Rayna-62.png" alt="Image" width="600" height="400" loading="lazy">
<em>Content guidelines section of Google's Material Design</em></p>
<h4 id="heading-accessibility-guidelines">Accessibility Guidelines</h4>
<p>Most design systems contain accessibility guidelines in order to increase the usability of products for people with all kinds of abilities. These guidelines ensure that the design is inclusive and complies with accessibility standards like WCAG (Web Content Accessibility Guidelines). This includes colour contrast, keyboard navigation and other accessibility features.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/Rayna-55.png" alt="Image" width="600" height="400" loading="lazy">
<em>Accessibility guidelines of Google's Material Design</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/Rayna-56.png" alt="Image" width="600" height="400" loading="lazy">
<em>Accessibility guidelines of the Atlassian design system</em></p>
<h4 id="heading-examples-and-use-cases">Examples and Use Cases</h4>
<p>Most design systems also contain examples and use cases of the design system in action to help designers and developers understand how to implement it effectively.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/Rayna-52.png" alt="Image" width="600" height="400" loading="lazy">
<em>Fintech Dashboard use case from Rayna UI design system</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/Rayna-63.png" alt="Image" width="600" height="400" loading="lazy">
<em>Applying type use case from Google's Material Design</em></p>
<h2 id="heading-differences-between-a-design-system-and-a-style-guide">Differences Between a Design System and a Style Guide</h2>
<p>Style guides and design systems are very similar and can often be confused for the same thing – but they're different. </p>
<p>Some differences between design systems and style guides are:</p>
<h3 id="heading-scope">Scope</h3>
<p>Style guides are relatively limited in scope and may not include detailed UI components or interactions. </p>
<p>Design systems on the other hand, are more comprehensive and encompass a broader range of elements including interactive components, user interface guidelines, amongst others.</p>
<h4 id="heading-consistency-1">Consistency</h4>
<p>Style guides typically focus on ensuring brand consistency, helping maintain a uniform look and feel across various materials and platforms. </p>
<p>Design systems aim to establish both brand and user interface consistency, by providing reusable components and interaction patterns.</p>
<h4 id="heading-evolution-and-scalability">Evolution and Scalability</h4>
<p>Style guides tend to evolve more slowly, and might not be as scalable as design systems. Design systems are more adaptable and evolve with the product or service.</p>
<h4 id="heading-collaboration-1">Collaboration</h4>
<p>Style guides are mainly used by designers to ensure visual consistency across a brand. They have a limited role in facilitating collaboration amongst designers and developers. </p>
<p>Design systems, on the other hand, promote collaboration by providing a common language and shared resources between designers and developers.</p>
<h3 id="heading-real-life-examples-of-design-systems">Real-Life Examples of Design Systems</h3>
<p>A lot of software corporations have created their own design systems to help ease the work of their designers and generally make it a smoother experience to build products. </p>
<p>Google, for instance, has a design system which they use for their products – you can see similar styles and elements in most of their products. </p>
<p>Most of these design systems are free and available to the public for use. Some examples of real life design systems are:</p>
<ul>
<li><a target="_blank" href="https://m3.material.io/">Google Material Design</a> by Google</li>
<li><a target="_blank" href="https://developer.apple.com/design/human-interface-guidelines">Apple Human Interface Guidelines</a> by Apple</li>
<li><a target="_blank" href="https://atlassian.design/">Atlassian Design System</a> by Atlassian</li>
<li><a target="_blank" href="https://polaris.shopify.com/">Polaris</a> by Shopify</li>
<li><a target="_blank" href="https://carbondesignsystem.com/">Carbon Design System</a> by IBM</li>
</ul>
<h2 id="heading-how-to-use-a-design-system-for-your-designs-rayna-ui-design-system-example">How to Use a Design System for Your Designs – Rayna UI Design System Example</h2>
<p>For this article, we'll be using the Rayna UI Design System to illustrate how to use a design system for your designs. </p>
<p>It's a newer design system that I recently learned about, so I thought I'd share my experience by using it for a challenge.</p>
<h3 id="heading-step-1-download-the-design-system">Step 1 – Download the Design System</h3>
<p>The first step will be to download the design system you're trying to use. In this case, we'll download the Rayna UI Design System. Go to their landing page @<a target="_blank" href="https://www.raynaui.com/">Rayna UI</a> and grab it from there.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/Rayna-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Rayna UI Landing page</em></p>
<p>Next, click on "Get Rayna UI" to download the design system. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/Rayna-2.png" alt="Image" width="600" height="400" loading="lazy">
<em>Rayna UI Landing page</em></p>
<p>Next, type your email in order to get the design system sent to your email address.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/rayna-3.png" alt="Image" width="600" height="400" loading="lazy">
<em>Provinding your email address</em></p>
<p>The link to the Figma file will be shared to your email, and you can open it.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/Rayna-4.png" alt="Image" width="600" height="400" loading="lazy">
<em>Checking your email</em></p>
<p>Scroll down in the email to find the link to view the Rayna UI Figma file.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/Rayna-5.png" alt="Image" width="600" height="400" loading="lazy">
<em>Checking your email</em></p>
<p>Click on the link sent to your email to open the design system. The link will open up the Rayna UI Design System on the Figma community. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/Rayna-1.1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Opening the Rayna UI file in Figma Community</em></p>
<p>Next, click on the "Open in Figma" button by the right side of your screen.  This will open up a Figma file containing all assets and components of the Rayna UI Design System.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/Rayna-6.png" alt="Image" width="600" height="400" loading="lazy">
<em>Opening the Rayna UI file in Figma</em></p>
<h3 id="heading-step-2-publish-the-rayna-ui-design-system-to-your-libraries">Step 2 – Publish the Rayna UI Design System to your libraries.</h3>
<p>The next step is to publish the Rayna UI Design System to your libraries, so you can use it for any design. </p>
<p>The third page on the Figma file (Get Started) contains a guide to getting started with the design system. Included in this guide are resources for beginners so you can gain a solid grasp of the basics, along with steps to take to publish and enable the library in other projects.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/Rayna-7.png" alt="Image" width="600" height="400" loading="lazy">
<em>Getting Started with the Rayna UI design system</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/Rayna-8.png" alt="Image" width="600" height="400" loading="lazy">
<em>Exploring the getting started section</em></p>
<p>Follow the steps given in the guide to publish the library. First, go to the assets panel in the top-left area of your screen, and press the book icon.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/Rayna-9.png" alt="Image" width="600" height="400" loading="lazy">
<em>Clicking on the "Assets" panel</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/Rayna-10.png" alt="Image" width="600" height="400" loading="lazy">
<em>Clickiing on the "book" icon</em></p>
<p>When you click on the book icon, it'll bring up a modal for you to publish the library. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/Rayna-1.2.png" alt="Image" width="600" height="400" loading="lazy">
<em>Publishing the library</em></p>
<p>Click on the publish button next to the file on the modal.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/Rayna-12.png" alt="Image" width="600" height="400" loading="lazy">
<em>Moving the library to a professional team</em></p>
<p>I was asked to move the library to a professional team, so I could publish there. Click on the "Move to team" button to move the file. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/Rayna-14.png" alt="Image" width="600" height="400" loading="lazy">
<em>Selecting a team.</em></p>
<p>Next, select the team file you want to publish the library to.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/Rayna-15.png" alt="Image" width="600" height="400" loading="lazy">
<em>Selecting a team</em></p>
<p>After selecting a team, you'll have to publish the design system to the team files.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/Rayna-16.png" alt="Image" width="600" height="400" loading="lazy">
<em>Publishing the design system</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/Rayna-17.png" alt="Image" width="600" height="400" loading="lazy">
<em>Publishing the design system</em></p>
<p>You'll receive a notification that your library has been published.</p>
<h2 id="heading-how-to-use-the-design-system-in-your-projects">How to Use the Design System in Your Projects</h2>
<p>Next, we'll be learning how to implement the design system in a design. I'll be designing a sign up screen for a fintech website to illustrate this. </p>
<p>Before starting your design, you can copy some icons you may need from the design system to your design file. I tend to copy the buttons and input field styles I may need, if I want to adhere strictly to the design system.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/Rayna-24-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Copied elements from the design system page.</em></p>
<p>For the sign up page I'm going to be designing, the details I need are the name of the website, input fields (full name, last name, email address, password, confirm password), and the buttons or CTAs (sign up and sign up with Google).</p>
<h2 id="heading-how-to-design-a-sign-up-web-screen">How to Design a Sign Up Web Screen</h2>
<h3 id="heading-step-1-select-a-frame">Step 1 – Select a Frame</h3>
<p>Firstly, I'll open the frame I'll be using. For this design, I'll be using the desktop frame (1440 x 1024). </p>
<p>To open a frame, go to the tools panel on the top left-hand corner of your screen. A panel with different kinds of frame types and sizes will come up. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/Rayna-25-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Tools panel-Frame</em></p>
<p>Open the Desktop section and choose "Desktop" (1440 x 1024). The frame will appear on your screen, and you can start designing. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/Rayna-26.1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Choosing a frame</em></p>
<h3 id="heading-step-2-add-grid-styles">Step 2 – Add Grid Styles</h3>
<p>I like using grids for arrangement and consistency in my designs, so I'll add a grid layout to the frame. </p>
<p>In the Rayna UI Design System, there are already existing grid styles so I can just choose one. To add a grid style, go to the panel on your right, and click on the 4-block menu on the <em>layout grid</em> section.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/Rayna-26-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Grid style panel</em></p>
<p>A list of different grid styles on the design system will come up, and you can choose any which corresponds with the kind of screen you're designing for. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/Rayna-27-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Choosing a grid style</em></p>
<p>Since I'm designing with a desktop frame, I'll choose <em>Large</em>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/Rayna-28-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Choosing a grid style for a frame</em></p>
<p>You can detach instance to see the specifications of the grid style you chose. To detach instance, click on the detach icon next to the eye icon on the layout grid section. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/Rayna-29-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Detaching style</em></p>
<p>You can now see the specifications for the grid style you chose. Since I chose <em>Large</em>, the grid specifications are: </p>
<ul>
<li>Count – 12, using columns</li>
<li>Colour – F4BBAE, with opacity set to 20%</li>
<li>Type – Stretch</li>
<li>Width – Auto </li>
<li>Margin – 112</li>
<li>Gutter – 32</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/Rayna-30.png" alt="Image" width="600" height="400" loading="lazy">
<em>Grid style specifications</em></p>
<h3 id="heading-step-3-add-content">Step 3 – Add Content</h3>
<p>I'll go ahead to start adding content to the screen. I'll use a text to represent my logo – Ketusha. </p>
<p>You can also control text styles and sizes on the design system. To do that, go to the Text panel on the left hand side of your screen. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/Rayna-31.png" alt="Image" width="600" height="400" loading="lazy">
<em>Editing text size</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/Rayna-32.png" alt="Image" width="600" height="400" loading="lazy">
<em>Confirming text size</em></p>
<p>Following the same format, I typed a heading for the form called "Sign Up".</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/Rayna-33.png" alt="Image" width="600" height="400" loading="lazy">
<em>Sign Up form heading</em></p>
<p>Earlier, I suggested that you copy the icons, buttons, and input fields samples from the design system file, so you can use them easily while designing. Now, I'm going to paste the input field sample I copied in my frame.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/Rayna-35.png" alt="Image" width="600" height="400" loading="lazy">
<em>Pasting input field sample in frame</em></p>
<p>Since I want the input field to be longer, I'll elongate it slightly to 400 width. It was previously 375 width.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/Rayna-36.png" alt="Image" width="600" height="400" loading="lazy">
<em>Elongating input field width</em></p>
<p>Next, I'll structure the input field to how I want it to look like – without icons.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/Rayna-37.png" alt="Image" width="600" height="400" loading="lazy">
<em>Input field without icons</em></p>
<p>Next, I'll edit the label to the label I want for my design.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/Rayna-38.png" alt="Image" width="600" height="400" loading="lazy">
<em>Editing label</em></p>
<p>Next, I'll just duplicate the input field until I'm satisfied, and also edit all the labels.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/Rayna-39.png" alt="Image" width="600" height="400" loading="lazy">
<em>Adding other input fields</em></p>
<p>Next, I'll add the buttons to the screen.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/Rayna-40.png" alt="Image" width="600" height="400" loading="lazy">
<em>Adding CTAs</em></p>
<p>I'll add the "Sign up with Google" button, so the user can have different options for signing up on the platform. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/Rayna-41.png" alt="Image" width="600" height="400" loading="lazy">
<em>Adding other sign up options</em></p>
<p>Next, I'll try to paste the google icon inside the "Sign up with Google" frame but that might not be possible.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/Rayna-42.png" alt="Image" width="600" height="400" loading="lazy">
<em>Pasting Google icon</em></p>
<p>To be able to paste and replace an item inside the selection, I'll have to detach the instance. To do this, right click on the item you're trying to replace. A list of options will come up. Click on "detach instance".</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/Rayna-43.png" alt="Image" width="600" height="400" loading="lazy">
<em>Detach instance</em></p>
<p>After that, right click on the icon again, and "paste to replace". </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/Rayna-44.png" alt="Image" width="600" height="400" loading="lazy">
<em>Paste to replace</em></p>
<p>The icon will be replaced instantly.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/Rayna-45.png" alt="Image" width="600" height="400" loading="lazy">
<em>Web sign up form</em></p>
<p>We just created a sign up page using the Rayna UI Design System!</p>
<p>Keep in mind that using a design system doesn't mean you cannot be creative and add your own flair. You can add your own style and creativity as much as you'd like as you go. </p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Using design systems is a necessary skill every designer and developer should cultivate. </p>
<p>Design systems are a critical component of modern product design and development, fostering collaboration, efficiency, and innovation.</p>
<p>Thank you for reading!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Create a Design System in Next.js with Tailwind CSS and Class Variance Authority ]]>
                </title>
                <description>
                    <![CDATA[ By Olasunkanmi Balogun Building a web application and producing a smooth user experience in the always changing world of web development requires more than just good looks – you also need to make sure that your application's design is efficient and c... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-a-design-system-in-next-js-with-tailwind-css-and-class-variance-authority/</link>
                <guid isPermaLink="false">66d4608c9f2bec37e2da065e</guid>
                
                    <category>
                        <![CDATA[ Design Systems ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Next.js ]]>
                    </category>
                
                    <category>
                        <![CDATA[ tailwind ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Thu, 21 Sep 2023 07:58:30 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/09/martin-adams-_OZCl4XcpRw-unsplash.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Olasunkanmi Balogun</p>
<p>Building a web application and producing a smooth user experience in the always changing world of web development requires more than just good looks – you also need to make sure that your application's design is efficient and consistent throughout. </p>
<p>If you have a design system in place, you can easily build UI components that are consistent and can be reused across numerous projects while still looking nice.</p>
<p>A design system is a set of reusable UI components and design tokens. These tokens are like building blocks that include things like buttons, colors, and fonts. Its goal is to enable developers and designers to create engaging product experiences by providing consistent user experience across all products.</p>
<p>Designers often use tools like Figma to create these systems. Here's an example of a design system made in Figma:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/Design-System.jpg" alt="Design-System" width="600" height="400" loading="lazy"></p>
<p>After designers make these parts, developers can use different tools to actually use them and build the website. There are various frameworks that frontend engineers can choose from to do this. Some popular ones are <code>MaterialUI</code> and <code>ChakraUI</code>. These libraries can make things easier, but they might not cover all the special cases you want.</p>
<p>If you or your design team have specific designs in mind that don't match what existing libraries offer, you'll need to dive into writing a substantial amount of code. However, this process can quickly become tiresome and burdensome, especially when the code you're creating lacks consistency or when you find yourself repeatedly constructing the same UI elements.</p>
<p>This is where a design system becomes incredibly valuable. Armed with the knowledge of how to implement a design system, you gain the ability to craft a tailored design that seamlessly integrates with the existing design system, offering the level of flexibility you desire.</p>
<p>Furthermore, this approach offers the advantage of only having to construct only the components you truly need. Unlike using libraries, which often come with numerous pre-built components you might never use, this method keeps your codebase focused and efficient.</p>
<p>Creating your own design might sound appealing, but it's not as straightforward as it might appear. </p>
<p>Nonetheless, with the assistance of styling tools such as <code>Tailwind CSS</code> (which is ideal due to its high level of customization), a library known as <a class="post-section-overview" href="#https://cva.style/docs"><code>cva</code></a> (which is short for <code>class-variance-authority</code>), and along with <code>TypeScript</code>, the process of establishing your custom design system within <code>Next.js</code> becomes notably achievable.</p>
<p>Now that you have a clear understanding of what a design system is and its significance, continue reading to discover how these tools can be effectively combined to achieve our objectives.</p>
<h2 id="heading-project-setup-installation-of-the-cva-library">Project Setup: Installation Of The CVA Library</h2>
<p>For the purpose of this article, it is assumed that you have already set up your <code>Next.js</code> project and incorporated <code>TypeScript</code> and <code>Tailwind CSS</code>. </p>
<p>If not, integrating these two elements into a new <code>Next.js</code> project is a straightforward process.</p>
<p>Following this initial setup, you can effortlessly add the <code>CVA</code> library to your project using the following command:</p>
<pre><code class="lang-npm">npm i class-variance-authority
</code></pre>
<p>With the inclusion of <code>CVA</code>, a user-friendly interface is at your disposal, simplifying the definition of variants. </p>
<p>These variants enable the conditional application of class sets, while also offering the means to express default variations. If this sounds a bit complex at the moment, don't worry – we'll delve into practical examples as we move forward.</p>
<h2 id="heading-practical-example-implementing-a-custom-design-system">Practical Example: Implementing a Custom Design System</h2>
<p>Imagine a situation where you're constructing a CRUD application, equipped with <code>buttons</code> to carry out various actions such as <code>create</code>, <code>read</code>, <code>update</code>, and <code>delete</code>.</p>
<p>While these <code>buttons</code> might share common attributes like <code>font-size</code> and <code>border-radius</code>, they might differ slightly – for instance, in their colors. Perhaps you'd prefer a red <code>button</code> for the delete action, a blue one for create, and a black one for update.</p>
<p>Traditionally, you might consider creating separate components for each <code>button</code> and assigning them distinct colors. For instance, to make the black <code>button</code>, you'd include the <code>Tailwind CSS</code> utility class <code>bg-black</code> to set the background color:</p>
<pre><code class="lang-tsx">export default function Button() {
  return (
    &lt;button
      className="bg-black rounded-3xl py-2 text-white w-80 font-sm"
      // other button attributes
    &gt;
      //button text
    &lt;/button&gt;
  );
}
</code></pre>
<p>However, instead of creating separate components for each <code>button</code>, you can streamline the process by designing a single <code>button</code> component that can adapt to the various button variants you need. This concept is the heart of a design system. </p>
<p>Let's explore how we can transform this same button component we previously created to suit our needs.</p>
<p>Our first step is to import the <code>cva</code> function and the <code>VariantProps</code> from the <code>class-variance-authority</code> library. As we proceed, the significance of these imports will become apparent:</p>
<pre><code class="lang-tsx">import { cva, VariantProps } from 'class-variance-authority'
</code></pre>
<p>Subsequently, we will define a variable named <code>buttonStyles</code>. This variable will house the invocation of the cva function. </p>
<p>Within this function, we'll first provide the default <code>styles</code> for the buttons, followed by the <code>variants</code> object. This object will contain the variations for the different types of buttons we desire. This segment is pivotal when implementing the design system. </p>
<p>In your code, include the following code snippet:</p>
<pre><code class="lang-tsx">const buttonStyles = cva("rounded-3xl py-2 text-white w-80 font-sm", {
  variants: {
    intent: {
      primary: "bg-blue-700",
      secondary: "bg-black",
      danger: "bg-red-600",
    },
    defaultVariants: {
      intent: "primary",
    },
  },
});
</code></pre>
<p>Within the embedded <code>variants</code> object, there exists another object named <code>intent</code>. This is where you assign names to the distinct button variations you desire – for instance, <code>primary</code>, <code>secondary</code>, and <code>danger</code>, corresponding to the <code>create</code>, <code>update</code>, and <code>delete</code> buttons respectively. </p>
<p>The style defined for the <code>intent</code> specified when rendering the <code>button</code> will be applied to that <code>button</code>, wherever it appears.</p>
<p>Additionally, the <code>variants</code> object features another property called <code>defaultVariants</code>. The <code>intent</code> within the <code>defaultVariant</code> object will be applied when no explicit <code>intent</code> is provided. In this instance, we have set the default <code>intent</code> to <code>primary</code>.</p>
<p>Next, we'll define an interface named <code>ButtonProps</code> which extends the <code>VariantProps</code> type provided by the <code>class-variance-authority</code> library:</p>
<pre><code class="lang-tsx">interface ButtonProps extends VariantProps&lt;typeof buttonStyles&gt; {
  text: string;
}
</code></pre>
<p>This interface is used to define the props that the <code>Button</code> component will accept. The <code>VariantProps</code> type from <code>class-variance-authority</code> adds the <code>intent</code> property, which will be used to determine the <code>variant</code> of the <code>button</code>. The interface also includes an additional property called <code>text</code>, which is of type <code>string</code>, it is the actual text that will appear on the <code>button</code>. </p>
<p>Having done this, we can go ahead and implement the <code>Button</code> component with respect to this defined <code>interface</code>:</p>
<pre><code class="lang-tsx">export default function Button({ intent, text, ...props }: ButtonProps) {
  return (
    &lt;button className={buttonStyles({ intent })} {...props}&gt;
      {text}
    &lt;/button&gt;
  );
}
</code></pre>
<p>In the <code>Button</code> component function, we used object destructuring to receive the <code>intent</code> property from the <code>ButtonProps</code> passed to the component. </p>
<p>Additionally, we used the spread operator <code>(...props)</code> to spread any other props that might be passed to the component. This allows us to easily pass down any other attributes or event handlers to the <code>&lt;button&gt;</code> element.</p>
<p>This also makes our <code>props</code> accurately typed, with their types precisely aligned as you hover over each one. For instance, the <code>intent</code> prop strictly adheres to the <code>intents</code> we defined within the <code>buttonStyles</code> variable, ensuring a robust type correspondence:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/Screenshot--166-.png" alt="Screenshot--166-" width="600" height="400" loading="lazy"></p>
<p>Moving on, the crucial part is the <code>className</code> attribute on the <code>&lt;button&gt;</code> element. We're using the <code>buttonStyles</code> function to pass in an object with the <code>intent</code> property, which corresponds to the desired button variant (<code>primary</code>, <code>secondary</code>, or <code>danger</code>). </p>
<p>This dynamically generates the appropriate <code>styles</code> based on the selected <code>intent</code>, applying the associated <code>styles</code> to the button.</p>
<p>At last, we've streamlined the process of creating <code>buttons</code> with different <code>styles</code>, allowing us to utilize a single <code>Button</code> component while dynamically altering its appearance through the <code>intent</code> prop, showcasing the effective implementation of our personalized design system.</p>
<p>With this in place, you're now equipped to render the <code>Button</code> component according to your needs and preferences. As a visual demonstration, let's observe the outcomes after rendering each of the variants:</p>
<pre><code class="lang-tsx">&lt;&gt;
  &lt;Button intent="primary" text="Create" /&gt; &lt;br /&gt; &lt;br /&gt;
  &lt;Button intent="secondary" text="Update" /&gt; &lt;br /&gt; &lt;br /&gt;
  &lt;Button intent="danger" text="Delete" /&gt; &lt;br /&gt; &lt;br /&gt;
&lt;/&gt;
</code></pre>
<p>Visual result:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/chrome-capture-2023-7-15--1-.png" alt="chrome-capture-2023-7-15--1-" width="600" height="400" loading="lazy"></p>
<p>This visual representation underscores the versatility and adaptability of our streamlined <code>Button</code> component, showcasing the distinct styling achieved through the intent-based approach within our own crafted design system.</p>
<h2 id="heading-wrapping-up">Wrapping Up</h2>
<p>Throughout this journey, you've gained insights into the potential of a design system to produce a versatile button component that dynamically changes colors in response to the provided intent. </p>
<p>It's important to note that this adaptability isn't confined solely to colors – you can similarly experiment with font sizes, text colors, and various other CSS properties.</p>
<p>Empowered by the insights you've gathered, you're now positioned to leverage this newfound knowledge to not only enhance your understanding of design systems but to also implement creative solutions that align with your unique project requirements. Happy Coding!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Create and Implement a Design System with CSS ]]>
                </title>
                <description>
                    <![CDATA[ If you are going to build a multi-page website, it is good to create a design system to help tie everything together. We just published a course on the freeCodeCamp.org YouTube channel that will teach you how to create and implement a design system w... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-create-and-implement-a-design-system-with-css/</link>
                <guid isPermaLink="false">66b20311712508eb16067855</guid>
                
                    <category>
                        <![CDATA[ CSS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Design Systems ]]>
                    </category>
                
                    <category>
                        <![CDATA[ youtube ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Beau Carnes ]]>
                </dc:creator>
                <pubDate>Tue, 08 Feb 2022 01:45:18 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/02/cssspace.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>If you are going to build a multi-page website, it is good to create a design system to help tie everything together.</p>
<p>We just published a course on the freeCodeCamp.org YouTube channel that will teach you how to create and implement a design system with CSS.</p>
<p>Kevin Powell created this course. Kevin is a CSS guru who has created many popular web development courses on a variety of platforms.  </p>
<p>This course will teach you how to bring high-quality Figma designs to life in the browser. You will learn how to create a space travel website from scratch.</p>
<p>In this course, you’ll test your HTML, CSS and JavaScript skills by building out a responsive, multi-page site featuring a homepage, buttons, a navigation bar, tabs, keyboard navigation and underline, dot and number indicators.</p>
<p>You’ll also learn how to create an effective design system to ensure that your site is sharp and professional, and your coding is as efficient as possible.</p>
<p>After completing this course, you’ll have a deep understanding of CSS and responsive design and the knowledge to build an interactive site which users will love.</p>
<p>Here all the topics covered in this course:</p>
<ul>
<li>Creating design systems</li>
<li>CSS resets</li>
<li>Utility classes</li>
<li>Using color</li>
<li>Responsive typography</li>
<li>Adding spacing</li>
<li>Effective buttons</li>
<li>Underline indicators</li>
<li>Dot indicators</li>
<li>Number indicators</li>
<li>Grid containers</li>
<li>Responsiveness</li>
<li>Adding background images</li>
<li>Navigation</li>
<li>Open/close buttons</li>
<li>Accessibility tweaks</li>
<li>Skip to content</li>
<li>Alignment</li>
<li>The picture element</li>
<li>Keyboard navigation</li>
<li>Tabs</li>
<li>Refactoring</li>
</ul>
<p>Watch the full course below or on <a target="_blank" href="https://www.youtube.com/watch?v=lRaL-8qZ0mM">the freeCodeCamp.org YouTube channel</a> (7-hour watch).</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/lRaL-8qZ0mM" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to build design system with SwiftUI ]]>
                </title>
                <description>
                    <![CDATA[ By Vince MingPu Shao Building a design system to support one product is not easy - it has to be robust and flexible at the same time for scalability. Though challenging, lots of great resources have shared useful principles and approaches that help t... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-build-design-system-with-swiftui/</link>
                <guid isPermaLink="false">66d4617736c45a88f96b7d13</guid>
                
                    <category>
                        <![CDATA[ Design ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Design Systems ]]>
                    </category>
                
                    <category>
                        <![CDATA[ iOS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Swift ]]>
                    </category>
                
                    <category>
                        <![CDATA[ SwiftUI ]]>
                    </category>
                
                    <category>
                        <![CDATA[ tech  ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Mon, 09 Sep 2019 23:42:20 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2019/09/preview-1.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Vince MingPu Shao</p>
<p>Building a design system to support one product is not easy - it has to be robust and flexible at the same time for scalability. Though challenging, <a target="_blank" href="https://www.designbetter.co/design-systems-handbook/building-design-system">lots</a> <a target="_blank" href="https://lightningdesignsystem.com/design-tokens/">of</a> <a target="_blank" href="https://medium.com/eightshapes-llc/tokens-in-design-systems-25dd82d58421">great</a> <a target="_blank" href="https://www.youtube.com/watch?v=wDBEc3dJJV8">resources</a> have shared useful principles and approaches that help teams build a good system both visually and programmatically. Standing on their shoulders, this article tries to contribute to an untouched ground by focusing on building a good system in <code>SwiftUI</code>.</p>
<h2 id="heading-why-do-i-write-this-article">Why do I write this article</h2>
<p>During my first summer in <a target="_blank" href="https://tisch.nyu.edu/itp">ITP</a> at New York, I'm lucky to have the opportunity to work as an iOS developer intern at <a target="_blank" href="https://www.linebreak.studio/">Line Break Studio</a>. One task I've been assigned to is building a design system in two steps: first visually in <a target="_blank" href="https://www.sketch.com/">Sketch</a>, and then programmatically in <code>SwiftUI</code>. The experience of experimenting with the new framework and building a design system with it has been amazing, but also buggy along the way. That's why we'd like to share our experience with the community, hopefully making your development process easier.</p>
<hr>
<h2 id="heading-what-is-swiftuihttpsdeveloperapplecomdocumentationswiftui">What is <a target="_blank" href="https://developer.apple.com/documentation/swiftui">SwiftUI</a></h2>
<p>Apple released this groundbreaking new framework in <a target="_blank" href="https://developer.apple.com/videos/wwdc2019/?q=swiftui">WWDC 2019</a>, which is one of the bests in years. From the point of view as a web developer, the project development experience in <code>SwiftUI</code> is closer to which in conventional front-end stack and frameworks.</p>
<p>This is definitely an awesome move because programming interface and managing states are drastically easier than before. And the best part of this improvement is that one can <a target="_blank" href="https://developer.apple.com/tutorials/swiftui/interfacing-with-uikit">integrate UIKit and SwiftUI smoothly</a>. To learn the basics of SwiftUI, the <a target="_blank" href="https://developer.apple.com/tutorials/swiftui/tutorials">official tutorials</a> provided by Apple are very helpful.</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/aH7oWxfxpJY" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<h2 id="heading-the-demo-project">The demo project</h2>
<p>For demonstration purpose, I put up a simplified version of design system we built in <a target="_blank" href="https://www.linebreak.studio/">Line Break Studio</a>. It a set of <strong>button</strong> components in different forms, which are built on top of two lower level parts: <strong>typography</strong> and <strong>colorPalette</strong>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/09/preview-record.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Dynamic rendering view of the demo project</em></p>
<p>The project is <a target="_blank" href="https://github.com/vince19972/SwiftUI-Design-System-Demo">public on GitHub</a>, and I'm using <code>Xcode 11 Beta 5</code> for development. An <a target="_blank" href="https://airtable.com/shrHQdv9vQGz7UMQj">Airtable base</a> as design system management hub (read <a target="_blank" href="https://www.vinceshao.com/blog/a-better-web-development-workflow-confluence-airtable-jira-and-abstract">more about workflow management</a>) is also public for reference.</p>
<hr>
<h2 id="heading-principles-of-building-design-system">Principles of building design system</h2>
<p>Design system in code is a middleware between designers and developers. Developer of the system takes inputs from design system in visual form, and produces API that's identical with which for further development. Following two principles should be recognized to complete this system in code:</p>
<h3 id="heading-1-communicate-with-tokenshttpsmediumcomeightshapes-llctokens-in-design-systems-25dd82d58421">1. Communicate with <a target="_blank" href="https://medium.com/eightshapes-llc/tokens-in-design-systems-25dd82d58421">tokens</a></h3>
<p>Fundamentally, the purpose of having a design system in program is not about better code management or development efficiency, but to make sure the <strong>view</strong> is consistent with design files. To achieve that goal, using tokens to signify certain color, font, size or any visual elements is crucial to maintain quality of communication between developers, designers and managers in a team.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/09/lightning-token.png" alt="Image" width="600" height="400" loading="lazy">
<em><a target="_blank" href="https://www.lightningdesignsystem.com/design-tokens/">Lightning Design System</a>'s tokens built by Salesforce</em></p>
<h3 id="heading-2-levels-of-hierarchy">2. Levels of hierarchy</h3>
<p>In <a target="_blank" href="https://medium.com/eightshapes-llc/tokens-in-design-systems-25dd82d58421">EightShapes' article</a>, it points out that we should "Show options first, then decisions next", because "You can't make decisions without options."</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/09/eightshape-article.png" alt="Image" width="600" height="400" loading="lazy">
<em><a target="_blank" href="https://medium.com/eightshapes-llc/tokens-in-design-systems-25dd82d58421">EightShapes' article</a> about design tokens</em></p>
<p>This kind of ordering architecture loosens  the degree of coupling between different levels, hence providing more flexibility and dynamic for possible revisions. The way I structure the levels is in this order from bottom to top: material → base → token. But it could be anyway the team's comfortable with.</p>
<hr>
<h2 id="heading-diving-into-code">Diving into code</h2>
<p>Following section is a list of highlights we'd like to point out based on our experience. Please <a target="_blank" href="https://github.com/vince19972/SwiftUI-Design-System-Demo">visit the GitHub repo</a> for complete code. Any feedbacks or critics are welcome for improvements.</p>
<h3 id="heading-1-architecting-levels-of-hierarchy">1. Architecting levels of hierarchy</h3>
<p>There're two ways of stacking materials at lower level to construct tokens at highest level:</p>
<ul>
<li><strong>Use <code>enum</code> for type safety and code literacy</strong></li>
</ul>
<p>Advantages of using enum in code as grouping wrapper or parameter in function have already been well recognized. One point worths mentioning here is the implementation of levels of hierarchy.</p>
<p>We always store the raw values, including font size (<code>CGFloat</code>) and font name (<code>String</code>), at the lowest level, because we don't want to mess around with it. But because raw value must be a literal in enum, we can't just assign a <code>case</code> to be a value from the other enum.</p>
<p>To work around this problem, we implement a function <code>getValue</code>, which returns the raw value in <code>switch</code> case when necessary.</p>




<ul>
<li><strong>Use <code>struct</code> for easier structure</strong></li>
</ul>
<p>Though enum is great, we don't need its unique feature in some cases. For example, because <code>Xcode</code> takes care of the heavy job of processing dynamic colors, and no parameter options are required in API endpoint, we can set up color palettes by simple two levels of struct.</p>




<h3 id="heading-2-clear-and-straightforward-naming-of-api-endpoint">2. Clear and straightforward naming of <code>API</code> endpoint</h3>
<p>Naming convention is another broad topic for discussion and debate. In addition to basic <a target="_blank" href="https://swift.org/documentation/api-design-guidelines/">Swift conventions</a>, the only two rules we abide are, 1) no acronym and 2) making it simple. For example, to use typography and color system, instead of creating new endpoints, we make extension from Font and Color structs. This approach decreases the effort to memorize unfamiliar API names for developers.</p>




<h3 id="heading-3-manage-color-sets-dynamically-in-two-modes">3. Manage color sets dynamically in two modes</h3>
<p>So dark mode has become a standard in industry, and both <a target="_blank" href="https://developer.apple.com/design/human-interface-guidelines/ios/visual-design/dark-mode/">iOS</a> and <a target="_blank" href="https://material.io/design/color/dark-theme.html">Android</a> team have implemented this feature. It's a good trend for users, but could bring designers and developers some challenges, including managing and naming the color sets, especially gray scale ones.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/09/material-dark.png" alt="Image" width="600" height="400" loading="lazy">
<em><a target="_blank" href="https://material.io/design/color/dark-theme.html">Material Design</a>'s dark theme guide</em></p>
<p>To think and communicate about gray scale colors dynamically, using terms like <em>white</em>, <em>light</em>, <em>black</em> or <em>dark</em> doesn't work. Because if we referred to a dynamic color <code>#000000</code> (black in HEX) <em>black</em> or <em>dark</em> in <code>light color scheme</code>, how do you talk about this particular color, which should turn into <code>#FFFFFF</code> (white in HEX), in <code>dark color scheme</code>? <em>defaultDark</em> or <em>lightDark</em>?</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/09/color-transition.png" alt="Image" width="600" height="400" loading="lazy">
<em>Confusing transition of color sets</em></p>
<p>It is very confusing to name gray scale dynamic color sets in conventional approach. To avoid this confusion, we use <code>theme</code> and <code>contrast</code> to manage one set of color in <code>light</code> and <code>dark</code> schemes instead.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/09/airtable-color-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Example color naming in demo <a target="_blank" href="https://airtable.com/shrHQdv9vQGz7UMQj">Airtable base</a></em></p>
<p>Note that a gray scale color doesn't always need to be reversed in opposite color mode. In these situations that light color remains light and dark remains dark, we simply name name it light or dark instead.</p>
<p>Once we wrap our head around this naming method, managing this architecture of color palette is easy in <code>Xcode</code>. To create a color set, simply create a new <code>Asset Catalog</code> file → add a new <code>Color Set</code> → and change <code>Appearances</code> to <code>Any, Light, Dark</code> will do.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2019/09/color-asset.png" alt="Image" width="600" height="400" loading="lazy">
<em>How to add color asset in Xcode</em></p>
<h3 id="heading-4-environment-settings">4. <code>environment</code> settings</h3>
<p>One awesome feature in SwiftUI framework is the <a target="_blank" href="https://developer.apple.com/documentation/swiftui/environment">environment modifier</a>, which provides ability to control <a target="_blank" href="https://developer.apple.com/documentation/swiftui/environmentvalues">environment values</a> on target view. In terms of building design system, this ability provides convenient approach to change app's font at root level. And the other advantage of using <code>environmentValue</code> is to change and test light and dark color schemes in development.</p>




<h3 id="heading-5-buttonstyle-and-button-label">5.  <code>buttonStyle</code> and button label</h3>
<p>Comparing to the old days in <a target="_blank" href="https://developer.apple.com/documentation/uikit">UIKit</a>, constructing reusable buttons in SwiftUI is drastically easier. The <a target="_blank" href="https://developer.apple.com/documentation/swiftui/button">Button view</a> consists of two parts, which are <code>action</code> closure (event to be fired as button is pressed) and <code>label</code> (body of the button). The view can then be chained with a modifier <code>buttonStyle</code>. To learn details about building reusable buttons,I recommend reading <a target="_blank" href="https://alejandromp.com/blog/2019/06/22/swiftui-reusable-button-style/">Alejandro's tutorial</a>, which is comprehensive and useful.</p>
<p>In our customized button components, first step is to create two structs, including <code>TokenButtonLabel</code> and <code>TokenButtonStyle</code>. These two structs are programmed according to the types of buttons we have in design files. For example, there're only two types of labels: icon and text. Each type has an according <code>init</code> function designed with different parameters for new instances.</p>


<p>On the other hand, there're four major types of button styles: circle icon, icon, capsule and text. To follow <code>ButtonStyle</code> protocol, a <code>makeBody</code> func has to be implemented. This function brings us a <code>configuration</code> property, providing a native <code>isPressed</code> value to monitor if the button is pressed or not.</p>


<p>Finally, stacking on top of <code>TokenButtonLabel</code> and <code>TokenButtonStyle</code>, the endpoint of the button component API will be <code>TokenButton</code> - a grouping that wraps content and style of button together, conforming to the button types in visual design system.</p>




<h3 id="heading-6-anyview-as-wrapper">6. <code>AnyView</code> as wrapper</h3>
<p>As we're dealing with the <code>makeBody</code> function brought by <code>ButtonStyle</code> protocol, we found a useful tip to work with <code>View</code>. To store a view in a variable, the type annotation could be indicated as <code>AnyView</code>, which works as a general container of views in SwiftUI.</p>
<p>In our case, because we want to add the opacity modifier to <code>configuration.label</code> to all types of buttons, instead of doing so repeatedly in each <code>switch</code> case, it makes more sense to chain the modifier at the end altogether. We can achieve this pattern by using the advantage of <code>AnyView</code> in this way:</p>




<h3 id="heading-7-build-view-modifier-with-mutating-function">7. Build view modifier with <code>mutating</code> function</h3>
<p>To update styles of the buttons dynamically, we can build our own modifier. First instantiate customized mutable state properties in view, and then create a <code>mutating</code> function which returns a <code>Self</code> type after updating the target state property.</p>




<h3 id="heading-8-tricky-border-style">8. Tricky border style</h3>
<p>One drawback of SwiftUI is styling a circle shape with circular border is not straightforward at all. I struggled for a while, and finally found a <a target="_blank" href="https://stackoverflow.com/questions/57269651/add-a-border-with-cornerradius-to-an-image-in-swiftui-xcode-beta-5">solution here on StackOverflow</a>. A <code>clipShape</code> and an <code>overlay</code> modifier are required to make it work.</p>




<hr>
<h2 id="heading-conclusion">Conclusion</h2>
<p>SwiftUI is an incredible improvement Apple makes. Though flaws still exist, building a robust and flexible design system with it, and furthermore complicated UI in iOS is way efficient than ever. I hope this article is helpful for any iOS team trying to build UI, and always welcome to any feedbacks!</p>
<p>? Read more of my works at <a target="_blank" href="https://www.vinceshao.com">vinceshao.com</a> / Follow me on <a target="_blank" href="https://twitter.com/vincemingpushao">Twitter</a> or <a target="_blank" href="https://www.linkedin.com/in/vinceshao/">LinkedIn</a></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to connect a React Design System with Firebase and Redux ]]>
                </title>
                <description>
                    <![CDATA[ By Nazare Emanuel Ioan After almost two years of working with ReactJS at Creative-Tim, years while I’ve been creating simple front-end ReactJS projects, front-end templates, I have started to learn more about React, and create some tutorials. After l... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-connect-a-react-design-system-with-firebase-and-redux-9646ca1c733f/</link>
                <guid isPermaLink="false">66c350b75ced6d98e4bd334f</guid>
                
                    <category>
                        <![CDATA[ Design Systems ]]>
                    </category>
                
                    <category>
                        <![CDATA[ General Programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Redux ]]>
                    </category>
                
                    <category>
                        <![CDATA[ tech  ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Tue, 02 Apr 2019 20:41:58 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*gILubZM4zMQnVf4CAm-NSA.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Nazare Emanuel Ioan</p>
<p>After almost two years of working with <a target="_blank" href="https://reactjs.org/">ReactJS</a> at <a target="_blank" href="https://www.creative-tim.com/?ref=trrfadr-medium">Creative-Tim</a>, years while I’ve been creating simple front-end ReactJS projects, front-end templates, I have started to learn more about React, and create some tutorials.</p>
<p>After long hours of watching and reading firebase tutorials, firebase &amp; react tutorials, and reading the officials docs of firebase, I am ready to write myself a tutorial.</p>
<p><strong>What I am going to use in this little tutorial article:</strong></p>
<ul>
<li><a target="_blank" href="https://www.npmjs.com/package/npm">npm@6.4.1</a></li>
<li><a target="_blank" href="https://nodejs.org/en/">nodejs@10.15.3 (LTS version)</a></li>
<li><a target="_blank" href="https://atom.io/">Atom Editor version 1.35.0</a></li>
<li><a target="_blank" href="https://reactstrap.github.io/">Reactstrap</a></li>
</ul>
<p>We are going to use Redux and Firebase for Login, Register and to create some dynamic stat cards.</p>
<p>I will focus my attention on Firebase, and give explanations just about this. If you do not know Redux, it would be best to take a look at my other <a target="_blank" href="https://medium.freecodecamp.org/how-to-use-redux-in-reactjs-with-real-life-examples-687ab4441b85">tutorial about what Redux is, and what it does</a>. After that, you can easily return here.</p>
<h3 id="heading-getting-started-with-a-react-design-system">Getting started with a React Design System</h3>
<p>Since we do not have time to walk through creating our own design system — this would require days, weeks or even months to do — we will take one I’ve already worked on.</p>
<p>To get this project you can do one of the following (I am going to use the first option):</p>
<ul>
<li>Clone from Github:</li>
</ul>
<pre><code>git clone https:<span class="hljs-comment">//github.com/creativetimofficial/argon-dashboard-react.git</span>
</code></pre><ul>
<li><a target="_blank" href="https://github.com/creativetimofficial/argon-dashboard-react/archive/master.zip">Download from Github</a> (by pressing the link, it will automatically start the download)</li>
<li><a target="_blank" href="https://www.creative-tim.com/product/argon-dashboard-react">Download from Creative-Tim</a> (you will need to have an account there)</li>
</ul>
<p>After you’ve got the project, cd into it (in my case will be):</p>
<pre><code>cd argon-dashboard-react
</code></pre><p>Let’s start the product and see how it looks like:</p>
<pre><code>npm run install:clean
</code></pre><p><img src="https://cdn-media-1.freecodecamp.org/images/4gzCHNeU-XA-EKgRe8fPoLAb5iSp1QqRmHzA" alt="Image" width="1889" height="1080" loading="lazy">
<em>npm run install:clean — output</em></p>
<h3 id="heading-adding-redux-to-this-starter-template">Adding Redux to this starter template</h3>
<h4 id="heading-actions-reducers-and-store">Actions, Reducers, and Store</h4>
<p>Let’s go back into the terminal and run:</p>
<pre><code>npm i -E redux redux-thunk react-redux
</code></pre><p>When I ran this command, on my machine the installed versions were as follows:</p>
<ul>
<li>redux@4.0.1</li>
<li>redux-thunk@2.3.0</li>
<li>react-redux@6.0.1</li>
</ul>
<p>At the beginning of the tutorial, we’ve set our goal to make two things happen: login and register (auth) and to be able to add some dynamic cards from our database (simple add). This means we’ll have two reducers, one for authentication and one for the dynamic cards (also, we’ll need one root reducer that will combine these two). We’ll also have four actions, one for login, one for register, one for adding the cards to our database (you can think about these as to some todos) and one for getting from the database all these cards (which we’ll render in our app). And also, just a store.</p>
<p>So, this being said let's run the following commands:</p>
<p>1 — Linux/Mac commands</p>
<pre><code>mkdir src/actionsmkdir src/reducerstouch src/actions/addStatCardAction.jstouch src/actions/getAllStatCardsAction.jstouch src/actions/loginAction.jstouch src/actions/registerAction.jstouch src/reducers/statCardReducer.jstouch src/reducers/authReducer.jstouch src/reducers/rootReducer.jstouch src/store.js
</code></pre><p>2 — Windows commands</p>
<pre><code>mkdir src\actionsmkdir src\reducersecho <span class="hljs-string">""</span> &gt; src\actions\addStatCardAction.jsecho <span class="hljs-string">""</span> &gt; src\actions\getAllStatCardsAction.jsecho <span class="hljs-string">""</span> &gt; src\actions\loginAction.jsecho <span class="hljs-string">""</span> &gt; src\actions\registerAction.jsecho <span class="hljs-string">""</span> &gt; src\reducers\statCardReducer.jsecho <span class="hljs-string">""</span> &gt; src\reducers\authReducer.jsecho <span class="hljs-string">""</span> &gt; src\reducers\rootReducer.jsecho <span class="hljs-string">""</span> &gt; src\store.js
</code></pre><h4 id="heading-actions">Actions</h4>
<p><strong>src/actions/addStatCardAction.js</strong></p>
<p>The stat card that we want to dynamically create is one of these:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/FuY9TJygUIsa-6GQcaufpcbow6BGjgMuuTxJ" alt="Image" width="800" height="86" loading="lazy">
<em>stat cards to dynamically create</em></p>
<p>As we can see, they have a name, a stat, an icon (that varies in color), a footer icon and percentage (that once again, varies in color) and a footer text.</p>
<p>So, we’ll need to create the action that will accept all of the above, like so:</p>
<pre><code><span class="hljs-keyword">const</span> addStatCardAction = <span class="hljs-function">(<span class="hljs-params">  statName,  statDescription,  statIcon,  statIconColor,  statFooterIcon,  statFooterIconState,  statFooterPercentage,  statFooterText</span>) =&gt;</span> <span class="hljs-keyword">async</span> dispatch =&gt; {  <span class="hljs-comment">// here we'll make a call to our database (firebase)  // to add our new stat card with the above details</span>
</code></pre><pre><code>  dispatch({    <span class="hljs-attr">type</span>: <span class="hljs-string">"addStatCard"</span>,    <span class="hljs-attr">payload</span>: {      <span class="hljs-attr">statName</span>: statName,      <span class="hljs-attr">statDescription</span>: statDescription,      <span class="hljs-attr">statIcon</span>: statIcon,      <span class="hljs-attr">statIconColor</span>: statIconColor,      <span class="hljs-attr">statFooterIcon</span>: statFooterIcon,      <span class="hljs-attr">statFooterIconState</span>: statFooterIconState,      <span class="hljs-attr">statFooterPercentage</span>: statFooterPercentage,      <span class="hljs-attr">statFooterText</span>: statFooterText    }  });};
</code></pre><pre><code><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> addStatCardAction;
</code></pre><p>As we can see, we’re going to work with async action creators, since we are making calls to a database. After the call is done, we’ll need to send to our store the data that we’ve just added to our database in firebase.</p>
<p><strong>src/actions/getAllStatCardsAction.js</strong></p>
<p>This one will not require any params, since it only retrieves something from the database. So the code will look like this:</p>
<pre><code><span class="hljs-keyword">const</span> getAllStatCardsAction = <span class="hljs-function">() =&gt;</span> <span class="hljs-keyword">async</span> dispatch =&gt; {  <span class="hljs-comment">// here we'll make a call to our database (firebase)  // that will retrieve all of our stat cards</span>
</code></pre><pre><code>  dispatch({ <span class="hljs-attr">type</span>: <span class="hljs-string">"getAllStatCards"</span> , <span class="hljs-attr">payload</span>: {}});};
</code></pre><pre><code><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> getAllStatCardsAction;
</code></pre><p><strong>src/actions/loginAction.js</strong></p>
<p>For login, we’ll have an email and a password, so this is the code for this action (also our login form has an email and a password):</p>
<pre><code><span class="hljs-keyword">const</span> loginAction = <span class="hljs-function">(<span class="hljs-params">email, password</span>) =&gt;</span> <span class="hljs-keyword">async</span> dispatch =&gt; {  <span class="hljs-comment">// at the moment, since we haven't yet connected to the database  // we are going to say that each time we try to login  // we should not be able to log in (that is why we send false)</span>
</code></pre><pre><code>  dispatch({ <span class="hljs-attr">type</span>: <span class="hljs-string">"login"</span>, <span class="hljs-attr">payload</span>: <span class="hljs-literal">false</span> });};
</code></pre><pre><code><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> loginAction;
</code></pre><p><strong>src/actions/registerAction.js</strong></p>
<pre><code><span class="hljs-keyword">const</span> registerAction = <span class="hljs-function">(<span class="hljs-params">name, email, password</span>) =&gt;</span> <span class="hljs-keyword">async</span> dispatch =&gt; {  <span class="hljs-comment">// at the moment, since we haven't yet connected to the database  // we are going to say that each time we try to register  // we should not be able to register (that is why we send false)</span>
</code></pre><pre><code>  dispatch({ <span class="hljs-attr">type</span>: <span class="hljs-string">"register"</span>, <span class="hljs-attr">payload</span>: <span class="hljs-literal">false</span> });};
</code></pre><pre><code><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> registerAction;
</code></pre><h4 id="heading-reducers">Reducers</h4>
<p><strong>src/reducers/statCardReducer.js</strong></p>
<p>Since we have two actions about the stat card, we’ll have two cases in this reducer:</p>
<pre><code><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> (state = {}, action) =&gt; {  <span class="hljs-keyword">switch</span> (action.type) {    <span class="hljs-keyword">case</span> <span class="hljs-string">"addStatCard"</span>:      <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"adding "</span>, action.payload);      <span class="hljs-comment">// since we will always fetch our stat cards      // from firebase, each time we add one new      // we will just return the state      return state;    case "getAllStatCards":      console.log("getting ", action.payload);      console.log(action.payload);      return {        // keep the old state        ...state,        // add all the cards from the database        // they will come in a json format,        // so we need to convert them to array        statCardState: Object.values(action.payload)      };    default:      return state;  }};</span>
</code></pre><p>We’re also logging what we are adding and what we are trying to get from our firebase.</p>
<p><strong>src/reducers/authReducer.js</strong></p>
<pre><code><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> (state = {}, action) =&gt; {  <span class="hljs-keyword">switch</span> (action.type) {    <span class="hljs-comment">// in both cases, we want to tell our app,    // if the user is logged in or not    // if the user registers, he will automatically be logged in</span>
</code></pre><pre><code>    <span class="hljs-keyword">case</span> <span class="hljs-string">"register"</span>:      <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"register is "</span>,action.payload);      <span class="hljs-keyword">return</span> {        <span class="hljs-comment">// keep old state        ...state,        // add true/false if the user is or not logged in        loggedIn: action.payload      };    case "login":      console.log("login is ",action.payload);      return {        // keep old state        ...state,        // add true/false if the user is or not logged in        loggedIn: action.payload      };    default:      return state;  }};</span>
</code></pre><p>When we register a new user, we’ll automatically log them in. We’ve also added some logs to see if the registration or the login is successful.</p>
<p><strong>src/reducers/rootReducer.js</strong></p>
<p>This is for combining the above reducers:</p>
<pre><code><span class="hljs-keyword">import</span> { combineReducers } <span class="hljs-keyword">from</span> <span class="hljs-string">"redux"</span>;
</code></pre><pre><code><span class="hljs-keyword">import</span> authReducer <span class="hljs-keyword">from</span> <span class="hljs-string">"reducers/authReducer"</span>;<span class="hljs-keyword">import</span> statCardReducer <span class="hljs-keyword">from</span> <span class="hljs-string">"reducers/statCardReducer"</span>;
</code></pre><pre><code><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> combineReducers({  <span class="hljs-comment">// the authReducer will work only with authState  authState: authReducer,  // the statCardReducer will work only with statCardState  statCardState: statCardReducer});</span>
</code></pre><h4 id="heading-store">Store</h4>
<p><strong>src/store.js</strong></p>
<p>Since we have async action creators, we’ll need a middleware that will allow us to use these actions creators, hence the usage of redux-thunk:</p>
<pre><code><span class="hljs-keyword">import</span> { createStore, applyMiddleware } <span class="hljs-keyword">from</span> <span class="hljs-string">"redux"</span>;<span class="hljs-keyword">import</span> reduxThunk <span class="hljs-keyword">from</span> <span class="hljs-string">"redux-thunk"</span>;
</code></pre><pre><code><span class="hljs-keyword">import</span> rootReducer <span class="hljs-keyword">from</span> <span class="hljs-string">"reducers/rootReducer"</span>;
</code></pre><pre><code><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">configureStore</span>(<span class="hljs-params">  state = { authState: {}, statCardState: {} }</span>) </span>{  <span class="hljs-keyword">return</span> createStore(rootReducer, state, applyMiddleware(reduxThunk));}
</code></pre><pre><code><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> configureStore;
</code></pre><h4 id="heading-connecting-our-app-to-our-store">Connecting our app to our store</h4>
<p>At the moment, if we were to start our app, nothing would happen, since all the actions and our store are not being rendered in our app. So this is what we are going to do now.</p>
<p>First, let’s add our store, for this, we need to fo inside <strong>src/index.js</strong>.</p>
<p>Before the <strong>ReactDOM.render()</strong> function we need to add the following imports:</p>
<pre><code><span class="hljs-keyword">import</span> { Provider } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-redux"</span>;<span class="hljs-keyword">import</span> configureStore <span class="hljs-keyword">from</span> <span class="hljs-string">"store"</span>;
</code></pre><p>And after that, we’ll wrap the <strong>BrowserRouter</strong> from the <strong>ReactDOM.render()</strong> function inside the <strong>Provider</strong> tag as follows:</p>
<pre><code>&lt;Provider store={configureStore()}&gt;  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">BrowserRouter</span>&gt;</span>    <span class="hljs-tag">&lt;<span class="hljs-name">Switch</span>&gt;</span>      <span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"/admin"</span> <span class="hljs-attr">render</span>=<span class="hljs-string">{</span>          <span class="hljs-attr">props</span> =&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">AdminLayout</span> {<span class="hljs-attr">...props</span>} /&gt;</span>      } /&gt;      <span class="hljs-tag">&lt;<span class="hljs-name">Route</span> <span class="hljs-attr">path</span>=<span class="hljs-string">"/auth"</span> <span class="hljs-attr">render</span>=<span class="hljs-string">{</span>          <span class="hljs-attr">props</span> =&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">AuthLayout</span> {<span class="hljs-attr">...props</span>} /&gt;</span>      } /&gt;      <span class="hljs-tag">&lt;<span class="hljs-name">Redirect</span> <span class="hljs-attr">from</span>=<span class="hljs-string">"/"</span> <span class="hljs-attr">to</span>=<span class="hljs-string">"/admin/index"</span> /&gt;</span>    <span class="hljs-tag">&lt;/<span class="hljs-name">Switch</span>&gt;</span>  <span class="hljs-tag">&lt;/<span class="hljs-name">BrowserRouter</span>&gt;</span></span>&lt;/Provider&gt;,
</code></pre><p>Our next concern is to make our users to be redirected to the login page if not authenticated and if they are authenticated to be redirected to the user page. Basically, if they are logged in, they will not be able to access the Auth layout (<strong>src/layouts/Auth.jsx</strong>), and if they are not, they won’t be able to access the Admin layout (<strong>src/layouts/Admin.jsx</strong>).</p>
<p>Let’s go inside <strong>src/layouts/Auth.jsx</strong> and after the <strong>React</strong> import, make the following imports:</p>
<pre><code><span class="hljs-keyword">import</span> { connect } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-redux"</span>;<span class="hljs-keyword">import</span> { Redirect } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-router-dom"</span>;
</code></pre><p>After that let’s change the export of this component as follows:</p>
<pre><code><span class="hljs-keyword">const</span> mapStateToProps = <span class="hljs-function"><span class="hljs-params">state</span> =&gt;</span> ({  ...state});
</code></pre><pre><code><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> connect(  mapStateToProps,  {})(Auth);
</code></pre><p>After this, we go inside the <strong>render function</strong> of this component, and before the <strong>return</strong>, add the following code:</p>
<pre><code><span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.props.authState.loggedIn) {  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Redirect</span> <span class="hljs-attr">to</span>=<span class="hljs-string">"/admin/user-profile"</span> /&gt;</span></span>;}
</code></pre><p>So, if the user is authenticated, they will be redirected to their profile page.</p>
<p>Next, we go inside <strong>src/layouts/Admin.jsx</strong> and make the same changes as with the <strong>Auth</strong> layout. So add the following imports:</p>
<pre><code><span class="hljs-keyword">import</span> { connect } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-redux"</span>;<span class="hljs-keyword">import</span> { Redirect } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-router-dom"</span>;
</code></pre><p>Change it’s export to:</p>
<pre><code><span class="hljs-keyword">const</span> mapStateToProps = <span class="hljs-function"><span class="hljs-params">state</span> =&gt;</span> ({  ...state});
</code></pre><pre><code><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> connect(  mapStateToProps,  {})(Admin);
</code></pre><p>Once again, in the <strong>render function</strong>, before the <strong>return</strong> we add:</p>
<pre><code><span class="hljs-keyword">if</span> (!<span class="hljs-built_in">this</span>.props.authState.loggedIn) {  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Redirect</span> <span class="hljs-attr">to</span>=<span class="hljs-string">"/auth/login"</span> /&gt;</span></span>;}
</code></pre><p>This time, we say <strong>!this.props.authState.loggedIn</strong>, since we want the user to be redirected to the login page if they are not authenticated.</p>
<p>Let us start again our project and see how, each time if we try to navigate to the <strong>Dashboard</strong> or <strong>Profile,</strong> we are not allowed since we are not logged in.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/i3yIhiqSEGtBulgXHfqhvGcYUVs9qQuB8zot" alt="Image" width="1920" height="1080" loading="lazy">
<em>Project after adding the redirects</em></p>
<p>Now, we need to go inside the <strong>Login</strong> and <strong>Register</strong> view-pages and add Redux to them as well.</p>
<h4 id="heading-connecting-our-login-page-to-redux-using-loginaction">Connecting our Login page to redux using loginAction</h4>
<p>First, let's go inside <strong>src/views/examples/Login.jsx</strong> and after the <strong>React</strong> import, add these imports:</p>
<pre><code><span class="hljs-keyword">import</span> { connect } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-redux"</span>;
</code></pre><pre><code><span class="hljs-keyword">import</span> loginAction <span class="hljs-keyword">from</span> <span class="hljs-string">"actions/loginAction"</span>;
</code></pre><p>Then, change the export at the end of the file with this:</p>
<pre><code><span class="hljs-keyword">const</span> mapStateToProps = <span class="hljs-function"><span class="hljs-params">state</span> =&gt;</span> ({  ...state});
</code></pre><pre><code><span class="hljs-keyword">const</span> mapDispatchToProps = <span class="hljs-function"><span class="hljs-params">dispatch</span> =&gt;</span> ({  <span class="hljs-attr">loginAction</span>:   <span class="hljs-function">(<span class="hljs-params">email, password</span>) =&gt;</span> dispatch(loginAction(email, password))});
</code></pre><pre><code><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> connect(  mapStateToProps,  mapDispatchToProps)(Login);
</code></pre><p>Now, before the render function we write:</p>
<pre><code>state = {  <span class="hljs-attr">email</span>: <span class="hljs-string">""</span>,  <span class="hljs-attr">password</span>: <span class="hljs-string">""</span>};onChange = <span class="hljs-function">(<span class="hljs-params">stateName, value</span>) =&gt;</span> {  <span class="hljs-built_in">this</span>.setState({    [stateName]: value  });};
</code></pre><p>We’ll need to keep a local <strong>state</strong> for the email and password and send these two to our firebase.</p>
<p>Then, we need to change <em>line 85</em> from:</p>
<pre><code>&lt;Input placeholder=<span class="hljs-string">"Email"</span> type=<span class="hljs-string">"email"</span> /&gt;
</code></pre><p>To:</p>
<pre><code>&lt;Input  placeholder=<span class="hljs-string">"Email"</span>  type=<span class="hljs-string">"email"</span>  onChange={<span class="hljs-function"><span class="hljs-params">e</span> =&gt;</span> <span class="hljs-built_in">this</span>.onChange(<span class="hljs-string">"email"</span>, e.target.value)}/&gt;
</code></pre><p>We’ll also change <em>line 99</em> from:</p>
<pre><code>&lt;Input placeholder=<span class="hljs-string">"Password"</span> type=<span class="hljs-string">"password"</span> /&gt;
</code></pre><p>To:</p>
<pre><code>&lt;Input  placeholder=<span class="hljs-string">"Password"</span>  type=<span class="hljs-string">"password"</span>  onChange={<span class="hljs-function"><span class="hljs-params">e</span> =&gt;</span> <span class="hljs-built_in">this</span>.onChange(<span class="hljs-string">"password"</span>, e.target.value)}/&gt;
</code></pre><p>We’re almost set for the login. Next we need to change the <strong>Sign in</strong> button so that, when we press it, it will call the <strong>loginAction</strong>. So change it from:</p>
<pre><code>&lt;Button className=<span class="hljs-string">"my-4"</span> color=<span class="hljs-string">"primary"</span> type=<span class="hljs-string">"button"</span>&gt;  Sign <span class="hljs-keyword">in</span>&lt;/Button&gt;
</code></pre><p>To:</p>
<pre><code>&lt;Button  className=<span class="hljs-string">"my-4"</span>  color=<span class="hljs-string">"primary"</span>  type=<span class="hljs-string">"button"</span>  onClick={<span class="hljs-function">() =&gt;</span>    <span class="hljs-built_in">this</span>.props.loginAction(      <span class="hljs-built_in">this</span>.state.email,      <span class="hljs-built_in">this</span>.state.password    )  }&gt;  Sign <span class="hljs-keyword">in</span>&lt;/Button&gt;
</code></pre><p>Now go back in your browser, and on the <strong>Login</strong> page, open your console, and try to log in. You should get an output of <strong>login is <em>false</em></strong>. So we know that our <strong>action</strong> and our <strong>reducer</strong> work.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/ph56L3CSbnOONWONDMOIKWBTCCsIjzahNieS" alt="Image" width="800" height="760" loading="lazy">
<em><strong>login is false</strong></em></p>
<h4 id="heading-connecting-our-register-page-to-redux-using-registeraction">Connecting our Register page to redux using registerAction</h4>
<p>Go inside <strong>src/views/examples/Register.jsx</strong> and do the same as the above. So first add the imports (this time with the <strong>registerAction</strong>):</p>
<pre><code><span class="hljs-keyword">import</span> { connect } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-redux"</span>;
</code></pre><pre><code><span class="hljs-keyword">import</span> registerAction <span class="hljs-keyword">from</span> <span class="hljs-string">"actions/registerAction"</span>;
</code></pre><p>Then, the export to:</p>
<pre><code><span class="hljs-keyword">const</span> mapStateToProps = <span class="hljs-function"><span class="hljs-params">state</span> =&gt;</span> ({  ...state});
</code></pre><pre><code><span class="hljs-keyword">const</span> mapDispatchToProps = <span class="hljs-function"><span class="hljs-params">dispatch</span> =&gt;</span> ({  <span class="hljs-attr">registerAction</span>: <span class="hljs-function">(<span class="hljs-params">name, email, password</span>) =&gt;</span> dispatch(registerAction(name, email, password))});
</code></pre><pre><code><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> connect(  mapStateToProps,  mapDispatchToProps)(Register);
</code></pre><p>Add the following before the <strong>render function</strong>:</p>
<pre><code>state = {  <span class="hljs-attr">name</span>: <span class="hljs-string">""</span>,  <span class="hljs-attr">email</span>: <span class="hljs-string">""</span>,  <span class="hljs-attr">password</span>: <span class="hljs-string">""</span>};onChange = <span class="hljs-function">(<span class="hljs-params">stateName, value</span>) =&gt;</span> {  <span class="hljs-built_in">this</span>.setState({    [stateName]: value  });};
</code></pre><p>Change:</p>
<pre><code>&lt;Input placeholder=<span class="hljs-string">"Name"</span> type=<span class="hljs-string">"text"</span> /&gt;
</code></pre><p>To:</p>
<pre><code>&lt;Input placeholder=<span class="hljs-string">"Name"</span> type=<span class="hljs-string">"text"</span> onChange={<span class="hljs-function"><span class="hljs-params">e</span> =&gt;</span> <span class="hljs-built_in">this</span>.onChange(<span class="hljs-string">"name"</span>, e.target.value)}/&gt;
</code></pre><p>Then:</p>
<pre><code>&lt;Input placeholder=<span class="hljs-string">"Email"</span> type=<span class="hljs-string">"email"</span> /&gt;
</code></pre><p>To:</p>
<pre><code>&lt;Input placeholder=<span class="hljs-string">"Email"</span> type=<span class="hljs-string">"email"</span> onChange={<span class="hljs-function"><span class="hljs-params">e</span> =&gt;</span> <span class="hljs-built_in">this</span>.onChange(<span class="hljs-string">"email"</span>, e.target.value)}/&gt;
</code></pre><p>And lastly, the password as well:</p>
<pre><code>&lt;Input placeholder=<span class="hljs-string">"Password"</span> type=<span class="hljs-string">"password"</span> /&gt;
</code></pre><p>To:</p>
<pre><code>&lt;Input placeholder=<span class="hljs-string">"Password"</span> type=<span class="hljs-string">"password"</span> onChange={<span class="hljs-function"><span class="hljs-params">e</span> =&gt;</span> <span class="hljs-built_in">this</span>.onChange(<span class="hljs-string">"password"</span>, e.target.value)}/&gt;
</code></pre><p>One more thing — the button, we need to change it from:</p>
<pre><code>&lt;Button className=<span class="hljs-string">"mt-4"</span> color=<span class="hljs-string">"primary"</span> type=<span class="hljs-string">"button"</span>&gt;  Create account&lt;/Button&gt;
</code></pre><p>To:</p>
<pre><code>&lt;Button className=<span class="hljs-string">"mt-4"</span> color=<span class="hljs-string">"primary"</span> type=<span class="hljs-string">"button"</span>   onClick={<span class="hljs-function">() =&gt;</span>  <span class="hljs-built_in">this</span>.props.registerAction(    <span class="hljs-built_in">this</span>.state.name,    <span class="hljs-built_in">this</span>.state.email,    <span class="hljs-built_in">this</span>.state.password  )}&gt;  Create account&lt;/Button&gt;
</code></pre><p>So, we are all set with Redux. Again, go to the Register page, type something inside the form, and then press the Create account button with the console opened. You should get a <strong>register is <em>false</em></strong>.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/jjNR3gDDVOYzZndVi3TpdZa3Qx7BXWSiTkPB" alt="Image" width="800" height="761" loading="lazy">
<em><strong>register is false</strong></em></p>
<h4 id="heading-connecting-our-header-component-to-redux-using-addstatcardaction-and-getallstatcardsaction-actions">Connecting our Header component to redux using addStatCardAction and getAllStatCardsAction actions</h4>
<p>Now we need to make our <strong>Stat Cards</strong> from the <strong>Header</strong> component (this component can be seen for example inside the <strong>Dashboard</strong> page) to be rendered from our <strong>store/firebase</strong>, and also, make them create dynamically — for example on a <strong>button click</strong>.</p>
<p>Go inside <strong>src/components/Headers/Header.jsx</strong> and add the following <strong>imports</strong> (after the <strong>React import</strong>):</p>
<pre><code><span class="hljs-keyword">import</span> {connect} <span class="hljs-keyword">from</span> <span class="hljs-string">"react-redux"</span>;
</code></pre><pre><code><span class="hljs-keyword">import</span> addStatCardAction <span class="hljs-keyword">from</span> <span class="hljs-string">"actions/addStatCardAction"</span>;<span class="hljs-keyword">import</span> getAllStatCardsAction <span class="hljs-keyword">from</span> <span class="hljs-string">"actions/getAllStatCardsAction"</span>;
</code></pre><pre><code><span class="hljs-keyword">import</span> { Button } <span class="hljs-keyword">from</span> <span class="hljs-string">"reactstrap"</span>;
</code></pre><p>Change the <strong>default export</strong> to:</p>
<pre><code><span class="hljs-keyword">const</span> mapStateToProps = <span class="hljs-function"><span class="hljs-params">state</span> =&gt;</span> ({  ...state});<span class="hljs-keyword">const</span> mapDispatchToProps = <span class="hljs-function"><span class="hljs-params">dispatch</span> =&gt;</span> ({  <span class="hljs-attr">getAllStatCardsAction</span>: <span class="hljs-function">() =&gt;</span> dispatch(getAllStatCardsAction()),  <span class="hljs-attr">addStatCardAction</span>: <span class="hljs-function">(<span class="hljs-params">    statName,    statDescription,    statIcon,    statIconColor,    statFooterIcon,    statFooterIconState,    statFooterPercentage,    statFooterText  </span>) =&gt;</span>    dispatch(      addStatCardAction(        statName,        statDescription,        statIcon,        statIconColor,        statFooterIcon,        statFooterIconState,        statFooterPercentage,        statFooterText      )    )});
</code></pre><pre><code><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> connect(  mapStateToProps,  mapDispatchToProps)(Header);
</code></pre><p>Then, let’s add a <strong>componentDidMount</strong> function right before the <strong>render</strong> one as follows:</p>
<pre><code>componentDidMount(){  <span class="hljs-built_in">this</span>.props.getAllStatCardsAction();}
</code></pre><p>And now, after the first <strong>div</strong> inside the <strong>return</strong> statement of the <strong>render</strong> function, we’ll add a <strong>Button</strong> that will add our stat cards inside our firebase:</p>
<pre><code>&lt;Container&gt;  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Row</span>&gt;</span>    <span class="hljs-tag">&lt;<span class="hljs-name">Col</span> <span class="hljs-attr">lg</span>=<span class="hljs-string">"6"</span> <span class="hljs-attr">xl</span>=<span class="hljs-string">"3"</span>&gt;</span>      <span class="hljs-tag">&lt;<span class="hljs-name">Button</span>        <span class="hljs-attr">color</span>=<span class="hljs-string">"primary"</span>        <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span>          this.props.addStatCardAction(            "Performance",            "49,65%",            "fas fa-percent",            "bg-info text-white rounded-circle shadow",            "fas fa-arrow-up",            "text-success",            " 12%",            "Since last month"          )        }      &gt;        Add stat card      <span class="hljs-tag">&lt;/<span class="hljs-name">Button</span>&gt;</span>    <span class="hljs-tag">&lt;/<span class="hljs-name">Col</span>&gt;</span>  <span class="hljs-tag">&lt;/<span class="hljs-name">Row</span>&gt;</span></span>&lt;<span class="hljs-regexp">/Container&gt;&lt;br /</span>&gt;
</code></pre><p>And, we now need to delete the whole contents of the <strong>Row</strong> tag (~<em>lines 48–165</em> — from <strong>&lt;R</strong>ow&amp;g<strong>t; to</strong> ), and replace it with the following:</p>
<pre><code>{<span class="hljs-comment">// we first verify if the statCardState is undefined  this.props.statCardState &amp;&amp;  // then verify if the statCardState.statCardState is  // populated with cards from our firebase  this.props.statCardState.statCardState &amp;&amp;  // and lastly, we render them using the map function  this.props.statCardState.statCardState.map((prop, key) =&gt; {    return (      &lt;Col lg="6" xl="3" key={key}&gt;        &lt;Card className="card-stats mb-4 mb-xl-0"&gt;          &lt;CardBody&gt;            &lt;Row&gt;              &lt;div className="col"&gt;                &lt;CardTitle                  tag="h5"                  className="text-uppercase text-muted mb-0"                &gt;                  {prop.statName}                &lt;/CardTitle&gt;                &lt;span className="h2 font-weight-bold mb-0"&gt;                  {prop.statDescription}                &lt;/span&gt;              &lt;/div&gt;              &lt;Col className="col-auto"&gt;                &lt;div                  className={                    "icon icon-shape " + prop.statIconColor                  }                &gt;                  &lt;i className={prop.statIcon} /&gt;                &lt;/div&gt;              &lt;/Col&gt;            &lt;/Row&gt;            &lt;p className="mt-3 mb-0 text-muted text-sm"&gt;              &lt;span                className={"mr-2 " + prop.statFooterIconState}              &gt;                &lt;i className={prop.statFooterIcon} /&gt;{" "}                {prop.statFooterPercentage}              &lt;/span&gt;{" "}              &lt;span className="text-nowrap"&gt;                {prop.statFooterText}              &lt;/span&gt;            &lt;/p&gt;          &lt;/CardBody&gt;        &lt;/Card&gt;      &lt;/Col&gt;    );  })}</span>
</code></pre><h3 id="heading-adding-firebase">Adding Firebase</h3>
<h4 id="heading-setting-firebase-account">Setting Firebase Account</h4>
<p>For this, you need to have a <a target="_blank" href="https://myaccount.google.com/">Google Account</a>. If you do not have one, Google offers you a fast (1 minute) <a target="_blank" href="https://support.google.com/mail/answer/56256?hl=en">Guide</a>.</p>
<p>After you’ve made your account, sign into it, or if you have one, sign into that one.</p>
<p>After that, navigate to <a target="_blank" href="https://firebase.google.com/">this page</a> (this is the homepage of firebase) and press the <strong>GO TO CONSOLE</strong> button, or just navigate directly to <a target="_blank" href="https://console.firebase.google.com/u/0/">this link</a>.</p>
<p>After that press on the <strong>Add project</strong> button. You will be prompted with a modal, with an input for a <strong>name</strong> (you can type whatever name you would like). For me, it will be <strong>react-redux-firebase-tutorial</strong>. You can leave everything else as is. <strong>Accept the terms</strong> and then press the <strong>Create Project</strong> button. You’ll have to wait a bit until it creates the project (around 30 seconds).</p>
<p>After that press the <strong>Continue</strong> button. That will automatically redirect you to the new project page. In the left menu press the <strong>Authentication</strong> link. On that press the <strong>Set up sign-in method</strong>. You will have a table with <strong>Provider</strong> and <strong>Status</strong>. Press on the line <strong>Email/Password</strong>. And check the first <strong>Switch</strong> and then press the <strong>Save</strong> button.</p>
<p>Now, go to <strong>Database</strong> link, scroll down the page and press <strong>Create database</strong> button, under the <strong>Realtime Database</strong>. After this, on the modal prompt that opens, choose <strong>Start in test mode</strong> radio and then press <strong>Enable</strong> and wait a few seconds.</p>
<p>Next, you’ll need to get your config file (config file that we will add it to our project in the next section). For this press on <strong>Project Overview</strong> link in the left menu, and after that press on the <strong>&lt;</strong>;/&gt; (Web) button. Cop<strong>y the</strong> config variable an<strong>d the firebase initiali</strong>zation. We’ll paste this in a new file, in the next section.</p>
<p>We are done!</p>
<p>We won’t need to create any tables for our users, our users’ details, or our dynamic cards, since firebase will automatically create them — we’ll talk about this in the next section.</p>
<p>Here are the above steps, as images:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/4COJIxHnrVZNkWZsV2SEUy9nnGooi5DfVNru" alt="Image" width="800" height="500" loading="lazy"></p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/-J4f7OkHSJHNX4Q16tnQqQwOQHEPtSY0CcPY" alt="Image" width="800" height="500" loading="lazy"></p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/g31yzK-Pt3iwx1ATEL0sZ9LoYdJDtH9rdp1o" alt="Image" width="800" height="500" loading="lazy"></p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/lTBqKAmZs34jLSgyVeXPIsXp4f-r4dFsF9T0" alt="Image" width="800" height="500" loading="lazy"></p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/qExTP7hRuHk3F0aQv3RCK3U28patPZ5BdBFj" alt="Image" width="800" height="500" loading="lazy"></p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/0HzPZhEt2cWYBO8beQSPTb5GWVARZ7M6tZRE" alt="Image" width="800" height="500" loading="lazy"></p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/wAhTEBfWmsLgX66S-BUVlcKF-5nR3-Fkvb3z" alt="Image" width="800" height="500" loading="lazy"></p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/nkxMOuEp9SUWVSwA36DAqX3EXXwXpu5J5kST" alt="Image" width="800" height="500" loading="lazy"></p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/htFFlwaTuyNn6okH9urG1askjORredSC9Eob" alt="Image" width="800" height="500" loading="lazy"></p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/eYC-jXvLpX3Mpu9EKcvEp0cJMtpydCw1TjsF" alt="Image" width="800" height="500" loading="lazy"></p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/VG9txfaAPtpb5tjGLoTAJnSyqcDa0qYsAb5H" alt="Image" width="800" height="500" loading="lazy"></p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/WoAZ5etvIEG9uJ8BaSYwrMMKxgIk8ADx3XL9" alt="Image" width="800" height="500" loading="lazy"></p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/9MwpNj7l32x5CqxCsVjV7fgciMHcBqFug8r2" alt="Image" width="800" height="500" loading="lazy"></p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/GygAEXlsQoQlvAoFOG9GAT0EGD3BTU6IoQcZ" alt="Image" width="800" height="500" loading="lazy">
<em><strong>Setting up a firebase project</strong></em></p>
<h4 id="heading-adding-firebase-to-our-project">Adding Firebase to our project</h4>
<p>Let’s install <strong>firebase</strong> in our app:</p>
<pre><code>npm i -E firebase
</code></pre><p>After this, we need to create a file for configuring our firebase in our app, so:</p>
<p>1 — Linux/Mac commands</p>
<pre><code>touch src/firebaseConfig.js
</code></pre><p>2 — Windows commands</p>
<pre><code>echo <span class="hljs-string">""</span> &gt; src\firebaseConfig.js
</code></pre><p>And let’s import <strong>firebase</strong> in this file, and then export firebase with the initialization (you need the code from the previous section — see the last image):</p>
<pre><code><span class="hljs-keyword">import</span> * <span class="hljs-keyword">as</span> firebase <span class="hljs-keyword">from</span> <span class="hljs-string">"firebase"</span>;
</code></pre><pre><code><span class="hljs-comment">// replace this variable, with your own config variable// from your firebase projectvar config = {  apiKey: "YOUR_KEY_HERE",  authDomain: "YOUR_DOMAIN_HERE",  databaseURL: "YOUR_URL_HERE",  projectId: "YOUR_ID_HERE",  storageBucket: "YOUR_BUCKET_HERE",  messagingSenderId: "YOUR_ID_HERE"};</span>
</code></pre><pre><code><span class="hljs-keyword">let</span> firebaseConfig = firebase.initializeApp(config);
</code></pre><pre><code><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> firebaseConfig;
</code></pre><p>Now, we can import our <strong>firebaseConfig</strong> everywhere we need it.</p>
<h4 id="heading-register">Register</h4>
<p>Let us first make our <strong>registerAction</strong> functional. So, we go inside <strong>src/actions/registerAction.js</strong> and at the beginning of the file we import our firebase config:</p>
<pre><code><span class="hljs-keyword">import</span> firebase <span class="hljs-keyword">from</span> <span class="hljs-string">"firebaseConfig"</span>;
</code></pre><p>After this, we may need for our users to keep stuff, like their name, their photos etc. so we are going to create a new table called user-details. If it doesn’t exist, add in it the name of our user.</p>
<p>Our form only has email, password, and name — firebase will automatically create a database table in which it will only put the credentials (email and password) of the account. So if we want to keep more details about our users, we’ll need to create a new table — my table will have the ID of the user, from the table with the credentials, and the user’s name.</p>
<p>So after the above import, we say:</p>
<pre><code><span class="hljs-comment">// get me the firebase database</span>
</code></pre><pre><code><span class="hljs-keyword">const</span> databaseRef = firebase.database().ref();
</code></pre><pre><code><span class="hljs-comment">// get me the table named user-details// if it does not exist, firebase will// automatically create it</span>
</code></pre><pre><code><span class="hljs-keyword">const</span> userDetailsRef = databaseRef.child(<span class="hljs-string">"user-details"</span>);
</code></pre><p>After that, we’ll change our dispatch code from:</p>
<pre><code>dispatch({ <span class="hljs-attr">type</span>: <span class="hljs-string">"register"</span>, <span class="hljs-attr">payload</span>: <span class="hljs-literal">false</span> });
</code></pre><p>To:</p>
<pre><code><span class="hljs-comment">// firebase offers us this function createUserWithEmailAndPassword// which will automatically create the user for us// it only has two arguments, the email and the password</span>
</code></pre><pre><code>firebase.auth().createUserWithEmailAndPassword(email, password)
</code></pre><pre><code><span class="hljs-comment">// then() function is used to know when the async call has ended// that way, we can notify our reducers that register was succesful</span>
</code></pre><pre><code>.then(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">user</span>) </span>{
</code></pre><pre><code>  <span class="hljs-comment">// we take the user id and it's name and we add it in our  // user-details table</span>
</code></pre><pre><code>  userDetailsRef.push().set({<span class="hljs-attr">userId</span>: user.user.uid, <span class="hljs-attr">userName</span>: name});
</code></pre><pre><code>  <span class="hljs-comment">// after that we dispatch to our reducers the fact that  // register was succesful by sending true</span>
</code></pre><pre><code>  dispatch({<span class="hljs-attr">type</span>:<span class="hljs-string">"register"</span>, <span class="hljs-attr">payload</span>: <span class="hljs-literal">true</span>});
</code></pre><pre><code><span class="hljs-comment">// if the register was not succesful we can catch the erros here</span>
</code></pre><pre><code>}).catch(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">error</span>) </span>{
</code></pre><pre><code>  <span class="hljs-comment">// if we have any erros, we'll throw an allert with that error</span>
</code></pre><pre><code>  alert(error);
</code></pre><pre><code>});
</code></pre><p>So in the end, our <strong>registerAction</strong> will look like this:</p>
<pre><code><span class="hljs-keyword">import</span> firebase <span class="hljs-keyword">from</span> <span class="hljs-string">"firebaseConfig"</span>;
</code></pre><pre><code><span class="hljs-keyword">const</span> databaseRef = firebase.database().ref();<span class="hljs-keyword">const</span> userDetailsRef = databaseRef.child(<span class="hljs-string">"user-details"</span>);
</code></pre><pre><code><span class="hljs-keyword">const</span> registerAction = <span class="hljs-function">(<span class="hljs-params">name, email, password</span>) =&gt;</span> <span class="hljs-keyword">async</span> dispatch =&gt; {  firebase    .auth()    .createUserWithEmailAndPassword(email, password)    .then(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">user</span>) </span>{      userDetailsRef.push().set(        { <span class="hljs-attr">userId</span>: user.user.uid, <span class="hljs-attr">userName</span>: name }      );      dispatch({ <span class="hljs-attr">type</span>: <span class="hljs-string">"register"</span>, <span class="hljs-attr">payload</span>: <span class="hljs-literal">true</span> });    })    .catch(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">error</span>) </span>{      alert(error);    });};
</code></pre><pre><code><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> registerAction;
</code></pre><p>Open the app again, and go to the register page. Type a name, a valid email and a password (something simple to remember — something like <strong>qwerty</strong>). After you press the <strong>Create account</strong> button you should be redirected to the <strong>user-profile</strong> page — this means that our registration was successful. We can now go back to our <strong>firebase project</strong> (<a target="_blank" href="https://console.firebase.google.com/u/0/">https://console.firebase.google.com/u/0/</a> — press on your project), click the <strong>Authentication</strong> link, and we’ll see that email that we’ve just written. Also, if we go to the <strong>Database</strong> link, we’ll see our <strong>user-details</strong> table.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/Fcvn-A-fMjcOHvtni0hCQNwIm3UAEtIOulZh" alt="Image" width="1256" height="1080" loading="lazy">
<em><strong>Register action is now working</strong></em></p>
<h4 id="heading-login"><strong>Login</strong></h4>
<p>we go inside <strong>src/actions/loginAction.js</strong> and at the beginning of the file we import our firebase config:</p>
<pre><code><span class="hljs-keyword">import</span> firebase <span class="hljs-keyword">from</span> <span class="hljs-string">"firebaseConfig"</span>;
</code></pre><p>For this action, we won’t need anything else, so the next thing is to change our dispatch code from:</p>
<pre><code>dispatch({ <span class="hljs-attr">type</span>: <span class="hljs-string">"login"</span>, <span class="hljs-attr">payload</span>: <span class="hljs-literal">false</span> });
</code></pre><p>To:</p>
<pre><code><span class="hljs-comment">// firebase offers us this function signInWithEmailAndPassword// which will automatically create the user for us// it only has two arguments, the email and the password</span>
</code></pre><pre><code>firebase  .auth()  .signInWithEmailAndPassword(email, password)  <span class="hljs-comment">// then() function is used to know when the async call has ended  // that way, we can notify our reducers that login was succesful    .then(function(user) {    // if the login was succesful, then     // we dispatch to our reducers the fact that    // login was succesful by sending true    dispatch({type:"login", payload: "true"});  })</span>
</code></pre><pre><code><span class="hljs-comment">// if the login was not succesful we can catch the erros here    .catch(function(error) {</span>
</code></pre><pre><code><span class="hljs-comment">// if we have any erros, we'll throw an allert with that error        alert(error);  });</span>
</code></pre><p>So in the end, our <strong>loginAction</strong> should look like this:</p>
<pre><code><span class="hljs-keyword">import</span> firebase <span class="hljs-keyword">from</span> <span class="hljs-string">"firebaseConfig"</span>;
</code></pre><pre><code><span class="hljs-keyword">const</span> loginAction = <span class="hljs-function">(<span class="hljs-params">email, password</span>) =&gt;</span> <span class="hljs-keyword">async</span> dispatch =&gt; {  firebase    .auth()    .signInWithEmailAndPassword(email, password)    .then(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">user</span>) </span>{      dispatch({ <span class="hljs-attr">type</span>: <span class="hljs-string">"login"</span>, <span class="hljs-attr">payload</span>: <span class="hljs-string">"true"</span> });    })    .catch(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">error</span>) </span>{      alert(error);    });};
</code></pre><pre><code><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> loginAction;
</code></pre><p>If we open again our app (we should be redirected by default to <strong>Login</strong> page), and if we enter our email and password, we will be able to login to our new account.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/KiDtGPZVvtaeDG8QbYNQxgjUcZgn1dEpoCxK" alt="Image" width="1251" height="1080" loading="lazy">
<em><strong>Login action working</strong></em></p>
<h4 id="heading-add-stat-cards-and-render-them">Add stat cards and render them</h4>
<p>Now, we need to make some changes to our actions regarding the stat cards.</p>
<p>Inside <strong>src/actions/getAllStatCardsAction.js</strong> we need to add the following <strong>imports</strong>:</p>
<pre><code><span class="hljs-keyword">import</span> firebase <span class="hljs-keyword">from</span> <span class="hljs-string">"firebaseConfig"</span>;
</code></pre><pre><code><span class="hljs-keyword">const</span> databaseRef = firebase.database().ref();<span class="hljs-comment">// this is to get the stat-cards table from firebaseconst statCardsRef = databaseRef.child("stat-cards");</span>
</code></pre><p>Then we need to change the <strong>dispatch</strong> from:</p>
<pre><code>dispatch({ <span class="hljs-attr">type</span>: <span class="hljs-string">"getAllStatCards"</span>, <span class="hljs-attr">payload</span>: {} });
</code></pre><p>To:</p>
<pre><code><span class="hljs-comment">// this function will get all the entires of the// stat-cards table, in a json formatstatCardsRef.on("value", snapshot =&gt; {  dispatch({    type: "getAllStatCards",    // if the json returns null, i.e. the    // stat-cards table is blank - empty    // then we'll return an empty object    payload: snapshot.val() || {}  });});</span>
</code></pre><p>This is how the action should now look:</p>
<pre><code><span class="hljs-keyword">import</span> firebase <span class="hljs-keyword">from</span> <span class="hljs-string">"firebaseConfig"</span>;
</code></pre><pre><code><span class="hljs-keyword">const</span> databaseRef = firebase.database().ref();<span class="hljs-keyword">const</span> statCardsRef = databaseRef.child(<span class="hljs-string">"stat-cards"</span>);
</code></pre><pre><code><span class="hljs-keyword">const</span> getAllStatCardsAction = <span class="hljs-function">() =&gt;</span> <span class="hljs-keyword">async</span> dispatch =&gt; {  statCardsRef.on(<span class="hljs-string">"value"</span>, <span class="hljs-function"><span class="hljs-params">snapshot</span> =&gt;</span> {    dispatch({      <span class="hljs-attr">type</span>: <span class="hljs-string">"getAllStatCards"</span>,      <span class="hljs-attr">payload</span>: snapshot.val() || {}    });  });};
</code></pre><pre><code><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> getAllStatCardsAction;
</code></pre><p>Next, is the <strong>src/actions/addStatCardAction.js</strong>. Like the previous one, we need some imports:</p>
<pre><code><span class="hljs-keyword">import</span> firebase <span class="hljs-keyword">from</span> <span class="hljs-string">"firebaseConfig"</span>;
</code></pre><pre><code><span class="hljs-keyword">const</span> databaseRef = firebase.database().ref();<span class="hljs-keyword">const</span> statCardsRef = databaseRef.child(<span class="hljs-string">"stat-cards"</span>);
</code></pre><p>Now, instead of the simple dispatch, we’ll overwrite it from:</p>
<pre><code>dispatch({  <span class="hljs-attr">type</span>: <span class="hljs-string">"addStatCard"</span>,  <span class="hljs-attr">payload</span>: {    <span class="hljs-attr">statName</span>: statName,    <span class="hljs-attr">statDescription</span>: statDescription,    <span class="hljs-attr">statIcon</span>: statIcon,    <span class="hljs-attr">statIconColor</span>: statIconColor,    <span class="hljs-attr">statFooterIcon</span>: statFooterIcon,    <span class="hljs-attr">statFooterIconState</span>: statFooterIconState,    <span class="hljs-attr">statFooterPercentage</span>: statFooterPercentage,    <span class="hljs-attr">statFooterText</span>: statFooterText  }});
</code></pre><p>To:</p>
<pre><code>statCardsRef  <span class="hljs-comment">// the push function will send to our firebase the new object  .push()  // and will set in a new row of the table stat-cards  // with the bellow object  .set({    statName: statName,    statDescription: statDescription,    statIcon: statIcon,    statIconColor: statIconColor,    statFooterIcon: statFooterIcon,    statFooterIconState: statFooterIconState,    statFooterPercentage: statFooterPercentage,    statFooterText: statFooterText  })  // when the push has terminated, we will dispatch to our  // reducer that we have successfully added a new row  .then(() =&gt; {    dispatch({      type: "addStatCard"    });  });</span>
</code></pre><p>So, it now should look like:</p>
<pre><code><span class="hljs-keyword">import</span> firebase <span class="hljs-keyword">from</span> <span class="hljs-string">"firebaseConfig"</span>;
</code></pre><pre><code><span class="hljs-keyword">const</span> databaseRef = firebase.database().ref();<span class="hljs-keyword">const</span> statCardsRef = databaseRef.child(<span class="hljs-string">"stat-cards"</span>);
</code></pre><pre><code><span class="hljs-keyword">const</span> addStatCardAction = <span class="hljs-function">(<span class="hljs-params">  statName,  statDescription,  statIcon,  statIconColor,  statFooterIcon,  statFooterIconState,  statFooterPercentage,  statFooterText</span>) =&gt;</span> <span class="hljs-keyword">async</span> dispatch =&gt; {  statCardsRef    .push()    .set({      <span class="hljs-attr">statName</span>: statName,      <span class="hljs-attr">statDescription</span>: statDescription,      <span class="hljs-attr">statIcon</span>: statIcon,      <span class="hljs-attr">statIconColor</span>: statIconColor,      <span class="hljs-attr">statFooterIcon</span>: statFooterIcon,      <span class="hljs-attr">statFooterIconState</span>: statFooterIconState,      <span class="hljs-attr">statFooterPercentage</span>: statFooterPercentage,      <span class="hljs-attr">statFooterText</span>: statFooterText    })    .then(<span class="hljs-function">() =&gt;</span> {      dispatch({        <span class="hljs-attr">type</span>: <span class="hljs-string">"addStatCard"</span>      });    });};
</code></pre><pre><code><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> addStatCardAction;
</code></pre><p>And we are all set. Run again the app, login into your account, navigate on the <strong>Dashboard</strong> page, and then press the <strong>Add stat card</strong> button. Stats should now start adding to your <strong>Header</strong>.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/ghyjERjE8Jp6HG2yCIUM5aP7ddP8HTX6HfUT" alt="Image" width="1319" height="1080" loading="lazy">
<em><strong>App is done</strong></em></p>
<h3 id="heading-thanks-for-reading">Thanks for reading!</h3>
<p>If you’ve enjoyed reading this tutorial give it a clap. I am very keen on hearing your thoughts about it. Just give this thread a comment and I’ll be more than happy to reply.</p>
<p>Useful links:</p>
<ul>
<li>Get the code for this tutorial from <a target="_blank" href="https://github.com/EINazare/react-redux-firebase-rds-tutorial">Github</a></li>
<li>Read more about ReactJS on <a target="_blank" href="https://reactjs.org/">their official website</a></li>
<li>Read more about <a target="_blank" href="https://redux.js.org/">Redux here</a></li>
<li>Read more about <a target="_blank" href="https://react-redux.js.org/">React-Redux</a></li>
<li>Read more about <a target="_blank" href="https://firebase.google.com/docs/">Firebase</a></li>
<li>Check out our platform to see <a target="_blank" href="https://www.creative-tim.com/">what we are doing</a> and <a target="_blank" href="https://www.creative-tim.com/presentation">who we are</a></li>
<li>Read more about <a target="_blank" href="https://reactstrap.github.io/">Reactstrap</a>, the core of Argon Dashboard React</li>
<li>Read my <a target="_blank" href="https://medium.freecodecamp.org/how-to-use-reactjs-with-webpack-4-babel-7-and-material-design-ff754586f618">Webpack tutorial</a> and/or my <a target="_blank" href="https://medium.freecodecamp.org/how-to-use-redux-in-reactjs-with-real-life-examples-687ab4441b85">Redux tutorial</a></li>
</ul>
<p>Find me on:</p>
<ul>
<li>Facebook: <a target="_blank" href="https://www.facebook.com/NazareEmanuel">https://www.facebook.com/NazareEmanuel</a></li>
<li>Instagram: <a target="_blank" href="https://www.instagram.com/manu.nazare/">https://www.instagram.com/manu.nazare/</a></li>
<li>Linkedin: <a target="_blank" href="https://www.linkedin.com/in/nazare-emanuel-ioan-4298b5149/">https://www.linkedin.com/in/nazare-emanuel-ioan-4298b5149/</a></li>
<li>Email: <a target="_blank" href="mailto:manu@creative-tim.com">manu@creative-tim.com</a></li>
</ul>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to use wireframes with design systems ]]>
                </title>
                <description>
                    <![CDATA[ By Leon Barnard In my 10+ years as a UX designer, one of the most frequent questions I’m asked about wireframes is how much visual detail to put into them. There’s an attractive elegance to a simple black and white sketch, but it can sometimes lead t... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-use-wireframes-with-design-systems-46f3040829b6/</link>
                <guid isPermaLink="false">66c355f5dae03919d93dc035</guid>
                
                    <category>
                        <![CDATA[ Design ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Design Systems ]]>
                    </category>
                
                    <category>
                        <![CDATA[ tech  ]]>
                    </category>
                
                    <category>
                        <![CDATA[ UX ]]>
                    </category>
                
                    <category>
                        <![CDATA[ #wireframe ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Mon, 17 Dec 2018 17:06:20 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*J7kjxgTFCyTHqm28222z6g.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Leon Barnard</p>
<p>In my 10+ years as a UX designer, one of the most frequent questions I’m asked about wireframes is how much visual detail to put into them.</p>
<p>There’s an attractive elegance to a simple black and white sketch, but it can sometimes lead to gaps in the shared understanding of what the final product will really look like.</p>
<p>Wireframes shine during the early phases of product development when ideation and rapid iteration are most valued. But what makes them ideal for this phase also hinders them in the next phase, when pixel precision and visual details are called upon for implementation.</p>
<p>As a result, many people (I’ve been guilty of this) try to incorporate fine-grained and aesthetic details into their wireframes by tuning fonts, adding colors, and using other visual effects.</p>
<p>This can often lead to confusion when these proto-high-fidelity wireframes are used as implementation specifications and sent “over the wall” to the development team. Most wireframing tools are not optimized for creating artifacts that look and feel like a finished product. Yet creating polished renditions of every screen or a high-fidelity prototype is time consuming and <a target="_blank" href="https://blog.teamtreehouse.com/rapidly-prototype-websites">may not translate well to the final product anyway</a>.</p>
<p>But, is there another way?</p>
<p><strong>There sure is</strong>! A way where you can keep your wireframes low fidelity, yet achieve that powerful shared understanding of the implemented look and feel.</p>
<h4 id="heading-design-systems-to-the-rescue">Design Systems to the Rescue</h4>
<p>An alternative to pushing wireframes beyond their limits is to keep them low fidelity and let another tool do the work of specifying the look and feel.</p>
<p>In this article, I’ll explain why, for web applications and sites at least, an excellent tool for this job is a <strong>design system</strong>.</p>
<p>Before diving in, let’s define what a design system is.</p>
<p>Like their precursor, style guides, design systems define the application’s look and feel. They go one step further though, in that they often define <strong>behavior</strong> as well and are backed by working code.</p>
<p>Large companies have been using design systems for a long time. Until recently, they were too labor intensive for smaller companies, as they often required dedicated designers and developers working outside of the primary product teams.</p>
<p>Here is an example, from the <a target="_blank" href="https://www.carbondesignsystem.com">IBM Carbon Design System</a>, showing appearance and code for buttons.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/Dy85oSgyI4dmDfnQAxbaHCZgDf1mgSOSC4fu" alt="Image" width="800" height="455" loading="lazy">
_[Carbon Design System](https://www.carbondesignsystem.com" rel="noopener" target="<em>blank" title=") buttons</em></p>
<p>The design system landscape changed after the <a target="_blank" href="http://getbootstrap.com/">Bootstrap</a> framework was released in 2011. It is a free starter kit for web development that provides compliant, robust HTML templates and generally good-looking CSS styles that can be customized to your brand.</p>
<p>It comes with its own grid and typography definitions as well as styles for buttons, forms, and more. In short, it takes a lot of the hard work out of starting a web project and making sure that it works across browsers.</p>
<p>Bootstrap and other frameworks like it have been used as a foundation for design systems for smaller companies that don’t have the resources to build their own.</p>
<p>As you can see below, Bootstrap is very similar to corporate design systems like the one shown above.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/iXL3oSzH7bcl5cyVfkIKyGwKG3duYSHVMEKn" alt="Image" width="800" height="364" loading="lazy">
_[Bootstrap](http://getbootstrap.com" rel="noopener" target="<em>blank" title=") buttons</em></p>
<h4 id="heading-design-systems-wireframes-in-practice">Design Systems + Wireframes in Practice</h4>
<p>The main advantage of pairing a design system with a wireframing tool is that it can free you from worrying about look, feel, and behavior when wireframing. Yet, they provide pixel-perfect renditions of the final product components.</p>
<p>When you already know what a button (or tab, menu, etc.) is going to look like and what its state transitions will be when you click it, then you don’t have to style it in your wireframe. Black and white and <a target="_blank" href="http://balsamiq.com/products/mockups/font/">Balsamiq Sans</a> is just fine.</p>
<blockquote>
<p><em>Having a design system to refer to can allow you to jump straight from wireframes to code without leaving the final vision undefined.</em></p>
</blockquote>
<p>Here’s how you can pair them together. You’ll find that they get along quite well together!</p>
<p>If you already have a design system, great. If not, you can start with a customized download of <a target="_blank" href="https://getbootstrap.com/docs/4.1/getting-started/introduction/">Bootstrap</a> or <a target="_blank" href="https://foundation.zurb.com/sites/download.html/">Foundation</a>. The next step is to create a mapping between it and the controls in your wireframing tool.</p>
<p>A mapping basically means developing a shared agreement of “this means that”. You can do this by creating a document showing these mappings or by just having a meeting with the design and development teams around a screen to work it out.</p>
<p>Here’s an example of how you might map some <a target="_blank" href="https://balsamiq.com">Balsamiq</a> controls to Bootstrap components (you could also start with the <a target="_blank" href="https://wireframestogo.com/#/search=bootstrap">Bootstrap Wireframes To Go library</a>).</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/5-jQm4qhKNfVlQHNjMfmrj7lztq1qq5g4U5z" alt="Image" width="541" height="395" loading="lazy">
<em>Simple mapping of wireframe controls to coded UI controls</em></p>
<blockquote>
<p><strong><em>Note:</em></strong> <em>It’s ok to use some color, but it should only be used as much as necessary to indicate states and selections, for example.</em></p>
</blockquote>
<p>Having this kind of mapping means that <strong>developers no longer have to wonder whether the colors in the wireframe are supposed to be used in their code</strong>. They can just translate in their head that a blue button in the wireframe actually means a green button in the UI (if that’s the color you use), and that breadcrumbs separated by the <code>&amp;</code>gt; character should actually be separated by t<code>h</code>e / character in the app, for example.</p>
<p>You can also extend your design system by creating your own Balsamiq controls as <a target="_blank" href="https://docs.balsamiq.com/desktop/symbols/">Symbols</a> to map to other components in your library, like this:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/C1NnmuTJ85ig6LUsmdiItM2ujt7SrqnBgIqs" alt="Image" width="793" height="421" loading="lazy">
<em>Balsamiq symbols mapped to design system components</em></p>
<p>This mapping can evolve and grow over time as needs and design language change in your organization.</p>
<p>Here’s a simple example showing what a completed wireframe could look like when built in conjunction with a design system.</p>
<blockquote>
<p><em>Note: Blue in the wireframe doesn’t have to mean blue in the finished product.</em></p>
</blockquote>
<p><img src="https://cdn-media-1.freecodecamp.org/images/c9J061zS0hvTuedNOF6BW1I4BzgrHEAjWVYl" alt="Image" width="800" height="423" loading="lazy">
<em>Created in Balsamiq</em></p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/NXKeYs7lM8jkV2Arf5x6ewTbt4y2rVazGyMn" alt="Image" width="800" height="374" loading="lazy">
<em>Created with code</em></p>
<p>Wireframe to working code with no additional design artifacts in between!</p>
<p>Having a design system also means that you’re reusing the same code across all parts of your application so that different developers produce the same UI which leads to better standards and consistency. And if the design system gets updated, the wireframes don’t have to change.</p>
<p>Finally, <strong>designers can rely more on the stock controls inside the tool</strong> rather than spending hours trying to replicate the look on their own, so both the design and development cycles are shortened.</p>
<h4 id="heading-summary">Summary</h4>
<p>Nothing works for everyone, of course. This approach isn’t guaranteed to work for all projects or organizations. For example, it is better suited to in-house teams.</p>
<p>Clients outside your organization are more likely to want to see a high-fidelity mockup. Also, most of the starter design systems are for web-based products. Desktop and mobile application design system templates and examples are less common.</p>
<p>Lastly, and perhaps most importantly, you should have <strong>good communication between design and development teams</strong> for this approach to work.</p>
<p>Much of the shared understanding of the connection between wireframes and design systems is created by <strong>having a conversation about it</strong>. Announcing it over email or simply posting it on your intranet alone probably won’t work. Waterfall and distant remote teams trying this might not fare as well.</p>
<p>That said, it does offer lots of advantages for many teams, such as:</p>
<ul>
<li>Saves time when wireframing</li>
<li>No mismatch between wireframe and reality</li>
<li>Good for Lean/Agile methodologies where deliverables don’t need to be so formal</li>
<li>Good for small teams and startups without many resources (especially when using frameworks)</li>
<li>Different skillsets can be applied to different design areas (e.g., visual designers and developers for the design system, interaction designers or PMs for the wireframes)</li>
<li>Design processes (wireframes vs. design system creation) can be done independently, resulting in fewer bottlenecks</li>
<li>More UI consistency across the product</li>
</ul>
<h3 id="heading-more-design-system-resources">More Design System Resources</h3>
<ul>
<li><a target="_blank" href="https://designsystemsrepo.com/design-systems/">Design Systems Gallery</a></li>
<li><a target="_blank" href="https://clearleft.com/posts/designing-design-systems">“Designing Design Systems”</a></li>
<li><a target="_blank" href="https://alistapart.com/blog/post/getting-started-with-pattern-libraries">“Getting Started with Pattern Libraries”</a></li>
<li><a target="_blank" href="http://atomicdesign.bradfrost.com/chapter-1/">Introduction to Atomic Design</a></li>
<li><a target="_blank" href="https://patternlab.io">Pattern Lab Design System Tool</a></li>
<li><a target="_blank" href="http://styleguides.io/">Website Style Guide Resources</a></li>
</ul>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ 8-Point Grid: Typography On The Web ]]>
                </title>
                <description>
                    <![CDATA[ By Elliot Dahl Web typography is confusing. Do you know the best practices? When I started looking around at popular websites to figure out the best practices for web typography, I must admit I was baffled. Below are some examples of typography scale... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/8-point-grid-typography-on-the-web-be5dc97db6bc/</link>
                <guid isPermaLink="false">66d45e3cb6b7f664236cbdbc</guid>
                
                    <category>
                        <![CDATA[ CSS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Design ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Design Systems ]]>
                    </category>
                
                    <category>
                        <![CDATA[ technology ]]>
                    </category>
                
                    <category>
                        <![CDATA[ typography ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Wed, 13 Jun 2018 16:22:43 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*a9-nNNgjaAsA8ImC-JF4NA.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Elliot Dahl</p>
<h2 id="heading-web-typography-is-confusing-do-you-know-the-best-practices">Web typography is confusing. Do you know the best practices?</h2>
<p>When I started looking around at popular websites to figure out the best practices for web typography, I must admit I was baffled. Below are some examples of typography scales I pulled from a few popular websites and design systems. Can you find the unifying pattern?</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/p7a5EwZKGq5FrIg-oXZ58WptVdYXB372hY97" alt="Image" width="700" height="382" loading="lazy">
<em>Samples simplified to fit onto a standard scale</em></p>
<p>Clearly there are different approaches to type systems. The reality is that as a web community we don’t all agree. However, like most design problems, it really starts by addressing the user’s needs.</p>
<h2 id="heading-the-three-archetypes-of-typography-systems">The three archetypes of typography systems</h2>
<p>Here are three general typography system archetypes. Most companies will utilize all three of these at some point but it’s important to recognize the underlying user needs being addressed by each orientation.</p>
<h4 id="heading-marketing-site">Marketing site</h4>
<ul>
<li><strong>Purpose:</strong> Built to tell a specific story and inspire visitors to spend their time and/or money on the site.</li>
<li><strong>Requirements:</strong> Each typeface will need its own set of styles and the variety of sizes will be based on art direction more than element fitting.</li>
<li><strong>Responsive use case:</strong> The system will need to flex through multiple sizes from mobile up to desktop.</li>
</ul>
<p><img src="https://cdn-media-1.freecodecamp.org/images/q4CC1WIXgGD1tXirl1L3tpkh7SOKKDgKPdT4" alt="Image" width="320" height="360" loading="lazy"></p>
<p>Web experiences geared to pitch you something end up in this category. The ambitious ones break all the rules of typography to create compelling and captivating experiences.</p>
<p>While a lot of thought goes into these sites, the focus is on making a splash rather than an extensible system that can be built upon in the future. These sites generally have a short shelf life and are discarded entirely for a top-to-bottom redesign.</p>
<p>An advanced example of this is the interpolation function used by <a target="_blank" href="https://twitter.com/lat">Leigh Taylor</a> and <a target="_blank" href="https://twitter.com/narrowd">Nick Jones</a> on <a target="_blank" href="https://www.invisionapp.com/">Invision’s landing page</a>.</p>
<p>The <code>&lt;</code>h1&gt; <code>has a font-size: calc(32px + ((24 * (100vw — 800px))/</code>799));. The typography on the page is meticulously calculated to work at every screen size.</p>
<blockquote>
<p>“Using math to do dynamic art direction” — <a target="_blank" href="https://twitter.com/lat">Leigh Taylor</a></p>
</blockquote>
<h4 id="heading-bloginfo-site">Blog/Info site</h4>
<ul>
<li><strong>Purpose:</strong> To convey a large amount of text-based information.</li>
<li><strong>Requirements:</strong> The main reading area may utilize a ratio based line-height system, just like this Medium article does.</li>
<li><strong>Responsive use case:</strong> Will likely be responsive but maintaining focus on readability.</li>
</ul>
<p><img src="https://cdn-media-1.freecodecamp.org/images/JWKQZX2pnsELv6JkIOGshLQ3imrMOaRYEkTk" alt="Image" width="320" height="360" loading="lazy"></p>
<p>This Medium article is an example of a web experience built for long-form reading.</p>
<p>The focus is not about interpreting little visualizations or filling out forms. The size ratios they’ve chosen are specifically built for readability constrained to get the desired line-length. I can comfortably read each line because the typography has been carefully crafted to fit my needs as a reader.</p>
<h4 id="heading-product">Product</h4>
<ul>
<li><strong>Purpose:</strong> Built to solve a user problem like filing taxes, managing a git repo, or visualizing performance metrics.</li>
<li><strong>Requirements:</strong> Text must fit nicely into the element hierarchy. Text is mostly utilized for labels, instructions, and displayed data.</li>
<li><strong>Responsive use case:</strong> Minimally responsive. Highly developed products will be utilizing adaptive design meaning different experiences for mobile and desktop. The focus is on the hierarchy of elements that support the user experience.</li>
</ul>
<p><img src="https://cdn-media-1.freecodecamp.org/images/AFvMJ3ln64feUAj9J5VvI-qsRE9hgmpSSff0" alt="Image" width="320" height="360" loading="lazy"></p>
<p>Google’s Material Design is a popular design language that is applicable to many product use cases.</p>
<p>Material’s <a target="_blank" href="https://material.io/design/layout/spacing-methods.html#baseline">spacing method</a> is based on an 8pt component grid system and a 4pt baseline grid for typography. They try to scale line-heights with increments of 4. Scaling by increments of 8 with your baseline grid can be difficult because the available line-heights are too far apart for some text sizes.</p>
<p>Allowing some of the font-sizes to be accompanied with a more appropriate line-height is a great path forward. You can always bump the spacing above or below a given line by 4px to make it align with the greater atomic grid.</p>
<p>When applied, the baseline grid system has the ability to align the element spatial system (8pt grid) with the typography system to create a compelling vertical rhythm in the design.</p>
<h2 id="heading-implementation-of-web-typography-in-reality">Implementation of web typography — in reality</h2>
<p>It is possible to have an opinionated and structured UI adhering to an 8pt grid that also has a long-form reading area.</p>
<p>Allow the fixed baseline grid system to handle the text inside of your structured components and use a modular scale to create an optimal reading experience for the blog or docs you’ve added onto your site.</p>
<p>Most digital product companies do this already between their marketing landing page, the digital product, and their documentation. Making the decision to structure these typographic realms separately can free you from an unsustainable complexity.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/AQRwQogPt9TiBR82ig3AbFMJBPZO8wz-KQG2" alt="Image" width="320" height="360" loading="lazy">
<em>Mixing content types together</em></p>
<h2 id="heading-the-pitfall-ems-rems-and-pixels-oh-my">The pitfall — Ems, rems, and pixels oh my!</h2>
<p>To express a clear and consistent system, typography measurements need to be easily interpreted by the product team building it.</p>
<p>Relative units like <a target="_blank" href="https://css-tricks.com/rem-global-em-local/">rems and ems</a> are sometimes misunderstood and, in my experience, this leads to an unsustainable typography system. For example, the ratio between 14px font-size and a 20px line-height shouldn’t be captured in relative units because that ratio should change as the font-size increases.</p>
<p>Defining a line-height of 1.4285714286em is ridiculous, because most folks can’t do that kind of math in their head. If the font-size increases to 16px the browser will render a line-height of 22.857142px and that kind of pixel splitting is a headache waiting to happen. This creates confusion and is a misuse of relative units. See a complete list of <a target="_blank" href="https://www.w3schools.com/cssref/css_units.asp">absolute vs relative units here</a>.</p>
<p>Why are so many design systems based on relative sizing today? The answer is “accessibility”.</p>
<p>However, browsers don’t scale the base font-size when you zoom in with <code>command +</code>. There are accessibility tools that will scale base font-sizes for users who need it. I recommend properly testing it to make sure it’s the experience you want users to have. Check-the-box accessibility can hurt more than it helps.</p>
<p>Utilizing rems and ems in your site/app is amazingly powerful. There are many very interesting use cases and they should be an important part of your toolkit.</p>
<p>My suggestion is to use them sparingly until you have a solid use for them. Baking them into the core of your typography system can open you up to confusion and unexpected user experiences.</p>
<h2 id="heading-8pt-grid-typography">8pt Grid Typography</h2>
<p>The most powerful part of the 8pt grid concept is its ability to drive consistency throughout your designs. You will need to assess the needs of your users and the best way to scale your typography to meet those needs.</p>
<p>I highly encourage design and engineering to collaborate on finalizing these standards for a company/product.</p>
<p>Here are samples from a few familiar names: <a target="_blank" href="https://material.io/design/typography/the-type-system.html#type-scale">Google Material</a>, <a target="_blank" href="https://styleguide.pivotal.io/typography">Pivotal</a>, <a target="_blank" href="https://atlassian.design/server/foundations/typography/">Atlassian</a>, <a target="_blank" href="https://designsystem.quickbooks.com/foundations/typography/">Intuit</a>.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/F8E-aK4T2KYa7HSEcgDUrq5ahyP9mvJv-M7e" alt="Image" width="700" height="382" loading="lazy">
<em>Samples simplified to fit onto a standard scale</em></p>
<h4 id="heading-references-and-related-reading">References and Related Reading</h4>
<ul>
<li>Priyanka Godbole: <a target="_blank" href="https://blog.prototypr.io/a-framework-for-creating-a-predictable-and-harmonious-spacing-system-8eee8aaf773c">A framework for creating a predictable &amp; harmonious spacing system for faster design-dev handoff</a></li>
<li>Richard Rutter: <a target="_blank" href="http://webtypography.net/intro/">The Elements of Typographic Style Applied to the Web</a></li>
<li>Ian Yates: <a target="_blank" href="https://webdesign.tutsplus.com/articles/how-to-establish-a-modular-typographic-scale--webdesign-14927">How to Establish a Modular Typographic Scale</a></li>
<li>Nathan Curtis: <a target="_blank" href="https://medium.com/eightshapes-llc/space-in-design-systems-188bcbae0d62">Space in Design Systems</a></li>
<li>Vincent De Oliveira: <a target="_blank" href="https://iamvdo.me/en/blog/css-font-metrics-line-height-and-vertical-align">Deep dive CSS: font metrics, line-height and vertical-align</a></li>
<li>Kezz Bracey: <a target="_blank" href="https://webdesign.tutsplus.com/tutorials/why-you-should-be-using-rem-based-layouts--cms-27828">Why You Should Be Using Rem-Based Layouts</a></li>
</ul>
<h4 id="heading-previous-8-point-grid-articles">Previous 8-Point Grid Articles:</h4>
<ol>
<li><a target="_blank" href="https://builttoadapt.io/intro-to-the-8-point-grid-system-d2573cde8632">Intro to The 8-Point Grid System</a></li>
<li><a target="_blank" href="https://builttoadapt.io/8-point-grid-borders-and-layouts-e91eb97f5091">8-Point Grid: Borders and Layouts</a></li>
<li><a target="_blank" href="https://builttoadapt.io/8-point-grid-vertical-rhythm-90d05ad95032">8-Point Grid: Vertical Rhythm</a></li>
</ol>
<h4 id="heading-questions">Questions:</h4>
<p>This is something I am still exploring. Do you have a good example to share? Do you have a different approach to an 8pt typography system?</p>
<p>If you’ve got thoughts, please leave a comment or reach out on <a target="_blank" href="https://twitter.com/Elliotdahl">Twitter</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
