<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Sylvain Hamann</title>
    <description>The latest articles on DEV Community by Sylvain Hamann (@sylvhama).</description>
    <link>https://dev.to/sylvhama</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F403962%2F17543c79-6143-42d8-b356-d98861cb804b.jpeg</url>
      <title>DEV Community: Sylvain Hamann</title>
      <link>https://dev.to/sylvhama</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sylvhama"/>
    <language>en</language>
    <item>
      <title>GPT is my new BFF (Backend for Frontends)</title>
      <dc:creator>Sylvain Hamann</dc:creator>
      <pubDate>Tue, 28 Mar 2023 19:58:44 +0000</pubDate>
      <link>https://dev.to/sylvhama/gpt-is-my-new-bff-backend-for-frontends-1g03</link>
      <guid>https://dev.to/sylvhama/gpt-is-my-new-bff-backend-for-frontends-1g03</guid>
      <description>&lt;p&gt;As a front-end developer I encountered several types of backend during my career (e.g. GraphQL). They were written with different languages (e.g. Rails or PHP). I don't consider myself as a fullstack developer, I always prefer focusing on crafting the UI.&lt;/p&gt;

&lt;p&gt;I saw people asking Chat GPT to answer with a JSON formatted response:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--abUQdOHZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/frohx6t2xgp2dixtu17j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--abUQdOHZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/frohx6t2xgp2dixtu17j.png" alt="Screenshot from a discussion with Chat GPT showing a prompt asking o generate a JSON containing a question about French history with four possible answers. The answer contains the expected JSON." width="880" height="459"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is clearly an example of BFF (&lt;a href="https://learn.microsoft.com/en-us/azure/architecture/patterns/backends-for-frontends"&gt;Backend for Frontends&lt;/a&gt;) pattern. &lt;br&gt;
It means we could now create a lot of projects without having  to worry about having a dedicated backend or database!&lt;/p&gt;

&lt;p&gt;This is exactly what I did with &lt;a href="https://github.com/sylvhama/daily-kanji"&gt;Daily Kanji&lt;/a&gt;. It will &lt;a href="https://github.com/sylvhama/daily-kanji/blob/main/ssr.ts#L12"&gt;prompt GPT&lt;/a&gt; to return a random Japanese Kanji and its translation as a JSON. A scheduled &lt;a href="https://github.com/sylvhama/daily-kanji/actions/workflows/render-video.yml"&gt;GitHub action&lt;/a&gt; (similar to a CRON job) will create a new video everyday thanks to &lt;a href="https://www.remotion.dev/"&gt;Remotion&lt;/a&gt;, a React framework to programmatically render videos. The video will then be published &lt;a href="https://www.instagram.com/your_daily_kanji/"&gt;on Instagram&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;With this kind of setup you don't really need to worry about your &lt;a href="https://platform.openai.com/docs/introduction"&gt;OpenAI API&lt;/a&gt; usage since it will only run once a day. During development you should rely on a JSON mock so you don't need to query OpenAI each time. With all my local tests an production runs I did not even reach $1. &lt;/p&gt;

&lt;p&gt;Instead of generating daily videos you could have some sort of daily quiz similar to &lt;em&gt;Wordle&lt;/em&gt;. Your only limit is your imagination! &lt;br&gt;
With frameworks such as &lt;a href="https://astro.build/"&gt;Astro&lt;/a&gt; you can generate a new static build each day based on data generated by GPT. The data would again be only &lt;a href="https://docs.astro.build/en/guides/data-fetching/"&gt;fetched once&lt;/a&gt; at build time via a &lt;a href="https://www.netlify.com/blog/how-to-schedule-deploys-with-netlify/"&gt;scheduled deploy&lt;/a&gt;. If for any reason the request failed or the data does not have the expected shape then you could cancel / retry the job.&lt;/p&gt;

&lt;p&gt;Something that would require further explorations: how to make sure each JSON is unique? For now I am using a little trick where I ask GPT to the the current timestamp as a seed, it seems to work!&lt;/p&gt;

</description>
      <category>gpt3</category>
      <category>javascript</category>
      <category>react</category>
      <category>node</category>
    </item>
    <item>
      <title>Use CSS to pass an element through your letters</title>
      <dc:creator>Sylvain Hamann</dc:creator>
      <pubDate>Thu, 02 Feb 2023 03:43:02 +0000</pubDate>
      <link>https://dev.to/sylvhama/use-css-to-pass-an-element-through-your-letters-2ad3</link>
      <guid>https://dev.to/sylvhama/use-css-to-pass-an-element-through-your-letters-2ad3</guid>
      <description>&lt;p&gt;A while ago I created an &lt;a href="https://threeforce.netlify.app/" rel="noopener noreferrer"&gt;animation&lt;/a&gt; to celebrate The Legend of Zelda: A Link to the Past anniversary. My main goal was to practice Three.js. But I had to find a way to recreate the logo effect where the sword goes through the "Z" with CSS. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9vljq30gqshjozf63z6z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9vljq30gqshjozf63z6z.png" alt="Zelda logo" width="800" height="549"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can have a look at &lt;a href="https://github.com/sylvhama/threeforce/blob/main/src/components/Title/Title.tsx" rel="noopener noreferrer"&gt;my implementation&lt;/a&gt; made with React. I also wanted to share a pure HTML/CSS version to show it's easy to make:&lt;/p&gt;

&lt;p&gt;The idea is to create the &lt;em&gt;illusion&lt;/em&gt; by duplicating each letter and superposing them via an absolute position. Then with the magic of &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/clip-path" rel="noopener noreferrer"&gt;clip-path&lt;/a&gt; you can hide letter parts. The result would look like this (hover the word to see the animation):&lt;/p&gt;

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

&lt;p&gt;More details:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;My letters are wrapped in a &lt;code&gt;span&lt;/code&gt; with a &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/::after" rel="noopener noreferrer"&gt;pseudo ::after element&lt;/a&gt; used to duplicate the letter;&lt;/li&gt;
&lt;li&gt;The letters parent &lt;code&gt;h1&lt;/code&gt; is a flex layout in order to remove white spaces;&lt;/li&gt;
&lt;li&gt;The text remains accessible (screen readers will ignore duplicated letters) and selectable (pseudo element won't be copied).&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>blockchain</category>
      <category>crypto</category>
      <category>offers</category>
      <category>web3</category>
    </item>
    <item>
      <title>How to test your web app accessibility?</title>
      <dc:creator>Sylvain Hamann</dc:creator>
      <pubDate>Tue, 21 Jun 2022 22:49:39 +0000</pubDate>
      <link>https://dev.to/sylvhama/how-to-test-your-web-app-accessibility-26di</link>
      <guid>https://dev.to/sylvhama/how-to-test-your-web-app-accessibility-26di</guid>
      <description>&lt;p&gt;In this post I will share tips from my previous experiences in order to test the accessibility of your web application or website.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's accessibility?
&lt;/h2&gt;

&lt;p&gt;In my own words I would say that the goal of accessibility (often abbreviated to a11y) is to make sure that anyone on any medium can use your web application or website. A lot of us browse the web on a computer with a keyboard and a mouse or via a mobile device with a touchscreen. Some people might use a keyboard exclusively or others assistive technologies such as screen readers (by the way mobiles have screen readers too!). We have to make sure that our user interface is usable in all those cases.&lt;/p&gt;

&lt;p&gt;If you seek for a deeper explanation about a11y, I suggest you to read this &lt;a href="https://developer.mozilla.org/en-US/docs/Web/Accessibility"&gt;MDN doc&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pull request review
&lt;/h2&gt;

&lt;p&gt;When someone opens a pull request affecting the user interface, I expect to be able to try their changes locally or on some sort of staging instance. I won't just review the code, I will also test the app in multiple scenarios e.g. different browsers with several screen resolutions. But don't be biased by your own habits. All users might not consume the Web like you do. E.g. People don't all have a powerful MacBook Pro with a giant external monitor and high speed internet. That's why it's important to write down some testing practices that each reviewer should go through before approving any PR. For example it could say "test the changes with a combo of mouse and keyboard, keyboard only, screen reader only, touch screen, disable motions etc..". This might seem long but automatic tests or tools won't catch every flaws in your UX and it's better to avoid accumulating too many issues.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tools to audit a web page
&lt;/h3&gt;

&lt;p&gt;There are several tools that will help you to detect a11y problems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Chrome users might already know the &lt;a href="https://github.com/GoogleChrome/lighthouse#using-lighthouse-in-chrome-devtools"&gt;Lighthouse&lt;/a&gt; tab in their dev tools. It can generate an accessibility report.&lt;/li&gt;
&lt;li&gt;However I prefer the &lt;a href="https://www.deque.com/axe/"&gt;axe DevTools&lt;/a&gt; extension because it's much faster to run. It highlights the nodes concerned by each issue and shares great tips to fix them. For example it will detect color contrast issues, images with no alt text, invalid HTML semantic...&lt;/li&gt;
&lt;li&gt;Chrome DevTools can also help to &lt;a href="https://developers.google.com/codelabs/devtools-cvd#4"&gt;fix contrast ratios&lt;/a&gt; or visualize the &lt;a href="https://developer.chrome.com/blog/full-accessibility-tree/"&gt;accessibility tree&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;You might know &lt;a href="https://www.browserstack.com/live"&gt;Browserstack&lt;/a&gt; that lets you do cross browser testing on desktop &amp;amp; mobile with &lt;strong&gt;real browsers&lt;/strong&gt;. Let me introduce you &lt;a href="https://assistivlabs.com/"&gt;Assistiv Labs&lt;/a&gt; that will let you use &lt;strong&gt;real assistive technologies&lt;/strong&gt; from different OS. It's not just screen readers, you can try others technologies such as the Windows high contrast mode.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;⚠️ Having a Lighthouse score of 100 or having zero issue in your axe report does not mean that your web app is fully accessible. &lt;/p&gt;

&lt;h2&gt;
  
  
  Automatic tests
&lt;/h2&gt;

&lt;h3&gt;
  
  
  DOM Testing
&lt;/h3&gt;

&lt;p&gt;What ever the framework or library you use, at the end your user's browser will always render HTML. Using semantic tags such as &lt;code&gt;main&lt;/code&gt;, &lt;code&gt;header&lt;/code&gt;, &lt;code&gt;footer&lt;/code&gt; are not only meant for SEO. Screen readers will rely on them in order to describe the current page to the user. &lt;a href="https://testing-library.com/"&gt;Testing Library&lt;/a&gt; will help you to write automatic tests based on the DOM. The goal is to have tests that represent a real user flow instead of testing implementation details. It's compatible with most of popular libraries, frameworks and tools.&lt;br&gt;
I recommend to always render the whole app / page and use API such as &lt;a href="https://testing-library.com/docs/dom-testing-library/api-within/"&gt;within&lt;/a&gt; if you want to test only one section of the UI. If a component is meant to be re-used across the apps (e.g. when creating a design system). Then I will also create a test suite juste for that component. &lt;/p&gt;

&lt;p&gt;Let's see different examples based on real test I wrote in the past:&lt;/p&gt;

&lt;p&gt;I contributed to a Single Page Application built with React. Since the browser would not reload after a page change I had to implement few logics to improve the accessibility:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;focus the &lt;code&gt;h1&lt;/code&gt; of the new page;&lt;/li&gt;
&lt;li&gt;render an &lt;code&gt;aria-live&lt;/code&gt; region announcing the new page;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Tests would like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;userEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;click&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getByText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Page link&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getByRole&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;heading&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Page title&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;level&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;})).&lt;/span&gt;&lt;span class="nx"&gt;toHaveFocus&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;getByText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;You navigated to Page title&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;toHaveAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;aria-live&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;polite&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With my team we had to build two different view modes for the same dataset. In order to do that we made two buttons using the &lt;code&gt;aria-pressed&lt;/code&gt; attribute. We wrote tests that interacted with each button and asserted their "pressed state":&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getByRole&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;button&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Table view&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;pressed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;})).&lt;/span&gt;&lt;span class="nx"&gt;toBeInTheDocument&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getByRole&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;button&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;List view&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;pressed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;})).&lt;/span&gt;&lt;span class="nx"&gt;toBeInTheDocument&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You might be used to see mobile designs with a 🍔 icon to expand the navigation. For this you could write tests that assert that the icon has the correct alternative text and check that the &lt;code&gt;aria-expanded&lt;/code&gt;, &lt;code&gt;aria-controls&lt;/code&gt; and &lt;code&gt;id&lt;/code&gt; attributes are present on the right nodes. Plus you can use the &lt;a href="https://testing-library.com/docs/dom-testing-library/api-accessibility/#isinaccessible"&gt;isInnacessible&lt;/a&gt; API to make sure that the mobile menu is correctly hidden but still present in the DOM. The mobile menu usually has a focus trap so I would use &lt;code&gt;userEvent&lt;/code&gt; to press tab multiple times and make sure it loops correctly. &lt;/p&gt;

&lt;p&gt;As you can see, when writing automatic tests you also have to remember that users don't only use just a mouse to interact with your UI. It's good to cover every scenarios to avoid any regression, especially those that you won't be able to see easily.&lt;/p&gt;

&lt;h3&gt;
  
  
  Visual tests
&lt;/h3&gt;

&lt;p&gt;With tools such as &lt;a href="https://www.chromatic.com/"&gt;Chromatic&lt;/a&gt; or  &lt;a href="https://percy.io/"&gt;Percy&lt;/a&gt; you could render a page after certain actions and make a snapshot of it in order to detect visual regressions. When building a design system you could have several snapshots of each component in different states such as the focus state make sure the focus style is not broken.&lt;br&gt;
Chromatic depends on Storybook which also provides &lt;a href="https://storybook.js.org/blog/accessibility-testing-with-storybook/"&gt;accessibility tests&lt;/a&gt; that could run in your CI too. This would help to automatically detect regressions without running axe devTools on every pages.&lt;br&gt;
Visual tests can be very annoying if they are not stable so make sure to fix flaky tests when you detect them. A co worker found out that disabling CSS animations when running those tests helps a lot. &lt;/p&gt;

&lt;h2&gt;
  
  
  Ask real humans
&lt;/h2&gt;

&lt;p&gt;If you can afford having real users to test your web app then please do it! This is not meant to replace any manual or automatic test you would do before shipping a PR. The purpose is to challenge all the assumptions and decisions you made during the design and development phases. I have seen many companies using tools such as inVision or Figma prototypes during those interviews. I guess that's great during the prototype / design phase but don't forget to test the real app with real users that rely on assistive technologies. After running those interviews or after a WCAG audit, any fix should come with an automatic test in order to prevent any regression in the future.&lt;/p&gt;

&lt;h2&gt;
  
  
  Team communication
&lt;/h2&gt;

&lt;p&gt;This paragraph is not really about testing but I wanted to give one last advice as a conclusion. I think my biggest frustration as a frontend developer is to have "incomplete" designs that force me to improvise or do a lot of back and forth with the design team. In order to avoid that it's good to set your expectations with your design team before they send you their design, for example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;each image or icon should have an alternative text;&lt;/li&gt;
&lt;li&gt;focus management: what should be the focus order? what element should be focused when revealing this section? etc...&lt;/li&gt;
&lt;li&gt;each page should have a document title, a h1, each section should have a h2 etc...&lt;/li&gt;
&lt;li&gt;what should be the alternative animation when reduce motion is on?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Building a &lt;strong&gt;design system&lt;/strong&gt; will help a lot since designers could re-create each component in their Figma and the whole team would use the same vocabulary when talking about the UI.  Documenting each component with best practices and listing DO and DON'T actions is also very helpful.&lt;/p&gt;

&lt;p&gt;Happy testing!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>a11y</category>
      <category>testing</category>
    </item>
    <item>
      <title>Multi-Directional Navigation</title>
      <dc:creator>Sylvain Hamann</dc:creator>
      <pubDate>Mon, 08 Jun 2020 20:21:26 +0000</pubDate>
      <link>https://dev.to/sylvhama/multi-directional-navigation-31k2</link>
      <guid>https://dev.to/sylvhama/multi-directional-navigation-31k2</guid>
      <description>&lt;p&gt;tl;dr &lt;a href="https://multi-directional-navigation.netlify.app/" rel="noopener noreferrer"&gt;demo&lt;/a&gt;, &lt;a href="https://github.com/sylvhama/multi-directional-navigation" rel="noopener noreferrer"&gt;repo&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In my previous job, I had the opportunity to work on a web application for a video game company. This web app is embedded within AAA games on PlayStation 4, Xbox One and Nintendo Switch. I want to share what I've learned during this experience, especially how to manage the navigation.&lt;/p&gt;

&lt;h2&gt;
  
  
  UI for a TV Screen 📺
&lt;/h2&gt;

&lt;p&gt;Most web developers are now used to develop responsive user interfaces for mobile, tablet and desktop computers. Your webpage should provide a user experience for people using a touch screen, a mouse, a keyboard, a screen reader...&lt;br&gt;
In our case however, the app gets rendered on television screens! or on the Switch screen when being used in portable mode.&lt;br&gt;
Gaming systems, even those supporting 4K resolutions, will render our web app in a 1080p resolution (1920x1080 pixels viewport). Other might render it in 720p (1280x720 pixels viewport). Each has their specificity, for instance, the Nintendo Switch reserves an area at the bottom of the screen to display their own footer.&lt;br&gt;
To handle all those resolutions, we better work on an &lt;strong&gt;adaptive design&lt;/strong&gt;. The content (such as the system logo) and its size will adapt to each system and its resolution. There is no reason to worry about unsupported resolutions here, simply because the user can't resize their viewport. &lt;br&gt;
People use a gamepad to navigate in the app. The goal is to provide them an User Experience that is similar to the one they see in-game. So we don't want to display a mouse cursor or scroll bars, this might break their momentum and create frustration.&lt;/p&gt;

&lt;p&gt;Here's a list of tips:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Display a legend somewhere to indicate which button can be pressed and what action do they trigger. For example, you want to tell them "by pressing this button you will go back".&lt;/li&gt;
&lt;li&gt;Look at existing game menus and dashboards. You want to use all the space available in the viewport and have some "fixed" content (e.g. a menu, header, footer...). &lt;a href="https://css-tricks.com/fun-viewport-units/" rel="noopener noreferrer"&gt;Viewport units&lt;/a&gt;, &lt;a href="https://css-tricks.com/confused-rem-em/" rel="noopener noreferrer"&gt;REM&lt;/a&gt; and &lt;a href="https://cssgrid.io/" rel="noopener noreferrer"&gt;CSS Grid&lt;/a&gt; help a lot! Some browsers might not support all those cool features, you can fallback to something else like &lt;a href="https://flexboxfroggy.com/" rel="noopener noreferrer"&gt;flexbox&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Highlight&lt;/em&gt; which element is focused. If you use React in your project you might want to try &lt;a href="https://styled-components.com/" rel="noopener noreferrer"&gt;styled-components&lt;/a&gt;. It lets you create components that have a &lt;a href="https://github.com/sylvhama/multi-directional-navigation/blob/master/src/components/shared/Base/Base.ts" rel="noopener noreferrer"&gt;dynamic style&lt;/a&gt; based on their props in a very smooth way.&lt;/li&gt;
&lt;li&gt;The URL is your friend. You can tell the gaming system to hide it. So the user won't be able to modify its content. Use it to do conditional rendering and to pass information from the game to your app via query strings.&lt;/li&gt;
&lt;li&gt;You can also use Node environment variables to create different builds to support different systems.&lt;/li&gt;
&lt;li&gt;Not all your teammates have a dev kit to start a game and test your app. Deploying a private version usable from any computer via its keyboard and tools such as &lt;a href="https://storybook.js.org/" rel="noopener noreferrer"&gt;Storybook&lt;/a&gt; helps a lot.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Gamepad Navigation 🎮
&lt;/h2&gt;

&lt;p&gt;The UI is made of &lt;strong&gt;focusable elements&lt;/strong&gt; where the user can navigate in at least &lt;strong&gt;four directions&lt;/strong&gt;: up, down, left and right.&lt;br&gt;
&lt;a href="https://multi-directional-navigation.netlify.app" rel="noopener noreferrer"&gt;&lt;img alt="Preview" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FY3r0vT7.gif"&gt;&lt;/a&gt;&lt;br&gt;
Browsers don't support such navigation natively. You might have heard about web accessibility that lets you use &lt;code&gt;tab&lt;/code&gt; and &lt;code&gt;shift&lt;/code&gt;+&lt;code&gt;tab&lt;/code&gt; to focus elements one by one. Accessibility best practices are a good source of inspiration. You might wonder, why not using the &lt;a href="https://www.voorhoede.nl/en/blog/navigating-the-web-with-a-gamepad/" rel="noopener noreferrer"&gt;gamepad api&lt;/a&gt;? Fun fact, not all gaming system browsers support it. We instead ask the system to map each button as keyboard keys. The goal is to create a custom focus manager that will take care of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;inserting/updating/removing elements in a list;&lt;/li&gt;
&lt;li&gt;programmatically focusing an element based on a direction.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In my &lt;a href="https://github.com/sylvhama/multi-directional-navigation" rel="noopener noreferrer"&gt;demo&lt;/a&gt; which uses React, I opted for &lt;a href="https://github.com/sylvhama/multi-directional-navigation/blob/master/src/contexts/MultiDirection/reducer/reducer.ts" rel="noopener noreferrer"&gt;useReducer&lt;/a&gt; and the &lt;a href="https://github.com/sylvhama/multi-directional-navigation/blob/master/src/contexts/MultiDirection/MultiDirection.tsx" rel="noopener noreferrer"&gt;Context API&lt;/a&gt;. But the logic can be reused with any other state management solution, such as Redux. I won't go into the implementation details, here are the main takeaways:   &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Each focusable &lt;a href="https://github.com/sylvhama/multi-directional-navigation/blob/master/src/contexts/MultiDirection/types.ts#L8" rel="noopener noreferrer"&gt;element&lt;/a&gt; is represented by an object containing a &lt;em&gt;unique&lt;/em&gt; id, its position (top, bottom, left, right) and its depth. We can use &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect" rel="noopener noreferrer"&gt;Element.getBoundingClientRect()&lt;/a&gt; or pass our own custom values. 
&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fvxqzahvyoktgxn10lo18.png" alt="Element"&gt;
&lt;/li&gt;
&lt;li&gt;Imagine the depth like an equivalent of the z-index in CSS. It let us handle different layers of focusable elements, such as a modal.&lt;/li&gt;
&lt;li&gt;We use a global event listener to listen to keyboard inputs. When matching one of the arrow keys we &lt;a href="https://github.com/sylvhama/multi-directional-navigation/blob/master/src/utils/findClosestNeighborId/findClosestNeighborId.ts" rel="noopener noreferrer"&gt;find the closest neighbour&lt;/a&gt; based on the current focused element and the current depth. My function to find the closest neighbour &lt;a href="https://github.com/sylvhama/multi-directional-navigation/blob/master/src/hooks/multiDirection/useDirectionListener/useDirectionListener.ts#L18" rel="noopener noreferrer"&gt;can be overriden&lt;/a&gt;. We could imagine different algorithms to find the next focused element depending on the current page.&lt;/li&gt;
&lt;li&gt;Then it's up to you to create custom hooks and to have fun! E.g. in &lt;a href="https://github.com/sylvhama/multi-directional-navigation/blob/master/src/components/App/App.tsx#L30" rel="noopener noreferrer"&gt;my app&lt;/a&gt; I am playing a "move" sound effect when the current focus id changes. Check this &lt;a href="https://joshwcomeau.com/react/announcing-use-sound-react-hook/" rel="noopener noreferrer"&gt;article&lt;/a&gt; if you want to useSound too!&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Testing 🤖
&lt;/h2&gt;

&lt;p&gt;Automated tests and continuous integration improve your confidence when shipping code. &lt;br&gt;
It's very important to write unit tests for vital parts of your apps, like the pure functions that are used to find the closest neighbour. I like writing &lt;a href="https://github.com/styled-components/jest-styled-components" rel="noopener noreferrer"&gt;snapshot tests&lt;/a&gt; for my Styled Components which have dynamic styles. I also have a few integration tests made with React Testing Library. &lt;br&gt;
But I believe that end-to-end tests are the best here because they are very natural to write and will cover all your business logic without needing to mock everything. That's why most of my hooks have no dedicated tests. For example here is a test made with &lt;a href="https://www.cypress.io/" rel="noopener noreferrer"&gt;Cypress&lt;/a&gt; that visits a page, opens a modal, navigates within it and then closes it. &lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FKS5p21M.gif" class="article-body-image-wrapper"&gt;&lt;img alt="end to end test" src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FKS5p21M.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thanks for reading, let me know if you have questions!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Check the &lt;a href="https://multi-directional-navigation.netlify.app/" rel="noopener noreferrer"&gt;demo&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;Browse the &lt;a href="https://github.com/sylvhama/multi-directional-navigation" rel="noopener noreferrer"&gt;repo&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Merci &lt;a href="https://twitter.com/jtrollia" rel="noopener noreferrer"&gt;Jean-Loup&lt;/a&gt; for proofreading. He was also one of my teammates!&lt;/p&gt;

</description>
      <category>react</category>
      <category>webdev</category>
      <category>a11y</category>
      <category>testing</category>
    </item>
  </channel>
</rss>
