<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Mary's Blog | A design engineer's journal]]></title><description><![CDATA[Everything I know about design and engineering]]></description><link>https://blog.maryojo.me</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1661110806005/IjHca-ROY.png</url><title>Mary&apos;s Blog | A design engineer&apos;s journal</title><link>https://blog.maryojo.me</link></image><generator>RSS for Node</generator><lastBuildDate>Mon, 12 Oct 2026 21:34:55 GMT</lastBuildDate><atom:link href="https://blog.maryojo.me/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[The Question I Ask Before Building Anything]]></title><description><![CDATA[Let's settle this once and for all: the progress of a product isn't measured by the number of features it has.
Why?
Because users rarely care about features. They care about getting things done. They ]]></description><link>https://blog.maryojo.me/the-question-i-ask-before-building-anything</link><guid isPermaLink="true">https://blog.maryojo.me/the-question-i-ask-before-building-anything</guid><category><![CDATA[product thinking]]></category><category><![CDATA[product development]]></category><category><![CDATA[UX]]></category><category><![CDATA[software development]]></category><category><![CDATA[AI]]></category><dc:creator><![CDATA[Mary Ojo]]></dc:creator><pubDate>Thu, 09 Jul 2026 23:31:27 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/5f9c4528b309125fbb6197f0/4d8ef06b-8cfb-4afa-b5a1-ccf8ee00d8eb.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Let's settle this once and for all: the progress of a product isn't measured by the number of features it has.</p>
<p>Why?</p>
<p>Because users rarely care about features. They care about getting things done. They care about outcomes.</p>
<p>If you were to announce any of these updates:</p>
<ul>
<li><p>An AI search feature was added.</p>
</li>
<li><p>Dark mode is now available.</p>
</li>
<li><p>We've launched a new dashboard.</p>
</li>
</ul>
<p>These sound exciting, but mainly to the person/team that built them, they don't mean much to users on their own.</p>
<p>What users really want is to:</p>
<ul>
<li><p>Find what they're looking for faster.</p>
</li>
<li><p>Better understand their business.</p>
</li>
<li><p>Save time and complete their tasks faster and easier.</p>
</li>
</ul>
<p>A feature is only valuable if it creates a meaningful outcome. That's why I try to build (and sell) outcomes, not features. So whenever I'm building something, I ask myself:</p>
<blockquote>
<p>What outcome does this feature create? Which user goal does it help achieve?</p>
</blockquote>
<p>If I can't answer these questions clearly, it's usually a sign that the feature needs more thought.</p>
<p>As AI makes product development even easier, the focus has changed from just writing code. The builders who stand out and get the most out of products will be those who combine product thinking, design, engineering and AI to solve real problems.</p>
<p>Next week, I'll share how applying this outcome-based approach increased how users engage in one of the products I'm currently building.</p>
<p>See you next time!</p>
<p><em>I'm Mary, a product engineer, who designs and builds usable, accessible and intelligent products</em></p>
]]></content:encoded></item><item><title><![CDATA[3 UX mistakes that might be costing you users]]></title><description><![CDATA[Let's talk about usability and 3 common mistakes you might be making when building that product.

Confusing 'Account Setup' with 'Onboarding': Your onboarding flow is meant to serve a primary purpose,]]></description><link>https://blog.maryojo.me/3-ux-mistakes-that-might-be-costing-you-users</link><guid isPermaLink="true">https://blog.maryojo.me/3-ux-mistakes-that-might-be-costing-you-users</guid><dc:creator><![CDATA[Mary Ojo]]></dc:creator><pubDate>Sun, 28 Jun 2026 22:53:49 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/5f9c4528b309125fbb6197f0/4508b38c-d848-45be-ae98-d04759482cbe.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Let's talk about usability and 3 common mistakes you might be making when building that product.</p>
<ol>
<li><p><strong>Confusing 'Account Setup' with 'Onboarding'</strong>: Your onboarding flow is meant to serve a primary purpose, which is to show the user why your product matters; lead users to their first 'Aha' moment. This is about discovering the value of your product and how it applies to them, more precisely, how it provides a solution to their pain point. We often think onboarding is for us (the product owners); to get the data we need for the product's functionality, but in reality, onboarding is for the user. Data collection for very critical functionalities is important but it should never replace the primary reason of why the onboarding flow exists in the first place. Every piece of information you ask for should try in making them see the value of your product. If asking for their 'Company Size' doesn't immediately change what they see on their dashboard, don't ask for it...yet. And in some cases, if done well, some parts of onboarding could also be used to collect critical setup data. But value must come before asking, helping your users understand the 'why' of your product would encourage them to provide their 'what'. In addition to this, the 'why' should also not be left out during data collection. Helping users understand why they need to provide their information also builds trust. Let’s look at a real-world example of a product that does this well.</p>
<p><strong>Sample Product:</strong> Duolingo<br /><strong>The User's Pain Point</strong>: The intimidating feeling that learning a new language is too hard or will take years.<br /><strong>The "Aha!" Moment:</strong> Realizing they can translate a complete sentence in a foreign language in less than 60 seconds (this would excite any new learner)<br /><strong>How Duolingo shows value during onboarding:</strong> Instead of starting with even a "Create Account" screen or asking for your name and email, Duolingo drops you straight into the product:<br />- Choose Your Goal: The user immediately selects what they want to achieve (e.g., "Spanish for Travel").<br />- The Interactive Lesson: The user is immediately placed in a mini-lesson. They click buttons, hear audio, and solve puzzles. Some infornation gotten includes the "Technical Setup" introduced as a game.<br />- The "Aha!" Moment: After 5-10 screens, the user has earned their first win and realized that they can 'do it'.<br />- The Delayed Setup: Only after a user has finished the lesson and felt the win does Duolingo ask them to 'set up' - save progress by creating an account.</p>
<img src="https://cdn.hashnode.com/uploads/covers/5f9c4528b309125fbb6197f0/0d02a9fd-d7e5-42f3-bf1f-fdaf8e7dfc40.png" alt="" style="display:block;margin:0 auto" />

<p>Now, imagine what this would have felt like if Duolingo started with a 10-field registration form and a "Verify Your Email" requirement, most users would lose interest before they ever learned a single word. The onboarding flow led with the solution and providing value (in this case it was learning) before earning the right to ask for the data (the account).</p>
<p>While this approach is harder to build (because you have to manage temporary "guest" states in your database or client side), the payoff in user conversion is almost always worth the engineering effort.</p>
</li>
<li><p><strong>Feature Overloading:</strong> It's easy to feel like having a lot of features increases the value of a product, but this isn't so, because more features would mean higher cognitive load and more friction points for the user. With feature overload, users would have to use more mental energy to navigate the product interface than actually achieving their core goals. It specifically hurts the product by trigerring decision paralysis. They become overwhelmed and confused about '<em>what to click on'</em>, '<em>what to click first</em>', etc. This isn't a coincidence but an actual phsychological principle, Hick's Law, which states that <em>the more choices you present, the longer it takes for a user to make a decision</em>. This in turn affects the product learning curve, making it a lot steeper because of feature clutter. It also further buries the main purpose of the app, the core value proposition that keeps them coming back. And if there are more chances for users to face friction points then there would also be high drop offs out of frustration. To fix this issue, it is important to ensure that the core functionalities of the the product are easy to access and priortised in the user flow. Patterns like progressive disclosure could be adopted to handle secondary features in sub-menus, internal pages, modals, accordions, etc where they would not be competing for the user's attention.</p>
<p>The design below shows menu and hamburger, an example of progressive disclosure. Design by <a href="https://dribbble.com/shots/18186485-Navio-Navigation-Bar">Nicholas Ergenia</a></p>
<img src="https://cdn.hashnode.com/uploads/covers/5f9c4528b309125fbb6197f0/51d58080-c577-431c-8f49-544d0a9c81c7.png" alt="" style="display:block;margin:0 auto" />
</li>
<li><p><strong>Skipping Usability Testing</strong>: Usability testing is commonly ignored and this shouldn't be so. Apart from the usual functional testing (which checks if the product works), you still need to test how usable your product is. Usability testing involves observing how real users interact with your product as they try to complete specific user tasks. It checks if the user can actually navigate and use the solution you’ve built. It shows where users get confused, where they hesitate, and where your assumptions about their behavior don't match reality. It also helps to validate the 'Aha' moment, whether it is reachable or if users are getting stuck on unnecessary friction points that you might not notice. The good thing about usability testing is that you can start small with about just 5 people, this usually leads to dicovering about 80% of usability issues. Skipping usability testing makes a large number of your users unknowingly test your app, but instead of reporting an issue as a bug, they totally stop using the product.</p>
</li>
</ol>
<p><strong>Follow me for more!</strong><br /><em>Hi, I'm Mary, i'm a design engineer, who designs and builds usable, accessible and intelligent products</em></p>
]]></content:encoded></item><item><title><![CDATA[Beyond Alt Texts: How AI can Help Solve the "Cognitive Gap" in Modern UX]]></title><description><![CDATA[Last year during Google's Built-In AI hackathon, I built an experimental Chrome extension called Clarity Lens. The product was inspired by thinking about the 'hidden 16%', the portion of the world's p]]></description><link>https://blog.maryojo.me/beyond-alt-texts-how-ai-can-help-solve-the-cognitive-gap-in-modern-ux</link><guid isPermaLink="true">https://blog.maryojo.me/beyond-alt-texts-how-ai-can-help-solve-the-cognitive-gap-in-modern-ux</guid><dc:creator><![CDATA[Mary Ojo]]></dc:creator><pubDate>Tue, 02 Jun 2026 22:18:56 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/5f9c4528b309125fbb6197f0/5dd635f7-19b2-487f-86d2-e20731f578fe.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Last year during Google's Built-In AI hackathon, I built an experimental Chrome extension called Clarity Lens. The product was inspired by thinking about the 'hidden 16%', the portion of the world's population who are often left behind by the modern web. According to the WHO, over 1 in 6 people live with a disability, many of whom navigate the web with cognitive differences that the rest of us simply glance over. For these users, the modern web is a high-friction environment that demands a lot of "cognitive energy" just to do simple tasks. As someone who has always cared about building usable products and experiences, I know that the standard experience often fails these users.</p>
<h3>The Cognitive Friction of the Modern Web</h3>
<p>I did some research and tried to better understand the major barriers these users face. The common observation was these:</p>
<ul>
<li><p><strong>ADHD and Sensory Overload:</strong> For users with ADHD, using a typical website might feel like trying to read when 3 people are shouting 3 different things at you. Auto-playing videos, promo and consent popups, and cluttered layouts create a kind of 'noise' that makes it nearly impossible to focus.</p>
</li>
<li><p><strong>Dyslexia and Visual Stress:</strong> Users with dyslexia often describe large blocks of text as <em>'swimming'</em> in their faces or blurry. Long sentences with complex words make it really hard to retain the meaning of the sentence by the time they reach the end.</p>
</li>
</ul>
<h3>An Experimental Solution</h3>
<p>I built this product to explore how AI could be beneficial in making the web more accessible, in ways we might have never thought of. It acts as a bridge, reducing cognitive stress by simplifying language and reducing digital clutter. Because this is a Chrome Extension built on Chrome’s built-in AI, the processing happens directly on the user's device. This project focused on two main functions:</p>
<ul>
<li><p><strong>Simplification</strong>: Rewriting complex jargon into plain, accessible language.</p>
</li>
<li><p><strong>Action Item Extraction:</strong> Surfacing "Action Items" (like deadlines or very important information) so users don’t have to hunt through 1,000 words of copy to find them.</p>
</li>
</ul>
<h3>Solving the "Privacy Tax"</h3>
<p>Building this project helped me see a much bigger picture regarding AI and ethics. For a user with a cognitive disability, using most AI tools would mean that they have no privacy anymore to even do something as basic as using the web because they often have to expose their private browsing data just to make a website readable. By building Clarity Lens as an extension using local, built-in AI; this <em>privacy tax</em> is eliminated because their data never leaves their browser.</p>
<p>This project showed that we can build AI-enabled products that are both deeply accessible and private by design, ensuring the web remains a place where everyone can navigate with dignity and ease.</p>
<p>Follow me for more!<br />Hi, I'm Mary, i'm a design engineer, who designs and builds products</p>
]]></content:encoded></item><item><title><![CDATA[That’s AI? Intelligence in Everyday Interfaces]]></title><description><![CDATA[If you've used Youtube long enough, you'd realize it gradually became better in understanding your needs. I'm sure you can relate to this - you think of something, next thing, you open Youtube and it's being advertised, or you come across it on your ...]]></description><link>https://blog.maryojo.me/thats-ai-intelligence-in-everyday-interfaces</link><guid isPermaLink="true">https://blog.maryojo.me/thats-ai-intelligence-in-everyday-interfaces</guid><category><![CDATA[AI]]></category><category><![CDATA[UI]]></category><category><![CDATA[UI Design]]></category><category><![CDATA[Frontend Development]]></category><dc:creator><![CDATA[Mary Ojo]]></dc:creator><pubDate>Sat, 03 Jan 2026 23:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1752537619066/491e6358-ab26-48cf-980f-e44203d8e435.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If you've used Youtube long enough, you'd realize it gradually became better in understanding your needs. I'm sure you can relate to this - you think of something, next thing, you open Youtube and it's being advertised, or you come across it on your feed on Instagram. Interfaces as we've know them, are evolving right in our faces, especially as the use and demand of AI applications constantly increases. The use of AI can be quiet or loud on the user interface, that it's usually not so obvious how much AI is being used in everyday interfaces. In this article, I'll be exploring what makes an interface AI-powered, the visible and invisible signs of AI in everyday interfaces and real-world examples that show how AI shows up differently across products.</p>
<h2 id="heading-is-this-ai-or-magic">Is this AI or magic?</h2>
<p>Beyond the obvious chatbots and fancy AI assistants we interact with, one way to detect that an interface is AI powered is how it responds to the user, it's smart. When you open an app and it already seems to know what you want, that’s the feeling of “smartness” and it shows up in different ways.</p>
<p>🔍 It’s in the search bar that completes your thought before you finish typing.<br />✉️ The email app that suggests a sentence you were just about to write.<br />🎶 And the music app that builds a playlist that actually fits your mood.</p>
<p>These experiences that feel 'just right', are a result of AI models learning patterns and adapting to the user or current context. What feels smart is most times a mix or one of the following:</p>
<ol>
<li><p><strong>Anticipation</strong> : when the system predicts your next move. e.g Gmail’s Smart Compose automatically suggests full sentences as you type, often matching your tone. The interface isn’t waiting for instructions, it’s predicting your next action in real time.</p>
</li>
<li><p><strong>Personalization</strong> : when it adapts based on your behavior, preferences or context. e,g. Instagram reshapes your Explore page based on what you pause on, repeat or interact with, not just what you like, quietly learning what holds your attention.</p>
</li>
<li><p><strong>Efficiency</strong> : when it reduces friction without asking you to explain yourself e.g Google Maps rerouting automatically when there's traffic ahead, without asking whether you want an alternative.</p>
</li>
<li><p><strong>Relevance</strong> : when results or suggestions feel tailored and timely e.g Spotify’s “Daylist” changing throughout the day based on time, your listening habits, and context.</p>
</li>
</ol>
<p>Most times, these interactions are not viewed as AI because they are quiet and don't show up as a chatbot or AI assistant would. But they are, and they tend to feel most natural because intelligence is neatly woven into the experience, yet deeply influencing user behaviour.</p>
<p>In everyday digital experiences, AI isn’t just a smart chatbot, it’s the quiet intelligence behind the scenes that makes interfaces feel smart, intuitive, and personal. So next time you use an app and you notice any of these things, try to think about how the design and architecture decisions behind the application, this would give a better understanding how AI works and is used on the UI. As AI continues to evolve, the boundary between what’s obviously algorithm-based and what feels more natural will only blur further, underscoring how deeply AI is woven into the interfaces we use every day.</p>
<h3 id="heading-resources">Resources</h3>
<ul>
<li>https://www.toptal.com/designers/product-design/anticipatory-design-how-to-create-magical-user-experiences</li>
<li>https://globalresearchandinnovationpublications.com/HCI/article/view/74</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Should We Really Build Carousels Without JS?]]></title><description><![CDATA[CSS-only carousels truly feel exciting and highlight so much about the power of modern CSS. It simplifies the creation of carousels from something which used to be about >200 line of codes to a few lines. This is because modern CSS handles interactiv...]]></description><link>https://blog.maryojo.me/should-we-really-build-carousels-without-js</link><guid isPermaLink="true">https://blog.maryojo.me/should-we-really-build-carousels-without-js</guid><category><![CDATA[Accessibility]]></category><category><![CDATA[CSS]]></category><category><![CDATA[JavaScript]]></category><dc:creator><![CDATA[Mary Ojo]]></dc:creator><pubDate>Sat, 03 Jan 2026 07:00:39 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1767132253294/6ceacdb4-5961-47a6-bf1e-0654123e4c62.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>CSS-only carousels truly feel exciting and highlight so much about the power of modern CSS. It simplifies the creation of carousels from something which used to be about &gt;200 line of codes to a few lines. This is because modern CSS handles interactivity with the scroll-snap-* properties. Some other new properties including the <code>::scroll-marker()</code>, and the proposed <code>interactivity: inert</code> now go a step further and give this interactivity some kind of accessibility.</p>
<p>While modern CSS provides the visual and structural foundation for carousels, a semantic JavaScript "patch" might still be necessary today to fulfill critical Web Content Accessibility Guidelines (WCAG) requirements. It would ensure that cross-browser compatibility, focus management, and other kinds of accessibility-related issues are handled for all users. We'll be looking some more into these issues in this article.</p>
<h2 id="heading-the-power-and-limitations-of-pure-css-how-do-css-only-carousels-even-work">The Power and Limitations of Pure CSS: How Do CSS-Only Carousels Even Work?</h2>
<p>The way CSS carousel works hinges on these features: the <code>scroll-snap-type</code>, <code>scroll-snap-align</code> and the <code>overflow-x</code>. As you would likely know, the overflow property is used to control how content is handled when it exceeds the boundaries of its containing element. In this case, it is used to enable scrolling when set to scroll, so that hidden carousel slides can be exposed by horizantally scrolling. This also means that slides which are not currently in view are "off" the screen, but still <em>exist</em>. This article gives a detailed overview of how CSS-only carousels work: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_overflow/CSS_carousels</p>
<p>The <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_scroll_snap">CSS Scroll Snap Module</a> , allows the creation of smooth carousels that “snap” perfectly into place as users scroll. This is done accurately and purely without JavaScript. This is possible because scroll-snap effectively assigns the complex behavior of the carousel to the browser's own scrolling engine, which is faster and more efficient.</p>
<p>The <code>scroll-snap-type</code> goes on the parent element (the carousel wrapper) that holds all the individual slides. It tells the browser that this element is a scroll container and it should utilize the snap behavior. On the other hand, the child elements (the individual slides) are tagged with the <code>scroll-snap-align</code> property. It specifies where on the slide the snap should align relative to the container/wrapper. So, when the user lifts their finger or releases the mouse, the browser automatically calculates the nearest center alignment point. The browser then uses a smooth, hardware-accelerated scroll to accurately land on that point, ensuring only one slide is fully visible and perfectly centered, copying the behavior of a traditional JavaScript carousel.</p>
<p><em>But here's the thing:</em></p>
<p>Building a CSS-only carousel like this can create a very frustrating user experience to users who use Assistive Technologies (AT), even though everything appears smooth on the surface. This brings us to the next part of this article.</p>
<h2 id="heading-the-semantic-gaps-where-css-falls-silent">The Semantic Gaps: Where CSS Falls Silent</h2>
<ol>
<li><p><strong>The first we'll look at is Focus Traps:</strong> The ATs and the browser itself which controls the snapping still typically see and recognize off-screen content as part of the page's document order. Screen readers and keyboard users would still be able to tab to an interactive element (like a button or link) that is visually off-screen, creating a frustrating experience known as a "focus trap" issue. This is against the  <a target="_blank" href="https://www.w3.org/WAI/WCAG21/Understanding/focus-order.html">WCAG 2.4.3 (Focus Order)</a> accessibilty guideline. Further going a bit deeper, we also see that this is where the HTML <code>inert</code> property comes in. It puts elements in an 'inert' state. The <code>inert</code> property tries to manage focus and interaction for off-screen content. It does this by:</p>
<ul>
<li><p><strong>Interaction Blocking</strong>: It prevents hidden elements from being unintentionally activated using mouse clicks or other input methods.</p>
</li>
<li><p><strong>Accessibility Tree Noise</strong>: It removes off-screen content from the accessibility tree, preventing screen readers from announcing content the user can't see.</p>
</li>
</ul>
</li>
</ol>
<p>    <strong>How JS fixes this</strong>: By dynamically applying <code>inert</code> to off-screen slides, keyboard users cannot tab into invisible elements, this helps to maintain a logical focus order for visible elements. One common method used is the combination of <code>IntersectionObserver</code> + <code>inert</code>.</p>
<ol start="2">
<li><p><strong>Inability to Update <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Guides/Live_regions">ARIA Live Regions</a>:</strong> CSS cannot dynamically update the DOM or trigger programmatic announcements. This is a significant technical limitation. It cannot alter the HTML structure, modify ARIA attributes, or intercept and control user input (like keyboard presses) to provide the necessary semantic information and interaction required by WCAG (Web Content Accessibility Guidelines). This is against the <a target="_blank" href="https://www.w3.org/TR/UNDERSTANDING-WCAG20/ensure-compat-rsv.html">WCAG 4.1.2 (Name, Role, Value)</a> and the lack of <em>programmatic context</em> for screen reader users. This is fundamental because it requires that for all user interface components (including hidden states, like a slide changing), the name and role can be programmatically determined, and that changes in these items are announced to the user. For example:</p>
<p>A change happens when the carousel slides from one image slide to the next. This is a crucial change in "value" (the content currently being displayed). There needs to be an announcement like "Image Slide X of Y" when this change occurs, but it fails because the state change is managed solely by visual scrolling in CSS, so the browser does not recognize a programmatic change to announce.</p>
<p> <strong>The JS Solution:</strong> This solution uses an <code>IntersectionObserver</code> to detect the exact moment a slide comes into view, this would then trigger the script to manually update a visually-hidden, aria-live="polite" element with the current position (e.g., "Slide 3 of 5"). This forces the screen reader to announce the state change, fulfilling the communication requirement of WCAG 4.1.2.</p>
</li>
<li><p><strong>The Missing Pause/Stop Functionality</strong>: This is a non-visual requirement. If the carousel automatically rotates or moves, CSS cannot provide a control to stop the animation. This goes against the WCAG 2.2.2: (Pause, Stop, Hide) accessibility requirement.</p>
<p> <strong>How JS Fixes this:</strong> A single line of JS to toggle the CSS <code>animation-play-state</code> property and also update the button's <code>aria-label</code> (e.g., from "Pause Slideshow" to "Play Slideshow").</p>
</li>
<li><p><strong>Incorrect ARIA Role (Semantic Mismatch)</strong> : Another major issue as pointed out by <a target="_blank" href="https://www.sarasoueidan.com/blog/css-carousels-accessibility/">Sara Soueidan</a> is incorrect ARIA Role which happens because the Browser exposes Carousel UI elements as ARIA "Tabs" and "Tablist". The scroll markers become <code>role="tab"</code>.</p>
<p> What this means is that the browser sees interactive scroll markers and makes a faulty assumption based on existing ARIA patterns (tabs, buttons, links). It defaults to the tablist pattern, which is wrong for a simple image carousel or gallery.</p>
<p> <strong>The JS Solution:</strong> JS is required to override the browser's guess by adding clear ARIA roles (e.g., <code>role="group"</code>, <code>aria-roledescription="carousel"</code>).</p>
</li>
</ol>
<h2 id="heading-conclusion">Conclusion</h2>
<p>So far, we see how CSS only carousels are not fully usable and might need the semantic JS fixes to properly cater for every user. It fails some important usability and accessibility checks.</p>
<p>The reality is that CSS is a styling engine, not a semantic language. When a carousel is created using CSS features like <code>overflow-x</code> and <code>scroll-snap-type</code>, we achieve a powerful visual component. However, the component is still semantically and functionally incomplete for assistive technology users. The browser simply cannot be relied on to correctly handle complex interactive requirements like focus management across hidden slides, programmatic announcement of state changes, etc</p>
<p>The use of JavaScript is not just a fix neither is it a failure of CSS; it is a good semantic patch that closes the gap between usability, performance and compliance.</p>
<p>This hybrid model shows how CSS dictates the motion and performance, while a few lines of JavaScript would help with the critical accessibility requirements for a carousel.</p>
<h2 id="heading-references">References:</h2>
<ul>
<li>https://www.w3.org/TR/css-scroll-snap-1/#overview</li>
<li>https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_scroll_snap/Basic_concepts</li>
<li>https://www.w3.org/TR/css-scroll-snap-1/#overview</li>
<li>https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Global_attributes/inert</li>
<li>https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API</li>
<li><a target="_blank" href="https://drafts.csswg.org/css-ui-4/#inertness%20https://groups.google.com/a/chromium.org/g/blink-dev/c/O5ZmbyRh9LE">The proposed CSS inert property</a></li>
<li>https://developer.mozilla.org/en-US/docs/Web/CSS/::scroll-marker</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Design Tokens: The Bridge Between Design and Code]]></title><description><![CDATA[I don't just see design tokens as the bridge between design and code, tokens are the foundation of that bridge, it's the system that makes building the bridge even possible.

The impact of design tokens in the product development today are huge and f...]]></description><link>https://blog.maryojo.me/design-tokens-the-bridge-between-design-and-code</link><guid isPermaLink="true">https://blog.maryojo.me/design-tokens-the-bridge-between-design-and-code</guid><category><![CDATA[UX]]></category><category><![CDATA[Frontend Development]]></category><dc:creator><![CDATA[Mary Ojo]]></dc:creator><pubDate>Tue, 28 Oct 2025 23:36:05 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1761692030718/7a224fbe-2881-48f5-9cbc-66931eb1ce60.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<blockquote>
<p>I don't just see design tokens as the bridge between design and code, tokens are the foundation of that bridge, it's the system that makes building the bridge even possible.</p>
</blockquote>
<p>The impact of design tokens in the product development today are huge and fundamentally changes how design systems scale and how designers and developers work together. At the core, design tokens are the atomic design decisions of any system, it is made up of the color values, spacing units, typography scales, etc stored as data rather than scattered across stylesheets, code and design files.</p>
<p>This is one of those terms that sound really abstract, but that in itself is exactly where it’s power lies, its abstraction. I like to think of it like this: Instead of hardcoding <code>#3B82F6</code> throughout my codebase, I define a token like <code>color.primary.500</code>.</p>
<p>This really simple action creates a single source of truth that can be referenced by both designers and developers. If your primary color value needs updating, you simply change one value, and the entire system updates automatically across every platform and implementation.</p>
<h3 id="heading-these-are-some-important-things-to-know-about-design-tokens">These are some important things to know about design tokens:</h3>
<ol>
<li><p>Design tokens follow a clear naming standard, which is based on the 3 types - the Primitive, Semantic and Component tokens.</p>
</li>
<li><p>Based on type of design property, tokens are usually organized into several categories, some major categories are: color tokens, spacing tokens, typography tokens, border tokens, shadow tokens, motion tokens, etc.</p>
</li>
<li><p>Major design systems like <a target="_blank" href="https://m3.material.io/foundations/design-tokens/overview">Material Design</a>,  <a target="_blank" href="https://www.npmjs.com/package/@shopify/polaris-tokens">Shopify’s Polaris</a> , <a target="_blank" href="https://atlassian.design/tokens/design-tokens">Atlassian Design System</a> rely heavily on tokens</p>
</li>
<li><p>Design tokens are not dependent on languages or plaforms they are used in. Tokens are defined once in a neutral format (usually JSON), then used in any target platform e.g CSS variables, React.js, iOS Swift code, React Native, etc. This means your iOS app, web application, and Android app can all reference the exact same design token, and therefore have the same result, ensuring true cross-platform consistency.</p>
</li>
<li><p>Design tokens were originally created by the Salesforce design system team.</p>
</li>
<li><p>I really do see tokens as a fundamental part of AI-driven design-development workflow.</p>
</li>
<li><p>The W3C is working on standardizing token formats. Check out the community group <a target="_blank" href="https://www.designtokens.org/">here</a></p>
</li>
</ol>
]]></content:encoded></item><item><title><![CDATA[Why your animations are making users wait]]></title><description><![CDATA[We all love animations that make a UI feel interactive. But poorly implemented animations can make any UI really slow. The secret to smooth and fast implementations is knowing how to avoid some common mistakes. 
Some of which are:

Transitioning heav...]]></description><link>https://blog.maryojo.me/why-your-animations-are-making-users-wait</link><guid isPermaLink="true">https://blog.maryojo.me/why-your-animations-are-making-users-wait</guid><category><![CDATA[UX]]></category><category><![CDATA[Frontend Development]]></category><dc:creator><![CDATA[Mary Ojo]]></dc:creator><pubDate>Sat, 25 Oct 2025 04:00:49 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1761255842492/e54143a6-4a48-434e-a0cc-0e0010ea1637.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>We all love animations that make a UI feel interactive. But poorly implemented animations can make any UI really slow. The secret to smooth and fast implementations is knowing how to avoid some common mistakes. </p>
<h3 id="heading-some-of-which-are">Some of which are:</h3>
<ol>
<li>Transitioning heavy properties - Animating properties like width, height, or left can cause serious performace issues. This happens because they trigger a repaint operation which is heavy. On the other hand, properties like transform and opacity should be used. The reason is because the latter properties use GPU processing which is optimized for rendering graphics-heavy properties.</li>
<li>Not using <code>will-change</code> as it should be used - The <code>will-change</code> CSS property can be used to improve the performance of animations and transitions, especially when working with complex filters, etc, but it should be used carefully as using it everywhere can waste memory resources and cause lags.</li>
<li>Animating <code>box-shadow</code> - Animating <code>box-shadow</code> will hurt performance, but you can create the same effect with the  smallest repaint operations by animating the opacity of a pseudo-element. This would help achieve smoother animations.</li>
<li>Using <code>transition: all</code> - The <code>transition: all</code> animates <strong> every </strong> property that can change, and you can imagine what this would do to any UI, especially if there are so many animations implemented. Transitioning should be directly set and applied to the specific elements. </li>
<li>Too many transitions all happening at the same time - Running a lot of transitions at once and at the same time can cause hanging on the UI, particularly on devices that are not built to handle heavy processing. </li>
<li>Animating during heavy JavaScript execution - Transitions clashing with heavy DOM manipulation done by JS can cause dragging animations.</li>
</ol>
<h3 id="heading-references">References:</h3>
<ul>
<li><a target="_blank" href="https://css-tricks.com/animate-box-shadow-silky-smooth-performance/">CSS-Tricks: "Animate box-shadow with Silky Smooth Performance" CSS-Tricks</a></li>
<li><a target="_blank" href="https://dev.to/leduc1901/costly-css-properties-and-how-to-optimize-them-3bmd">DEV Community: "Costly CSS Properties and How to Optimize Them"</a></li>
<li><a target="_blank" href="https://www.lambdatest.com/blog/css-gpu-acceleration/">LambdaTest: "Boosting Web Performance With CSS GPU Acceleration"</a> </li>
</ul>
]]></content:encoded></item><item><title><![CDATA[The 100ms rule]]></title><description><![CDATA[It takes about 100 milliseconds to blink and in the digital world, this time frame is critical! It's the absolute limit. When an interaction takes longer than 100ms, the average user loses the sensation of "feeling instant" and feels a noticeable lag...]]></description><link>https://blog.maryojo.me/the-100ms-rule</link><guid isPermaLink="true">https://blog.maryojo.me/the-100ms-rule</guid><category><![CDATA[UX]]></category><category><![CDATA[Frontend Development]]></category><dc:creator><![CDATA[Mary Ojo]]></dc:creator><pubDate>Thu, 23 Oct 2025 21:27:33 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1761254082907/466856f8-6637-415b-af25-167124d41848.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>It takes about 100 milliseconds to blink and in the digital world, this time frame is critical! It's the absolute limit. When an interaction takes longer than 100ms, the average user loses the sensation of "feeling instant" and feels a noticeable lag. Perceived performance is a fundamental concept in (UX). It refers to how fast or responsive a system “feels” to a user, which is often more important than its actual, technical speed. It's about managing human time perception and employing strategies to improve perceived speed. Since actual speed is finite, UX strategies are used as psychological tricks to shorten the perceived waiting time.</p>
<h2 id="heading-some-top-strategies-to-improve-perception-are">Some top strategies to improve perception are:</h2>
<ol>
<li><p>Immediate Feedback (The 100ms Rule) - Make the system acknowledge the user's input immediately, even before processing starts. An example is when a user clicks a button, the button should visually darken or depress within 100ms. This instantly tells the user, "My click was registered," which prevents them from clicking again or thinking the app is frozen.</p>
</li>
<li><p>Illusion of Progress (Loading state) - Add loading states because filled time is perceived as shorter than empty time. Provide constant visual updates so the user is in an active state (watching progress) rather than a passive/paused state (just waiting). Examples of this are:</p>
<ul>
<li><p>Skeleton Screens: Showing the outline of the content (like gray boxes) as it loads. This makes the user feel the content is already there and just "filling in."</p>
</li>
<li><p>Progress Bars: Bars that move smoothly and even accelerate slightly toward the end are perceived as faster than bars that move erratically.</p>
</li>
<li><p>Loading Spinners: Used for short waits (less than a second). For longer waits, they should be accompanied by explanatory text.</p>
</li>
</ul>
</li>
</ol>
<ol start="3">
<li><p>Load Critical Content first - Prioritize what the user came for, making the interface usable before it's fully loaded. A good example of this can be illustrated with what happens on a news site, the main article text and key navigation links load first, while high-resolution images or ads load in the background. The page appears "done" to the user much sooner.</p>
</li>
<li><p>Non-Linear Loading &amp; Background Tasks - Pre-emptively load or calculate data for the next likely action the user will take. An example of this is when a checkout page loads the shipping options while the user is still typing their address. The transition to the next step feels instant because the data is already ready.</p>
</li>
</ol>
<h3 id="heading-references">References</h3>
<ul>
<li><a target="_blank" href="https://www.oreilly.com/library/view/designing-and-engineering/9780321562944/">Designing and Engineering Time: The Psychology of Time Perception in Software Book</a></li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Why That Button Color Feels Right: The Pyschology of Color on Interfaces]]></title><description><![CDATA[The more I work on interfaces, the more I see how even slight shifts in color could change how I would want people to feel or behave. A deep blue can make an interface feel more immersive. A bright orange button can feel urgent, but sometimes, a litt...]]></description><link>https://blog.maryojo.me/why-that-button-color-feels-right-the-pyschology-of-color-on-interfaces</link><guid isPermaLink="true">https://blog.maryojo.me/why-that-button-color-feels-right-the-pyschology-of-color-on-interfaces</guid><category><![CDATA[color]]></category><category><![CDATA[UI]]></category><category><![CDATA[UI Design]]></category><category><![CDATA[Frontend Development]]></category><category><![CDATA[frontend]]></category><dc:creator><![CDATA[Mary Ojo]]></dc:creator><pubDate>Fri, 11 Jul 2025 19:46:19 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1751743799107/1240ba33-189e-4618-bdb8-64f365bb41f0.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The more I work on interfaces, the more I see how even slight shifts in color could change how I would want people to feel or behave. A deep blue can make an interface feel more immersive. A bright orange button can feel urgent, but sometimes, a little too urgent. I realized color wasn’t just about style and it was about psychology and putting people in the right feelings.</p>
<p>This article explores how color in UI shapes behavior, trust, urgency, and even perception of quality.</p>
<h2 id="heading-why-colors-feel-the-way-they-do">Why colors feel the way they do</h2>
<blockquote>
<p>Imagine if traffic lights had green stop signs and red go signs. Would they still work?</p>
</blockquote>
<p>While the <em>meaning</em> might change if we collectively decided it did, the <em>instinctive reaction</em> would be difficult to override due to learned associations.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751620349461/0a1427dc-4fc6-4b05-aa78-cb9a2b2311f5.png" alt class="image--center mx-auto" /></p>
<p>Through nature, color instinctively guides us. We know that plants, forests and vegetation are green in color and this is psychologically interpreted as calmness, renewal, and stability because this is how we feel when we sight these things. Same goes for red, which is pyshcologically interpreted as danger because it shows up in blood and fire. On the UI, these associations guide everything from CTA colors to warnings, because you're not just styling a button, <em>you're signaling a behaviour</em>. A good example of how color has feelings is basically how most people feel on rainy days vs. how they feel on a bright and sunny day. This chart below shows a summary of some common colors and their association.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751891480210/d00ab1c2-1e82-491f-a1d0-231283f0dbcb.png" alt class="image--center mx-auto" /></p>
<p>Image from <a target="_blank" href="https://www.fifteendesign.co.uk/blog/how-colour-influences-our-decision-colour-psychology-in-design/">Fifteen Designs</a></p>
<h2 id="heading-cultural-nuances-in-color-perception">Cultural Nuances in Color Perception</h2>
<p>On the flip side, color perception isn’t global, due to cultural associations. An instance is the color red, which means luck in China, but danger in the US and a lot of other places. This <a target="_blank" href="https://medium.com/story-of-eggbun-education/why-is-red-considered-a-lucky-color-for-the-chinese-2ebe2b044275">article</a> by Chris Lee further verifies this, it says that in the US, declining stock prices are reflected with red color but in China, Korea, and Japan, rising stock prices are indicated in red because it is associated with wealth and stock gains. This shows how important it is to consider cultural perceptions because it determines what a user primarily feels based on their environment (what comes naturally to them). This is a very essential factor to consider especially when building for global and diverse audiences. This is the reason why McDonald's uses green in Europe but red in the US. To signal environmental consciousness and align with eco-friendly values more prominent in European markets. Their websites and app themes also adopted more earth tones and minimalism in these regions. Watch <a target="_blank" href="https://www.youtube.com/watch?v=4tFiI6%5C_gKek">this video</a> to learn more. Another example is Airbnb, which localizes colors and imagery on landing pages and mobile app UIs to reflect regional architecture, mood, and cultural color associations. Airbnb uses a primary color, #FF5A5F (a shade of pink), which represents openness, inclusivity, and community. Beyond the global color, Airbnb incorporates local color palettes inspired by the unique cultural and natural elements of each location. They also have a secondary palette featuring bold shades of purple and teal, named after and inspired by streets in cities around the world, further supports the brand's values and adds a local touch, according to The Branding Journal. In Middle Eastern markets, palettes may feature deeper jewel tones or sandy neutrals compared to pastel-heavy Western versions, because of the historical use of jewel tones and association with desert landscapes for sandy neutrals.</p>
<p>But here’s the thing, color <em>in itself</em> alone doesn’t carry meaning. A red can feel urgent or elegant. A blue can feel trustworthy or playful. What determines it's true meaning is how that color is tuned.</p>
<h2 id="heading-tuning-color-for-trust-urgency-amp-emotional-clarity">Tuning Color for Trust, Urgency &amp; Emotional Clarity</h2>
<p>Color properties such as hue, brightness, contrast and saturation affect tone, hierarchy, and usability on the UI. This is a major piece that connects the user's emotions, color perception and how colors are properly used on the interface. It also gives color it's true meaning.</p>
<p>For instance as shown in the image below, Spotify leans heavily into vibrant green and black to create an energetic and expressive feel. The green does more than brand the interface, it cues action and creativity. Its contrast against the dark UI and immersive images and videos, making the interface feel modern, expressive, and tuned in to a younger, music-loving audience. This use of color not only reinforces Spotify's brand voice but also helps users navigate intuitively.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1752008893557/da337b6e-5bff-45a5-a6b5-040cdea5a968.png" alt class="image--center mx-auto" /></p>
<p>So now, what is hue, saturation, brightness and contrast and how do these things affect the user experience? Well, these are fundamental properties of color and understanding them gives you powerful control over how color works in UI. So here's what they each mean and do:</p>
<ol>
<li><p><strong>Hue</strong>: This is what we typically think of as “color”, red, blue, yellow, green, etc and changing this means changing the base color.</p>
</li>
<li><p><strong>Saturation</strong>: This refers to how intense or pure the color is. High saturation would give vivid, bold, vibrant colors while low saturation gives off muted, soft, grayscale-ish version of the same hue. In the UI, a highly saturated color is attention-grabbing (useful for CTAs or alerts), while a low saturated version of the same hue is calm and subtle (good for backgrounds, secondary UI). An easy way to define saturation is that it is how much gray is mixed in.</p>
</li>
<li><p><strong>Brightness</strong>: This is basically how light or dark a color is. A color with high brightness is closer is to white and a color is low brightness is closer to black. A <strong>tint</strong> of a color is how much white is mixed in while a <strong>shade</strong> of the same color is how much black is mixed in</p>
</li>
<li><p><strong>Contrast</strong>: This refers to the relationship between two or more colors. It’s about how a particular color stands out against something else or another color. It shows how a saturated yellow might have low contrast on a white background because the brightness levels are close but a low-saturation blue on a black background might have high contrast because of brightness difference.</p>
</li>
</ol>
<p>It's important to understand how these color properties work together and the effect on the UI. How these affect things like: CTA visibility, error state perception and brand tone.</p>
<p>💡One tip is this: Don’t just choose colors, adjust their intensity, brightness and contrast based on the screen context and use case.</p>
<p>Still using Spotify as an example, we see how the primary color which is green is used for interface elements. It shows how button states using the same primary color but now a tinted version for the disabled state and a shaded version for pressed and hover states, all bring meaning to an interface and properly guide the user.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1752098266119/e14948e5-de1f-4542-9aaa-7677a3485af5.avif" alt class="image--center mx-auto" /></p>
<p>Image from <a target="_blank" href="https://www.figma.com/blog/creating-coherence-how-spotifys-design-system-goes-beyond-platforms/">Figma's Blog</a></p>
<h2 id="heading-using-colors-strategically-on-the-ui"><strong>Using Colors Strategically on the UI</strong></h2>
<p>So far, we’ve taken a look at how emotional psychology, cultural environment and color properties can affect color choices on the UI. I have curated a checklist of things to consider when dealing with colors on the UI.</p>
<ul>
<li><p>What action or message is this color supposed to show? A confirm action needs trust or clarity (e.g., green/blue), while a warning needs urgency (e.g., red/orange).</p>
</li>
<li><p>Is this color already associated with a meaning in my product, platform or generally? Like the example of the traffic light given, users subconsciously have expectations (e.g., red always means “error”). Breaking it causes confusion.</p>
</li>
<li><p>Will this color stand out in its context? A “primary” button shouldn’t blend into the background. Contrast and visual hierarchy matter.</p>
</li>
<li><p>Is it accessible (sufficient contrast)? No matter how nice it looks, if it fails contrast, it fails function especially for users with visual impairments.</p>
</li>
<li><p>Does this align with the brand voice or tone? A financial app using playful colors may feel unserious. A children's app using deep navy blue as the primary color may feel cold.</p>
</li>
<li><p>How will this color behave in light vs dark mode? Some hues (like yellow or pale orange) lose their visibility or richness when flipped into dark mode.</p>
</li>
<li><p>Is the color communicating a state? Hover, disabled, active, focus, error, success, etc. often require slight tone, brightness or saturation shifts. In fact, a quick color tactic is this: Use tints for gentle backgrounds or soft states, use shades for depth, hover, or dark mode and use saturation shifts for subtle hierarchy or to create "inactive" or "disabled" states (e.g., grayed-out buttons)</p>
</li>
</ul>
<h2 id="heading-passing-color-decisions-to-ui-development">Passing Color Decisions to UI Development</h2>
<p>Intentional color decisions in Figma is important, but if this is not held up in the code, users won’t feel the difference. Color is more than visual, it is behavioral, emotional, and functional. This is why developers play a critical role in making sure those color choices aren’t lost in translation. Use the checklist below to ensure that your interface honors the intention behind each color, not just visually, but functionally, accessibly, and at scale.</p>
<ul>
<li>Is the color token semantically named? Colors should be named based on their functionality on the interface e.g. primary, info, danger, surface-muted, avoid using color names alone e.g blue-1, blue-3. This helps to avoid inconsistent usage across dev and design and also matches how colors are meant to feel, not just look.</li>
</ul>
<ul>
<li>Have all interaction states been accounted for? Developers tend to skip or misuse interaction states like the active or hover state of a button which are usually differentiated with color by using shades or tints. These states are important because they give users a visual feedback, it helps them know what's clickable or interactive and if they have interacted with it</li>
</ul>
<ul>
<li><p>Is the color used consistently across states? Accounting for interactive states is not enough, states should be clearly defined in your palette e.g., --color-primary-hover, --color-disabled-text. This ensures consistency in user experience.</p>
</li>
<li><p>Does this color choice affect perception (trust, urgency, etc.)? A blue alert that says 'Something went wrong' is wrong color choice as it doesn't give the user the right perception of an action they have taken on the UI which failed. Things like this are very important and the right colors in the right shades or tints should be used.</p>
</li>
</ul>
<ul>
<li>Has this color been tested in both light and dark modes? A color might look really good in light mode but is hard to see in dark mode. And yes, the UI design might only be done for light mode interfaces, but users still have the freedom to change to dark mode using system or OS settings. If both modes are not properly tested and accounted for, it could greatly impact user experience for a specific set of people.</li>
</ul>
<h2 id="heading-conclusion">Conclusion</h2>
<p>So far we've gone over why color feels the way it does, cultural nuances that could impact color perception, and how this translates to colors on the interface.</p>
<p>Color on the UI is about clarity. It helps users make decisions, feel trust, notice urgency, and navigate confidently often at a quick glance and without reading a single word.</p>
<p>That’s why designing with color isn’t just about picking beautiful palettes, it’s mainly about making intentional, context-aware choices that help elevate the UX, scale across themes, and hold up under accessibility standards.</p>
<p>Thoughtful color is a form of communication. The more deliberate you are, the more intuitive the experience becomes.</p>
<h2 id="heading-useful-resources">Useful Resources:</h2>
<ol>
<li><p>A long list of colors, their meaning, how they can be combined and used on the UI: <a target="_blank" href="https://www.figma.com/colors/">https://www.figma.com/colors/</a></p>
</li>
<li><p>Find the color of anything: <a target="_blank" href="https://picular.co/">https://picular.co/</a></p>
</li>
<li><p>A one-of-a-kind tool for creating, managing, and sharing accessible color systems for user interface design: <a target="_blank" href="https://leonardocolor.io/">https://leonardocolor.io/</a></p>
</li>
<li><p>A Figma plugin to generate color palettes within Figma <a target="_blank" href="https://www.figma.com/community/plugin/1286792998372727741/color-wheel-palette-generator">https://www.figma.com/community/plugin/1286792998372727741/color-wheel-palette-generator</a></p>
</li>
<li><p>A Figma plugin for creating color palettes based on Design Systems like Material, Atlassian, Orbit and Ant Design: <a target="_blank" href="https://www.figma.com/community/plugin/1024452006068794933/foundation-color-generator">https://www.figma.com/community/plugin/1024452006068794933/foundation-color-generator</a></p>
</li>
<li><p>A tool to create beautiful color palettes with AI. Generate color palettes from names, images, text, or hex codes <a target="_blank" href="https://colormagic.app/">https://colormagic.app/</a></p>
</li>
<li><p>A Figma plugin crafted to automate color and button creation: <a target="_blank" href="https://www.figma.com/community/plugin/1344368111040867237/design-system-generator">https://www.figma.com/community/plugin/1344368111040867237/design-system-generator</a></p>
</li>
</ol>
<h2 id="heading-references">References:</h2>
<p>https://www.figma.com/resource-library/color-combinations/</p>
]]></content:encoded></item><item><title><![CDATA[10 useful CSS tools for Developers]]></title><description><![CDATA[1. CSS layout generator: https://layout.bradwoods.io/
Useful for: Anyone who wants to level up their CSS layout skills (flexbox and grids)
This website is all about helping developers get better at CSS layouts in a fun, hands-on way. It’s like a play...]]></description><link>https://blog.maryojo.me/10-useful-css-tools-for-developers</link><guid isPermaLink="true">https://blog.maryojo.me/10-useful-css-tools-for-developers</guid><category><![CDATA[CSS]]></category><category><![CDATA[CSS3]]></category><category><![CDATA[CSS Animation]]></category><category><![CDATA[tools]]></category><category><![CDATA[Frontend Development]]></category><category><![CDATA[frontend]]></category><category><![CDATA[Design]]></category><category><![CDATA[UI]]></category><category><![CDATA[React]]></category><category><![CDATA[JavaScript]]></category><dc:creator><![CDATA[Mary Ojo]]></dc:creator><pubDate>Sun, 02 Feb 2025 18:16:14 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1738520126461/44c795db-b562-4f0c-a911-852c6dd21031.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-1-css-layout-generator-httpslayoutbradwoodsiohttpslayoutbradwoodsio">1. CSS layout generator: <a target="_blank" href="https://layout.bradwoods.io/">https://layout.bradwoods.io/</a></h2>
<p><strong>Useful for</strong>: Anyone who wants to level up their CSS layout skills (flexbox and grids)</p>
<p>This website is all about helping developers get better at <strong>CSS layouts</strong> in a fun, hands-on way. It’s like a playground where you can practice using <strong>CSS Grid</strong> and <strong>Flexbox</strong> to create cool, responsive layouts. You write code, see the results instantly, and tackle challenges that mimic real-world layout problems and whether you’re just starting out or brushing up on your skills, it’s a great way to learn by doing.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738418770659/81a59e6f-bd37-4cdf-8adf-d52a1294aff0.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-2-css-clip-path-generator-httpsbennettfeelycomclippyhttpsbennettfeelycomclippy">2. CSS Clip path generator: <a target="_blank" href="https://bennettfeely.com/clippy/">https://bennettfeely.com/clippy/</a></h2>
<p><strong>Useful for</strong>: Getting quick and clean clip-path CSS code.</p>
<p>This website is for <strong>creating cool shapes</strong> on the web. Made by <strong>Bennett Feely</strong>, this tool lets you easily generate <strong>CSS clip-path code</strong> for all kinds of shapes—polygons, circles, stars, and more. Instead of struggling with complex code, you can just tweak a few settings, copy the code, and voilà! You’ve got a unique shape ready to use in your design.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738414579825/372993a4-c522-49d2-a73b-4936263fd650.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-3-css-backgrounds-httpssuperdesignercotoolscss-backgroundshttpssuperdesignercotoolscss-backgrounds">3. CSS Backgrounds <a target="_blank" href="https://superdesigner.co/tools/css-backgrounds">https://superdesigner.co/tools/css-backgrounds</a></h2>
<p><strong>Useful for</strong>: Adding quick background patterns to the UI.</p>
<p>This website contains a collection of over 100 free pattern backgrounds created using CSS, these patterns can be used to add textures to hero sections, as background layers/overlays, used in the footer design or hover effects for creating beautiful CSS backgrounds. It’s part of the Super Designer toolkit and makes it really easy to customize the patterns and textures—all with just a few clicks. You can play around with colors, and styles to create something truly unique, and you get the clean CSS code ready to use in your project.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738414456397/231a64cd-f865-4b0e-b300-458e0a24e916.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-4-grid-garden-httpscssgridgardencomhttpscssgridgardencom">4. Grid garden: <a target="_blank" href="https://cssgridgarden.com/">https://cssgridgarden.com/</a></h2>
<p><strong>Useful for</strong>: Beginners who want to learn more about CSS Grids</p>
<p>This website is a <strong>playful and interactive way</strong> to learn <strong>CSS Grid</strong>. Created by <strong>Thomas Park</strong> , it turns CSS grids into a game where you grow a garden by the code. Each level introduces new concepts, like aligning plants or watering specific plots, making it a fun and engaging way to get comfortable with CSS Grid.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738412773358/5783f74f-9711-4c28-8816-55fc8c483301.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-5-typescale-httpstypescalecomhttpstypescalecom">5. Typescale: <a target="_blank" href="https://typescale.com/">https://typescale.com/</a></h2>
<p><strong>Useful for</strong>: Designers and developers who want to ensure their typography is balanced and professional.</p>
<p>This website is a great tool for creating balanced and visually appealing typography scales for your projects. It allows you to experiment with different font sizes, ratios, and scales (like the golden ratio, perfect fifth, or modular scale) to find the perfect typography hierarchy. You can preview how your text will look, adjust settings, and get the corresponding CSS code to implement it seamlessly into your website.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738411950580/7fdce897-5d6e-4c29-b4a4-7a176cf0cb45.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-6-keyframes-httpskeyframesappanimatehttpskeyframesappanimate">6. Keyframes: <a target="_blank" href="https://keyframes.app/animate">https://keyframes.app/animate</a></h2>
<p><strong>Useful for</strong>: Creating CSS animations to add to your websites</p>
<p>This website is like a shortcut for creating smooth CSS animations. It’s super easy to use—just tweak settings like timing, easing, and movement, and it spits out clean CSS code for you. Whether you’re adding a subtle hover effect or a full-blown animation, this tool makes it really easy.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738411221637/2fa6f1ae-0ad0-4239-bce0-00482fa69e77.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-7-haikei-app-httpshaikeiapphttpshaikeiapp">7. Haikei App: <a target="_blank" href="https://haikei.app/">https://haikei.app/</a></h2>
<p><strong>Useful for</strong>: Modifying unique patterns &amp; visuals to add to the user interface.</p>
<p>This is a very useful tool for generating unique, customizable SVG shapes, blobs, waves, and other design elements. It’s perfect for adding visual flair to your projects. With a simple interface, you can tweak colors, shapes, and patterns, and then download the assets as SVG or PNG files. Whether you need a background, a divider, or a decorative element, Haikei makes it quick and easy to create something eye-catching.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738444910108/4863e69d-3847-4ec6-8bc9-76dac00261eb.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-8-css-loaders-httpscss-loaderscomhttpscss-loaderscom">8. CSS loaders: <a target="_blank" href="https://css-loaders.com/">https://css-loaders.com/</a></h2>
<p><strong>Useful for</strong>: Getting simple loading animations.</p>
<p>This is a <strong>handy resource</strong> for finding and customizing simple, ready-to-use CSS loading animations. It offers a wide variety of pre-built loaders, from simple spinners to more complex animations, all made with pure CSS. You can preview the animations, tweak the code, and easily copy it into your project to keep users engaged while content loads.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738416506731/a7daccee-f286-41f6-ad8a-e1ac95299968.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-9-pure-css-icons-httpscssgghttpscssgg">9. Pure CSS Icons: <a target="_blank" href="https://css.gg/">https://css.gg/</a></h2>
<p><strong>Useful for</strong>: Adding scalable icons to projects without the hassle of managing image files or external libraries. It’s perfect for anyone looking for a lightweight, customizable icon solution.</p>
<p>This is a <strong>minimalist icon library</strong> built entirely with CSS. It offers over 700 customizable, open-source icons that are lightweight and easy to use in your projects. Each icon is designed with pure CSS, meaning no images or external dependencies are required. You can easily copy the code, adjust the size and color, and integrate the icons seamlessly into your website or app.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738412869850/7aae4f3e-c89b-4e7e-8e8a-1f6eda23f1bf.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-10-css-filters-httpswwwcssfilterscohttpswwwcssfiltersco">10. CSS filters: <a target="_blank" href="https://www.cssfilters.co/">https://www.cssfilters.co/</a></h2>
<p><strong>Useful for</strong>: Applying and testing cool effects to images using CSS filters.</p>
<p>This is a <strong>visual playground</strong> for experimenting with CSS filter effects. It lets you apply and customize filters like blur, grayscale, brightness, and contrast directly on an image, showing the results in real time. Once you’ve tweaked the effects to your liking, you can grab the CSS code and use it in your own projects. It’s a simple and fun way to add creative touches to your images without needing any design software.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1738410839558/fdb9467d-f688-4480-a25f-31df48f6c264.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-thanks-for-reading">Thanks for reading! ⭐</h2>
<p>I hope you found this list helpful! You can bookmark and share with others. If you have any other CSS tools you consistently use, you can add it in the comments below!</p>
]]></content:encoded></item><item><title><![CDATA[Development Limitations That UI Designers Should Know About]]></title><description><![CDATA[Reality Check
You've wrapped up your design, and it looks amazing, sleek, clean, and exactly how you envisioned it. You’re excited to see it come to life and watch users interact with your thoughtfully crafted interface and the features. But then, la...]]></description><link>https://blog.maryojo.me/development-limitations-that-ui-designers-should-know-about</link><guid isPermaLink="true">https://blog.maryojo.me/development-limitations-that-ui-designers-should-know-about</guid><category><![CDATA[UI Design]]></category><category><![CDATA[development]]></category><category><![CDATA[Frontend Development]]></category><category><![CDATA[ux design]]></category><dc:creator><![CDATA[Mary Ojo]]></dc:creator><pubDate>Sun, 12 Jan 2025 14:00:30 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1752570291549/da845103-cfd1-4dee-9ea3-624bff2af8b2.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-reality-check">Reality Check</h1>
<p>You've wrapped up your design, and it looks amazing, sleek, clean, and exactly how you envisioned it. You’re excited to see it come to life and watch users interact with your thoughtfully crafted interface and the features. But then, launch day comes, and you're left wondering: is this even the same design I worked on, or did the developers decide to remix it?</p>
<p>This article sheds light on common challenges that arise during development and what designers need to know about them. Understanding these aspects will help you create UI designs that are practical to implement, reducing the risk of disappointment.</p>
<p>As a Frontend Engineer with experience in both UI/UX design and development, I’ve encountered this issue firsthand and understand why it happens sometimes. In this article, I’ll explain the reasons behind these implementation gaps and share tips to help designers navigate this process more effectively.</p>
<h1 id="heading-introduction">Introduction</h1>
<p>The interaction between design and development has changed a lot in modern web applications. Designers can’t just work on their own anymore; technical limitations and opportunities need to be considered from the very start. This does not mean limiting creativity, but about making smarter decisions that lead to better user experiences, while giving room for technical considerations.</p>
<p>When designers get a handle on things like component structure and how performance and security affects the design, they can be creative while still making sure it’s doable. It also helps designers and developers work together better, shifting the conversation from "Can we even do this?" to "What’s the best way to make this happen?"</p>
<p>The following highlghts are key technical factors UI designers should know about to create digital experiences that are not just creative and usable but also practical and functional.</p>
<h3 id="heading-cross-browserplatform-compatibility-amp-rendering-differences"><strong>Cross-Browser/Platform Compatibility &amp; Rendering Differences</strong></h3>
<ul>
<li><p><strong>Advanced CSS Styling Differences:</strong> Some advanced CSS features can behave differently depending on the browser that is being used. This applies to some CSS grid features and how it is handled or if it’s even recognized in some older browsers. This would affect a design trend like bento grid which relies heavily on CSS grids.</p>
</li>
<li><p><strong>Form Elements:</strong> Native form elements (like the checkboxes, radio buttons, dropdowns, checkboxes, sliders, etc) can look and work differently between browsers and operating systems. Custom styling helps to keep things consistent but sometimes, overriding default styling is harder or easier also based on the browser type.</p>
</li>
<li><p><strong>Fonts and Typography</strong>: Depending on the browser, fonts can look a bit different because of how some font properties are handled. Also custom fonts can look a bit off or act unpredictably across different devices and browsers. An example is when the font <strong>"Roboto"</strong> is used with a specified font-weight of <code>300</code> for headings, this is what happens on different browsers:</p>
<ul>
<li><p><strong>Chrome (Windows):</strong> The font renders as expected, light and clean due to Chrome's font rendering and anti-aliasing settings.</p>
</li>
<li><p><strong>Firefox (Windows):</strong> The font appears slightly bolder compared to Chrome, as Firefox uses different anti-aliasing methods that emphasize clarity over weight precision.</p>
</li>
<li><p><strong>Safari (Mac):</strong> The font looks sharper but slightly thinner because Safari tends to favor macOS’s native font smoothing.</p>
</li>
</ul>
</li>
<li><p><strong>Color Display and Manangement:</strong> Colors might appear a bit different because there’s no universal color management across all browsers. Colors sometimes vary based on the device’s color profile. e.g an AMOLED display on Android might make the color appear more saturated than an LCD display on an older iPhone.</p>
</li>
</ul>
<h3 id="heading-performance-issues"><strong>Performance Issues</strong></h3>
<ul>
<li><p><strong>Animations:</strong> Complex animations or those with high frame rates might cause lag on older browsers or devices with lower power.</p>
</li>
<li><p><strong>Heavy Graphics:</strong> Large images, SVGs, or videos can slow down load times and might even cause the browser to crash. Always keep performance in mind.</p>
</li>
</ul>
<h3 id="heading-challenges-with-responsiveness"><strong>Challenges with Responsiveness</strong></h3>
<ul>
<li><p><strong>Breakpoints:</strong> Complex design makes development more complicated escpecially when considering that it has to fit across a lot of different breakpoints (like different tablets and small phones).</p>
</li>
<li><p><strong>Scaling Issues:</strong> Designs that are created to look perfect at a specific size (a fixed size inside Figma) might not adapt well to other screen sizes or resolutions. For example, elements could appear too small on a larger screen or too cramped on a smaller one if responsiveness isn’t considered during the design process.</p>
</li>
<li><p><strong>Images</strong>: In designing for responsiveness, one image might not be adequate for all screen sizes.</p>
</li>
</ul>
<h3 id="heading-scalability-and-maintenance"><strong>Scalability and Maintenance</strong></h3>
<ul>
<li><p><strong>Over-customization:</strong> Highly unique or custom designs can be tough to maintain or update over time.</p>
</li>
<li><p><strong>Reusable Components:</strong> Designs that don’t follow consistent patterns might not fit well into the already existing reusable component strategy usually done by developers. This is why it's important to work with a component library or design system</p>
</li>
</ul>
<h3 id="heading-state-management-complexity"><strong>State Management Complexity</strong></h3>
<ul>
<li><p><strong>Dynamic States:</strong> Designs that include complex UI states like multi-step forms or dynamic filters can be challenging to implement without causing bugs or slowdowns.</p>
</li>
<li><p><strong>Error Handling:</strong> Things like error states, validation, and loading indicators sometimes get overlooked in designs, but they’re key to providing an overall smooth experience for users.</p>
</li>
</ul>
<h3 id="heading-backend-and-api-constraints"><strong>Backend and API Constraints</strong></h3>
<ul>
<li><p><strong>Data Availability:</strong> If your design depends on specific data, like real-time updates or detailed analytics, it’s important to know whether the backend can support those needs.</p>
</li>
<li><p><strong>Performance Implications:</strong> Features like infinite scrolling or heavy data visualizations can put a lot of pressure on APIs and databases, which might affect performance.</p>
</li>
<li><p><strong>Security Implications:</strong> Features like infinite scrolling or heavy data visualizations can put a lot of pressure on APIs and databases, which might affect performance.</p>
</li>
</ul>
<h3 id="heading-content-and-localization"><strong>Content and Localization</strong></h3>
<ul>
<li><p><strong>Text Lengths:</strong> When designing for multilingual sites, remember that translations can sometimes be longer than the original text. If this isn’t planned for, it can break the interface layout.</p>
</li>
<li><p><strong>Dynamic Content:</strong> Placeholder/fixed text (usually done in Figma) is often much shorter than real content. If you don’t design with actual content  in mind (for both short and long text), it might end up in unexpected layout issues like text overflow.</p>
</li>
</ul>
<h2 id="heading-tips-for-practical-ui-designs"><strong>Tips for Practical UI Designs</strong></h2>
<p>The following tips help in ensuring that your designs translate well into code while maintaining functionality and performance:</p>
<ol>
<li><p>Design with modularity in mind: Think in reusable components. Instead of designing every button, card, or input from scratch, create a library of consistent, modular elements. This makes it easier for developers to replicate your designs across different pages or features. It also makes it easy for design to create interfaces. This is called a component library and a more detailed approach would be creating a design system which is made up of the design styles, component library, pattern library and interface elements.</p>
</li>
<li><p>Provide Layout Fallbacks: Not every browser or device will support complex layouts perfectly. Design alternative versions that adapt gracefully to technical constraints. An example is if a CSS Grid-based layout fails in implementation, ensure a flexbox or block-based fallback still delivers a readable and functional experience.</p>
</li>
<li><p>Provide Font Fallbacks: Custom fonts might not always load or render as expected. Provide or specify alternative system fonts to ensure your typography remains visually appealing and legible. On the frontend this is usually handled like by specifying in CSS like this - "Roboto", "Helvetica Neue", Arial, sans-serif.</p>
</li>
<li><p>Optimize Assets: Provide developers with optimized images, SVGs, and font files to improve performance and loading speed. Offer different image sizes (e.g., 1x, 2x, 3x) for responsive designs, and ensure SVGs are cleaned to remove unnecessary metadata (e.g an unwanted background or really small overlooked part).</p>
</li>
<li><p>Account for Edge Cases that go beyond the “ideal” scenario. Think about how your design will handle edge cases like extremely long user names or input values, empty states where no data is available, unexpected user behaviors, such as clicking buttons multiple times.</p>
</li>
<li><p>Design Loading and Error States: Include visuals for loading indicators, error messages, and empty states. These are sometimes overlooked but are critical for a seamless user experience.</p>
</li>
<li><p>Provide a Prototype: Interactive prototypes help developers understand your vision beyond static screens. Prototypes help to demonstrate how transitions, animations, and interactions should work. It also helps you as a designer to connect the flow step-by-step, which could help identify implementation issues and missing steps of the user flows.</p>
</li>
<li><p>Provide Animation Fallbacks: Animations can elevate user experience, but not all devices or browsers handle them well. Provide fallback designs for scenarios where animations can’t run smoothly.</p>
</li>
<li><p>Preview Designs Across Devices: Test your designs on various devices to identify potential issues early. This ensures your designs look and function as intended everywhere. This could be done by using the Figma's Preview and Figma Mirror after designing.</p>
</li>
<li><p>Design for Breakpoints Responsive design is essential. Define how your layout adapts across screen sizes by creating breakpoints for mobile, tablet, and desktop views. Test that the design works for the defined breakpoints. For example a breakpoint of </p>
</li>
</ol>
<p>By following these practices, you’ll make your designs more practical for development, reduce back-and-forth, and create a better experience for both users and developers.</p>
<p>To developers, mention other limitations you would like designers to know about in the comments!</p>
<h2 id="heading-credits">Credits</h2>
<p>Cover image from <a target="_blank" href="https://uxdworld.com/20-famous-design-memes-to-make-you-laugh/">https://uxdworld.com/20-famous-design-memes-to-make-you-laugh/</a></p>
]]></content:encoded></item><item><title><![CDATA[Create a Loader with Infinite Movement using Framer Motion]]></title><description><![CDATA[Difficulty: ⭐️ (1/5 stars)
Setup/Prerequisites: React.js, TailwindCSS, Framer Motion
Key Concepts: Using infinite animation in Framer Motion
The Challenge
Day 2 is a simple loader which shows infinite animation by bouncing. This animation is quite si...]]></description><link>https://blog.maryojo.me/create-a-loader-with-infinite-movement-using-framer-motion</link><guid isPermaLink="true">https://blog.maryojo.me/create-a-loader-with-infinite-movement-using-framer-motion</guid><category><![CDATA[React]]></category><category><![CDATA[framer-motion]]></category><category><![CDATA[#MICROINTERACTIONS]]></category><category><![CDATA[animation]]></category><dc:creator><![CDATA[Mary Ojo]]></dc:creator><pubDate>Sat, 30 Nov 2024 16:26:50 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1732983718615/bb1c24a4-6954-4677-9c3c-9423d01718bc.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><strong>Difficulty</strong>: ⭐️ (1/5 stars)</p>
<p><strong>Setup/Prerequisites</strong>: React.js, TailwindCSS, Framer Motion</p>
<p><strong>Key Concepts</strong>: Using infinite animation in Framer Motion</p>
<h2 id="heading-the-challenge">The Challenge</h2>
<p>Day 2 is a simple loader which shows infinite animation by bouncing. This animation is quite simple but shows how Framer Motion handles infinite movements which is commonly used on loaders.</p>
<h2 id="heading-key-animation-features">Key Animation Features</h2>
<ul>
<li><p><em>Infinity movement</em></p>
</li>
<li><p>Easing function for a more natural movement</p>
</li>
</ul>
<h2 id="heading-code-breakdown">Code Breakdown</h2>
<h3 id="heading-1-implementation-details">1. Implementation Details</h3>
<p>The ball is added first before going on to implement the infinite state and adding animations.</p>
<p>The animation happens in three main steps:</p>
<ol>
<li><p>Wrap the ball image component with a <code>motion.div</code> element instead of directly applying motion to the image element to separate it’s styling.</p>
</li>
<li><p>Identify the states. There is only one state here - which is the infinite movement. The <code>loaderVariants</code> object is where this state is defined.</p>
</li>
<li><p>Specifying the transition type: The ininite movement and how it happens is defined in the transition property. Here, on the y-axis, I’m using the <code>repeatType</code> and <code>repeat</code> to create the infinite movement and the <code>duration</code> to define how fast this movement would be.</p>
<pre><code class="lang-plaintext">   y: {
         repeatType: "mirror",
         repeat: Infinity,
         duration: 0.5,
      }
</code></pre>
</li>
</ol>
<h3 id="heading-2-adding-the-image">2. Adding the Image</h3>
<pre><code class="lang-tsx">import { easeOut, motion } from "framer-motion";
import logoo from "../assets/image.png";
import grass from "../assets/grass.png";

const InfiniteLoader = () =&gt; {
  return (
    &lt;div className="h-screen w-screen flex flex-col items-center justify-center afcad-flux"&gt;
      &lt;motion.div&gt;
        &lt;img src={logoo} className="w-16 h-16" /&gt;
      &lt;/motion.div&gt;
      &lt;div&gt;
        &lt;img src={grass} className="h-24 " /&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  );
};

export default InfiniteLoader;
</code></pre>
<h3 id="heading-3-defining-the-animations-using-code">3. Defining the Animations Using Code</h3>
<p>In the <code>loaderVariants</code> object, the infinite state which has been previously identified is defined.</p>
<p>💡Remember to use gentle transitions</p>
<pre><code class="lang-tsx">  const loaderVariants = {
    infiniteState: {
      y: [50, -50],
      transition: {
        y: {
          repeatType: "mirror",
          repeat: Infinity,
          duration: 0.7,
          easing: easeOut,
        },
      },
    },
  };
</code></pre>
<h2 id="heading-live-demo">Live Demo</h2>
<iframe src="https://s7fn6d-5173.csb.app/infinite-spinner-01" style="width:100%;height:400px;border:0;border-radius:4px;overflow:hidden;background:#fff" sandbox="allow-presentation allow-same-origin allow-scripts"></iframe>

<h2 id="heading-resources-used">Resources Used</h2>
<ul>
<li><a target="_blank" href="https://www.youtube.com/watch?v=uxjMjXNZV_4">Youtube tutorial by Framer Motion</a></li>
</ul>
<h2 id="heading-ideas-for-enhancement">Ideas for Enhancement ✨</h2>
<p>What animation ideas do you suggest I add to this? I’m thinking of these:</p>
<ul>
<li><p>Adding sound effects</p>
</li>
<li><p>Testing out other kinds of images, shapes and movement</p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Create an Animated Scaling Button using Framer Motion (Motion for React)]]></title><description><![CDATA[Difficulty: ⭐️ (1/5 stars)
Setup/Prerequisites: React.js, TailwindCSS, Framer Motion
Key Concepts: Using animate, whileHover, whileTap and variants in Framer Motion
The Challenge
Since today is day 1, I’m starting with a simple animation - a button t...]]></description><link>https://blog.maryojo.me/create-an-animated-scaling-button-using-framer-motion</link><guid isPermaLink="true">https://blog.maryojo.me/create-an-animated-scaling-button-using-framer-motion</guid><category><![CDATA[framer-motion]]></category><category><![CDATA[framer]]></category><category><![CDATA[React]]></category><category><![CDATA[projects]]></category><dc:creator><![CDATA[Mary Ojo]]></dc:creator><pubDate>Fri, 15 Nov 2024 16:00:39 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1731608021091/0c0fcbce-38f6-449d-b67b-f4031c0597e4.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><strong>Difficulty</strong>: ⭐️ (1/5 stars)</p>
<p><strong>Setup/Prerequisites</strong>: React.js, TailwindCSS, Framer Motion</p>
<p><strong>Key Concepts</strong>: Using animate, whileHover, whileTap and variants in Framer Motion</p>
<h2 id="heading-the-challenge">The Challenge</h2>
<p>Since today is day 1, I’m starting with a simple animation - a button that scales on hover and tap. This animation is quite simple but shows core Framer Motion concepts like variants and gesture animations.</p>
<h2 id="heading-key-animation-features">Key Animation Features</h2>
<ul>
<li><p><em>Smooth</em> scale animation on hover</p>
</li>
<li><p><em>Slight</em> scale reduction on click/tap</p>
</li>
<li><p><em>Subtle</em> shadow animation</p>
</li>
<li><p>Spring animation for natural movement</p>
</li>
</ul>
<p>Some things you should take note of in these highlighted features are the italicized words and that’s because animations work best when they are used just in the right amount and in the right places - they should feel natural🤗</p>
<h2 id="heading-code-breakdown">Code Breakdown</h2>
<h3 id="heading-1-implementation-details">1. Implementation Details</h3>
<p>The button is created first before going on to implement the different states and adding animations.</p>
<p>The animation happens in three main steps:</p>
<ol>
<li><p>Wrap the button component with a <code>motion.div</code> element instead of directly applying motion to the button element to separate it’s styling.</p>
</li>
<li><p>Identify the states. Looking at the key animation features, there are 3 defined states I could get. The <code>buttonVariants</code> object is where the states are defined:</p>
<ul>
<li><p><code>initial</code>: The button's default state and styling</p>
</li>
<li><p><code>hover</code>: The state where the button scales up and adds shadow on hover</p>
</li>
<li><p><code>tap</code>: In this state, the button slightly scales down when clicked/tapped</p>
</li>
</ul>
</li>
<li><p>Specifying the transition type: This defines how the button changes from one state to another. Here I’m using the spring transition which creates a bouncy, natural feel. The other properties related to the ‘spring’ transition are also set to properly add the mild transition effect.</p>
<ul>
<li><p><code>stiffness: 400</code> makes the animation “snap“</p>
<p>  The value here usually ranges from 0 to 1000, with higher values making the animation more rigid, while lower values make it softer and slower.</p>
</li>
<li><p><code>damping: 10</code> This adds a slight bounce</p>
<p>  For damping the value ranges from 0 to 100, with higher values make the animation settle faster, while lower values create more bounce.</p>
</li>
</ul>
</li>
</ol>
<h3 id="heading-2-coding-the-animated-button">2. Coding the Animated Button</h3>
<pre><code class="lang-tsx">import { motion } from "framer-motion";

export default function AnimatedButton() {
  return (
    &lt;div className="flex min-h-screen items-center justify-center bg-gray-100"&gt;
      &lt;motion.div
        variants={buttonVariants}
        initial="initial"
        whileHover="hover"
        whileTap="tap"
      &gt;
        &lt;button className="bg-blue-500 px-6 py-2 text-white"&gt;
          Hover Me
        &lt;/button&gt;
      &lt;/motion.div&gt;
    &lt;/div&gt;
  );
}
</code></pre>
<h3 id="heading-3-defining-the-animations-using-code">3. Defining the Animations Using Code</h3>
<p>In the <code>buttonVariants</code> object, the different states which have been previously identified are defined using the styling specific to each state.</p>
<p>💡Remember to use subtle shadows</p>
<pre><code class="lang-tsx">const buttonVariants = {
  initial: {
    scale: 1,
    boxShadow: "0px 0px 0px rgba(0,0,0,0.2)",
  },
  hover: {
    scale: 1.1,
    boxShadow: "0px 5px 15px rgba(0,0,0,0.2)",
    transition: {
      type: "spring",
      stiffness: 400,
      damping: 10
    }
  },
  tap: {
    scale: 0.95,
    boxShadow: "0px 2px 5px rgba(0,0,0,0.2)",
  }
};
</code></pre>
<h2 id="heading-live-demo">Live Demo</h2>
<iframe src="https://s7fn6d-5173.csb.app/animated-button-01" style="width:100%;height:200px;border:0;border-radius:4px;overflow:hidden;background:#fff" sandbox="allow-presentation allow-same-origin allow-scripts"></iframe>

<h2 id="heading-key-takeaways">Key Takeaways</h2>
<ul>
<li><p>Spring animations feel more natural than linear ones like for interface elements.</p>
</li>
<li><p>Small scale changes (like 0.95-1.1) are often more realistic.</p>
</li>
<li><p>Combining scale with mild shadow creates a great three-dimensional effect.</p>
</li>
</ul>
<h2 id="heading-resources-used">Resources Used</h2>
<ul>
<li><p><a target="_blank" href="https://www.framer.com/motion/gestures/">Framer Motion Gestures Documentation</a></p>
</li>
<li><p><a target="_blank" href="https://www.framer.com/motion/transition/">Spring Animation Documentation</a></p>
</li>
</ul>
<h2 id="heading-ideas-for-enhancement">Ideas for Enhancement ✨</h2>
<p>What animation ideas do you suggest I add to this button? I’m thinking of these:</p>
<ul>
<li><p>Adding sound effects for interaction</p>
</li>
<li><p>Creating different variants for different button states (loading, success and error)</p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Building SOLID React Apps]]></title><description><![CDATA[Introduction
SOLID is a set of object-oriented design principles. These principles establish practices for developing classes in object-oriented programming.

The SOLID principles aims to serve one purpose which is to create reusable, maintainable, f...]]></description><link>https://blog.maryojo.me/building-solid-react-apps</link><guid isPermaLink="true">https://blog.maryojo.me/building-solid-react-apps</guid><category><![CDATA[React]]></category><category><![CDATA[Beginner Developers]]></category><dc:creator><![CDATA[Mary Ojo]]></dc:creator><pubDate>Tue, 28 May 2024 10:02:26 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1715807527966/a03d611b-f921-4d33-8bd2-553787d8423f.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introduction">Introduction</h2>
<p>SOLID is a set of object-oriented design principles. These principles establish practices for developing classes in object-oriented programming.</p>
<blockquote>
<p>The SOLID principles aims to serve one purpose which is to create reusable, maintainable, flexible and easy-to-understand code in order to facilitate collaborative software development.</p>
</blockquote>
<p>Despite being created for object-oriented programming, the principles of SOLID can be applied in React applications, although they may manifest slightly differently due to the nature of React being a library for building user interfaces rather than a strict object-oriented programming paradigm. In this article, you would see how each SOLID principle can be applied in the context of React.</p>
<h3 id="heading-s-single-responsibility-principle-srp">S - Single Responsibility Principle (SRP):</h3>
<p>Components should have a single responsibility. Separate concerns such as rendering, state management, and data fetching into different components or hooks to keep each component focused and maintainable.</p>
<p>For example, a Product Card component on an eCommerce website responsible for rendering product information (name, image, description) should only handle rendering the product and not perform unrelated tasks such as fetching data or component actions (e.g. on button click). Container components which sit above presentational components like ProductCard should handle data fetching, application logic, and pass down the data as props to presentational components.</p>
<p>From the image below, <a target="_blank" href="https://gist.github.com/maryojo/0c8f146a4ac28de768161a6c0906a453">the code at the top</a>, violates SRP because it has two concerns in the component code:</p>
<ul>
<li><p>Displaying product details</p>
</li>
<li><p>Handling cart interactions (adding the product and managing errors).</p>
</li>
</ul>
<p>The <a target="_blank" href="https://gist.github.com/maryojo/7740f3dbf1fae3371fd77fa38312aeff">corrected code</a> shows separated functionalities:</p>
<ul>
<li><p>The ProductCard now renders only product information (presentational information).</p>
</li>
<li><p>The parent/container component handles interactions and other actions related to the children components.</p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716017914167/5b7b3735-37ac-4ce0-9546-fe110db5f9c2.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-o-openclosed-principle-ocp">O - Open/Closed Principle (OCP):</h3>
<p>You should be able to extend the behavior of a component without needing to directly modify its source code. Use higher-order components (HOCs), composition or props to customize and extend the behavior of components rather than modifying their internals directly. This is closely related to the first principle.</p>
<p>Still using the <code>ProductCard</code> component, the first part of the image shows the component which violates the OCP principle, this makes it hard to reuse the <code>ProductCard</code> across the application because it now has a local <code>handleAddCart</code> function which cannot be customized.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716017003485/27030696-8df1-43a2-a369-c5255037b319.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-l-liskov-substitution-principle-lsp">L - Liskov Substitution Principle (LSP):</h3>
<p>This principle emphasizes that objects (components in this case) of a superclass should be replaceable with objects of its subclasses without causing unexpected behavior. Create reusable components with well-defined props that can be easily substituted for one another in different parts of the application.</p>
<p>An example of this is a basic <code>Button</code> component that renders a button with a label and onClick handler. You then create a derived component <code>PrimaryButton</code> that inherits from <code>Button</code> and adds styles for a primary style button.</p>
<p>The first image which violates LSP, shows how the <code>PrimaryButton</code> directly modifies the props passed to the Button component - adding a style attribute. If another component expects a plain <code>Button</code> without styles and uses <code>PrimaryButton</code> as a replacement, it might break the UI due to unexpected styling.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716018536609/6dffe870-6513-43bb-9ec7-d44c9802241d.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-i-interface-segregation-principle-isp">I - Interface Segregation Principle (ISP):</h3>
<p>The I in SOLID stands for the Interface Segregation Principle. This principle emphasizes that instead of having large, monolithic interfaces(props), it's better to break them down into smaller, more specific interfaces. This allows for greater flexibility and reduces the burden on classes (components) that implement these interfaces.</p>
<p>React heavily utilizes components, and interfaces(props) define the way components can interact with each other. ISP emphasizes that avoid passing large prop objects to components. Instead, break down props into smaller, more specific ones that components can use independently. The example below shows how the Interface Segregation Principle can be applied in React:</p>
<p>A <code>ProductCard</code> component that displays product information and allows users to add the product to their cart. Initially, you define a single interface, <code>ProductProps</code>, that includes all functionalities:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716890256667/42380948-6f5c-45d5-9d89-b0812f2e35e1.png" alt class="image--center mx-auto" /></p>
<p>This interface serves the <code>ProductCard</code> component well. However, what if you want to reuse the product information display functionality (name, price, image) in another component, say a <code>ProductSearchList</code> component that displays a list of products? In this case, the <code>ProductSearchList</code> component doesn't need the <code>addToCart</code> functionality.</p>
<p>Following the Interface Segregation Principle, you can split the original <code>ProductProps</code> interface into two smaller ones:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716890370166/1b49f82a-534f-4293-9a3b-7a945f4b92f5.png" alt class="image--center mx-auto" /></p>
<p>Now, the <code>ProductCard</code> component can implement both <code>ProductInfoProps</code> and <code>AddToCartProps</code>, while the <code>ProductSearchList</code> component only needs to implement <code>ProductInfoProps</code>. This promotes better code reusability and reduces the dependencies between components.</p>
<p>Consider using ISP for components with multiple, distinct functionalities and potential for future growth.</p>
<h3 id="heading-d-dependency-inversion-principle-dip">D - Dependency Inversion Principle (DIP):</h3>
<p>Avoid tight coupling between components by using dependency injection, context, or props drilling to pass dependencies down the component tree. Favor abstractions and interfaces over concrete implementations to decouple components and make them easier to test and maintain.</p>
<p>An example of how the DIP in React is this: Imagine you have a <code>ProductCard</code> component that fetches product data from a hardcoded API endpoint within the component itself. This creates tight coupling between the component and the specific data source.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1716019285713/ab632cb3-7bbf-40f0-87b5-10223268db73.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-summary">Summary</h2>
<p>While React may not be strictly object-oriented, the principles of SOLID can still guide you in writing cleaner, more maintainable React applications by encouraging modular, decoupled, and reusable component designs.</p>
<p>Though originally intended for object-oriented programming, the core concepts translate well to React's component-based structure.</p>
]]></content:encoded></item><item><title><![CDATA[Building a Portfolio Website: Free Resources and Templates for Frontend Developers]]></title><description><![CDATA[As a frontend developer, your portfolio is very important and would go a long way in showing potential employers or clients your frontend skillset in areas like responsive design, accessibility and website optimisation.
Getting Started

Building from...]]></description><link>https://blog.maryojo.me/building-a-portfolio-website-free-resources-and-templates-for-frontend-developers</link><guid isPermaLink="true">https://blog.maryojo.me/building-a-portfolio-website-free-resources-and-templates-for-frontend-developers</guid><category><![CDATA[portfolio]]></category><category><![CDATA[Frontend Development]]></category><category><![CDATA[frontend]]></category><category><![CDATA[free resources]]></category><dc:creator><![CDATA[Mary Ojo]]></dc:creator><pubDate>Sat, 23 Mar 2024 06:23:20 GMT</pubDate><content:encoded><![CDATA[<p>As a frontend developer, your portfolio is very important and would go a long way in showing potential employers or clients your frontend skillset in areas like responsive design, accessibility and website optimisation.</p>
<h2 id="heading-getting-started">Getting Started</h2>
<ul>
<li><p><strong>Building from scratch:</strong> When you build a portfolio website from scratch, you get to have full control over it and show off all your development skills. Using Static Site Generators (SSGs) like Gatsby.js makes this process even easier. Gatsby uses GraphQL to connect your website to different sources of information without needing you to deal with complicated setups. This helps you manage your projects and blog content smoothly. Plus, Gatsby makes sure your website runs fast, which helps it rank higher in search engines and gives users a better experience when they visit. I built my portfolio using Gatsby.js. But if you prefer other SSGs like Hugo or Jekyll, they're also good options. And if you want to have complete control, you can build your portfolio using HTML, CSS, and JavaScript or other JavaScript libraries you're familiar with.</p>
</li>
<li><p><strong>Using free templates</strong>: Leveraging free templates provides a convenient starting point for your portfolio website. These templates offer pre-designed layouts and styles, saving you time and effort in the initial setup. With a variety of options available, you can easily find a template that aligns with your aesthetic preferences and showcases your work effectively. Additionally, free templates often come with built-in responsiveness and compatibility across different devices, ensuring a seamless user experience. While using free templates may limit customization to some extent, they offer a practical solution for quickly establishing a professional online presence without the need for extensive coding knowledge or design skills.</p>
</li>
</ul>
<h2 id="heading-free-templates-and-resources">Free Templates and Resources</h2>
<h3 id="heading-website-templates">Website templates</h3>
<ul>
<li><p><a target="_blank" href="https://themewagon.com/theme-tag/html5-css3/?swoof=1&amp;paged=1&amp;pa_price=free&amp;really_curr_tax=422-product_tag">Themewagon</a>: This website offers a wide collection of both free and paid modern website templates which can be downloaded and easily customized. You can sort based on website type, frameworks used to build the website.</p>
</li>
<li><p><a target="_blank" href="https://html5up.net/">HTML5Up</a>: HTML5Up is another good resource. They provide sleek website templates that look modern. These templates are built using basic tools like HTML5 and CSS3, making them easy to customize and use for your own projects.</p>
</li>
<li><p><a target="_blank" href="https://colorlib.com/wp/templates/">Colorlib</a>: Colorlib offers contemporary website templates that are not only stylish but also conveniently available in HTML, CSS, and Bootstrap formats.</p>
</li>
</ul>
<p>Building a portfolio with a free template is a straightforward process. Typically, you'll download the template, edit the content to showcase your projects and skills, and customize the design to fit your style (based on the possible customizations of the templates which is usually in a README.md file).</p>
<h3 id="heading-hosting">Hosting</h3>
<p>When it comes to free hosting options for your website, 3 great platforms are GitHub Pages, Vercel, and Netlify.</p>
<ul>
<li><p><a target="_blank" href="https://pages.github.com/">Github pages</a>: With Github Pages, you to host static websites directly from your GitHub repositories. It's straightforward to set up and use, making it an excellent choice for hosting simple projects or personal portfolios.</p>
</li>
<li><p><a target="_blank" href="https://vercel.com/">Vercel</a>: Vercel specializes in hosting modern web projects, including static sites, Jamstack applications, and serverless functions. With its easy to use deployment process and advanced features, Vercel is a popular choice among developers for hosting frontend projects.</p>
</li>
<li><p><a target="_blank" href="https://www.netlify.com/">Netlify</a>: Netlify offers a comprehensive platform for hosting static sites and web applications. It provides features like continuous deployment, serverless functions, and form handling, all with an easy-to-use interface. Netlify's generous free tier makes it an attractive option for developers looking to host their projects</p>
</li>
</ul>
<h3 id="heading-domain">Domain</h3>
<ul>
<li><a target="_blank" href="https://www.freenom.com/en/index.html?lang=en">Freenom</a>: Freenom offers a variety of domain extensions like .tk, .ml, .ga, .cf, and .gq, which you can register at no cost for a set period of time. While these domains may not be as traditional as .com or .net, they are still viable options for personal projects or experimentation. Freenom's user-friendly interface and straightforward registration process make it a good choice for obtaining a free domain name for your personal projects.</li>
</ul>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Your portfolio is essential as a frontend developer to display your skills effectively. You have the option to either build it from scratch using tools like Gatsby.js or use free templates from platforms mentioned above. Hosting services like GitHub Pages, Vercel, and Netlify provide reliable free hosting, while Freenom offers free domain names to enhance professionalism. By making use of these complimentary resources and platforms, you can craft a standout portfolio that showcases your frontend development prowess and creativity.</p>
]]></content:encoded></item><item><title><![CDATA[Using the Github API in your React application]]></title><description><![CDATA[Prerequisites:
Knowledge about the following is required to better understand this guide:

Node.js and npm:

Ensure you have Node.js installed on your machine. You can download it from the official Node.js website.

Verify its installation by running...]]></description><link>https://blog.maryojo.me/using-the-github-api-in-your-react-application</link><guid isPermaLink="true">https://blog.maryojo.me/using-the-github-api-in-your-react-application</guid><category><![CDATA[GitHub]]></category><category><![CDATA[Git]]></category><category><![CDATA[React]]></category><category><![CDATA[APIs]]></category><dc:creator><![CDATA[Mary Ojo]]></dc:creator><pubDate>Fri, 12 Jan 2024 20:04:44 GMT</pubDate><content:encoded><![CDATA[<h2 id="heading-prerequisites">Prerequisites:</h2>
<p>Knowledge about the following is required to better understand this guide:</p>
<ol>
<li><p>Node.js and npm:</p>
<ul>
<li><p>Ensure you have Node.js installed on your machine. You can download it from the <a target="_blank" href="https://nodejs.org/">official Node.js website</a>.</p>
</li>
<li><p>Verify its installation by running npm -v in your terminal.</p>
</li>
</ul>
</li>
<li><p>React application: This guide assumes that you have correctly setup your React application using create-react-app or vite.</p>
</li>
<li><p>A Github account: You can signup here</p>
</li>
<li><p>A personal access token from your Github account:</p>
<p> Generate a personal access token by following these steps:</p>
<ul>
<li><p>Go to your GitHub settings.</p>
</li>
<li><p>Navigate to "Developer settings" &gt; "Personal access tokens."</p>
</li>
<li><p>Click on "Generate token" and follow the instructions.</p>
<p>  <strong>Note</strong>: Keep your token secure and do not share it publicly.</p>
</li>
</ul>
</li>
</ol>
<h2 id="heading-step-1-understanding-the-github-api">Step 1: Understanding the Github API</h2>
<p>The Github API is used for different types of data related to a Github user. It provides a wide range of functionalities that allow users to interact with various aspects of the GitHub platform programmatically. Some common actions that can be performed using the GitHub API include:</p>
<ul>
<li><p><strong>Retrieve User Information</strong>: fetch details about a GitHub user, including their profile information, repositories, and activities(commits, stars, and followers).</p>
</li>
<li><p><strong>Manage Repositories:</strong></p>
<p>  Create new repositories, list repositories a user owns or has access to. Get information about a specific repository, including its branches, contributors, and issues.</p>
</li>
<li><p><strong>Issues and Pull Requests:</strong></p>
<p>  List issues and pull requests for a repository. Create, close, or comment on issues and pull requests.</p>
</li>
<li><p><strong>Gists:</strong></p>
<p>  Create, list, and manage GitHub Gists (small snippets of code or notes).</p>
</li>
<li><p><strong>Organization Information:</strong></p>
<p>  Retrieve details about GitHub organizations, including members, repositories, and teams.</p>
</li>
<li><p><strong>Search:</strong></p>
<p>  Perform advanced searches for repositories, users, and code.</p>
</li>
<li><p><strong>Notifications:</strong></p>
<p>  Get information about a user's notifications and mark them as read.</p>
</li>
<li><p><strong>Webhooks:</strong></p>
<p>  Set up and manage webhooks to receive notifications about events happening in a repository.</p>
</li>
<li><p><strong>Deployments:</strong></p>
<p>  Access information about deployments for a repository.</p>
</li>
<li><p><strong>Actions:</strong></p>
<p>  Trigger GitHub Actions workflows programmatically.</p>
</li>
</ul>
<p>To learn more about the Github API, visit <a target="_blank" href="https://docs.github.com/en/rest">Github's documentation.</a> For this tutorial, the focus would be on fetching a user's realtime activity.</p>
<h2 id="heading-step-2-setting-up-the-github-api">Step 2: Setting up the Github API</h2>
<p>The following are the steps to take to set up the Github API and fetch a users activity data:</p>
<ul>
<li><p>Install the GitHub client package</p>
<pre><code class="lang-bash">  npm i @octokit/rest
</code></pre>
</li>
<li><p>Store token in .env file</p>
<p>  Create a file called .env and store the token gotten from Github. This file should be placed in the root</p>
<pre><code class="lang-bash">  REACT_APP_GITHUB_TOKEN = <span class="hljs-string">"RandomStringsGottenFromGithub"</span>
</code></pre>
</li>
<li><p>Fetch data using endpoint</p>
<p>  NOTE: Excluding the Authorization token from the request only gives you access to data that is publicly available.</p>
<pre><code class="lang-javascript">  <span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
  <span class="hljs-keyword">import</span> { Octokit } <span class="hljs-keyword">from</span> <span class="hljs-string">"@octokit/rest"</span>;

  <span class="hljs-keyword">const</span> fetchGithubActivityData = <span class="hljs-keyword">async</span> () =&gt; {
      <span class="hljs-keyword">try</span> {
        <span class="hljs-keyword">const</span> octokit = <span class="hljs-keyword">new</span> Octokit({
          <span class="hljs-attr">auth</span>: process.env.REACT_APP_GITHUB_TOKEN,
        });

        <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> octokit.request(<span class="hljs-string">"GET /users/{username}/events"</span>, {
          <span class="hljs-attr">username</span>: <span class="hljs-string">"{username}"</span>,
          <span class="hljs-attr">headers</span>: {
            <span class="hljs-attr">accept</span>: <span class="hljs-string">"application/vnd.github+json"</span>,
            <span class="hljs-string">"X-GitHub-Api-Version"</span>: <span class="hljs-string">"2022-11-28"</span>,
          },
          <span class="hljs-attr">per_page</span>: <span class="hljs-number">8</span>,
        });
        <span class="hljs-keyword">return</span> response.data;

      } <span class="hljs-keyword">catch</span> (e) {
        <span class="hljs-built_in">console</span>.log(e);
      }
    };
</code></pre>
</li>
<li><p>Use data in user interface as required:</p>
<p>  The data retrieved from the GET users event (activity) endpoint shows an array of a users recent activity. Github categorizes users activity into 17 events which have been further described <a target="_blank" href="https://docs.github.com/en/rest/using-the-rest-api/github-event-types?apiVersion=2022-11-28#createevent">here</a>.</p>
<p>  The data shows event type, repository, repository url, user activity on repository among a lot of other information which can be used in the UI as desired.</p>
<p>  Take note that without the 'auth' key in the request only public user activities are retrieved</p>
</li>
<li><p>Consider loading and error states</p>
</li>
</ul>
<h2 id="heading-rate-limiting">Rate Limiting</h2>
<p>The number of requests a user can make at a given time is controlled bby Github. For unauthenticated requests, the rate limit is 60 requests per hour, while for authenticated users, there's a personal rate limit of 5,000 requests per hour.</p>
<h2 id="heading-more-resources">More resources</h2>
<ul>
<li><p><a target="_blank" href="https://docs.github.com/en/rest/using-the-rest-api/getting-started-with-the-rest-api?apiVersion=2022-11-28">Github API documentation</a></p>
</li>
<li><p><a target="_blank" href="https://www.npmjs.com/package/octokit">Octokit npm package</a></p>
</li>
<li><p><a target="_blank" href="https://docs.github.com/en/rest/using-the-rest-api/rate-limits-for-the-rest-api?apiVersion=2022-11-28">Rate limiting</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Gatsby.js or Create React App?]]></title><description><![CDATA[Introduction
In this article, I will be making a comparison between Gatsby and Create React App(CRA) to help you decide which is better for your project. These two are part of the most popular tools used to build React-based applications.
What is Gat...]]></description><link>https://blog.maryojo.me/gatsbyjs-or-create-react-app</link><guid isPermaLink="true">https://blog.maryojo.me/gatsbyjs-or-create-react-app</guid><category><![CDATA[Gatsby]]></category><category><![CDATA[React]]></category><category><![CDATA[create-react-app]]></category><category><![CDATA[portfolio]]></category><dc:creator><![CDATA[Mary Ojo]]></dc:creator><pubDate>Wed, 17 May 2023 23:06:39 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1684361607202/f4ad0c13-5ab0-4153-8009-ec2a28d96d0b.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introduction">Introduction</h2>
<p>In this article, I will be making a comparison between Gatsby and Create React App(CRA) to help you decide which is better for your project. These two are part of the most popular tools used to build React-based applications.</p>
<h3 id="heading-what-is-gatsbyjs">What is Gatsby.js?</h3>
<p><a target="_blank" href="https://www.gatsbyjs.com/">Gatsby</a> is a static site generator that is built using React as a framework. It uses React for the user interface and <a target="_blank" href="https://graphql.org/">GraphQL</a> for data querying &amp; management. It is built with <strong>performance</strong> and <strong>scalability</strong> in mind, and it offers many features out of the box that can speed up development, such as image optimization and the use of plugins. With Gatsby, you can create websites that are both fast and friendly to search engines, which is important if you want people to find your website easily.</p>
<h3 id="heading-what-is-create-react-app">What is Create React App?</h3>
<p><a target="_blank" href="https://create-react-app.dev/">Create React App</a> is a command-line tool that is used to set up a basic React application with only the minimal configuration required. It is a simple and lightweight solution for building React applications. With CRA, you can quickly get started building a React application without worrying about any extra configurations.</p>
<h2 id="heading-things-to-consider">Things to consider</h2>
<h3 id="heading-performance">Performance</h3>
<p>Performance is one of the biggest benefits of Gatsby. This is because Gatsby uses server-side rendering (SSR) to generate static HTML pages, which are served instantly to the user, resulting in faster page load times. In addition to this, Gatsby automatically optimizes images and other website assets, which further improves performance. CRA, on the contrary, does not use SSR and requires more configuration to optimize performance.</p>
<h3 id="heading-functionality">Functionality</h3>
<p>Gatsby and Create React App significantly differ in terms of their core functionalities. Gatsby functions as a static site generator, whereas Create React App serves as a development tool. Gatsby generates static HTML and assets during the build process, while Create React App dynamically generates and serves your application at runtime. This fundamental difference influences the types of web applications each tool is best suited for.</p>
<p>Static web applications, like those built with Gatsby, focus on displaying pre-built content to visitors. These websites are constructed using HTML, CSS, and JavaScript, with the displayed content remaining fixed and unchanging. Examples of static web applications include blogs and portfolios, where the primary purpose is to present information to users.</p>
<p>Conversely, dynamic web applications, which are better built with Create React App, are built to deliver more personalized content to users based on how they interact with the site. These applications leverage server-side scripting, databases, and APIs to provide content that is tailored to each user's specific needs. E-commerce websites are a good example of dynamic web applications, as they dynamically update product listings, shopping carts, and user account information based on real-time interactions.</p>
<p>If your project primarily involves presenting pre-built content without much interactivity, Gatsby's static site generation capabilities make it an ideal choice. However, if you require a highly interactive and personalized web application that dynamically updates content based on user interactions, Create React App would be better.</p>
<h3 id="heading-data-management">Data Management</h3>
<p>Another key difference between Gatsby and CRA is their approach to data management. Gatsby uses GraphQL, a query language for APIs, to fetch and manage data. This makes it easy to pull data from various conventional and even unconventional sources like Airtable and incorporate it into your website. Create React App, on the other hand, leaves data management up to you. You'll need to set up your own data fetching and management system, which can be time-consuming and complicated.</p>
<h3 id="heading-development-approach">Development Approach</h3>
<p>CRA provides just a basic React application structure without any additional features which offer a simpler, more familiar development experience for developers who prefer a "development from scratch" approach. This approach has its own benefits - you have complete control over the project structure and configuration. Meanwhile, Gatsby provides a more structured development experience, with many built-in features and a plugin system that can provide additional functionality to the site. It also offers many features out of the box that can speed up development, such as image optimization and pre-fetching. It also has a large collection of plugins and themes that can further enhance your web application's functionality.</p>
<h2 id="heading-how-to-determine-which-is-better-for-your-project">How to determine which is better for your project</h2>
<p>To determine the most suitable tool for building your application, consider asking yourself the following questions:</p>
<ol>
<li><p><strong>Do you want to build a static site or a dynamic web application?</strong></p>
<p> As explained earlier, Gatsby is designed for static web applications that don't require a lot of dynamic content. If you're building a simple blog or portfolio site, Gatsby is a great option while Create React App is better suited for dynamic web applications that require a lot of interactivity and real-time updates like E-commerce websites.</p>
</li>
<li><p><strong>What is your development plan or approach?</strong></p>
<p> It is essential to consider your project's specific requirements and your development preferences. Create React App helps developers make customised configurations from scratch. However, it is worth noting that this customization process can require a deeper understanding of the underlying tools and build configurations. If your project needs a more streamlined development experience without extensive configuration, Gatsby might be a more suitable choice as it also provides a pre-configured setup and a comprehensive set of features, reducing the initial setup complexity and allowing you to focus more on the content and functionality of your website.</p>
</li>
<li><p><strong>What is your data management approach?</strong></p>
<p> Gatsby uses GraphQL (a query language for APIs) to fetch and manage data. This makes it easy to pull data from different sources and incorporate it into your website. Meanwhile, you will need to set up data fetching &amp; management in your Create React App, which can be complicated. Some more questions to ask yourself regarding this are:</p>
<ul>
<li><p>Are you familiar with GraphQL and prefer its data querying capabilities?</p>
</li>
<li><p>Are you willing to set up your own data fetching and management system?</p>
</li>
</ul>
</li>
<li><p><strong>Is SEO important to your project?</strong></p>
<p> Gatsby is designed to be SEO-friendly out of the box. It automatically generates optimized HTML and meta tags, which can help your website rank higher in search engine results. Create React App, on the other hand, requires manual configuration to ensure good SEO practices.</p>
</li>
<li><p><strong>What is your project deployment approach?</strong></p>
<p> Due to Gatsby's static site generation, it is easier to deploy your website to a static web hosting service, such as Netlify, Github Pages or Vercel. Create React App, on the other hand, needs a server to run, which means you will need to deploy it to a hosting service that supports server-side rendering, like Heroku.</p>
</li>
</ol>
]]></content:encoded></item><item><title><![CDATA[Overriding & Extending Global styles in Chakra UI]]></title><description><![CDATA[What is Chakra UI
Chakra UI is an open-source library of pre-built user interface components that simplifies web development for developers by allowing them to create functional websites quickly and easily without writing custom CSS or HTML code. The...]]></description><link>https://blog.maryojo.me/overriding-extending-global-styles-in-chakra-ui</link><guid isPermaLink="true">https://blog.maryojo.me/overriding-extending-global-styles-in-chakra-ui</guid><category><![CDATA[Chakra-ui]]></category><category><![CDATA[React]]></category><category><![CDATA[TypeScript]]></category><category><![CDATA[Frontend Development]]></category><dc:creator><![CDATA[Mary Ojo]]></dc:creator><pubDate>Fri, 28 Apr 2023 09:44:54 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1682677589555/778f437f-4dfc-474b-9159-697ccb142e8e.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-what-is-chakra-ui">What is Chakra UI</h2>
<p>Chakra UI is an open-source library of pre-built user interface components that simplifies web development for developers by allowing them to create functional websites quickly and easily without writing custom CSS or HTML code. These components, such as buttons, forms, and modals, are customizable and follow accessibility, usability, and responsive design best practices, making them user-friendly and accessible.</p>
<p>Chakra UI works well with popular front-end frameworks such as React and Next.js, but it can also be integrated with other tools and libraries. Although it provides several React-specific features, it is still built on top of CSS and HTML, allowing its CSS styles and components to be used with non-React web frameworks.</p>
<p>However, some of Chakra UI's features may not work optimally with non-React web frameworks. For example, its responsive design system relies on React's useState hook to detect screen size, so it may not work as expected without React. Additionally, Chakra UI's theming system relies on emotion, a CSS-in-JS library, so it may not work as expected.</p>
<h2 id="heading-benefits-of-chakra-ui">Benefits of Chakra UI</h2>
<ul>
<li><p>Theming system: With ChakraUI, you can easily customize the look and feel of your application. This means you can quickly and easily change the colour scheme, typography, and other design elements of your site to suit your style guide without having to rewrite any code.</p>
</li>
<li><p>Accessibility: Chakra UI is designed with accessibility in mind, and it provides several accessibility features out of the box. For example, all components have proper aria attributes, the keyboard navigation is supported, and the colour contrast ratios comply with <a target="_blank" href="https://www.w3.org/TR/WCAG21/">WCAG 2.1 guidelines</a>. This ensures that websites built using Chakra UI are user-friendly and accessible to everyone.</p>
</li>
<li><p>Use of best practices: Chakra UI is designed to follow best practices in accessibility, usability, and responsive design.</p>
</li>
<li><p>Performance: Best practices integrated into this library ensure your application runs quickly and efficiently. Chakra UI uses a modern and lightweight design system based on <a target="_blank" href="https://www.styled-components.com/">styled-components</a>. This allows the library to avoid heavy dependencies and ensures the CSS code is optimized for performance.</p>
</li>
<li><p>Extensive features: Lazy loading and code splitting are part of the unique features ChakraUI gives developers access to. These features help to reduce the amount of code that needs to be loaded and executed by the browser, which can significantly improve page load times.</p>
</li>
</ul>
<h2 id="heading-global-styles-in-chakraui">Global Styles in ChakraUI</h2>
<p>Since ChakraUI is built with a theming system, <a target="_blank" href="https://chakra-ui.com/docs/styled-system/theme">default styling</a> exists for all components and elements in the library. This can help ensure consistency in the appearance and behaviour of your UI components.</p>
<p>This tutorial will guide you through the process of modifying the <a target="_blank" href="https://chakra-ui.com/docs/styled-system/theme">default ChakraUI styling</a> of any React application utilising this library by extending or overriding the global styles provided.</p>
<h2 id="heading-how-to-modify-global-styles-in-chakra-ui">How to modify Global Styles in Chakra UI</h2>
<h3 id="heading-the-project">The Project</h3>
<p>To demonstrate how to modify ChakraUI, I'll be building a simple one-page website containing an <a target="_blank" href="https://www.frontendmentor.io/challenges/order-summary-component-QlPmajDUj">Order summary component</a> as shown in the image below.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1682506839029/86822bde-3acd-4286-871c-3f0de19245f3.jpeg" alt class="image--center mx-auto" /></p>
<h3 id="heading-setting-up-chakraui">Setting up ChakraUI</h3>
<p>In React.js, there are two ways to install ChakraUI:</p>
<p><strong>a. In a new folder:</strong></p>
<ul>
<li>Simply run the following command in terminal</li>
</ul>
<pre><code class="lang-bash">npx create-react-app &lt;APPNAME&gt; --template @chakra-ui
</code></pre>
<p><strong>b. Or, in a newly installed create-react-app:</strong></p>
<ul>
<li><p>Install react app</p>
<pre><code class="lang-bash">  npx create-react-app &lt;APPNAME&gt;
  <span class="hljs-built_in">cd</span> &lt;APPNAME&gt;
</code></pre>
</li>
<li><p>Inside the project directory, run the following in the terminal</p>
<pre><code class="lang-bash">  npm i @chakra-ui/react @emotion/react @emotion/styled framer-motion
</code></pre>
</li>
<li><p>Setup Provider: You need to set up the <code>ChakraProvider</code> at the root of your application. This should be in your <code>index.js</code> file</p>
<pre><code class="lang-javascript">  <span class="hljs-comment">//index.js file</span>
  <span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
  <span class="hljs-keyword">import</span> ReactDOM <span class="hljs-keyword">from</span> <span class="hljs-string">"react-dom/client"</span>;
  <span class="hljs-keyword">import</span> <span class="hljs-string">"./index.css"</span>;

  <span class="hljs-comment">// 1. import `ChakraProvider` component</span>
  <span class="hljs-keyword">import</span> { ChakraProvider } <span class="hljs-keyword">from</span> <span class="hljs-string">"@chakra-ui/react"</span>;
  <span class="hljs-keyword">import</span> App <span class="hljs-keyword">from</span> <span class="hljs-string">"./App"</span>;

  <span class="hljs-comment">// 2. Wrap ChakraProvider at the root of your app</span>
  <span class="hljs-keyword">const</span> root = ReactDOM.createRoot(<span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"root"</span>));
  root.render(
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">React.StrictMode</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">ChakraProvider</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">App</span> /&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">ChakraProvider</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">React.StrictMode</span>&gt;</span></span>
  );
</code></pre>
</li>
</ul>
<h3 id="heading-using-chakrauis-default-styling">Using ChakraUI's default styling</h3>
<ul>
<li><p>I setup the project and developed it using CharaUI's default styling and this is what the frontend code looks like <a target="_blank" href="https://github.com/maryojo/order-summary-chakra-tutorial/blob/d0a00421de81a43760e93c0ba547d033c1adf658/src/App.js">https://github.com/maryojo/order-summary-chakra-tutorial/blob/d0a00421de81a43760e93c0ba547d033c1adf658/src/App.js</a></p>
</li>
<li><p>Result: <a target="_blank" href="https://644b7458337d8467791f868c--lambent-llama-1b74cc.netlify.app/">https://644b7458337d8467791f868c--lambent-llama-1b74cc.netlify.app/</a></p>
</li>
</ul>
<h3 id="heading-modifying-global-styles-in-chakraui">Modifying global styles in ChakraUI</h3>
<p>Theming in Chakra UI follows the <a target="_blank" href="https://styled-system.com/theme-specification/">Styled System Theme Specification</a> approach, where a theme object defines the application’s colour palette, font, breakpoints, spacing, and more.</p>
<p>To modify the existing codebase to suit the application's theme, we'll be overriding the default font family and colours of some components</p>
<ul>
<li><p>Create a file named <code>Theme.js</code> in the <code>src</code> folder</p>
</li>
<li><p>Import <code>extendTheme</code> module in <code>Theme.js</code> file</p>
<pre><code class="lang-javascript">  <span class="hljs-comment">//Theme.js file</span>
  <span class="hljs-comment">//1. Import extendTheme</span>
  <span class="hljs-keyword">import</span> { extendTheme } <span class="hljs-keyword">from</span> <span class="hljs-string">"@chakra-ui/react"</span>;
</code></pre>
</li>
<li><p>Create a <code>theme</code> object which would contain the formatted styles as shown below:</p>
<pre><code class="lang-javascript">  <span class="hljs-comment">//Theme.js file</span>
  <span class="hljs-comment">//1. Import extendTheme</span>
  <span class="hljs-keyword">import</span> { extendTheme } <span class="hljs-keyword">from</span> <span class="hljs-string">"@chakra-ui/react"</span>;

  <span class="hljs-comment">//2. Theme object containing custom styling</span>
  <span class="hljs-keyword">const</span> themes = {
    <span class="hljs-attr">styles</span>: {
      <span class="hljs-attr">global</span>: {
        <span class="hljs-string">'html, body'</span>: {
          <span class="hljs-attr">backgroundColor</span>: <span class="hljs-string">'hsl(225, 100%, 94%)'</span>,
          <span class="hljs-attr">fontFamily</span>: <span class="hljs-string">`'Red Hat Display', sans-serif`</span>,
        },
        <span class="hljs-attr">a</span>: {
          <span class="hljs-attr">color</span>: <span class="hljs-string">'hsl(245, 75%, 52%)'</span>,
        },
        <span class="hljs-attr">h1</span>: {
          <span class="hljs-attr">color</span>: <span class="hljs-string">'hsl(245, 75%, 52%)'</span>,
          <span class="hljs-attr">fontSize</span>: <span class="hljs-string">'64px'</span>,
           <span class="hljs-attr">lineHeight</span>: <span class="hljs-string">'80px'</span>,
        },
      },
    },
  }
</code></pre>
</li>
<li><p>Export theme</p>
<pre><code class="lang-javascript">  <span class="hljs-comment">//Theme.js file</span>
  <span class="hljs-comment">//1. Import extendTheme</span>
  <span class="hljs-keyword">import</span> { extendTheme } <span class="hljs-keyword">from</span> <span class="hljs-string">"@chakra-ui/react"</span>;

  <span class="hljs-comment">//2. Theme object containing custom styling</span>
  <span class="hljs-keyword">const</span> themes = {
    <span class="hljs-attr">styles</span>: {
      <span class="hljs-attr">global</span>: {
        <span class="hljs-string">'html, body'</span>: {
          <span class="hljs-attr">backgroundColor</span>: <span class="hljs-string">'hsl(225, 100%, 94%)'</span>,
          <span class="hljs-attr">fontFamily</span>: <span class="hljs-string">`'Red Hat Display', sans-serif`</span>,
        },
        <span class="hljs-attr">a</span>: {
          <span class="hljs-attr">color</span>: <span class="hljs-string">'hsl(245, 75%, 52%)'</span>,
        },
        <span class="hljs-attr">h1</span>: {
          <span class="hljs-attr">color</span>: <span class="hljs-string">'hsl(245, 75%, 52%)'</span>,
          <span class="hljs-attr">fontSize</span>: <span class="hljs-string">'64px'</span>,
           <span class="hljs-attr">lineHeight</span>: <span class="hljs-string">'80px'</span>,
        },
      },
    },
  }
  <span class="hljs-comment">//3. Export theme</span>
  <span class="hljs-keyword">const</span> theme = extendTheme(themes);
  <span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> theme;
</code></pre>
</li>
<li><p>Call the theme as a prop in ChakraProvider in the index.js file</p>
<pre><code class="lang-javascript">   <span class="hljs-comment">//index.js file</span>
   <span class="hljs-keyword">import</span> React <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;
   <span class="hljs-keyword">import</span> ReactDOM <span class="hljs-keyword">from</span> <span class="hljs-string">"react-dom/client"</span>;
   <span class="hljs-keyword">import</span> <span class="hljs-string">"./index.css"</span>;
</code></pre>
</li>
</ul>
<p>import theme from Theme;</p>
<p>// 1. import <code>ChakraProvider</code> component import { ChakraProvider } from "@chakra-ui/react"; import App from "./App";</p>
<p>// 2. Wrap ChakraProvider at the root of your app const root = ReactDOM.createRoot(document.getElementById("root")); root.render( &lt;React.StrictMode&gt; &lt;/React.StrictMode&gt; ); ```</p>
<h3 id="heading-final-result">Final result</h3>
<p>Any more custom styling could be added to the Theme.js file in the format shown. ChakraUI's styling could also be used to create custom styles for components.</p>
<p>Code: <a target="_blank" href="https://github.com/maryojo/order-summary-chakra-tutorial/blob/main/src/App.js">https://github.com/maryojo/order-summary-chakra-tutorial</a></p>
<p>Live site: <a target="_blank" href="https://lambent-llama-1b74cc.netlify.app/">https://lambent-llama-1b74cc.netlify.app/</a></p>
<h3 id="heading-further-steps">Further steps</h3>
<p>Read more about ChakraUI's global styles from the <a target="_blank" href="https://chakra-ui.com/docs/styled-system/global-styles">documentation</a></p>
]]></content:encoded></item><item><title><![CDATA[Web accessibility: Semantics]]></title><description><![CDATA[Introduction
Accessibility matters even on the web!
The goal of web accessibility is to ensure that everyone has equal access to information, services, and a good user experience irrespective of their abilities or disabilities. Web accessibility refe...]]></description><link>https://blog.maryojo.me/web-accessibility-semantics</link><guid isPermaLink="true">https://blog.maryojo.me/web-accessibility-semantics</guid><category><![CDATA[HTML5]]></category><category><![CDATA[HTML]]></category><category><![CDATA[Accessibility]]></category><category><![CDATA[Web Development]]></category><dc:creator><![CDATA[Mary Ojo]]></dc:creator><pubDate>Sat, 22 Apr 2023 11:23:06 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1682159856698/16ee72e8-e3d2-463b-b198-9454b66d5049.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introduction">Introduction</h2>
<p>Accessibility matters even on the web!</p>
<p>The goal of web accessibility is to ensure that everyone has equal access to information, services, and a good user experience irrespective of their <strong>abilities</strong> or <strong>disabilities</strong>. Web accessibility refers to measures taken to ensure that all individuals inclusive of those with disabilities can access and use websites and digital content <strong>with ease</strong>. To achieve this, websites should be created in a way that is perceivable, operable, understandable, and robust, providing access for everyone. This approach fosters inclusivity and equal opportunities for all users.</p>
<h3 id="heading-semantics">Semantics</h3>
<p>The word 'semantic' means the study of the meaning of language. It helps to ensure that communication is clear and accurate by providing context and meaning to language. In the same vein, semantic HTML is the use of HTML markup in a way that accurately conveys the meaning and purpose of the content on a web page. Semantic HTML is a backbone for web accessibility. It is how accessibility is incorporated into websites.</p>
<h3 id="heading-why-do-we-need-semantic-web-content">Why do we need Semantic web content?</h3>
<ul>
<li><p>It adds meaning to your HTML content, which lets web browsers, search engines, screen readers, RSS readers, and ultimately users understand it and easily navigate and interact.</p>
</li>
<li><p>It improves SEO. Semantic HTML makes it easier for search engines to understand the flow and content of a page. This makes your website easier to discover.</p>
</li>
<li><p>Code written in semantic HTML makes it easier for other developers to maintain and update.</p>
</li>
</ul>
<h2 id="heading-using-semantic-html">Using Semantic HTML</h2>
<p>There are 2 major ways to give HTML content more meaning.</p>
<ol>
<li><h3 id="heading-the-proper-use-of-html-tags">The proper use of HTML tags</h3>
<p> The proper use of HTML tags is crucial for providing structure and meaning to web content, making it easily understandable to both humans and machines. <strong>It is essential to use HTML tags in a semantically correct manner, where they accurately reflect the content and purpose of the element they are applied to.</strong></p>
<p> For instance, it is semantically correct to use the <code>&lt;h1&gt;</code> tag to mark up the main heading of a web page. In contrast, using a <code>&lt;div&gt;</code> tag with a large font size is not semantically correct and should be avoided.</p>
<p> By using HTML tags correctly, web content becomes more accessible to users with disabilities. An example is using the <code>&lt;img&gt;</code> tag to include alternative text descriptions for images helps users with visual impairments understand the content of the image. Similarly, using the <code>&lt;label&gt;</code> tag with form elements such as text inputs and checkboxes makes it easier for screen reader users to understand the purpose of the form element and how to interact with it.</p>
<p> In addition to the <code>&lt;h1&gt;</code>, <code>&lt;img&gt;</code>, and <code>&lt;label&gt;</code> tags, several other semantic HTML tags are commonly used to provide structure and meaning to web content.</p>
<p> The <code>&lt;nav&gt;</code> tag is used to mark up the navigation section of a web page, while the <code>&lt;article&gt;</code> tag is used to define a self-contained piece of content, such as a blog post or news article. The <code>&lt;header&gt;</code> and <code>&lt;footer&gt;</code> tags are used to define the header and footer sections of a web page, respectively. The <code>&lt;main&gt;</code> tag is used to define the main content of a web page, while the <code>&lt;aside&gt;</code> tag is used to define content that is tangentially related to the main content, such as a sidebar or a call-to-action section.</p>
<p> Using these tags correctly helps to make web content more accessible and understandable for all users, including those with disabilities. A comprehensive list of semantic HTML tags and their uses can be found on <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element">the MDN website</a>, which provides a reference for web developers to follow when creating accessible and semantically correct web content.</p>
</li>
<li><h3 id="heading-aria-attributes">ARIA attributes</h3>
<p> ARIA stands for Accessible Rich Internet Applications. These attributes are a set of <a target="_blank" href="https://www.w3schools.com/html/html_attributes.asp">HTML attributes</a> used to define accessibility features for web content. Assistive technologies such as screen readers use the additional information provided by ARIA attributes. ARIA attributes can be used along with semantic HTML tags or whenever semantic HTML cannot be used. ARIA attributes can be used to provide additional information about the elements on a web page, specifically in four ways:</p>
</li>
<li><ul>
<li><p><strong>Roles</strong>: ARIA roles define the type of element and its purpose. For example, an element can have a <code>role="button"</code> to indicate that it is a clickable button.</p>
<ul>
<li><p><strong>States</strong>: ARIA states describe the current state of an element. These states can be combined with ARIA roles and properties to provide a more complete picture of the accessibility and functionality of elements on a web page. An example is an element with <code>aria-expanded="true"</code> to indicate that it is currently expanded.</p>
</li>
<li><p><strong>Properties</strong>: ARIA properties provide additional information about an element. For example, an element can have aria-level="3" to indicate that it is a heading at level 3.</p>
</li>
<li><p><strong>Labels</strong>: ARIA labels provide a way to associate a visible label with an element that is not visible or has an ambiguous label. For example, an icon that represents a trash bin can have aria-label="Delete" to indicate its function.</p>
</li>
</ul>
</li>
</ul>
</li>
</ol>
<p>This <a target="_blank" href="https://developer.mozilla.org/en-US/docs/web/Accessibility/ARIA/Attributes">webpage</a> provides a list of all ARIA roles, properties, states and labels, which have been defined by W3C (the organization that develops web standards).</p>
<h3 id="heading-example-showing-the-use-of-aria-attributes">Example showing the use of ARIA attributes</h3>
<pre><code class="lang-xml"><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en"</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"UTF-8"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>About Us<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>

  <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">role</span>=<span class="hljs-string">"banner"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>About Us<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">nav</span> <span class="hljs-attr">role</span>=<span class="hljs-string">"navigation"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">role</span>=<span class="hljs-string">"menu"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">role</span>=<span class="hljs-string">"menuitem"</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/"</span> <span class="hljs-attr">role</span>=<span class="hljs-string">"link"</span>&gt;</span>Home<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">role</span>=<span class="hljs-string">"menuitem"</span> <span class="hljs-attr">aria-current</span>=<span class="hljs-string">"page"</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/about"</span> <span class="hljs-attr">role</span>=<span class="hljs-string">"link"</span>&gt;</span>About<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">role</span>=<span class="hljs-string">"menuitem"</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/contact"</span> <span class="hljs-attr">role</span>=<span class="hljs-string">"link"</span>&gt;</span>Contact Us<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">nav</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

  <span class="hljs-tag">&lt;<span class="hljs-name">main</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">role</span>=<span class="hljs-string">"region"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>Our Mission<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">role</span>=<span class="hljs-string">"paragraph"</span>&gt;</span>Lorem ipsum dolor sit amet, consectetur              adipiscing elit. Aliquam auctor nisl eget augue laoreet vestibulum. Sed sit amet orci bibendum, tincidunt ex ac, euismod velit. <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">main</span>&gt;</span>

<span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<h2 id="heading-testing-web-semantics-using-accessibility-tools-and-resources">Testing web semantics using accessibility tools and resources</h2>
<p>There are many tools and resources which range from simple web browser extensions to accessibility testing suites that help developers create semantic and accessible web content for all users.</p>
<h3 id="heading-tools">Tools</h3>
<ol>
<li><p>HTML validators:</p>
<p> HTML validators check the syntax and validity of HTML code and report any errors or warnings. They can help identify and fix issues that may affect the accessibility of web content, such as missing or incorrect attributes, nested elements, or deprecated elements.</p>
<ul>
<li><p>Online HTML validation tools: An example is <a target="_blank" href="https://validator.w3.org/">The W3C Markup Validation Service</a>, this validator checks the markup validity of web documents in HTML, XHTML, etc. It supports HTML5, SVG 1.1, etc. It can validate by URI, file upload, or direct input.</p>
</li>
<li><p>HTML Validation IDE settings: Some Integrated Development Environments (IDEs), such as <a target="_blank" href="https://www.rj-texted.se/index.html">RJTextEd</a>, have built-in HTML validators that can be used to validate HTML code.</p>
</li>
<li><p>HTML validation extensions: In cases whereby the IDE does not have a built-in HTML validator, extensions like <a target="_blank" href="https://htmlhint.com/">HTMLHint</a> which is available for VSCode could be installed.</p>
</li>
</ul>
</li>
<li><p>Screen reader emulators:</p>
<p> By using a screen reader emulator, developers can test their web content and ensure that it is properly structured and labelled with the appropriate HTML tags. A screen reader emulator can help developers ensure that their web content is compatible with popular screen readers like JAWS, ChromeVox, NVDA, and VoiceOver. Some examples are:</p>
<ul>
<li><p><a target="_blank" href="https://stackoverflow.com/questions/43340690/is-there-an-online-emulating-screen-reader-tool-to-test-against-a-custom-web-pag">WebAnywhere</a>: This is a web-based screen reader that works from any browser without installation. It can read aloud web pages and provide keyboard navigation. It is free and open source.</p>
</li>
<li><p><a target="_blank" href="https://silktide.com/resources/toolbar/">Silktide Disability Toolbar</a>: This is a Chrome extension that allows you to experience your website with a range of simulated disabilities, including blindness and partial sightedness. It also has a screen reader simulator that can read aloud text and navigate with keyboard or mouse. It is free to use.</p>
</li>
</ul>
</li>
<li><p>Accessibility testing tools:</p>
<ul>
<li><p>The <a target="_blank" href="https://wave.webaim.org/">WAVE Web Accessibility Evaluation Tool</a>, which is a free web browser extension can help identify accessibility issues on a web page.</p>
</li>
<li><p><a target="_blank" href="https://developer.chrome.com/docs/lighthouse/overview/">Lighthouse</a>, which can be used in Chrome DevTools, from the command line, or as a Node module. It generates a report on how well the web page did in terms of performance, accessibility, and more and then provides suggestions for improvement.</p>
</li>
</ul>
</li>
</ol>
<h3 id="heading-resources">Resources</h3>
<p>In addition to tools, there are also many online resources available.</p>
<ul>
<li><p>The <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element">MDN doc</a> mentioned above.</p>
</li>
<li><p>The <a target="_blank" href="https://www.w3.org/WAI/standards-guidelines/wcag/">Web Content Accessibility Guidelines</a> (WCAG) by the World Wide Web Consortium (W3C).</p>
</li>
<li><p>The <a target="_blank" href="https://www.w3.org/WAI/ARIA/apg/">ARIA Authoring Practices Guide</a>, which guides on how to use ARIA attributes to improve the accessibility of web content.</p>
</li>
<li><p><a target="_blank" href="https://html.spec.whatwg.org/dev/">The HTML Living Standard</a></p>
</li>
</ul>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Web accessibility is a critical aspect of development that ensures everyone can access and use digital content. Semantic HTML is one of the fundamental building blocks of web accessibility, as it provides structure and meaning to web content. Using HTML tags in a semantically correct way is important because it helps both humans and machines understand the purpose and function of different elements on a web page. In addition to using semantic HTML tags, developers can utilize ARIA attributes to further enhance web accessibility. These attributes can define roles, states, properties, and labels for elements on a web page, making it easier for users with disabilities to interact with web content.</p>
<p>To create more accessible web content, developers and designers can use a variety of tools and resources available online. By prioritizing web accessibility in their development or design practices, they can help ensure that everyone has equal access to digital content.</p>
]]></content:encoded></item><item><title><![CDATA[Create an image analysis app using Azure Computer Vision with React App]]></title><description><![CDATA[Introduction
In this tutorial, I will be creating a simple image recognition app in order to explain how to integrate Azure Computer Vision into client-side applications. You could also adapt the steps here to build similar applications using other s...]]></description><link>https://blog.maryojo.me/create-an-image-analysis-app-using-azure-computer-vision-with-react-app</link><guid isPermaLink="true">https://blog.maryojo.me/create-an-image-analysis-app-using-azure-computer-vision-with-react-app</guid><category><![CDATA[React]]></category><category><![CDATA[Azure]]></category><category><![CDATA[Artificial Intelligence]]></category><category><![CDATA[images]]></category><category><![CDATA[JavaScript]]></category><dc:creator><![CDATA[Mary Ojo]]></dc:creator><pubDate>Thu, 18 Aug 2022 18:38:09 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1660353728372/zsAsFX9xu.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introduction">Introduction</h2>
<p>In this tutorial, I will be creating a simple image recognition app in order to explain how to integrate Azure Computer Vision into client-side applications. You could also adapt the steps here to build similar applications using other services in Azure Computer Vision.</p>
<p><strong>Prerequisites:</strong> Knowledge of React.js, An Azure account (you can get it free <a target="_blank" href="https://azure.microsoft.com/en-us/free/">here</a>), Github, Hosting service e.g. Netlify</p>
<p><strong>Links:</strong> <a target="_blank" href="https://github.com/maryojo/react-azurevision-demo">Code</a> <a target="_blank" href="https://nimble-griffin-90126f.netlify.app/">Live Site</a></p>
<h2 id="heading-steps">Steps:</h2>
<h3 id="heading-step-1-create-and-setup-react-app-then-install-dependencies">Step 1. Create and setup React App, then install dependencies</h3>
<ul>
<li>Start by creating the react project:</li>
</ul>
<pre><code class="lang-plaintext">npx create-react-app &lt;APP_NAME&gt;
cd &lt;APP_NAME&gt;
</code></pre>
<ul>
<li><p>Delete unused default files in boilerplate e.g. App.test.js, App.css</p>
</li>
<li><p>Install Azure Computer Vision &amp; MS Rest Azure npm package</p>
</li>
</ul>
<pre><code class="lang-plaintext">npm i @azure/ms-rest-azure-js  @azure/cognitiveservices-computervision
</code></pre>
<h3 id="heading-step-2-setup-resources-on-azure">Step 2. Setup resources on Azure</h3>
<ul>
<li><p>Log in to the <a target="_blank" href="https://portal.azure.com">Azure Portal</a></p>
</li>
<li><p><a target="_blank" href="https://portal.azure.com/#create/Microsoft.CognitiveServicesComputerVision">Create a new Computer Vision</a> resource in Azure</p>
</li>
<li><p>Fill out the form with the required information</p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1660847365710/_xSbPM7Lz.png" alt="Azure Computer Vision setup" /></p>
</li>
<li><p>Click on 'Review+Create'</p>
</li>
<li><p>The screen below shows after the resource has been deployed</p>
</li>
<li><p>Click on manage keys to copy the API key and endpoint</p>
</li>
</ul>
<h3 id="heading-step-3-add-azure-details-to-the-local-react-app">Step 3. Add Azure details to the local React App</h3>
<ul>
<li><p>In the react app root folder, create a new file called <em>.env</em> to store Azure access information in your local environment i.e. <code>&lt;APP_NAME&gt;/.env</code></p>
</li>
<li><p>Open the .gitignore file and add <code>.env</code> to the list</p>
</li>
<li><p>Open the .env file and save the API key and endpoint here</p>
</li>
</ul>
<pre><code class="lang-plaintext">// &lt;APP_NAME&gt;/.env
REACT_APP_apiKey = &lt;YOUR_API_KEY&gt;
REACT_APP_endPoint = &lt;YOUR_ENDPOINT&gt;
</code></pre>
<ul>
<li>In the terminal, run the command <code>npm start</code> to view the app in your browser</li>
</ul>
<h3 id="heading-step-4-creating-the-azure-vision-component">Step 4. Creating the Azure Vision Component</h3>
<ul>
<li><p>Create a new folder called <em>components</em> in <code>./src</code></p>
</li>
<li><p>Create a new file called <em>AzureVisionService.js</em></p>
</li>
<li><p>In the new file, copy and paste the code below, it contains information for requesting from the API. The documentation to better understand this part of the code is <a target="_blank" href="https://westus.dev.cognitive.microsoft.com/docs/services/computer-vision-v3-2/operations/56f91f2e778daf14a499f21f">here</a>. The <code>describeImage</code> method used is one of the available Azure Vision API methods. It describes an image with complete English sentences. Another similar method is the <code>analyzeImage</code> method which extracts a rich set of visual features based on the image content.</p>
</li>
</ul>
<pre><code class="lang-plaintext">// ./scr/components/AzureVisionService

// Importing the Azure SDK client libraries
import { ComputerVisionClient } from '@azure/cognitiveservices-computervision';
import { ApiKeyCredentials } from '@azure/ms-rest-js';

// Authentication requirements
const key = process.env.REACT_APP_apiKey;
const endpoint = process.env.REACT_APP_endPoint;

// Cognitive service features
const options = {
    maxCandidates: 5,
    language: "en"
  };

// Describe Image from URL
export const computerVision = async (url) =&gt; {

    // authenticate to Azure service
    const computerVisionClient = new ComputerVisionClient(
        new ApiKeyCredentials({ inHeader: { 'Ocp-Apim-Subscription-Key': key } }), endpoint);

    // describe image using the describeImage method
    const analysis = await computerVisionClient.describeImage(url, options)
    .then((result) =&gt; {
        console.log("The result is:");
        console.log(result);
        return { "URL": url, ...result};
      })
      .catch((err) =&gt; {
        console.log("An error occurred:");
        console.error(err);
        alert(err + "Upload an image with a smaller size");
      });

    // all information about image
    console.log("This is:" +analysis);
    if(analysis === undefined){
        return "There is something wrong with the image"
    }
    return { "URL": url, ...analysis};
}
</code></pre>
<h3 id="heading-step-5-connect-the-azurevision-component-with-the-rest-of-the-app">Step 5: Connect the AzureVision Component with the rest of the app.</h3>
<ul>
<li>Import the required functions from the AzureVIsion Component into App.js</li>
</ul>
<pre><code class="lang-plaintext">// ./src/App.js
import React, { useState } from 'react';
import { computerVision } from './components/AzureVisionService';

function App() {
  const [file, setFile] = useState(null);
  const [analysis, setAnalysis] = useState(null);
  const [processing, setProcessing] = useState(false);

  const handleChange = (e) =&gt; {
    setFile(e.target.value)
  }
  const onFileUrlEntered = () =&gt; {

    // hold UI
    setProcessing(true);
    setAnalysis(null);

    computerVision(file).then((item) =&gt; {

      // reset state/form
      setAnalysis(item);
      setFile("");
      setProcessing(false);
    });

  };

  // Display JSON data in readable format
  const PrettyPrintJson = (data) =&gt; {
    return (&lt;div&gt;&lt;pre&gt;{JSON.stringify(data, null, 2)}&lt;/pre&gt;&lt;/div&gt;);
  }

  const DisplayResults = () =&gt; {
    return (
      &lt;div&gt;
        &lt;h2&gt;Computer Vision Analysis&lt;/h2&gt;
        &lt;div&gt;&lt;img src={analysis.URL} height="200" border="1" alt={(analysis.description &amp;&amp; analysis.description.captions &amp;&amp; analysis.description.captions[0].text ? analysis.description.captions[0].text : "can't find caption")} /&gt;&lt;/div&gt;
        {PrettyPrintJson(analysis)}
      &lt;/div&gt;
    )
  };

  //Describe image
  const Describe = () =&gt; {
    return (
    &lt;div&gt;
      &lt;h1&gt;Describe image&lt;/h1&gt;
      {!processing &amp;&amp;
        &lt;div&gt;
          &lt;div&gt;
            &lt;label&gt;URL&lt;/label&gt;
            &lt;input type="text" placeholder="Enter an image URL" size="50" onChange={handleChange}&gt;&lt;/input&gt;
          &lt;button onClick={onFileUrlEntered}&gt;Describe&lt;/button&gt;
          &lt;/div&gt;
        &lt;/div&gt;
      }
      {processing &amp;&amp; &lt;div&gt;Processing...&lt;/div&gt;}
      &lt;hr /&gt;
      {analysis &amp;&amp; DisplayResults()}
      &lt;/div&gt;
    )
  }

  return (
    &lt;div&gt;
      &lt;Describe/&gt;
    &lt;/div&gt;

  );
}

export default App;
</code></pre>
<h3 id="heading-step-6-hosting-your-web-app">Step 6: Hosting your web app</h3>
<p>You could use any preferred hosting service like <a target="_blank" href="https://azure.microsoft.com/en-us/services/app-service/static/">Azure Static Web Apps</a>, <a target="_blank" href="https://www.netlify.com/">Netlify</a>, <a target="_blank" href="https://vercel.com/">Vercel</a>, <a target="_blank" href="https://firebase.google.com/">Firebase</a> or <a target="_blank" href="https://www.heroku.com/">Heroku</a>. For this tutorial, I'll make use of Netlify. One important thing to note is that whichever hosting platform you use, remember to add the <em>REACT_APP_apiKey</em> and the <em>REACT_APP_endPoint</em> to the host environment variables.</p>
<ul>
<li><p>The first step here is to push the local react app to Github. Create a new <em>empty</em> repository in Github, you should get the screen shown below</p>
</li>
<li><p>In your local react app folder, open a new terminal. Then run the following commands</p>
</li>
</ul>
<pre><code class="lang-plaintext">// In bash terminal
git init
git add .
git commit -m "first commit"
git branch -M main
git remote add origin https://github.com/&lt;USERNAME&gt;/&lt;REPO_NAME&gt;.git
git push -u origin main
</code></pre>
<ul>
<li><p>Your code is now pushed to Github. Next, open your hosting website and import the existing project from Github.</p>
</li>
<li><p>In the build and deploy setup interface, click on 'Advanced Settings' then 'Add New Variable' to store the secret keys</p>
</li>
<li><p>Then deploy your site</p>
</li>
</ul>
<p>Your site is deployed!!</p>
<h3 id="heading-references">References:</h3>
<ol>
<li><p><a target="_blank" href="https://docs.microsoft.com/en-us/azure/developer/javascript/tutorial/static-web-app-image-analysis">Microsoft Docs Image Analysis Tutorial</a></p>
</li>
<li><p><a target="_blank" href="https://www.npmjs.com/package/@azure/cognitiveservices-computervision">Azure Computer Vision npm doc</a></p>
</li>
<li><p><a target="_blank" href="https://westus.dev.cognitive.microsoft.com/docs/services/computer-vision-v3-2/operations/56f91f2e778daf14a499f21f">Azure Computer Vision API doc</a></p>
</li>
</ol>
]]></content:encoded></item></channel></rss>