<?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: Viviana Yanez</title>
    <description>The latest articles on DEV Community by Viviana Yanez (@vivitt).</description>
    <link>https://dev.to/vivitt</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%2F1118852%2F2255ab28-9e24-4f4a-89b2-90a47b3565de.png</url>
      <title>DEV Community: Viviana Yanez</title>
      <link>https://dev.to/vivitt</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/vivitt"/>
    <language>en</language>
    <item>
      <title>One Bit Explainer: Neural Networks</title>
      <dc:creator>Viviana Yanez</dc:creator>
      <pubDate>Fri, 21 Jun 2024 09:26:05 +0000</pubDate>
      <link>https://dev.to/vivitt/one-bit-explainer-neural-networks-lg7</link>
      <guid>https://dev.to/vivitt/one-bit-explainer-neural-networks-lg7</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for &lt;a href="https://dev.to/challenges/cs"&gt;DEV Computer Science Challenge v24.06.12: One Byte Explainer&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Explainer
&lt;/h2&gt;

&lt;p&gt;Neural networks enable computers to learn from data patterns and relations. Inspired by the human brain, they process information through interconnected layers of nodes, thriving in solving hard-to-systematize problems such as image and speech recognition.&lt;/p&gt;

&lt;h2&gt;
  
  
  Additional Context
&lt;/h2&gt;

&lt;p&gt;This week, I participated in a &lt;a href="https://www.tensorflow.org/js" rel="noopener noreferrer"&gt;TensorFlow.js&lt;/a&gt; workshop that was a great motivation to start learning about AI. I loved the session, and truly believe that with AI being more and more present in our lives, it's so important to break down its magic by developing a basic understanding of the technologies behind it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.memecreator.org%2Fstatic%2Fimages%2Fmemes%2F5589884.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.memecreator.org%2Fstatic%2Fimages%2Fmemes%2F5589884.jpg" alt="A meme where SpongeBob is holding a rainbow with the text 'AI just like magic'"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And for anybody who is interested in learning about AI, while researching, I found this book by Michael Nielsen: &lt;a href="http://neuralnetworksanddeeplearning.com/" rel="noopener noreferrer"&gt;Neural Networks and Deep Learning book&lt;/a&gt;. It has great explanations and helped me grasp some basic concepts.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>cschallenge</category>
      <category>computerscience</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Frontend Challenge: Pride Month Pure CSS Pixel Art</title>
      <dc:creator>Viviana Yanez</dc:creator>
      <pubDate>Sun, 09 Jun 2024 02:33:18 +0000</pubDate>
      <link>https://dev.to/vivitt/frontend-challenge-pride-month-pure-css-pixel-art-213i</link>
      <guid>https://dev.to/vivitt/frontend-challenge-pride-month-pure-css-pixel-art-213i</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for &lt;a href="https://dev.to/challenges/frontend-2024-05-29"&gt;Frontend Challenge v24.04.17&lt;/a&gt;, CSS Art: June.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Inspiration
&lt;/h2&gt;

&lt;p&gt;I've been living in the northern hemisphere for almost ten years now. Although I still find it hard to get used to having summer during the southern winter months...&lt;/p&gt;

&lt;p&gt;So, I've decided not to focus on seasons and instead use this challenge to create a Pride flag to celebrate and advocate for Pride month.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;This is the result:&lt;/p&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/vivitt/embed/BaedJRK?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;You can also see &lt;a href="https://github.com/vivitt/pure-css/blob/main/README.md"&gt;the code in GitHub&lt;/a&gt;, or view an &lt;a href="https://vivitt.github.io/pure-css/"&gt;online demo here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Journey
&lt;/h2&gt;

&lt;p&gt;I've been looking for a chance to experiment with some pixel art CSS drawing, so this challenge turned out to be a great opportunity.&lt;/p&gt;

&lt;p&gt;I came across &lt;a href="https://css-tricks.com/fun-times-css-pixel-art/"&gt;this amazing blog post&lt;/a&gt; by Geoff Graham, where I learned about different ways of drawing pixel art with CSS.&lt;/p&gt;

&lt;p&gt;I decided to use the &lt;strong&gt;box-shadow&lt;/strong&gt; technique because it seemed to allow me to make quick progress without much setup and also gave me the possibility to animate my illustration.&lt;/p&gt;

&lt;p&gt;This technique involves creating a container that serves as the base for the drawing. You can think of this element as a grid, where you will be placing 'pixels' to create the design.&lt;/p&gt;

&lt;p&gt;Before starting to draw, we need to define the measurement of the pixel unit in the illustration. I used an 8px by 8px square.&lt;/p&gt;

&lt;p&gt;Next, let's set the width and height of the container element, keeping in mind that these values must represent the maximum area the drawing will take. hey must also be multiples of the measurement we are using for the pixel unit.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.flag__container {
    width: 320px;
    height: 320px;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The combination of the container width and height with the pixel size will define the definiton of the image. You can create more or less detailed illustrations by changing those values.&lt;/p&gt;

&lt;p&gt;Now that we have set a width and height in the element container, we can place a new div element inside it, with the chosen dimensions to represent a pixel unit in the drawing.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.flag__pixels {
    height: 8px;
    width: 8px;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The next step is to start drawing. The illustration is created by adding the box-shadow property, "pixel by pixel", as needed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.flag__pixels {
    height: 8px;
    width: 8px;
    box-shadow: 
    0px 8px rgb(226, 226, 226),
    /* many pixels here... */

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

&lt;/div&gt;



&lt;p&gt;Once you are ready, you can create keyframes to animate the &lt;code&gt;box-shadow&lt;/code&gt; property as needed. Pretty cool!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.flag__pixels {
    height: 8px;
    width: 8px;
    box-shadow: 
    0px 8px rgb(226, 226, 226),
    /* many more pixels here... */
    animation: flag 3s infinite; 
}

@keyframes flag {
 0% {
      box-shadow: 
      0px 8px rgb(226, 226, 226),
      /* many more pixels here... */
    }
50% {
      0px 16px rgb(226, 226, 226),
      /* many more pixels here... */
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I find Dev Challenges are great opportunities to push myself to try out ideas I have in mind and learn about new things. There's nothing like deadlines :D&lt;/p&gt;

&lt;p&gt;I had a lot of fun drawing and I'm sure I will keep creating more pixel art illustrations.&lt;/p&gt;

&lt;p&gt;Thanks for checking out my work and reading!&lt;/p&gt;

</description>
      <category>frontendchallenge</category>
      <category>devchallenge</category>
      <category>css</category>
    </item>
    <item>
      <title>The prefers-contrast and forced-colors CSS media features</title>
      <dc:creator>Viviana Yanez</dc:creator>
      <pubDate>Tue, 14 May 2024 10:49:10 +0000</pubDate>
      <link>https://dev.to/vivitt/the-prefers-contrast-and-forced-colors-css-media-features-g7m</link>
      <guid>https://dev.to/vivitt/the-prefers-contrast-and-forced-colors-css-media-features-g7m</guid>
      <description>&lt;p&gt;Last week, I learnt about the possibility of a background image disappearing from the UI &lt;a href="https://support.microsoft.com/en-gb/windows/change-color-contrast-in-windows-fedc744c-90ac-69df-aed5-c8a90125e696"&gt;Windows High Contrast Mode&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I really didn't know much about scenarios in which users have expressed certain color preferences in their operating system settings and how this impacts styles and accessibility on a website.&lt;/p&gt;

&lt;p&gt;So, I engaged in what I call CDL (Curiosity-Driven Learning), and spent some hours exploring links related to the subject of contrast preferences and its impact on website accessibility and styles. This blog post is a summary of the highlights from this research.&lt;/p&gt;

&lt;h2&gt;
  
  
  CSS at-rules
&lt;/h2&gt;

&lt;p&gt;In CSS, we have at-rules, which are statements that provide instructions on how to behave. They begin with an at sign, '@,' and include everything up to the next semicolon or the next CSS block, whichever comes first&lt;sup id="fnref1"&gt;1&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;There are several at-rules, each with its own syntax, but they can be separated into two main groups: regular and nested.&lt;/p&gt;

&lt;p&gt;In this blog post, we will focus on the second group, specifically the conditional group rules, which are a subset of nested rules.&lt;/p&gt;

&lt;p&gt;All of them share a common syntax and are linked to some kind of condition. If this condition evaluates to true, all the statements within the group will be applied.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a class="mentioned-user" href="https://dev.to/media"&gt;@media&lt;/a&gt; CSS at-rule and media queries
&lt;/h2&gt;

&lt;p&gt;One very commonly used conditional group rule is the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/@media"&gt;@media CSS at-rule&lt;/a&gt;. This rule can be used to apply part of a stylesheet (a block of CSS) if, and only if, a media query evaluates to true.&lt;/p&gt;

&lt;p&gt;Media queries can be used to check many things, such as screen resolution, orientation, width and height of the viewport, and user preferences, such as preferring reduced motion, among others.&lt;/p&gt;

&lt;p&gt;A media query includes an optional media type and any number of media feature expressions, which can also be combined using logical operators:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Media types describe the general category of a device.&lt;/li&gt;
&lt;li&gt;Media features describe specific characteristics of the user agent, output device, or environment.&lt;/li&gt;
&lt;li&gt;The logical operators 'not,' 'and,' 'only,' and 'or' can be used to compose a complex media query.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the next lines, we will focus on two of the user agent media features: the prefers-contrast and the forced-colors.&lt;/p&gt;

&lt;h2&gt;
  
  
  prefers-contrast and forced-colors media features
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-contrast"&gt;prefers-contrast CSS media feature&lt;/a&gt; is used to detect if the user has requested the web content to be presented with a lower or higher contrast.&lt;/p&gt;

&lt;p&gt;Browsers are likely to rely on the settings provided by the operating system, so if users have informed more contrast preference, styles can be overwrited by:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
@media (prefers-contrast: more) {
    /* overwrite styles */
}

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

&lt;/div&gt;



&lt;p&gt;Both Mac and Windows support this preference selection, although it's wise to keep in mind that some users may not be aware of this feature. Therefore, one should not rely only on this media query to handle contrast on a web page.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/@media/forced-colors"&gt;forced-colors CSS media feature&lt;/a&gt; indicates if the browser is currently in forced-colors mode, limiting the styles in a website to a user-chosen color palette. &lt;br&gt;
It has two possible values: &lt;code&gt;none&lt;/code&gt; and &lt;code&gt;active&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This is the list of properties that receive browser-specified values based on native element semantics when forced colors mode is active. Note that these browser-specified values do not affect the style cascade because values are forced by the browser at paint time:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;color&lt;/li&gt;
&lt;li&gt;background-color&lt;/li&gt;
&lt;li&gt;text-decoration-color&lt;/li&gt;
&lt;li&gt;text-emphasis-color&lt;/li&gt;
&lt;li&gt;border-color&lt;/li&gt;
&lt;li&gt;outline-color&lt;/li&gt;
&lt;li&gt;column-rule-color&lt;/li&gt;
&lt;li&gt;-webkit-tap-highlight-color&lt;/li&gt;
&lt;li&gt;SVG fill attribute&lt;/li&gt;
&lt;li&gt;SVG stroke attribute&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are also some properties that have special behavior in forced colors mode:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;box-shadow is forced to 'none'&lt;/li&gt;
&lt;li&gt;text-shadow is forced to 'none'&lt;/li&gt;
&lt;li&gt;background-image is forced to 'none' for values that are not url-based&lt;/li&gt;
&lt;li&gt;color-scheme is forced to 'light dark'&lt;/li&gt;
&lt;li&gt;scrollbar-color is forced to 'auto'&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As a general rule, as developers, we should prioritize usability and avoid using the forced-colors media feature to create a separate design for users with a forced color palette preference.&lt;/p&gt;

&lt;p&gt;Instead, we should consider user-chosen color preferences, especially when attempting to remove certain properties by witting &lt;code&gt;border: none&lt;/code&gt;, &lt;code&gt;outline: none&lt;/code&gt;, or &lt;code&gt;text-decoration: none&lt;/code&gt;. Removing these properties can cause issues, as backgrounds color or images are removed, and elements rely completely on borders to differentiate from their backgrounds. This case can be solved with &lt;code&gt;border: 2px solid transparent&lt;/code&gt;, as nicely explained, among other possible cases, in &lt;a href="https://www.smashingmagazine.com/2022/06/guide-windows-high-contrast-mode/"&gt;this great article&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;The intended usage of the forced-colors media feature is to make small tweaks when the default application of forced colors does not result in good usability for a page or a given portion of the content on a page:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@media (forced-colors: active) {
    /* overwrite styles only when needed */
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Before closing, let's mention the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/forced-color-adjust"&gt;forced-color-adjust CSS property&lt;/a&gt;, which allows opting certain elements out of forced colors mode, restoring the control of those values to CSS.&lt;/p&gt;

&lt;p&gt;It has two possible values: &lt;code&gt;auto&lt;/code&gt; and &lt;code&gt;none&lt;/code&gt;. Like the previously mentioned media queries, it should not prevent user choices from being applied and should only be used to make changes that support a user's color and contrast requirements.&lt;/p&gt;




&lt;p&gt;Like many other topics that impact website accessibility, this is a continuous improvement journey. Being aware of the diversity of user preferences and needs is essential for developers who care about creating inclusive experiences. Thanks for reading :)&lt;/p&gt;




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/At-rule"&gt;https://developer.mozilla.org/en-US/docs/Web/CSS/At-rule&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
      <category>frontend</category>
      <category>css</category>
      <category>a11y</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Glam Up My Markup Submission: Earth Day Celebration</title>
      <dc:creator>Viviana Yanez</dc:creator>
      <pubDate>Sun, 28 Apr 2024 18:51:52 +0000</pubDate>
      <link>https://dev.to/vivitt/glam-up-my-markup-submission-earth-day-celebration-5gm</link>
      <guid>https://dev.to/vivitt/glam-up-my-markup-submission-earth-day-celebration-5gm</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for &lt;a href="https://dev.to/devteam/join-us-for-the-next-frontend-challenge-earth-day-edition-52e4"&gt;Frontend Challenge v24.04.17&lt;/a&gt;, Glam Up My Markup: Earth Day Celebration Landing Page&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;I created a landing page with a friendly style, adding illustrations and animations to the provided HTML. My goal was to create a welcoming and playful design.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzn20q3tzkyjic8lk96qc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzn20q3tzkyjic8lk96qc.png" alt="Screenshot of my Earth Day Celebration landing's hero section" width="800" height="797"&gt;&lt;/a&gt;&lt;br&gt;
Find here a &lt;a href="https://vivitt.github.io/earth-day-dev-challenge/"&gt;link to my project&lt;/a&gt; and in this one you will find &lt;a href="https://github.com/vivitt/earth-day-dev-challenge"&gt;a public repo with my code&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Journey
&lt;/h2&gt;

&lt;p&gt;It was really fun to work on this project, as I spent some time trying out ideas I've had for a while and experimenting with animations and CSS.&lt;/p&gt;

&lt;p&gt;I learned how to create scroll-driven animations, and it was a great chance to try out the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/animation-timeline"&gt;animation timeline&lt;/a&gt; CSS property. However, since it's still in an experimental state, I prioritized JavaScript-based animations to move elements based on scroll in my project. So I could ensure a more consistent experience across browsers and devices.&lt;br&gt;
One interesting learning was how to create my own feature detection tests using &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/CSS/supports_static"&gt;CSS.suports()&lt;/a&gt;.&lt;br&gt;
Also, I learned more about DOM manipulation and became more confortable using CSS grid. &lt;br&gt;
Certainly, the most challenging part was achieving an acceptable appearance on small devices while retaining the visual interest of my design.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>frontendchallenge</category>
      <category>css</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Participating in The Collab Lab: Week #8 &amp; #9</title>
      <dc:creator>Viviana Yanez</dc:creator>
      <pubDate>Thu, 11 Apr 2024 09:25:44 +0000</pubDate>
      <link>https://dev.to/vivitt/participating-in-the-collab-lab-week-8-9-2aci</link>
      <guid>https://dev.to/vivitt/participating-in-the-collab-lab-week-8-9-2aci</guid>
      <description>&lt;p&gt;During the final weeks of the project, we focused on improving the user interface's look of our app. We collected some inspiration in a mood board and then started by creating some mockups for the different views in our app.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final weeks check-in
&lt;/h2&gt;

&lt;p&gt;All this process was quite fun for me, as it allowed me to play around with design tools and experiment and learn more about using Figma. Once we had an idea of what we wanted, we added some fonts to the project and ensured that the chosen color palette was accessible.&lt;br&gt;
We decided to use Tailwind, which I think was a great choice, as it allowed us to make great progress in a few days.&lt;/p&gt;

&lt;p&gt;Also, some team members worked on branding for our app and came up with an name for it: &lt;strong&gt;Despiensa&lt;/strong&gt;, a wordplay on the Spanish words &lt;em&gt;despensa&lt;/em&gt; and &lt;em&gt;piensa&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvmf9ir4betzj28yr0tbk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvmf9ir4betzj28yr0tbk.png" alt="Screenshot of Despiensa's landing page" width="800" height="470"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Learning highlights of my last weeks
&lt;/h2&gt;

&lt;p&gt;I took on an issue that involved styling the List view of the app. This view renders all the list's items ordered by their estimated next purchase date.&lt;/p&gt;

&lt;h3&gt;
  
  
  Styling a checkbox with Tailwind
&lt;/h3&gt;

&lt;p&gt;Each element in the list includes the item's name, a delete button to eliminate the item from the list, and a checkbox that allows users to mark the item as purchased. This is the way we use to store the purchase date for each item, so we can use it to calculate the user's buying habits and order items in the list.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fofx1ntflamgtvyb4ntau.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fofx1ntflamgtvyb4ntau.png" alt="Screenshot of the List's view including a list of grocery items" width="800" height="607"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This checkbox was quite interesting to build because it needed to be fully customized with styling, but we also wanted to keep its full functionality and accessibility. I learned a lot while working on this and published &lt;a href="https://dev.to/vivitt/a-fully-accessible-checkbox-styled-with-tailwind-56nk"&gt;a blog post sharing how I implemented the final checkbox using Tailwind&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Programmatically setting focus on different inputs
&lt;/h3&gt;

&lt;p&gt;Another interesting element in this issue was that we decided to include at the top of the list view, just below the search input, two buttons to make it easier for new users to find how to add an item or share a list.&lt;/p&gt;

&lt;p&gt;Those two actions are performed in the ManageList view, so those buttons are mere links to this view of the app. While they already made the navigation more intuitive, I think that the current implementation could be improved by including programmatically set focus on the input associated with the action the user wants to perform. That means that when a user navigates to the ManageList view through any of those buttons, the corresponding input is focused. That would improve the user experience and make our app more accessible.&lt;/p&gt;

&lt;p&gt;I came across a posible solution for this adding an &lt;a href="https://reactrouter.com/en/main/route/route#optional-segments"&gt;optional segment&lt;/a&gt; in the Route’s path for this view, and using it to know if users have just clicked one of those buttons before.&lt;/p&gt;




&lt;p&gt;As we just concluded the program, I published a summary of the final app and the highlights of my journey in &lt;a href="https://dev.to/vivitt/participating-in-the-collab-lab-wrapping-up-2bmf"&gt;the final blog post of my Collab Lab series&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Thanks for reading :)&lt;/p&gt;

</description>
    </item>
    <item>
      <title>A fully accessible checkbox styled with Tailwind</title>
      <dc:creator>Viviana Yanez</dc:creator>
      <pubDate>Thu, 11 Apr 2024 08:46:40 +0000</pubDate>
      <link>https://dev.to/vivitt/a-fully-accessible-checkbox-styled-with-tailwind-56nk</link>
      <guid>https://dev.to/vivitt/a-fully-accessible-checkbox-styled-with-tailwind-56nk</guid>
      <description>&lt;p&gt;I am working in a React and Tailwind app. Last week, I worked on implementing the styling of the UI for a view that included a list of items, each of which included a checkbox to change its status.&lt;/p&gt;

&lt;p&gt;It was a pretty interesting challenge because to adapt to the design specs, I needed to completely change the appearance of the checkbox. However, I wanted to do this without affecting its functionality, that means, keeping it fully accessible and interactable.&lt;/p&gt;

&lt;p&gt;This was the design specification, showing an unmarked and a marked item:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff6jy3hjkzfn7dkqbph8m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff6jy3hjkzfn7dkqbph8m.png" alt="A user interface containing two list items, each of them displaying a rounded checkbox, the item name, and a delete button represented by a trash icon. One of the checkboxes is checked." width="800" height="197"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The approach I chose to take is inspired by &lt;a href="https://www.sarasoueidan.com/blog/inclusively-hiding-and-styling-checkboxes-and-radio-buttons/"&gt;this great blog post&lt;/a&gt; and consists on keeping the checkbox in the screen while hiding it visually and placing an SVG on top of it. All of these are wrapped in the corresponding label element. The checkbox is still interactable but not visible, while the SVG can be styled in any way the design specs require.&lt;/p&gt;

&lt;p&gt;Let's see the process in detail. As we will be talking about styling in this blog post, I removed all the functionality related code that was unrelevant from code examples. If you want to see the complete resulting code, you can &lt;a href="https://github.com/the-collab-lab/tcl-71-smart-shopping-list"&gt;check it out in the GitHub repo&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The starting point was a &lt;code&gt;&amp;lt;li&amp;gt;&lt;/code&gt; element that included the the checkbox, the item name and a delete button:&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;li&amp;gt;
  &amp;lt;label&amp;gt;
    {`Mark ${name} as purchased`}
    &amp;lt;input type="checkbox" onChange={() =&amp;gt; {}} id={itemId} /&amp;gt;
  &amp;lt;/label&amp;gt;
  &amp;lt;span&amp;gt;{name}&amp;lt;/span&amp;gt;
  &amp;lt;button&amp;gt;Delete&amp;lt;/button&amp;gt;
&amp;lt;/li&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the rendered view:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm6outv8cgsijeeu5t9ik.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm6outv8cgsijeeu5t9ik.png" alt="A user interface featuring an unstyled checkbox input with its corresponding text label, an item name, and a delete button." width="800" height="100"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We will now focus on the checkbox part. As I said before, I used the input label to wrap the checkbox input and an SVG element. I also wrapped the text label with a &lt;code&gt;&amp;lt;span&amp;gt;&lt;/code&gt; element.&lt;/p&gt;

&lt;p&gt;I hide the checkbox by adding the &lt;code&gt;opacity-0&lt;/code&gt; Tailwind class and hide the text label visually without hiding it from screen readers, leveraging the &lt;code&gt;sr-only&lt;/code&gt; Tailwind class for this purpose.&lt;/p&gt;

&lt;p&gt;The SVG element is the visual replacement for the checkbox, so I applied some classes to style it following my design specs.&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;label className="flex items-center justify-center"&amp;gt;
  &amp;lt;input type="checkbox" id={itemId} className="opacity-0” /&amp;gt;
  &amp;lt;svg version="1.1" width="22" height="22" fill=“white" xmlns="http://www.w3.org/2000/svg” className="rounded-xl fill-white stroke-2 stroke-lightPurple"&amp;gt;
    &amp;lt;circle cx="11" cy="11" r="10" /&amp;gt;
  &amp;lt;/svg&amp;gt;
  &amp;lt;span className="sr-only"&amp;gt;{`Mark ${name} as purchased`}&amp;lt;/span&amp;gt;
&amp;lt;/label&amp;gt;
&amp;lt;span&amp;gt;{name}&amp;lt;/span&amp;gt;

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

&lt;/div&gt;



&lt;p&gt;And the visual result: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbu9jzi2bmgrpky50z1ed.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbu9jzi2bmgrpky50z1ed.png" alt="An interface element displaying the word 'Apples' with a circular checkbox icon next to it." width="800" height="95"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, let’s see how we can use the checkbox status to change the style applied to the SVG.&lt;/p&gt;

&lt;p&gt;In Tailwind, every utility class can be applied conditionally by &lt;a href="https://tailwindcss.com/docs/hover-focus-and-other-states#custom-modifiers"&gt;adding a modifier&lt;/a&gt; after the class name that describes the condition to target.&lt;/p&gt;

&lt;p&gt;This way, I could add any styles based on the focus or checked status. But in this case, I don’t want to style the checkbox itself but the SVG, which is its sibling.&lt;br&gt;
This is when the Tailwind &lt;code&gt;peer&lt;/code&gt; class becomes really handy. It allows us to simply mark the sibling with the peer class, and then use the &lt;code&gt;peer-checked&lt;/code&gt; or any modifiers to style the target element.&lt;/p&gt;

&lt;p&gt;In the case of needing to &lt;a href="https://tailwindcss.com/docs/hover-focus-and-other-states#styling-based-on-parent-state"&gt;style an element based on parent state&lt;/a&gt;, the &lt;code&gt;group&lt;/code&gt; class might be used instead of the &lt;code&gt;peer&lt;/code&gt; one.&lt;/p&gt;

&lt;p&gt;The final code and UI will look like this:&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;label className="flex items-center justify-center"&amp;gt;
  &amp;lt;input type="checkbox" id={itemId} className="peer opacity-0" /&amp;gt;
  &amp;lt;svg version=“1.1" width=“22" height=“22" xmlns="http://www.w3.org/2000/svg” fill=“white" className="rounded-xl fill-white stroke-2 stroke-lightPurple peer-focus:ring-2 ring-blue-900 peer-checked:fill-lightPurple" &amp;gt;
    &amp;lt;circle cx="11" cy="11" r="10" /&amp;gt;
  &amp;lt;/svg&amp;gt;
  &amp;lt;span className="sr-only"&amp;gt;{`Mark ${name} as purchased`}&amp;lt;/span&amp;gt;
&amp;lt;/label&amp;gt;

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

&lt;/div&gt;



&lt;p&gt;And this is the view of the resulting checkboxes:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcookidilhn5wqzplymuy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcookidilhn5wqzplymuy.gif" alt="A list of items with circular and unfilled checkboxes positioned to the left of each item. When a checkbox is checked, it becomes filled." width="864" height="864"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At this point, I can just continue by adding the rest of styles to completely match the specifications:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqfdmzunz4gaun9s1my47.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqfdmzunz4gaun9s1my47.png" alt="An interface displaying a list of grocery items with a rounded checkbox and a trash icon next to it." width="800" height="401"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you found it useful and want to take a deeper look at the entire functionality, check out the &lt;a href="https://github.com/the-collab-lab/tcl-71-smart-shopping-list"&gt;complete code on GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Thanks for reading :)&lt;/p&gt;

</description>
      <category>tailwindcss</category>
      <category>a11y</category>
      <category>frontend</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Participating in The Collab Lab: Wrapping up</title>
      <dc:creator>Viviana Yanez</dc:creator>
      <pubDate>Tue, 09 Apr 2024 18:17:18 +0000</pubDate>
      <link>https://dev.to/vivitt/participating-in-the-collab-lab-wrapping-up-2bmf</link>
      <guid>https://dev.to/vivitt/participating-in-the-collab-lab-wrapping-up-2bmf</guid>
      <description>&lt;p&gt;This is the last entry of my &lt;a href="https://dev.to/vivitt/series/26359"&gt;Collab Lab’s participation series&lt;/a&gt;. During the last week my team successfully shipped the fully functional web app that we have been working on since February.&lt;br&gt;
As a wrap up I want to share some final thoughts on my experience being part of &lt;a href="https://the-collab-lab.codes/"&gt;The Collab Lab&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Our final app is live 🚀
&lt;/h3&gt;

&lt;p&gt;We spent the past weeks working on making the user interface of our app look professional and welcoming, and I collected the &lt;a href="https://dev.to/vivitt/participating-in-the-collab-lab-week-8-9-2aci"&gt;most relevant parts of these weeks in another blog post&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;After this process, our app is fully functional and looks great. You can &lt;a href="https://tcl-71-smart-shopping-list.web.app/"&gt;see it live here&lt;/a&gt;.&lt;br&gt;
You can also watch the &lt;a href="https://cdn.zappy.app/c4fb07e5fb336cbd34543e7220db3755.mp4"&gt;recording of the 2024 first cohort demo&lt;/a&gt;, where each team showcased their app to the rest of the participants. Ours starts around minute 8, but I find it super cool seeing how each team comes to a very different result with the same prompts.&lt;/p&gt;

&lt;h3&gt;
  
  
  Presenting Despiensa
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Despiensa&lt;/strong&gt; is a wordplay on the Spanish words &lt;em&gt;despensa&lt;/em&gt; and &lt;em&gt;piensa&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;It's a React, Tailwind &amp;amp; Firebase web app that allows users to register and create shopping lists, which they can also share with other users. The app also records the user's buying habits, so it displays the list items ordered by their likely next purchase date.&lt;/p&gt;

&lt;p&gt;Here are some views of our app. When users arrive, they are prompted to register using Google:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnt05c5tz0mmdhycaw4pt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnt05c5tz0mmdhycaw4pt.png" alt="Despiensa’s landing page" width="800" height="470"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then they can start creating a list or navigating to the one they want to use:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz5n4yx25551u2o8w0kc2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz5n4yx25551u2o8w0kc2.png" alt="Despiensa’s All my lists view, without any list." width="800" height="470"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5e5fdut9axayiliu4f1o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5e5fdut9axayiliu4f1o.png" alt="Despiensa’s All my lists view, with two lists." width="800" height="467"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once in the list page, users can interact with the items in the list and filter them using the input at the top:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9r275icw60re25tih493.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9r275icw60re25tih493.png" alt="List view, filter input is empty and all list items are shown" width="800" height="469"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhqfdokamm8acpl4cvtp5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhqfdokamm8acpl4cvtp5.png" alt="List view, filter input contains the text " width="800" height="467"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finally, in the manage list page, users can add new items to their list or share the list with other users:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3da59kixpngrt5wj8i2x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3da59kixpngrt5wj8i2x.png" alt="Manage List view, displaying a form to add items and another one to share the list." width="800" height="468"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We still want to add a few more nice-to-have features such as &lt;a href="https://github.com/the-collab-lab/tcl-71-smart-shopping-list/issues"&gt;adding a dark mode&lt;/a&gt;, and we plan to work on those during the next few weeks.&lt;/p&gt;

&lt;h2&gt;
  
  
  My personal wins during the program
&lt;/h2&gt;

&lt;p&gt;Now looking back, what I value most is that joining The Collab Lab helped me build confidence in my work and also in explaining and showcasing it to others.&lt;/p&gt;

&lt;p&gt;I consistently wrote about the issues I worked on and kept this series active by publishing our progress almost weekly. &lt;/p&gt;

&lt;p&gt;Also, I returned to the React mental model. After spending some months focused on Vue.js, it was really great to come back to working with React and be able to gain deeper understanding of core concepts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping up The Collab Lab experience
&lt;/h2&gt;

&lt;p&gt;❤️ Most of all, The Collab Lab is a great experience to connect with amazing people.&lt;/p&gt;

&lt;p&gt;💫 I am really grateful with the entire team, volunteers, and mentors. Their commitment with the project made the whole experience really enjoyable and contributed to creating a safe space to learn and grow.&lt;/p&gt;

&lt;p&gt;🙌🏽 I also want to thank the rest of the team members: &lt;a href="https://github.com/borjaMarti"&gt;Borja&lt;/a&gt;, &lt;a href="https://github.com/ocsiddisco"&gt;Celine&lt;/a&gt;, and &lt;a href="https://github.com/BikeMouse"&gt;Judith&lt;/a&gt;. The collaboration with them was great, and we learned a lot together.&lt;/p&gt;

&lt;p&gt;🌱 I am glad I participated in this cohort, and I strongly recommend the experience to any early-stage career developers out there.&lt;/p&gt;

&lt;p&gt;Thanks for reading :)&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>beginners</category>
      <category>thecollablab</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Participating in The Collab Lab: Week #7</title>
      <dc:creator>Viviana Yanez</dc:creator>
      <pubDate>Mon, 25 Mar 2024 11:05:28 +0000</pubDate>
      <link>https://dev.to/vivitt/participating-in-the-collab-lab-week-7-1lif</link>
      <guid>https://dev.to/vivitt/participating-in-the-collab-lab-week-7-1lif</guid>
      <description>&lt;p&gt;We are pretty close to the end of our Collab Lab project 🤯.&lt;/p&gt;

&lt;p&gt;Since we started, I worked each week pairing with another developer on an issue assigned to us. Usually, it was a new feature to add, and it was great that the complexity was growing at a very nice pace, so it kept us really engaged with the project.&lt;/p&gt;

&lt;p&gt;Last week, we adopted a more spontaneous approach, as we wanted to address several open issues before beginning to work on the UI styling. We paired on those issues based on our interests, and collaboration was mostly asynchronous.&lt;/p&gt;

&lt;h2&gt;
  
  
  Define a CSS framework or library
&lt;/h2&gt;

&lt;p&gt;At the moment, we've decided that our next step and focus for the upcoming weeks will be to start working on improving the UI and enhancing the look of our app. We've already begun collecting references in a Figma mood board, although I must admit that working on it wasn't my top priority until now. I've been doing some research on CSS frameworks and component libraries that we might want to use for the project, and we'll be defining our choice in the next few days.&lt;/p&gt;

&lt;p&gt;My fav options are: &lt;/p&gt;

&lt;p&gt;🛠️ &lt;strong&gt;Tailwind&lt;/strong&gt;: is a CSS framework that uses a utility-first CSS approach. It offers a low-level utility API with classes to build any design directly in your markup without writing CSS, and a set of ready-to-use components.&lt;br&gt;
It might take some effort to get used to it, but it simplifies the development process and provides a lot of flexibility. A main benefit is that it encourages a consistent use of colors, spacing, typography, shadows, and other styling elements within your app.&lt;br&gt;
Another benefit is that it automatically removes all unused CSS when building for production, so the result is a final CSS bundle that is as small as possible.&lt;br&gt;
The website has extensive documentation, and there is an active community plenty of resources, plugins, and extensions available.&lt;/p&gt;

&lt;p&gt;🛠️ &lt;strong&gt;Chakra UI&lt;/strong&gt;: is a simple and modular component library that allows you to build visually appealing UIs fast. It has a strong focus on accessibility and strictly follows WAI-ARIA standards for all components. It is themeable, and components are customizable to match the design needs of your app and it includes dark mode support. &lt;br&gt;
It uses a composable approach that keeps complexity low and ensures that the styles and functionality are flexible and extensible. You can easily compose new components from existing ones.&lt;br&gt;
Chakra UI also has an active community and great documentation. It includes resources, tutorials, and examples to get started.&lt;/p&gt;




&lt;h2&gt;
  
  
  Learning highlights of my week
&lt;/h2&gt;

&lt;p&gt;It was a really enjoyable week for me, as it involved writing code, but also a lot of writing and reading. I also made some time to finish the useState blog post, so now &lt;a href="https://dev.to/vivitt/series/26502"&gt;my React Hooks learning series&lt;/a&gt; includes three articles.&lt;/p&gt;




&lt;p&gt;See you next week! Thanks for reading :)&lt;/p&gt;

</description>
    </item>
    <item>
      <title>React Hooks: a look into useState</title>
      <dc:creator>Viviana Yanez</dc:creator>
      <pubDate>Mon, 25 Mar 2024 09:25:26 +0000</pubDate>
      <link>https://dev.to/vivitt/react-hooks-a-look-into-usestate-1eek</link>
      <guid>https://dev.to/vivitt/react-hooks-a-look-into-usestate-1eek</guid>
      <description>&lt;p&gt;There are some React Hooks that I have been using for a while and others that are completely news for me, but I am still using this opportunity to review the most popular React hooks to gain a deeper understanding about it.&lt;/p&gt;

&lt;p&gt;I certainly already have been using useState but I wanted to re read about it, as I feel that I can have now a much more deeper understanding of concepts that when I started learning React. &lt;/p&gt;

&lt;p&gt;If you are quite new to React or want to review how this hook works, here you will find a complete guide.&lt;/p&gt;

&lt;p&gt;I am currently working on a shopping list app with React and Firebase, so the code examples you will find in this blogpost come from this code.&lt;/p&gt;

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

&lt;p&gt;The &lt;code&gt;useState&lt;/code&gt; hook lets you add a state variable to your component, and as every React hook, it must be called at the top level.&lt;/p&gt;

&lt;p&gt;It accepts one parameter &lt;code&gt;initialState&lt;/code&gt;, the initial value that you want the state to have. This can be any value type, including a function.&lt;br&gt;
But if you pass a function as parameter, it should be pure with no arguments and must have a return value. React will store this value as the initial state value.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;useState&lt;/code&gt; returns an array with two values: the current state and the set function. During the first render, the current state will match the &lt;code&gt;initialState&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;The convention is to name state variables like [something, setSomething] using array destructuring:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const [value, setValue] = useState(initialState);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The &lt;code&gt;set&lt;/code&gt; function
&lt;/h2&gt;

&lt;p&gt;The set function lets you update the state value and will trigger a re-render each time the state value changes.&lt;/p&gt;

&lt;p&gt;It accepts the &lt;code&gt;nextState&lt;/code&gt; as only argument. It is possible to pass the next state value directly, or calculate it with a function from the previous state.&lt;br&gt;
Important to note that the set function only updates the state value for the next render, and does not change the current state in the already executing code.&lt;/p&gt;
&lt;h3&gt;
  
  
  Passing a function as parameter to the set function
&lt;/h3&gt;

&lt;p&gt;When calculating a nextState based on previous state, you can pass an updater function as parameter to the set function. However this is not always necessary.&lt;/p&gt;

&lt;p&gt;If you pass a function as &lt;code&gt;nextState&lt;/code&gt; argument, React will treat it as an updater function. It takes as the only argument the pending state and returns the next state.for setValue but it is not always necesary.&lt;/p&gt;

&lt;p&gt;There is a convention in React for naming the pending state argument with the first letter of the state variable name:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;setValue(v =&amp;gt; v + 1)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, what's the difference between using &lt;code&gt;setValue(value +1)&lt;/code&gt; or &lt;code&gt;setValue(v =&amp;gt; v + 1)&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;As mentioned earlier, the set function updates the state for the next render, and it not change the state value in already executing code. That means that if there is an event that triggers several updates of a state value, you might need to use a updater function.&lt;/p&gt;

&lt;p&gt;Let's see the difference within the following example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useState } from 'react';
export function ListItem({ name }) {
    const [quantity, setQuantity] = useState(1);
    const addItem = (currentItems) =&amp;gt; currentItems + 1;
    return (
        &amp;lt;li className="ListItem"&amp;gt;
            &amp;lt;span&amp;gt;{quantity}&amp;lt;/span&amp;gt;
            &amp;lt;span&amp;gt;{name}&amp;lt;/span&amp;gt;
            &amp;lt;button onClick={() =&amp;gt; setQuantity(addItem(quantity))}&amp;gt;+1&amp;lt;/button&amp;gt;
            &amp;lt;button
                onClick={() =&amp;gt; {
                    setQuantity(addItem(quantity));
                    setQuantity(addItem(quantity));
                }}
            &amp;gt;
                +2
            &amp;lt;/button&amp;gt;
        &amp;lt;/li&amp;gt;
    );
}

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

&lt;/div&gt;



&lt;p&gt;In the previous code, the &lt;code&gt;+2&lt;/code&gt; button doesn’t work as expected, because when the event is fired, the &lt;code&gt;quantity&lt;/code&gt; value can’t be updated during execution:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyvbg40sandj46e0lxnkd.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyvbg40sandj46e0lxnkd.gif" alt="Image description" width="600" height="509"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Wait! What?? Every time addItem reads the state variable after calling the set function, it gets the old value that was on the screen before the call.&lt;/p&gt;

&lt;p&gt;If multiple updates are required, or if accessing the state variable directly is not convenient, then an updater function can be helpful.&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;li className="ListItem"&amp;gt;
            &amp;lt;span&amp;gt;{quantity}&amp;lt;/span&amp;gt;
            &amp;lt;span&amp;gt;{name}&amp;lt;/span&amp;gt;
            &amp;lt;button onClick={() =&amp;gt; setQuantity((q) =&amp;gt; addItem(q))}&amp;gt;+1&amp;lt;/button&amp;gt;
            &amp;lt;button
                onClick={() =&amp;gt; {
                    setQuantity((q) =&amp;gt; addItem(q));
                    setQuantity((q) =&amp;gt; addItem(q));
                }}
            &amp;gt;
                +2
            &amp;lt;/button&amp;gt;
        &amp;lt;/li&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case, the updater function is queued and return the next state from calculating it from the pending state:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzg76llavb6ru6s6mwutw.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzg76llavb6ru6s6mwutw.gif" alt="Image description" width="600" height="509"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Objects and arrays as state
&lt;/h2&gt;

&lt;p&gt;React states can hold object and array values. In JavaScript, objects and arrays are mutable, differing from primitives like strings and numbers, which are immutable. They can be mutated after creation.&lt;br&gt;
But you should treat object and array states in React as read-only immutable values when you store them in state. This means that even though it is technically possible to mutate them, you should replace the value instead of mutating it.&lt;/p&gt;

&lt;p&gt;Let's see a code example for this. To update an object state you shouldn’t change it directly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Don't ❌
item.name = 'apples';
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But you should create a new copy of the object, and then update the state to use that copy.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Do ✅
setItem({
  ...item,
  name: 'bananas'
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Something similar applies to arrays, where you should avoid mutating them directly and avoid using mutating array methods such as push() or pop()&lt;sup id="fnref1"&gt;1&lt;/sup&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Don't ❌
items[0] = 'bananas'
// Do ✅
const newItems = items.map((i) =&amp;gt; {
      if (i === 0) {
        return 'bananas'
      } 
   }
setItems(newItems)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is important because mutating the object without using the state-setting function will modify the state value from the previous render. It will not trigger any response in your React app, and the state will not be reactive to this change. Even though mutating state can work in some cases, the recommendation is to always treat the state value as read-only.&lt;/p&gt;

&lt;h2&gt;
  
  
  Avoid unconditionally setting state
&lt;/h2&gt;

&lt;p&gt;A common troubleshooting case you'll encounter is when, for whatever reason, you end up unconditionally setting state during render. This causes your app to enter a loop: it renders, setState is called, it renders again, and so on. You'll receive an error message stating: &lt;code&gt;Too many re-renders. React limits the number of renders to prevent an infinite loop&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;A very common cause is calling an event handler during render:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    const [quantity, setQuantity] = useState(1);

    const handleAddItem = () =&amp;gt; {
        setQuantity(quantity + 1);
    };
    return (
        &amp;lt;li className="ListItem"&amp;gt;
            &amp;lt;span&amp;gt;{quantity}&amp;lt;/span&amp;gt;
            &amp;lt;span&amp;gt;{name}&amp;lt;/span&amp;gt;
            // Don't ❌
            &amp;lt;button onClick={handleAddItem()}&amp;gt;+1&amp;lt;/button&amp;gt;
            // Do ✅
            &amp;lt;button onClick={handleAddItem}&amp;gt;+1&amp;lt;/button&amp;gt;
        &amp;lt;/li&amp;gt;
    );
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The difference between those examples is that the first one calls the event handler during render, while the second one passes it down.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final notes
&lt;/h2&gt;

&lt;p&gt;There is so much to discuss about useState. This article aims to summarize some of the basic principles for its correct usage. I hope you find these notes useful, and if you do, feel free to check out my other posts about React hooks. Thanks for reading!&lt;/p&gt;




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;Find here &lt;a href="https://react.dev/learn/updating-arrays-in-state#updating-arrays-without-mutation"&gt;a complete list of mutating array methods and their preferred replacement in React&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
      <category>webdev</category>
      <category>react</category>
      <category>frontend</category>
      <category>beginners</category>
    </item>
    <item>
      <title>DEV Challenge: a Pure CSS Alfajor</title>
      <dc:creator>Viviana Yanez</dc:creator>
      <pubDate>Sun, 24 Mar 2024 17:55:25 +0000</pubDate>
      <link>https://dev.to/vivitt/dev-challenge-pure-css-alfajor-4eli</link>
      <guid>https://dev.to/vivitt/dev-challenge-pure-css-alfajor-4eli</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for DEV Challenge v24.03.20, CSS Art: Favorite Snack.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Inspiration
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Alfajor"&gt;Alfajor&lt;/a&gt; is a common (and delicious) sweet snack among several regions in Latin America. Recently, I received a visit from my family and have been eating so many of them... So here's my tribute to this very much loved snack.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;&lt;iframe height="600" src="https://codepen.io/vivitt/embed/NWmjoPp?height=600&amp;amp;default-tab=result&amp;amp;embed-version=2"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;You will also find the code in &lt;a href="https://github.com/vivitt/pure-css"&gt;this public repo&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Journey
&lt;/h2&gt;

&lt;p&gt;I have always been curious about drawing with CSS, so this was the perfect opportunity to get started.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;I learned about using the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/clip-path"&gt;clip-path&lt;/a&gt; property to create custom shapes. This property adds a clipping region to set which part of an element is shown.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I also used the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-elements"&gt;pseudo-elements&lt;/a&gt; ::before and ::after, which provide two additional boxes to add details to the drawing without adding more elements to the markup.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Finally, I wanted to create a bit of texture in my drawing, so I came across this great article where I learned how to add a grainy gradient using SVG. &lt;a href="https://css-tricks.com/grainy-gradients/"&gt;this great article, where I learn how to add a grainy gradient using SVG&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;And had lots of fun creating this :) Thanks for reading!&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>frontendchallenge</category>
      <category>devchallenge</category>
      <category>css</category>
    </item>
    <item>
      <title>Participating in The Collab Lab: Week #5 &amp; #6</title>
      <dc:creator>Viviana Yanez</dc:creator>
      <pubDate>Fri, 22 Mar 2024 10:36:17 +0000</pubDate>
      <link>https://dev.to/vivitt/participating-in-the-collab-lab-week-5-6-4ngc</link>
      <guid>https://dev.to/vivitt/participating-in-the-collab-lab-week-5-6-4ngc</guid>
      <description>&lt;p&gt;Those past weeks have been a bit busy on my side, so I am summarizing both in this new blog entry.&lt;/p&gt;

&lt;p&gt;✨ Our shopping list app's functionality is now almost completed, and we are really close to starting work on the UI styling.&lt;/p&gt;

&lt;p&gt;💅🏼 We will soon define whether we want to add any CSS framework or component library to the project, and we are currently collecting visual references in a moodboard so we can work as a whole team to define the visual appearance and tone of our app.&lt;/p&gt;

&lt;p&gt;✅ During the last weeks, I worked on three different features. One of those was to prevent users from resubmitting an item that is already included in a list. To achieve this, we wrote a function to compare two strings: the new one the user is trying to submit and the one already included in the database. It was interesting because we needed to normalize the user input, lowercasing the item name and removing any white space or non alphabetic characters, so I learned more about string methods. Here is &lt;a href="https://dev.to/vivitt/comparing-strings-in-javascript-how-to-check-for-equal-normalized-values-1hma"&gt;a blogpost explaining the implementation&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;✅ The other two features pushed me to learn more about Firebase, as we needed to implement functionality to allow users to perform updates on documents such as deleting items from a list or deleting an entire list if they are the owners. But we also have references to this lists documents inside other users documents in the firebase store. So I also learned how to write queries in Firestore to retrieve all the matching docs from a collection.&lt;/p&gt;




&lt;p&gt;I am starting to have the feeling of being closer to finish the project and already know that I will miss a lot the collaboration flow that we created as a team.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>collablab</category>
      <category>beginners</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Comparing Strings in JavaScript: How to check for Equal Normalized Values</title>
      <dc:creator>Viviana Yanez</dc:creator>
      <pubDate>Fri, 22 Mar 2024 10:06:22 +0000</pubDate>
      <link>https://dev.to/vivitt/comparing-strings-in-javascript-how-to-check-for-equal-normalized-values-1hma</link>
      <guid>https://dev.to/vivitt/comparing-strings-in-javascript-how-to-check-for-equal-normalized-values-1hma</guid>
      <description>&lt;h2&gt;
  
  
  Context
&lt;/h2&gt;

&lt;p&gt;Last week, I worked on implementing a feature to prevent users from submitting input values that already exist in the database.&lt;/p&gt;

&lt;p&gt;The chosen approach was to create a function that compares two strings: one representing the user input value and the other being the name property value from the database document. Then, iterate over the data retrieved from the database each time the user attempt to add a new document, checking if the new data have the same value as any of the existing ones.&lt;/p&gt;

&lt;p&gt;What added a bit of complexity was that we needed to ensure as well that the new string didn't have the same value as any other in the database with punctuation and casing normalized. This means that users who have an item called 'apples' in their list should not be able to add another item with the name 'apples!' nor 'a pples' or 'Apples'. So before applying the comparison function, the strings must be normalized. This means lowercasing the strings and removing all characters that are not alphabetic.&lt;/p&gt;

&lt;p&gt;Let's see the code that implements this. &lt;/p&gt;

&lt;h2&gt;
  
  
  Code example
&lt;/h2&gt;

&lt;p&gt;We have an input that allows users to add items to their list:&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;label&amp;gt;Add item
    &amp;lt;input type="text" name="item"&amp;gt;&amp;lt;/input&amp;gt;
&amp;lt;/label&amp;gt;
&amp;lt;button type="submit"&amp;gt;Submit&amp;lt;/button&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;First, we check if the input has any value:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export const inputHasValue = (value) =&amp;gt; {
    return value.trim().length === 0 ? false : true;
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We also want to prevent users from submitting a string that is composed only by digits:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export const inputHasOnlyNUmbers = (string) =&amp;gt; {
    return !!string.match(/^\d+$/);
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, let's normalize the string. The &lt;code&gt;normalizeString&lt;/code&gt; function lowercase all characters, applies the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/trim"&gt;&lt;code&gt;trim()&lt;/code&gt;&lt;/a&gt; method to remove whitespaces, and then removes all non-alphabetic characters using the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace"&gt;&lt;code&gt;replace()&lt;/code&gt;&lt;/a&gt; method and a regex expression matching the characters we want to remove.&lt;br&gt;
Later, we can use this function on any string, as done inside the &lt;code&gt;stringsHaveSameValue&lt;/code&gt; function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const normalizeString = (string) =&amp;gt; {
    const regex = /[^a-z]/g;
    return string.toLowerCase().trim().replace(regex, '');
};

export const stringsHaveSameValue = (inputValue, existingItem) =&amp;gt; {
    return normalizeString(inputValue) === normalizeString(existingItem)
}

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

&lt;/div&gt;



&lt;p&gt;Finally, we iterate over the retrieved data and use the stringsHaveSameValue function to determine whether an item is already in the list. If any existing data values match the one submitted, we prevent users from adding it. Otherwise, we add the new item to the database:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if (data.some((item) =&amp;gt; stringsHaveSameValue(item.name, itemName))) {
        setAddItemErrMessage('This item is already in your list');
        return;
        }
let response = await addItem(listPath, { itemName, daysUntilNextPurchase });
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Final note
&lt;/h2&gt;

&lt;p&gt;While this solution works seamlessly if the data is not big, you may need to optimize it if you are dealing with a great amount of data that might make the iteration slow. Also, if you're using React, a nice possibility is to &lt;a href="https://dev.to/vivitt/react-hooks-when-to-use-usememo-5cc"&gt;use the useMemo hook to cache data calculations and avoid impacting the app's performance&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Thanks for reading :)&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>beginners</category>
      <category>frontend</category>
    </item>
  </channel>
</rss>
