<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Frontend on Osmar Petry</title><link>https://osmarpetry.dev/tags/frontend/</link><description>Recent content in Frontend on Osmar Petry</description><generator>Hugo</generator><language>en-US</language><lastBuildDate>Mon, 01 Sep 2025 00:00:00 +0000</lastBuildDate><atom:link href="https://osmarpetry.dev/tags/frontend/rss.xml" rel="self" type="application/rss+xml"/><item><title>Web Accessibility V3 — Topics cheat-sheet &amp; decision guide</title><link>https://osmarpetry.dev/blog/web-accessibility/</link><pubDate>Mon, 01 Sep 2025 00:00:00 +0000</pubDate><guid>https://osmarpetry.dev/blog/web-accessibility/</guid><description>&lt;h2 id="summary"&gt;Summary&lt;/h2&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;Course map covers &lt;strong&gt;Screen Readers&lt;/strong&gt;, &lt;strong&gt;Accessible HTML&lt;/strong&gt;, &lt;strong&gt;ARIA&lt;/strong&gt;, &lt;strong&gt;Focus Management&lt;/strong&gt;, and &lt;strong&gt;Visual Considerations&lt;/strong&gt;, plus &lt;strong&gt;Debugging &amp;amp; team process&lt;/strong&gt;.&lt;/li&gt;&#10;&lt;li&gt;Aim: ship &lt;strong&gt;perceivable, operable, understandable, robust&lt;/strong&gt; experiences (POUR) with practical exercises and team-ready debugging habits.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="topics--what-to-do-at-a-glance"&gt;Topics → what to do (at a glance)&lt;/h2&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;Screen Readers:&lt;/strong&gt; learn how they work, enable them, write solid &lt;strong&gt;alt text&lt;/strong&gt;, and test.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Accessible HTML:&lt;/strong&gt; prefer &lt;strong&gt;semantic elements&lt;/strong&gt; and set &lt;strong&gt;document language&lt;/strong&gt;; fix invalid markup.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;ARIA:&lt;/strong&gt; add only when semantics aren’t enough; know &lt;strong&gt;roles, states, properties&lt;/strong&gt;, &lt;strong&gt;names/descriptions&lt;/strong&gt;, and &lt;strong&gt;live regions&lt;/strong&gt;.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Focus Management:&lt;/strong&gt; full keyboard support, &lt;strong&gt;skip links&lt;/strong&gt;, logical &lt;strong&gt;Tab&lt;/strong&gt; order, avoid &lt;strong&gt;focus traps&lt;/strong&gt;, and review shortcuts.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Visual:&lt;/strong&gt; check &lt;strong&gt;color contrast&lt;/strong&gt;, &lt;strong&gt;reflow/zoom&lt;/strong&gt;, &lt;strong&gt;reduced motion&lt;/strong&gt;, and &lt;strong&gt;prefers-color-scheme&lt;/strong&gt;; connect performance with accessibility.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Debugging:&lt;/strong&gt; use linters/devtools, improve team workflows, go &lt;strong&gt;beyond compliance&lt;/strong&gt;, and practice with hands-on exercises.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="decision-heuristics"&gt;Decision heuristics&lt;/h2&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;Semantics first → ARIA last.&lt;/strong&gt; If a native element already communicates role/state, &lt;strong&gt;don’t add ARIA&lt;/strong&gt;.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Keyboard is the truth.&lt;/strong&gt; If it’s not operable with keyboard and visible focus, it’s not accessible.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Name, role, value:&lt;/strong&gt; can a screen reader expose them correctly? If not, fix semantics, labels, or ARIA.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Respect user prefs:&lt;/strong&gt; &lt;code&gt;prefers-reduced-motion&lt;/code&gt;, &lt;code&gt;prefers-color-scheme&lt;/code&gt;, and zoom/reflow without loss.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="team-workflow"&gt;Team workflow&lt;/h2&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;&lt;strong&gt;Set standards&lt;/strong&gt; (WCAG targets, browser/AT matrix).&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Lint &amp;amp; test early&lt;/strong&gt; (HTML validity, axe, devtools).&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Exercise mindset:&lt;/strong&gt; practice with screen readers and keyboard on real UI (modals, forms, navigation).&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Go beyond checklists:&lt;/strong&gt; optimize usability for assistive technology users, not just box-ticking.&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="dev-checklist"&gt;Dev checklist&lt;/h2&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Landmark structure (&lt;code&gt;header&lt;/code&gt;, &lt;code&gt;nav&lt;/code&gt;, &lt;code&gt;main&lt;/code&gt;, &lt;code&gt;aside&lt;/code&gt;, &lt;code&gt;footer&lt;/code&gt;).&lt;/li&gt;&#10;&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Page language (&lt;code&gt;&amp;lt;html lang&amp;gt;&lt;/code&gt;).&lt;/li&gt;&#10;&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Forms: &lt;code&gt;&amp;lt;label&amp;gt;&lt;/code&gt; + programmatic names; error text announced.&lt;/li&gt;&#10;&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Interactive controls are &lt;strong&gt;native&lt;/strong&gt; or fully re-created (role, keyboard, focus, ARIA).&lt;/li&gt;&#10;&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Focus order and &lt;strong&gt;visible&lt;/strong&gt; focus style.&lt;/li&gt;&#10;&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Contrast meets WCAG; no information by color alone.&lt;/li&gt;&#10;&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Motion: provide a &lt;strong&gt;reduced motion&lt;/strong&gt; path; avoid parallax autoplay by default.&lt;/li&gt;&#10;&lt;li&gt;&lt;input disabled="" type="checkbox"&gt; Respect zoom/reflow at 200–400% without horizontal scroll.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="references"&gt;References&lt;/h2&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;Web Accessibility — All Topics (Frontend Masters companion site)&lt;/strong&gt;: &lt;a href="https://web-accessibility-v3.vercel.app/topics" target="_blank" rel="noreferrer"&gt;https://web-accessibility-v3.vercel.app/topics&lt;/a&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;GitHub repo&lt;/strong&gt;: &lt;a href="https://github.com/marcysutton/frontend-masters-web-accessibility-v3" target="_blank" rel="noreferrer"&gt;https://github.com/marcysutton/frontend-masters-web-accessibility-v3&lt;/a&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="related-notes"&gt;Related Notes&lt;/h2&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;[[react-forwardRef|Forwarding Ref]]&lt;/li&gt;&#10;&lt;li&gt;[[svg-are-the-best|SVG are the Best]]&lt;/li&gt;&#10;&lt;/ul&gt;</description></item><item><title>XState — model UI behavior correctly and make it testable</title><link>https://osmarpetry.dev/blog/xstate-model-ui-bahavior/</link><pubDate>Sat, 12 Jul 2025 00:00:00 +0000</pubDate><guid>https://osmarpetry.dev/blog/xstate-model-ui-bahavior/</guid><description>&lt;h2 id="the-problem-were-solving"&gt;The problem we&amp;rsquo;re solving&lt;/h2&gt;&#10;&lt;p&gt;Imagine you join a company that runs an e-commerce platform. Product asks you to build a &lt;strong&gt;search page&lt;/strong&gt; — the kind of page every user hits dozens of times a day. It sounds simple: a text input, a button, show results.&lt;/p&gt;&#10;&lt;p&gt;But then reality kicks in. The page has to handle empty queries, network failures, slow connections, retries, and race conditions where a user submits a second search before the first one finishes. A junior developer might reach for a handful of &lt;code&gt;useState&lt;/code&gt; calls — &lt;code&gt;isLoading&lt;/code&gt;, &lt;code&gt;hasError&lt;/code&gt;, &lt;code&gt;data&lt;/code&gt;, &lt;code&gt;submitted&lt;/code&gt; — and suddenly you&amp;rsquo;re juggling four booleans that produce sixteen possible combinations. Most of those combinations are impossible, but nothing in the code prevents them. A loading spinner stays visible after an error. A success message flashes before the data arrives. Bugs creep in not because the developer made a logic error, but because the &lt;strong&gt;model itself was never defined&lt;/strong&gt;.&lt;/p&gt;</description></item><item><title>React ForwardRef</title><link>https://osmarpetry.dev/blog/react-forwardref/</link><pubDate>Wed, 15 Jan 2025 00:00:00 +0000</pubDate><guid>https://osmarpetry.dev/blog/react-forwardref/</guid><description>&lt;p&gt;By default, React does not let a parent component access the DOM node of a child component. &lt;code&gt;forwardRef&lt;/code&gt; breaks that boundary explicitly — the child opts in to exposing its DOM node (or instance) to whoever holds the ref.&lt;/p&gt;&#10;&lt;p&gt;The typical need is imperative control from a parent: focusing an input inside a design-system &lt;code&gt;&amp;lt;Input&amp;gt;&lt;/code&gt; wrapper, scrolling a &lt;code&gt;&amp;lt;List&amp;gt;&lt;/code&gt; to a specific row, or triggering animations on a child element. Without &lt;code&gt;forwardRef&lt;/code&gt;, the parent would need to own the DOM directly, which defeats the purpose of encapsulation.&lt;/p&gt;</description></item><item><title>React.Suspense</title><link>https://osmarpetry.dev/blog/react-suspense/</link><pubDate>Wed, 15 Jan 2025 00:00:00 +0000</pubDate><guid>https://osmarpetry.dev/blog/react-suspense/</guid><description>&lt;p&gt;&lt;code&gt;React.Suspense&lt;/code&gt; is a boundary component that lets you declaratively specify a fallback UI while its children are &amp;ldquo;suspended&amp;rdquo; — waiting for code to load or, in frameworks like Next.js/Remix, for async data to resolve. It decouples the loading concern from the component that needs the data, keeping each piece focused on its own responsibility.&lt;/p&gt;&#10;&lt;h2 id="why-use-suspense"&gt;Why use Suspense&lt;/h2&gt;&#10;&lt;p&gt;Suspense lets you declaratively handle loading states for code-splitting and async data (with frameworks that support it). It improves first-load performance and keeps your UI logic focused on states that matter.&lt;/p&gt;</description></item><item><title>SVG Are the Best</title><link>https://osmarpetry.dev/blog/svg-are-the-best/</link><pubDate>Wed, 15 Jan 2025 00:00:00 +0000</pubDate><guid>https://osmarpetry.dev/blog/svg-are-the-best/</guid><description>&lt;p&gt;SVG and icon fonts can solve similar problems, especially for icons. However, icon fonts must be downloaded correctly and mapped to the expected glyphs. When that fails, users may see empty squares or broken characters. SVG does not have that problem because the graphic itself is rendered directly.&lt;/p&gt;&#10;&lt;h2 id="svg-vs-font-icons"&gt;SVG vs. Font Icons&lt;/h2&gt;&#10;&lt;p&gt;Both approaches can be used for icons, but SVG is usually the better choice.&lt;/p&gt;&#10;&lt;h3 id="why-svg-is-better"&gt;Why SVG is better&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;It does not depend on a font being loaded correctly&lt;/li&gt;&#10;&lt;li&gt;It can be styled and animated with CSS&lt;/li&gt;&#10;&lt;li&gt;It scales well across screen sizes&lt;/li&gt;&#10;&lt;li&gt;It works well for diagrams, illustrations, and UI icons&lt;/li&gt;&#10;&lt;li&gt;It supports filters and visual effects&lt;/li&gt;&#10;&lt;li&gt;It is accessible when used correctly&lt;/li&gt;&#10;&lt;li&gt;It exists as structured markup in the DOM&lt;/li&gt;&#10;&lt;li&gt;It is code, so it can be versioned, reviewed, and edited easily&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="svg-benefits"&gt;SVG Benefits&lt;/h2&gt;&#10;&lt;h3 id="1-interactive-and-stylable-with-css"&gt;1. Interactive and stylable with CSS&lt;/h3&gt;&#10;&lt;p&gt;SVG elements can be targeted directly with CSS. You can change properties such as &lt;code&gt;fill&lt;/code&gt;, &lt;code&gt;stroke&lt;/code&gt;, &lt;code&gt;opacity&lt;/code&gt;, &lt;code&gt;transform&lt;/code&gt;, and more.&lt;/p&gt;</description></item><item><title>useRef</title><link>https://osmarpetry.dev/blog/react-useref/</link><pubDate>Wed, 15 Jan 2025 00:00:00 +0000</pubDate><guid>https://osmarpetry.dev/blog/react-useref/</guid><description>&lt;p&gt;&lt;code&gt;useRef&lt;/code&gt; gives you a mutable container — &lt;code&gt;{ current: value }&lt;/code&gt; — that persists for the full lifetime of the component without triggering re-renders when changed. This makes it the right tool for two distinct jobs: holding a reference to a DOM node for imperative operations, and storing any mutable value that your component needs to remember across renders but that should &lt;em&gt;not&lt;/em&gt; drive the UI.&lt;/p&gt;&#10;&lt;p&gt;The key mental model: &lt;code&gt;useState&lt;/code&gt; is for values that should be &lt;em&gt;shown&lt;/em&gt;; &lt;code&gt;useRef&lt;/code&gt; is for values that should be &lt;em&gt;remembered&lt;/em&gt;.&lt;/p&gt;</description></item><item><title>Testing Concepts Notes</title><link>https://osmarpetry.dev/blog/testing-concepts-notes/</link><pubDate>Fri, 15 Jan 2021 00:00:00 +0000</pubDate><guid>https://osmarpetry.dev/blog/testing-concepts-notes/</guid><description>&lt;h2 id="bdd"&gt;&lt;strong&gt;BDD&lt;/strong&gt;&lt;/h2&gt;&#10;&lt;p&gt;BDD (Behavior Driven Development) is a method of testing where you use &amp;ldquo;Given&amp;rdquo; for the scenario, &amp;ldquo;When&amp;rdquo; for the environment of the action, and &amp;ldquo;Then&amp;rdquo; for the action.&lt;/p&gt;&#10;&lt;p&gt;Imagine &lt;strong&gt;AutoLot&lt;/strong&gt;, a car dealership chain building an online vehicle marketplace. A product manager, a developer, and a QA engineer sit together and write this scenario in plain English:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Given a customer browsing the SUV category&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;When the customer clicks &amp;#34;Schedule Test Drive&amp;#34; on a 2024 Honda CR-V&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Then the test drive request should appear as &amp;#34;pending&amp;#34; in the customer&amp;#39;s dashboard&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This is BDD in practice — the three roles agree on the expected behavior before any code is written. The npm package &lt;code&gt;jest-cucumber&lt;/code&gt; lets you map these Gherkin-style scenarios directly to Jest tests.&lt;/p&gt;</description></item><item><title>Testing Library vs Enzyme</title><link>https://osmarpetry.dev/blog/testing-library-vs-enzyme/</link><pubDate>Fri, 15 Jan 2021 00:00:00 +0000</pubDate><guid>https://osmarpetry.dev/blog/testing-library-vs-enzyme/</guid><description>&lt;h2 id="introduction"&gt;&lt;strong&gt;Introduction&lt;/strong&gt;&lt;/h2&gt;&#10;&lt;p&gt;Testing Library is built around a simple philosophy: the more your tests resemble the way your software is used, the more confidence they can give you. Its three core principles are: tests only break when your app breaks (not when implementation details change), you interact with your app the same way as your users, and built-in selectors find elements the way users do to help you write inclusive code.&lt;/p&gt;</description></item></channel></rss>