<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Eelco Verbrugge</title>
    <description>The latest articles on DEV Community by Eelco Verbrugge (@eelcoverbrugge).</description>
    <link>https://dev.to/eelcoverbrugge</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F201386%2F61ee0795-464f-4253-a748-63dbdb98ac4b.jpeg</url>
      <title>DEV Community: Eelco Verbrugge</title>
      <link>https://dev.to/eelcoverbrugge</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/eelcoverbrugge"/>
    <language>en</language>
    <item>
      <title>Achieving WCAG 2.1 Status A: Accessible Menubar</title>
      <dc:creator>Eelco Verbrugge</dc:creator>
      <pubDate>Tue, 06 Feb 2024 09:26:50 +0000</pubDate>
      <link>https://dev.to/eelcoverbrugge/achieving-wcag-21-status-a-accessible-menubar-pa1</link>
      <guid>https://dev.to/eelcoverbrugge/achieving-wcag-21-status-a-accessible-menubar-pa1</guid>
      <description>&lt;p&gt;Unlock the secrets of building a Menubar that meets WCAG 2.1 Status A guidelines. My step-by-step guide makes accessibility in webdevelopment simple and effective.&lt;/p&gt;

&lt;h2&gt;
  
  
  Accessibility Considerations (WCAG 2.1 Level A):
&lt;/h2&gt;

&lt;p&gt;1.4.1 Use of Color: Ensure that color is not the only means of conveying information or indicating an action.&lt;/p&gt;

&lt;p&gt;2.1.1 Keyboard: The MenuBar, including dropdowns and submenus, must be fully navigable using a keyboard.&lt;/p&gt;

&lt;p&gt;1.3.1 Info and Relationships: The structure of the menu and its items should be clearly defined for assistive technologies.&lt;/p&gt;

&lt;p&gt;2.4.4 Link Purpose (In Context): Ensure that the purpose of each menu item link is clear from its text or context.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key words
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Menubar= A Menubar is the container of items that represents any choices&lt;/li&gt;
&lt;li&gt;Menuitem = A Menuitem is each choice within a Menubar &lt;/li&gt;
&lt;li&gt;Menu = A Menu opens a submenu, also known as a parent Menuitem.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Rules
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A Menubar should exist of these semantic html elements

&lt;code&gt;&amp;lt;nav&amp;gt;, &amp;lt;ul&amp;gt;, &amp;lt;li&amp;gt; and &amp;lt;a&amp;gt;&lt;/code&gt;

.&lt;/li&gt;
&lt;li&gt;If there are multiple menu's, use aria-label to distinguish them from each other.&lt;/li&gt;
&lt;li&gt;A Menu has the aria-expanded set to false when collapsed and set to true when expanded&lt;/li&gt;
&lt;li&gt;The menu has the attribute tabindex set to -1 or 0&lt;/li&gt;
&lt;li&gt;The menu has the attribute aria-activedescendant set to the ID of the focused item&lt;/li&gt;
&lt;li&gt;Each item in a menu has the attribute tabindex set to -1, except in a menubar where the first item has tabindex 0&lt;/li&gt;
&lt;li&gt;Whenever a menuitem is disabled the attribute aria-disabled is set to true&lt;/li&gt;
&lt;li&gt;A menubar has the attribute aria-label OR aria-labeledby when the menubar has a visible label. Aria-labeledby refers to the labelling element.&lt;/li&gt;
&lt;li&gt;The menubar has a default value of aria-orientation for horizontally orientation. If it is vertically oriented, set the attribute aria-orientation to vertical.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Hamburgermenu
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;If some trigger will open a Menu (submenu) or mobile version of the Menubar, set aria-haspopup to true to indicate&lt;/li&gt;
&lt;li&gt;Add aria-label=“Menu” when there is a hamburger icon within the button and not any text&lt;/li&gt;
&lt;li&gt;Hamburgemenu icon preferably needs to be 44 x 44 pixels&lt;/li&gt;
&lt;li&gt;Button need to be triggered by Enter or Space key&lt;/li&gt;
&lt;li&gt;When expanded, focus need to stay on hamburgemenu&lt;/li&gt;
&lt;li&gt;When Tab is pressed, the first element of the content must be selected&lt;/li&gt;
&lt;li&gt;When javascript turned off, the menu should be expanded&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Example
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;nav&lt;/span&gt; &lt;span class="na"&gt;aria-label=&lt;/span&gt;&lt;span class="s"&gt;"Accessible Menubar"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;ul&lt;/span&gt; &lt;span class="na"&gt;role=&lt;/span&gt;&lt;span class="s"&gt;"menubar"&lt;/span&gt; &lt;span class="na"&gt;aria-label=&lt;/span&gt;&lt;span class="s"&gt;"Accessible Menubar"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;li&lt;/span&gt; &lt;span class="na"&gt;role=&lt;/span&gt;&lt;span class="s"&gt;"none"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;role=&lt;/span&gt;&lt;span class="s"&gt;"menuitem"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#home"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; Home &lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;li&lt;/span&gt; &lt;span class="na"&gt;role=&lt;/span&gt;&lt;span class="s"&gt;"none"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;role=&lt;/span&gt;&lt;span class="s"&gt;"menuitem"&lt;/span&gt; &lt;span class="na"&gt;aria-haspopup=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt; &lt;span class="na"&gt;aria-expanded=&lt;/span&gt;&lt;span class="s"&gt;"false"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#about"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                About
            &lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;ul&lt;/span&gt; &lt;span class="na"&gt;role=&lt;/span&gt;&lt;span class="s"&gt;"menu"&lt;/span&gt; &lt;span class="na"&gt;aria-label=&lt;/span&gt;&lt;span class="s"&gt;"About"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;li&lt;/span&gt; &lt;span class="na"&gt;role=&lt;/span&gt;&lt;span class="s"&gt;"none"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;role=&lt;/span&gt;&lt;span class="s"&gt;"menuitem"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#overview"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Overview&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;li&lt;/span&gt; &lt;span class="na"&gt;role=&lt;/span&gt;&lt;span class="s"&gt;"none"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;role=&lt;/span&gt;&lt;span class="s"&gt;"menuitem"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#administration"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Administration&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;li&lt;/span&gt; &lt;span class="na"&gt;role=&lt;/span&gt;&lt;span class="s"&gt;"none"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;role=&lt;/span&gt;&lt;span class="s"&gt;"menuitem"&lt;/span&gt; &lt;span class="na"&gt;aria-haspopup=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt; &lt;span class="na"&gt;aria-expanded=&lt;/span&gt;&lt;span class="s"&gt;"false"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#facts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                        Facts
                    &lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;ul&lt;/span&gt; &lt;span class="na"&gt;role=&lt;/span&gt;&lt;span class="s"&gt;"menu"&lt;/span&gt; &lt;span class="na"&gt;aria-label=&lt;/span&gt;&lt;span class="s"&gt;"Facts"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                        &lt;span class="nt"&gt;&amp;lt;li&lt;/span&gt; &lt;span class="na"&gt;role=&lt;/span&gt;&lt;span class="s"&gt;"none"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                            &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;role=&lt;/span&gt;&lt;span class="s"&gt;"menuitem"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#history"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;History&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
                        &lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
                        &lt;span class="nt"&gt;&amp;lt;li&lt;/span&gt; &lt;span class="na"&gt;role=&lt;/span&gt;&lt;span class="s"&gt;"none"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                            &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;role=&lt;/span&gt;&lt;span class="s"&gt;"menuitem"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#current-statistics"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Current Statistics&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
                        &lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
                        &lt;span class="nt"&gt;&amp;lt;li&lt;/span&gt; &lt;span class="na"&gt;role=&lt;/span&gt;&lt;span class="s"&gt;"none"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                            &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;role=&lt;/span&gt;&lt;span class="s"&gt;"menuitem"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#awards"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Awards&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
                        &lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/nav&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sources:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.w3.org/WAI/ARIA/apg/patterns/menubar/"&gt;W3 Menu and Menubar Pattern
&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.udemy.com/course/creating-accessible-websites/"&gt;Creating Accessible Websites&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>a11y</category>
      <category>menubar</category>
      <category>html</category>
      <category>wcag</category>
    </item>
    <item>
      <title>Simple navbar in html, css and javascript</title>
      <dc:creator>Eelco Verbrugge</dc:creator>
      <pubDate>Sun, 17 Dec 2023 18:40:06 +0000</pubDate>
      <link>https://dev.to/eelcoverbrugge/simple-navbar-in-html-css-and-javascript-3j82</link>
      <guid>https://dev.to/eelcoverbrugge/simple-navbar-in-html-css-and-javascript-3j82</guid>
      <description>&lt;p&gt;This navbar will feature a centered logo, menu items, a call-to-action (CTA) button, and a custom hamburger menu for mobile screens. We'll use HTML, CSS, and a bit of JavaScript.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Setting Up the HTML Structure
&lt;/h2&gt;

&lt;p&gt;First things first, we gotta lay down the basic structure for our navigation bar in html.&lt;/p&gt;

&lt;h3&gt;
  
  
  index.html
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"style.css"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"viewport"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"width=device-width, initial-scale=1"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;nav&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"navbar"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"menu-left"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Home&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Services&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;About&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"logo"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"logo.png"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Logo"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"menu-right"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"cta-button"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Contact Us&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"hamburger"&lt;/span&gt; &lt;span class="na"&gt;onclick=&lt;/span&gt;&lt;span class="s"&gt;"toggleMobileMenu()"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;span&amp;gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;span&amp;gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;span&amp;gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/nav&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"mobileMenu"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"mobile-menu"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"closebtn"&lt;/span&gt; &lt;span class="na"&gt;onclick=&lt;/span&gt;&lt;span class="s"&gt;"toggleMobileMenu()"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;&lt;span class="ni"&gt;&amp;amp;times;&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Home&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Services&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;About&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"cta-button"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Contact Us&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"script.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 2: Styling with CSS
&lt;/h2&gt;

&lt;p&gt;Now, let's get fancy with the visuals. We're talking modern design vibes here—subtle shadows, smooth transitions, the works.&lt;/p&gt;

&lt;h3&gt;
  
  
  style.css
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.navbar&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;justify-content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;space-between&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;align-items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#333&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;white&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10px&lt;/span&gt; &lt;span class="m"&gt;20px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;box-shadow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;2px&lt;/span&gt; &lt;span class="m"&gt;5px&lt;/span&gt; &lt;span class="n"&gt;rgba&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0.2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.menu-left&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;.menu-right&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;.logo&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;align-items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.logo&lt;/span&gt; &lt;span class="nt"&gt;img&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;max-height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;50px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.hamburger&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;pointer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;flex-direction&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;column&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;justify-content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;space-around&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;30px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;25px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.hamburger&lt;/span&gt; &lt;span class="nt"&gt;span&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;white&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;transition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;all&lt;/span&gt; &lt;span class="m"&gt;0.3s&lt;/span&gt; &lt;span class="n"&gt;ease&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.cta-button&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#007bff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;white&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10px&lt;/span&gt; &lt;span class="m"&gt;20px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;text-decoration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;transition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;background-color&lt;/span&gt; &lt;span class="m"&gt;0.3s&lt;/span&gt; &lt;span class="n"&gt;ease&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.cta-button&lt;/span&gt;&lt;span class="nd"&gt;:hover&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#0056b3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.mobile-menu&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;fixed&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;z-index&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#111&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;overflow-x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;hidden&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;transition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;width&lt;/span&gt; &lt;span class="m"&gt;0.5s&lt;/span&gt; &lt;span class="n"&gt;ease&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;padding-top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;60px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.mobile-menu&lt;/span&gt; &lt;span class="nt"&gt;a&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;15px&lt;/span&gt; &lt;span class="m"&gt;25px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;text-decoration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;22px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;white&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;block&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;transition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt; &lt;span class="m"&gt;0.3s&lt;/span&gt; &lt;span class="n"&gt;ease&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.mobile-menu&lt;/span&gt; &lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="nd"&gt;:hover&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#ddd&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.mobile-menu&lt;/span&gt; &lt;span class="nc"&gt;.closebtn&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;absolute&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;right&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;25px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;36px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;pointer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="n"&gt;screen&lt;/span&gt; &lt;span class="n"&gt;and&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;768px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;.menu-left&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;.menu-right&lt;/span&gt; &lt;span class="nc"&gt;.cta-button&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nc"&gt;.menu-right&lt;/span&gt; &lt;span class="nc"&gt;.hamburger&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="n"&gt;screen&lt;/span&gt; &lt;span class="n"&gt;and&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;min-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;768px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;.mobile-menu&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;a&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;white&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;text-decoration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;transition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt; &lt;span class="m"&gt;0.3s&lt;/span&gt; &lt;span class="n"&gt;ease&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="nd"&gt;:hover&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#ddd&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.navbar&lt;/span&gt; &lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="nd"&gt;:not&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;.cta-button&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10px&lt;/span&gt; &lt;span class="m"&gt;15px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;5px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;transition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;background-color&lt;/span&gt; &lt;span class="m"&gt;0.3s&lt;/span&gt; &lt;span class="n"&gt;ease&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.navbar&lt;/span&gt; &lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="nd"&gt;:not&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;.cta-button&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="nd"&gt;:hover&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;rgba&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;255&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;255&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;255&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 3: Adding JavaScript for Interactivity
&lt;/h2&gt;

&lt;p&gt;For the mobile crowd, we'll sprinkle a bit of JavaScript magic. When you hit that burger menu, it'll conjure up the mobile menu in style.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;toggleMobileMenu&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;menu&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mobileMenu&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;menu&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;100%&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;menu&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;menu&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;width&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;100%&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;And there you have it, a super cool and responsive navigation bar, ready to rock the digital world.&lt;/p&gt;

</description>
      <category>navbar</category>
      <category>responsive</category>
      <category>simple</category>
    </item>
    <item>
      <title>Install Drupal 10 with Lando</title>
      <dc:creator>Eelco Verbrugge</dc:creator>
      <pubDate>Thu, 16 Nov 2023 19:45:10 +0000</pubDate>
      <link>https://dev.to/eelcoverbrugge/install-drupal-10-with-lando-55ga</link>
      <guid>https://dev.to/eelcoverbrugge/install-drupal-10-with-lando-55ga</guid>
      <description>&lt;p&gt;In this post, we will guide you through the process of setting up a Drupal 10 project using Lando, a powerful local development environment. &lt;/p&gt;

&lt;p&gt;Before we begin, make sure you have PHP, Composer, Docker and Lando installed on your system. We'll then download Drupal 10 and configure a basic Lando setup.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Install PHP&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Ensure PHP is installed on your machine. You can follow the official PHP installation guide for your operating system.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.php.net/manual/en/install.php"&gt;php.net&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2: Install Composer (Make it Global)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Install Composer and make it globally accessible. You can download it from &lt;a href="https://getcomposer.org/"&gt;getcomposer.org&lt;/a&gt; and follow the installation instructions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3: Install Docker&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Download and install Docker from the official Docker website.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.docker.com/engine/install/"&gt;docs.docker.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 4: Install Lando&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Install Lando by following the instructions on the official Lando website or by using a package manager like Homebrew.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.lando.dev/getting-started/installation.html"&gt;docs.lando.dev&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 5: Download Drupal 10&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Download Drupal 10 to your desired location. You can use git or download the tarball from Drupal's official website.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.drupal.org/download"&gt;drupal.org&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 6: Initialize Lando&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Navigate to your Drupal 10 project directory and run the following commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;lando init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Follow the prompts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Choose current working directory as the app's codebase.&lt;/li&gt;
&lt;li&gt;Select 'drupal10' as the recipe.&lt;/li&gt;
&lt;li&gt;Set the webroot relative to the init destination as './web'.&lt;/li&gt;
&lt;li&gt;Name your app, e.g., 'my-first-drupal-10-project'.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Step 7: Start Lando&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Start your Lando environment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;lando start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 8: Check Database Information&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To access your database, use the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;lando info
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Take note of the database name, password, user, and optionally, the hostname.&lt;/p&gt;

&lt;p&gt;Go to your browser and follow the Drupal installation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bonus
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Step 9: Stop Lando&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Stop your Lando environment when needed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;lando stop
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 10: Modify PHP Version&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Edit your &lt;code&gt;.lando.yml&lt;/code&gt; file to set the PHP version to 7.4 under the config section.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 11: Restart Lando with PHP 7.4&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Restart Lando to apply the changes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;lando start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 12: Verify PHP Version&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Access your Lando environment and check the PHP version:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;lando ssh
&lt;span class="nv"&gt;$ &lt;/span&gt;php &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 13: Rebuild Lando&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If needed, rebuild your Lando environment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;lando rebuild
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 14: Verify PHP Version Again&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;After rebuilding, check the PHP version once more:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;lando ssh
&lt;span class="nv"&gt;$ &lt;/span&gt;php &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Summary:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Congratulations! You've successfully set up a Drupal 10 project using Lando, managing PHP versions seamlessly. Remember, these steps provide a foundation for your local development environment, allowing you to efficiently work on your Drupal projects.&lt;/p&gt;

</description>
      <category>drupal</category>
      <category>lando</category>
      <category>docker</category>
      <category>setup</category>
    </item>
    <item>
      <title>Next.js 13: Introducing App Router and Server Components</title>
      <dc:creator>Eelco Verbrugge</dc:creator>
      <pubDate>Thu, 08 Jun 2023 10:49:50 +0000</pubDate>
      <link>https://dev.to/eelcoverbrugge/nextjs-13-introducing-app-router-and-server-components-2kn4</link>
      <guid>https://dev.to/eelcoverbrugge/nextjs-13-introducing-app-router-and-server-components-2kn4</guid>
      <description>&lt;p&gt;Next.js 13 is a major release of the popular React framework that introduces several new features and improvements.&lt;/p&gt;

&lt;h2&gt;
  
  
  App Router and Server Components
&lt;/h2&gt;

&lt;p&gt;One of the significant changes in Next.js 13 is the introduction of a new routing system called App Router. This new routing system is a complete rewrite of the previous one and coexists with the existing pages directory. The new App Router comes with a concept called Server Components (RSC), a new type of React component that runs on the server and returns compiled JSX to the client. Server Components are the default component type in the new app directory.&lt;/p&gt;

&lt;h2&gt;
  
  
  Layouts and Performance Improvements
&lt;/h2&gt;

&lt;p&gt;Layouts are another important feature introduced in Next.js 13. They are foundational components that wrap pages and allow for displaying a common UI across pages and reusing logic and data fetching. Layouts also solve the waterfall problem that was present in the previous routing system and provide performance improvements.&lt;/p&gt;

&lt;h2&gt;
  
  
  Enhanced Router and Flexible Component Structure
&lt;/h2&gt;

&lt;p&gt;The enhanced router in Next.js 13 allows for adding various types of components in the app directory using conventional filenames, enabling a more flexible and organized structure. Pages, layouts, errors, and loading states can be defined using specific filenames, contributing to a more flexible component structure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Server Components and Constraints
&lt;/h2&gt;

&lt;p&gt;Server Components, the new default component type in Next.js, run on the server and return compiled JSX to the client. They are useful for rendering the skeleton of a page, reducing the amount of JavaScript sent to the client, and improving routing performance for server-rendered pages. Server Components have some constraints, such as not being able to use browser-only APIs, React hooks, or Context.&lt;/p&gt;

&lt;h2&gt;
  
  
  Server Actions and Complex Logic
&lt;/h2&gt;

&lt;p&gt;Server Actions, although still in the alpha stage, offer a new way to execute functions on the server without wiring them through an API handler. They are useful for executing server-side logic such as sending emails or updating a database. Server Actions can be used for submitting forms, executing server-side logic, and redirecting the user to a new page. They also provide the ability to revalidate data fetched from Server Components, eliminating the need for complex client-side state management.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pages, Metadata, and Loading Indicators
&lt;/h2&gt;

&lt;p&gt;Pages in the new app directory are defined with the page.tsx convention. Page metadata and SEO information can be specified using the metadata property, and dynamic data can be accessed using the generateMetadata function. Static pages can be generated using the generateStaticParams function. Loading indicators can be implemented using the loading.tsx file, which can be defined in every directory.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Next.js 13 brings significant improvements and new capabilities to the framework, making it even more powerful and efficient for building React applications. The new routing system, Server Components, enhanced router, layouts, and other features contribute to improved performance, code organization, and developer productivity.&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>react</category>
      <category>javascript</category>
      <category>update</category>
    </item>
    <item>
      <title>Server-Side Rendering (SSR) or Static Site Generation (SSG)?</title>
      <dc:creator>Eelco Verbrugge</dc:creator>
      <pubDate>Fri, 02 Jun 2023 15:06:24 +0000</pubDate>
      <link>https://dev.to/eelcoverbrugge/server-side-rendering-ssr-or-static-site-generation-ssg-3m0</link>
      <guid>https://dev.to/eelcoverbrugge/server-side-rendering-ssr-or-static-site-generation-ssg-3m0</guid>
      <description>&lt;p&gt;When it comes to Next.js development, choosing the right data fetching and rendering approach can greatly impact your application's performance and user experience. Two popular methods at your disposal are server-side rendering (SSR) and static site generation (SSG). In this blog post, we'll explore the factors to consider when deciding between SSR and SSG, helping you make an informed choice for your Next.js projects.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding Server-Side Rendering (SSR)
&lt;/h2&gt;

&lt;p&gt;Server-side rendering involves generating HTML content on the server for each incoming request. Here are some scenarios where SSR might be the preferred approach:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Dynamic Content: If your application relies heavily on dynamic data that frequently changes, SSR is an excellent choice. By fetching data on the server and rendering it dynamically, you can ensure that users receive up-to-date information.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Search Engine Optimization (SEO): SSR is highly beneficial for SEO. Search engines can easily crawl and index server-rendered content, leading to better discoverability and improved search engine rankings for your pages.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Personalized User Experience: SSR allows you to personalize the content based on user-specific data. This is useful when you need to show personalized recommendations, user-specific data, or implement features that require user authentication.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Exploring Static Site Generation (SSG)
&lt;/h2&gt;

&lt;p&gt;Static site generation involves pre-rendering your application's content at build time, generating static HTML files that can be served to users. Consider the following scenarios where SSG might be the right choice:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Content Stability: If your application's content does not change frequently or requires periodic updates, SSG can be an efficient approach. By pre-rendering and serving static files, you can reduce the load on your server and deliver fast-loading pages to your users.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Performance and Scalability: SSG provides excellent performance benefits, as users receive pre-rendered HTML files that load quickly. Additionally, CDNs can cache these static files, enhancing scalability and reducing server load, making it ideal for high-traffic websites.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Offline Availability: With SSG, you can leverage service workers to make your application available offline. Pre-rendered HTML content allows users to access your application even when they have limited or no internet connectivity.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Choosing the Right Approach:
&lt;/h2&gt;

&lt;p&gt;To determine whether SSR or SSG is the right fit for your Next.js project, consider the following factors:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Data Freshness: If your application requires real-time or frequently updated data, SSR is the way to go. However, if your content is relatively stable and periodic revalidation is sufficient, SSG can provide excellent performance benefits.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;SEO Requirements: If search engine visibility is crucial for your application, SSR is recommended. Search engines can crawl and index server-rendered content more effectively, improving your website's discoverability.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;User Experience: Consider whether you need to provide a personalized user experience based on dynamic data. SSR allows you to fetch user-specific data on the server, while SSG requires additional client-side rendering or data fetching techniques for personalization.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Build Time Considerations: SSG requires content to be generated at build time, which may increase the overall build time for larger applications. Evaluate whether the build time impact is acceptable for your project.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Both SSR and SSG offer distinct advantages for Next.js development, and choosing the right approach depends on your project's requirements. SSR excels in scenarios where dynamic content, SEO, and personalization are crucial. On the other hand, SSG provides exceptional performance benefits, scalability, and offline availability for applications with stable or periodically updated content.&lt;/p&gt;

&lt;p&gt;Evaluate the freshness of your data, SEO needs, user experience requirements, and build time considerations to make an informed decision. Remember, Next.js offers the flexibility to combine SSR and SSG techniques, allowing you to tailor the data fetching and rendering approach according to specific pages or components within your application.&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>ssr</category>
      <category>ssg</category>
      <category>javascript</category>
    </item>
    <item>
      <title>May the Forms be with You: A Jedi's Guide to onBlur, onChange and onTouched</title>
      <dc:creator>Eelco Verbrugge</dc:creator>
      <pubDate>Fri, 05 May 2023 09:23:49 +0000</pubDate>
      <link>https://dev.to/eelcoverbrugge/may-the-forms-be-with-you-a-jedis-guide-to-onblur-onchange-and-ontouched-7d6</link>
      <guid>https://dev.to/eelcoverbrugge/may-the-forms-be-with-you-a-jedis-guide-to-onblur-onchange-and-ontouched-7d6</guid>
      <description>&lt;p&gt;React Hook Form (RHF) knows the modes: onChange, onBlur and onTouched. If you are familiar with RHF but don’t know what they do, you could use some help of a Jedi master!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/8hMD9YakVza3452SpN/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/8hMD9YakVza3452SpN/giphy.gif" width="512" height="215"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  onChange
&lt;/h2&gt;

&lt;p&gt;Let's start with onChange. Like a Jedi using the Force to feel the will of the user, onChange is triggered whenever there is a change in the value of an input field. Whether the change comes from the user typing or from a programmatic change of the value, onChange is there to help you update the value of the input field as the user types.&lt;/p&gt;

&lt;p&gt;But beware, young Padawan, for there is a dark side to onChange. If you're not careful, it can be dangerous and negatively impact the performance of your app. Imagine you have a text field where users can enter their name. If you use onChange to update the value with every keystroke, it can lead to unnecessary re-rendering and delays in your app. So use onChange with care and wisdom.&lt;/p&gt;

&lt;h2&gt;
  
  
  onBlur
&lt;/h2&gt;

&lt;p&gt;Now let's move on to onBlur. Like a Jedi focusing on feeling the energy of their surroundings, onBlur is triggered when an input field loses focus. For example, if the user moves to another field, onBlur is triggered to help you validate the entered value.&lt;/p&gt;

&lt;p&gt;But be careful, young Jedi, as there are certain circumstances where onBlur is not triggered. For example, if the user clicks the browser's back button or refreshes the page, onBlur is not triggered. So if you're using onBlur to validate data, make sure to use other methods to ensure your data is safe.&lt;/p&gt;

&lt;h2&gt;
  
  
  onTouched
&lt;/h2&gt;

&lt;p&gt;Last but not least, onTouched. Like a Jedi using their powers to sense the thoughts of others, onTouched is triggered when a user touches or interacts with an input field. This is useful if you want to let the user know which fields they have already touched and where they still need to work.&lt;/p&gt;

&lt;p&gt;But beware, as onTouched can sometimes be misleading, just like the dark side of the Force. It doesn't necessarily mean that data has actually been entered into the input field. Sometimes a user can touch a field and then decide not to enter data into it. So use onTouched in conjunction with other validation methods to ensure your data is accurate and complete.&lt;/p&gt;

</description>
      <category>onblur</category>
      <category>onchange</category>
      <category>ontouched</category>
      <category>reacthookform</category>
    </item>
    <item>
      <title>Multi-step Docker build process</title>
      <dc:creator>Eelco Verbrugge</dc:creator>
      <pubDate>Wed, 05 Apr 2023 07:41:58 +0000</pubDate>
      <link>https://dev.to/eelcoverbrugge/multi-step-docker-build-process-5nn</link>
      <guid>https://dev.to/eelcoverbrugge/multi-step-docker-build-process-5nn</guid>
      <description>&lt;p&gt;Multi-step Docker build process is a technique that allows you to optimize your Docker images by breaking the build process into multiple stages, and it involves the following steps:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Define the base image
&lt;/h3&gt;

&lt;p&gt;Start by defining the base image for your Dockerfile using the FROM statement. This is the image that will be used to create the first stage of the build process.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Copy the necessary files
&lt;/h3&gt;

&lt;p&gt;Use the COPY or ADD command to copy the necessary files and folders into the first stage of the Docker build.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Build your application
&lt;/h3&gt;

&lt;p&gt;Run any necessary build commands, such as compiling code, installing dependencies, or running tests, within the first stage of the build process.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Define the second stage
&lt;/h3&gt;

&lt;p&gt;Use another FROM statement to define a second stage for the build process. This second stage will be based on a different image, such as a minimal runtime image, and will not include any unnecessary files or dependencies from the first stage.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Copy files from the first stage
&lt;/h3&gt;

&lt;p&gt;Use the COPY --from= command to copy the necessary files and artifacts from the first stage into the second stage of the Docker build.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Define the startup command
&lt;/h3&gt;

&lt;p&gt;Finally, use the CMD or ENTRYPOINT command to define the startup command for the second stage of the Docker build.&lt;/p&gt;

&lt;p&gt;By using a multi-step Docker build process, you can create smaller and more efficient Docker images by only including the necessary files and dependencies in the final image.&lt;/p&gt;

&lt;h2&gt;
  
  
  Let’s get started
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;make sure you have nodejs installed&lt;br&gt;
&lt;code&gt;$ node -v&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create a React app called &lt;code&gt;frontend&lt;/code&gt;&lt;br&gt;
&lt;code&gt;$ npx create-react-app frontend&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;React startup commands are:&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Development server: &lt;code&gt;$ npm run start&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Run tests: &lt;code&gt;$ npm run test&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Builds a production version: &lt;code&gt;$ npm run build&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;Create &lt;code&gt;Dockerfile.dev&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FROM node:16-alpine

WORKDIR '/app'

#copy package.json to /app
COPY package.json .
#install all our dependencies
RUN npm install

#copy everything else from our project directory
COPY . .

#startup our project
CMD ["npm", "run", "start"]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Build our docker container in our development env&lt;br&gt;
&lt;code&gt;$ docker build -t frontend -f Dockerfile.dev .&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Run your build&lt;br&gt;
&lt;code&gt;$ docker run frontend -p 3000:3000 -v /app/node_modules -v $(pwd):/app&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Check out &lt;a href="http://localhost/3000" rel="noopener noreferrer"&gt;http://localhost/3000&lt;/a&gt; to see your brand new app running in a docker container.&lt;/p&gt;

&lt;h2&gt;
  
  
  Docker compose
&lt;/h2&gt;

&lt;p&gt;Docker Compose is a tool that allows you to define and run multi-container Docker applications. It is used to manage the dependencies and services required by your application, and it simplifies the process of defining, running, and connecting multiple Docker containers.&lt;/p&gt;

&lt;p&gt;In a Docker Compose file, you define the services that make up your application, including the images used, environment variables, volumes, network connections, and other settings. You can then use the docker-compose command to create and start all the necessary containers for your application.&lt;/p&gt;

&lt;p&gt;Docker Compose simplifies the process of building and running complex multi-container applications by providing a simple and flexible way to manage the dependencies and configurations of your services.&lt;/p&gt;

&lt;p&gt;Let’s create a docker-compose file for our dev environment so we can run our container in just 1 simple command.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create &lt;code&gt;docker-compose.yml&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;version: '3'
services:
  web:
    container_name: web
    build:
      context: . #specifying where we want all the files and folders for this image to be pulled from
      dockerfile: Dockerfile.dev #location of dockerfile to be used
    ports:
      - "3000:3000"
    volumes:
      - /app/node_modules #this means "do not try to map a folder up against node_modules inside the container"
      - .:/app #the . is the current folder outside the container: the /app folder is inside the container

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

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Run your docker-compose file
&lt;code&gt;$ docker-compose up&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Check out &lt;a href="http://localhost/3000" rel="noopener noreferrer"&gt;http://localhost/3000&lt;/a&gt; again to see your app is running, but this time from a single command with the help of docker-compose.&lt;/p&gt;

&lt;h2&gt;
  
  
  Production
&lt;/h2&gt;

&lt;p&gt;For the production we need nginx as a webserver to run our website. Let’s see how this works.&lt;/p&gt;

&lt;p&gt;Multi-step Docker build process:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Build Phase: Use node:alpine -&amp;gt; Copy the package.json file -&amp;gt; Install dependencies -&amp;gt; Run 'npm run build'&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Run Phase: Use nginx -&amp;gt; Copy over the result of 'npm run build' -&amp;gt; Start nginx&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;Create &lt;code&gt;Dockerfile&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#Build Phase
FROM node:16-alpine as builder #tagged as the builder-fase
WORKDIR '/app'
COPY package.json .
RUN npm install
COPY . .
RUN npm run build

#Run Phase
FROM nginx
COPY --from =builder /app/build  /usr/share/nginx/html #copy the stuff we care about from the other phase to this specifical nginx folder
#default command of the ngxin container/image is going to startup nginx for us
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Build your container&lt;br&gt;
&lt;code&gt;$ docker build .&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Run your build&lt;br&gt;
&lt;code&gt;$ docker run -p 8080:80 [build_image_id]&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In production we won’t use docker-compose, this is only for our dev environment.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>productivity</category>
    </item>
    <item>
      <title>React class to functional: states</title>
      <dc:creator>Eelco Verbrugge</dc:creator>
      <pubDate>Wed, 28 Dec 2022 11:08:08 +0000</pubDate>
      <link>https://dev.to/eelcoverbrugge/react-class-to-functional-states-3l90</link>
      <guid>https://dev.to/eelcoverbrugge/react-class-to-functional-states-3l90</guid>
      <description>&lt;p&gt;In 2018 React introduced Hooks. "They let you use state and other React features without writing a class." Hooks can be used in functional components but a lot of projects are still written in class components.&lt;/p&gt;

&lt;p&gt;In this serie I'll explain how easy it is to convert/refactor your class component to a functional component so you can use Hooks.&lt;/p&gt;

&lt;h1&gt;
  
  
  States
&lt;/h1&gt;

&lt;h2&gt;
  
  
  class component
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from 'react';
import {Button} from "react-bootstrap";

class Example extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            show: false
        }
        this.handleShow = this.handleShow.bind(this);
    }

    handleShow() {
        this.setState({show: true});
    }

    render() {
        const {show} = this.state;

        return (
            &amp;lt;&amp;gt;
                &amp;lt;Button onClick={this.handleShow}&amp;gt;Show&amp;lt;/Button&amp;gt;
                {show &amp;amp;&amp;amp; &amp;lt;h1&amp;gt;Awesome&amp;lt;/h1&amp;gt;}
            &amp;lt;/&amp;gt;
        )
    }
}

export default Example;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  functional component
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const Example = () =&amp;gt; {
  const [show, setShow] = useState(false);

  const handleShow = () =&amp;gt; {
    setShow(true);
  }

  return (
    &amp;lt;&amp;gt;
      &amp;lt;Button onClick={handleShow}&amp;gt;Show&amp;lt;/Button&amp;gt;
      {show &amp;amp;&amp;amp; &amp;lt;h1&amp;gt;Awesome&amp;lt;h1&amp;gt;}
    &amp;lt;/&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;1. Extends&lt;/strong&gt;&lt;br&gt;
Functional components no longer need to extends from React.Component&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Constructor&lt;/strong&gt;&lt;br&gt;
Where as a constructor is needed in a class component to set states, a functional component can use the "useState" hook. Just import this hook to use it &lt;code&gt;import React, {useState} from 'react';&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Passing Functions to Components&lt;/strong&gt;&lt;br&gt;
In class components it is necessary to pass functions to components in the constructor by &lt;code&gt;.bind(this)&lt;/code&gt; in order to work. Not needed in a functional component anymore.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Function&lt;/strong&gt;&lt;br&gt;
Functions are written a little different. The good old &lt;code&gt;myFunction() { ... }&lt;/code&gt; has been replaced by &lt;code&gt;myFunction = () =&amp;gt; { ... }&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Variables&lt;/strong&gt;&lt;br&gt;
Not needed anymore to point out to &lt;code&gt;this.state.myState&lt;/code&gt;, but just use &lt;code&gt;myState&lt;/code&gt;&lt;/p&gt;

</description>
      <category>watercooler</category>
    </item>
    <item>
      <title>Create generic React components</title>
      <dc:creator>Eelco Verbrugge</dc:creator>
      <pubDate>Thu, 17 Nov 2022 16:09:48 +0000</pubDate>
      <link>https://dev.to/eelcoverbrugge/create-generic-react-components-3bi4</link>
      <guid>https://dev.to/eelcoverbrugge/create-generic-react-components-3bi4</guid>
      <description>&lt;p&gt;As your application starts to grow, you often write repeated code. A simple example of this is with a form:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const SignupForm = () =&amp;gt; {
  return (
    &amp;lt;form onSubmit={handleSubmit}&amp;gt;
      &amp;lt;label&amp;gt;Nickname&amp;lt;/label&amp;gt;
      &amp;lt;input
        type="text"
        required
        onChange={handleChange}
        name="nickname"
        value={nickname} /&amp;gt;

      &amp;lt;label&amp;gt;Email&amp;lt;/label&amp;gt;
      &amp;lt;input
        type="email"
        required
        onChange={handleChange}
        name="email"
        value={email} /&amp;gt;

      &amp;lt;label&amp;gt;Password&amp;lt;/label&amp;gt;
      &amp;lt;input
        type="password"
        required
        onChange={handleChange}
        name="password"
        value={password} /&amp;gt;

      &amp;lt;button type="submit"&amp;gt;Submit&amp;lt;/button&amp;gt;
    &amp;lt;/form&amp;gt;
  )
}

export default SignupForm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The combination of label + input is repeated 3 times with the same attributes but differences in some values.&lt;/p&gt;

&lt;h2&gt;
  
  
  Generic component
&lt;/h2&gt;

&lt;p&gt;In order to reduce our code we'll create a new component FormInput where we group every label + input so we can reuse this code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from 'react';

const INPUT_TYPE = {
    text: 'text',
    email: 'email',
    password: 'password',
}

const FormInput = ({ label, type, ...otherAttributes  }) =&amp;gt; {

    if (!type) {
        throw Error('form input is missing the required type attribute');
    }

    return (
        &amp;lt;div&amp;gt;
            {label &amp;amp;&amp;amp; (
                &amp;lt;label className="form-label"&amp;gt;{label}&amp;lt;/label&amp;gt;
            )}
            &amp;lt;input type={INPUT_TYPE[type]} className="form-input" {...otherAttributes} /&amp;gt;
        &amp;lt;/div&amp;gt;
    )
}

export default FormInput
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I've separate the label prop from all other attributes (...otherAttributes) which can be passed on, to keep it clean and readable. We'll check the label prop to make sure it exists, since maybe in the future we want to use an input without a label.&lt;/p&gt;

&lt;p&gt;Now we can import our FormInput to our SignupForm, make sure your path is set right, so we can replace every label + input bij our FormInput component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import FormInput from "./FormInput" // imports our component

const SignupForm = () =&amp;gt; {
  return (
    &amp;lt;form onSubmit={handleSubmit}&amp;gt;
      &amp;lt;FormInput
        label="Nickname" // label prop with title as string
        type="text" // followed by all otherAttributes...
        required
        onChange={handleChange}
        name="nickname"
        value={nickname} /&amp;gt;

      &amp;lt;FormInput
        label="Email"
        type="email"
        required
        onChange={handleChange}
        name="email"
        value={email} /&amp;gt;

      &amp;lt;FormInput
        label="Password"
        type="password"
        required
        onChange={handleChange}
        name="password"
        value={password} /&amp;gt;
    &amp;lt;/form&amp;gt;
  )
}

export default SignupForm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Congrats! You just created a generic component.&lt;/p&gt;

</description>
      <category>react</category>
      <category>beginners</category>
      <category>generic</category>
      <category>components</category>
    </item>
    <item>
      <title>Pair programming in PHPStorm</title>
      <dc:creator>Eelco Verbrugge</dc:creator>
      <pubDate>Thu, 22 Sep 2022 09:15:30 +0000</pubDate>
      <link>https://dev.to/eelcoverbrugge/pair-programming-in-phpstorm-4emc</link>
      <guid>https://dev.to/eelcoverbrugge/pair-programming-in-phpstorm-4emc</guid>
      <description>&lt;h2&gt;
  
  
  What is pair programming
&lt;/h2&gt;

&lt;p&gt;According to &lt;a href="https://en.wikipedia.org/wiki/Pair_programming"&gt;wikipedia&lt;/a&gt;: Pair programming is an agile software development technique in which two programmers work together at one workstation.&lt;/p&gt;

&lt;p&gt;Best said: you and your colleague program together at the same time. Wether you sit next to each other or do this online, the idea is you switch roles now and then so you both programmed a part of the code. One is coding and the other will help you while you write your code and both players think out loud.&lt;/p&gt;

&lt;p&gt;Like drivers in a rally car:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/cekCJqDUpzrm86n7Kf/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/cekCJqDUpzrm86n7Kf/giphy.gif" width="480" height="270"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why would you pair program
&lt;/h2&gt;

&lt;p&gt;For many reasons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Problems are better solved, code quality increases&lt;/li&gt;
&lt;li&gt;Your code is being reviewed on the go&lt;/li&gt;
&lt;li&gt;Better ideas by talking through your ideas and solutions&lt;/li&gt;
&lt;li&gt;Learning from each other when having different approaches&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How to pair program in PHPStorm
&lt;/h2&gt;

&lt;p&gt;Of course you can share your screen and pair program, but I prefer doing so via PHPStorm and this is how to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Start a session&lt;/li&gt;
&lt;/ol&gt;

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

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Access control&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ElVVjTDt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/crn7oj9tyw5bv54ceslw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ElVVjTDt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/crn7oj9tyw5bv54ceslw.png" alt="Image description" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Accept&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--pJ1sQJQO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gt7pifo48upiqbildojq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pJ1sQJQO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gt7pifo48upiqbildojq.png" alt="Image description" width="800" height="289"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Send url for invitation&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;CongratS! You are officially pair programming now&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/QyKwWQzeOSl9e/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/QyKwWQzeOSl9e/giphy.gif" width="180" height="180"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Bonus: follow your colleague
&lt;/h2&gt;

&lt;p&gt;When a sessions is running, you can easily follow each other by clicking on the name of your colleague. It should color your window and say something like "Following colleague..."&lt;/p&gt;

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

&lt;p&gt;Checkout the documentation for more info and how to setup your session from the start (&lt;a href="https://www.jetbrains.com/help/idea/code-with-me.html#start-guest)%5Bhttps://www.jetbrains.com/help/idea/code-with-me.html#start-guest%5D"&gt;https://www.jetbrains.com/help/idea/code-with-me.html#start-guest)[https://www.jetbrains.com/help/idea/code-with-me.html#start-guest]&lt;/a&gt;&lt;/p&gt;

</description>
      <category>pairprogramming</category>
      <category>phpstorm</category>
      <category>sharingiscaring</category>
    </item>
    <item>
      <title>Why your password is weak</title>
      <dc:creator>Eelco Verbrugge</dc:creator>
      <pubDate>Mon, 18 Jul 2022 10:34:39 +0000</pubDate>
      <link>https://dev.to/eelcoverbrugge/why-your-password-is-to-weak-1dp9</link>
      <guid>https://dev.to/eelcoverbrugge/why-your-password-is-to-weak-1dp9</guid>
      <description>&lt;p&gt;Does your password requires at least the following?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Must be a minimum of 8 characters&lt;/li&gt;
&lt;li&gt;Must contain at least 1 number&lt;/li&gt;
&lt;li&gt;Must contain at least one uppercase character&lt;/li&gt;
&lt;li&gt;Must contain at least one lowercase character&lt;/li&gt;
&lt;li&gt;Must contain at least one special character (!@#$%^&amp;amp;*)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Research recently showed this password is &lt;strong&gt;cracked in 39 minutes&lt;/strong&gt;! Yes... you took a risk for brain damage in order to come up with a password like this or let your password manager did the job en still it can be cracked so so fast.&lt;/p&gt;

&lt;p&gt;In 2020 this password was cracked in 8 hours. That's just 12 times slower then what it is now, imagine how fast it will be within the next 2 years from now.&lt;/p&gt;

&lt;h3&gt;
  
  
  Password on steroids
&lt;/h3&gt;

&lt;p&gt;Best possible way to come up with a password is according to the Diceware-method &lt;a href="https://diceware.dmuth.org/"&gt;https://diceware.dmuth.org/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Experts use this to add randomness to the words your password contains. Every 5 numbers you throw in a row belongs to a word. Repeat this process until you have at least 7 words and create a passphrase:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Safety vs userfriendly
&lt;/h3&gt;

&lt;p&gt;One problem is this won't be acceptable by our minimal requirements like we said in the beginning. Of course we can add a number and exclamation mark or whatever, but this isn't the best solution.&lt;/p&gt;

&lt;p&gt;Also this is pretty harshe to ask everyone to do for "just a password". This also depends on what the value is of what you are trying to secure. But since people are lazy, lets come up with a solution that works for everyone.&lt;/p&gt;

&lt;p&gt;What we can do is higher the least minimal of characters used. If you go from 8 to 12, this means it can be cracked in 3000 years(!) in 2022. Still in 2020 this was 34000 years, so what will it be within the next 2 years? But this takes waaayyyy more time to crack so hopefully the hackers decides to target an easier victim.&lt;/p&gt;

&lt;p&gt;Source: &lt;a href="https://www.hivesystems.io/blog/are-your-passwords-in-the-green?utm_source=tabletext"&gt;https://www.hivesystems.io/blog/are-your-passwords-in-the-green?utm_source=tabletext&lt;/a&gt;&lt;/p&gt;

</description>
      <category>security</category>
      <category>webdev</category>
    </item>
    <item>
      <title>React Redux introduction</title>
      <dc:creator>Eelco Verbrugge</dc:creator>
      <pubDate>Fri, 01 Jul 2022 13:12:36 +0000</pubDate>
      <link>https://dev.to/eelcoverbrugge/react-redux-introduction-1n11</link>
      <guid>https://dev.to/eelcoverbrugge/react-redux-introduction-1n11</guid>
      <description>&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;Redux is used to enhance your application when the complicity continues to grow by simplifying the state management. States can include data from 3 different sources:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Servers&lt;/li&gt;
&lt;li&gt;Cache&lt;/li&gt;
&lt;li&gt;Locally&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This can be complicated in order to manage and this is where Redux enters the party. Redux is a State Management Tool for Javascript applications such as React.&lt;/p&gt;

&lt;p&gt;Redux stores the entire states of the application in a central location (called a store) so state manipulation and inner communication can be simplified. In the image below, the view is delivered by React with a template and various components. Redux takes the responsibility of managing the states using various components like Actions, Reducers, Action creators and Selectors. In order to connect Redux and the view (React) a Connector is been used in the form of a Container.&lt;/p&gt;

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

&lt;h1&gt;
  
  
  Let's get started
&lt;/h1&gt;

&lt;p&gt;Create a new file called &lt;code&gt;index2.html&lt;/code&gt; in your public folder of a brand new React application. Past the following code and start adding my sections one by one in place of [ INSERT SECTIONS HERE ]&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
  &amp;lt;head&amp;gt;
    &amp;lt;meta charset="UTF-8"&amp;gt;
    &amp;lt;title&amp;gt;REDUX STATES&amp;lt;/title&amp;gt;
    &amp;lt;link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/4.1.1/normalize.min.css" type="text/css"&amp;gt;
    &amp;lt;link rel="stylesheet" href="app.css" type="text/css"&amp;gt;
    &amp;lt;link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.6.1/css/font-awesome.css" type="text/css" /&amp;gt;
  &amp;lt;/head&amp;gt;
  &amp;lt;body&amp;gt;
    &amp;lt;div id="app"&amp;gt;
     Application Initiailizing...
    &amp;lt;/div&amp;gt;
    &amp;lt;script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.11.2/lodash.min.js"&amp;gt;&amp;lt;/script&amp;gt;
    &amp;lt;script src="https://cdnjs.cloudflare.com/ajax/libs/redux/3.5.2/redux.js" type="text/javascript"&amp;gt;&amp;lt;/script&amp;gt;
    &amp;lt;script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.0.1/react.js" type="text/javascript"&amp;gt;&amp;lt;/script&amp;gt;
    &amp;lt;script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.0.1/react-with-addons.js" type="text/javascript"&amp;gt;&amp;lt;/script&amp;gt;
    &amp;lt;script src="https://cdnjs.cloudflare.com/ajax/libs/react-redux/4.4.5/react-redux.js" type="text/javascript"&amp;gt;&amp;lt;/script&amp;gt;
    &amp;lt;script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.23/browser.min.js" type="text/javascript"&amp;gt;&amp;lt;/script&amp;gt;
    &amp;lt;script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.0.1/react-dom.js" type="text/javascript"&amp;gt;&amp;lt;/script&amp;gt;
    &amp;lt;script type="text/babel"&amp;gt;

[ INSERT SECTIONS HERE ]

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

  &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Libraries
&lt;/h2&gt;

&lt;p&gt;We begin by declaring all the required libraries and objects. I will explain them one by one:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;connect and Provider from ReactRedux is used to connect Redux to Reacts components&lt;/li&gt;
&lt;li&gt;Redux is used for various methods like createStore which is used to build the store&lt;/li&gt;
&lt;li&gt;Component from React is used to build a React component&lt;/li&gt;
&lt;li&gt;Map is used to manipulate content
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;      const {connect, Provider} = ReactRedux;
      const {createStore, compose} = Redux;
      const {Component} = React;
      const {map} = _;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Create Event Handlers
&lt;/h2&gt;

&lt;p&gt;Create a component called ListTable and extend from Component. Add a constructor with props and context. Let's bind our Event Handlers so we can declare them to dispatch. Dispatch will sent the event to Redux to manipulate our states.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;      class ListTable extends Component {
        constructor (props, context) {

          super(props, context);
          this.addItem = this.addItem.bind(this);
          this.removeItem = this.removeItem.bind(this);
          this.editItem = this.editItem.bind(this);
        }

        /* EVENT HANDLERS */
        addItem () {
          this.props.dispatch(addItemAction())
        }
        removeItem (index) {
          this.props.dispatch(removeItemAction(index))
        }
        editItem (index, event)  {
          this.props.dispatch(editItemAction(index, event.target.value))
        }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Render
&lt;/h2&gt;

&lt;p&gt;Lets render the outcome of items. Pretty much selfdeclaring, but just to be sure:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;onChange is to edit the item on every input &lt;/li&gt;
&lt;li&gt;onClick is to remove the item when clicked the delete button&lt;/li&gt;
&lt;li&gt;onClick is also used to add a new item when clicked on add
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;        render () {
          const {items, addItem} = this.props;

          return (&amp;lt;div&amp;gt;
            &amp;lt;table&amp;gt;
              &amp;lt;tbody&amp;gt;
                {map(items, (item, index) =&amp;gt; {
                  return (&amp;lt;tr key={index}&amp;gt;
                    &amp;lt;td&amp;gt;&amp;lt;input onChange={this.editItem.bind(null, index)} type="text" value={item} /&amp;gt;&amp;lt;/td&amp;gt;
                    &amp;lt;td&amp;gt;
                      &amp;lt;button onClick={this.removeItem.bind(null, index)} className="delete"&amp;gt;
                        remove
                      &amp;lt;/button&amp;gt;
                    &amp;lt;/td&amp;gt;
                  &amp;lt;/tr&amp;gt;);
                })}
              &amp;lt;/tbody&amp;gt;
            &amp;lt;/table&amp;gt;
            &amp;lt;button onClick={this.addItem} className="add"&amp;gt;
            Click
            &amp;lt;/button&amp;gt;
            &amp;lt;InfoBox /&amp;gt;
          &amp;lt;/div&amp;gt;);
        }
      }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Component
&lt;/h2&gt;

&lt;p&gt;This is the most important method, this is how you integrate Redux with React. Whenever there is a change in state, this will call the method mapStateToProps. This will map the states to the props of the React component.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;      class InfoBox extends Component {
        render () {
          return (&amp;lt;div&amp;gt;
            &amp;lt;p className="spiel"&amp;gt;
             SKill soft redux
            &amp;lt;/p&amp;gt;
          &amp;lt;/div&amp;gt;);
        }
      }
      /* MAP STATE TO PROPS */

      const mapStateToProps = (state) =&amp;gt; {
        return {
          items: state.items,
        }
      }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Reducers
&lt;/h2&gt;

&lt;p&gt;Reducers will listen to all actions that are dispatch and react according to the logic we apply. We now so far that all the states and Redux are immutable because they never change, so we have to return a new state object, that is what we are specifying in the reducer. We are adding appReducer and declaring items following which we are slicing items.&lt;/p&gt;

&lt;p&gt;Slice is an important method which clones an array without storing any reference of it. This is used when deciding which event to process. All the events we've specified will be processed through the appReducer.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If the action type is addItem, it push a new item.&lt;/li&gt;
&lt;li&gt;If it's removeItem, it will remove an item&lt;/li&gt;
&lt;li&gt;And if it's editItem, it will keep the new data value
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;      /* Reducers */
      const appReducer = (state = {items: []}, action) =&amp;gt; {
        let items = state.items.slice();
        console.log('Actions', action); 
        switch (action.type) {
          case 'ADD_ITEM':
            items.push('') // Add an extra element to items
            break;
          case 'REMOVE_ITEM':
            items.splice(action.index, 1); // Removes element at `index`
            break;
          case 'EDIT_ITEM':
            items[action.data.index] = action.data.value; // Change value of `index` to new value
            break;
        }

        const newState = {
          items: items,
        }
        console.log('Current State', newState);
        return newState;
      }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Store
&lt;/h2&gt;

&lt;p&gt;Let's creat a Redux store to store our states. Redux provides the capability of maintaining a centralized store to store the data that we want to project. To specify a store we will create a store with the createStore method and pass our appReducer.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;      /* REDUX STORE */
      let store = createStore(appReducer, {
        items: [
          'item1',
          'item2',
          'item3',
          'item4'
        ]
      }, window.devToolsExtension ? window.devToolsExtension() : undefined)

      // Use Redux connect to attach our mapStateToProps and so to our ListTable component
      const ListApp = connect(
        mapStateToProps
      )(ListTable)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Redux DevTools
&lt;/h3&gt;

&lt;p&gt;I have added a devtool which is downloadable for Chrome and Firefox to ensure that Redux connect will attach the method mapStateToProps to the ListTable component.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Chrome: &lt;a href="https://chrome.google.com/webstore/detail/redux-devtools/lmhkpmbekcpmknklioeibfkpmmfibljd"&gt;Redux DevTools&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Firefox: &lt;a href="https://addons.mozilla.org/nl/firefox/addon/reduxdevtools/"&gt;Redux DevTools&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;      ReactDOM.render(
        &amp;lt;Provider store={store}&amp;gt;
          &amp;lt;ListApp /&amp;gt;
        &amp;lt;/Provider&amp;gt;,
        document.getElementById('app')
      );
      if (window.devToolsExtension) {
        window.devToolsExtension.open();
      }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Tadaa!
&lt;/h2&gt;

&lt;p&gt;You have created your own React app with Redux. Checkout your index2.html page in the browser, open the console and try to add, remove and edit items. You should see every action you make as output in the console from the Reducer.&lt;/p&gt;

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

&lt;p&gt;Check out the full index2.html from my Github and see for your self &lt;a href="https://github.com/eelcoverbrugge/redux/blob/main/public/index2.html"&gt;https://github.com/eelcoverbrugge&lt;/a&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>beginners</category>
      <category>redux</category>
    </item>
  </channel>
</rss>
