<?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>Forem: André Matulionis</title>
    <description>The latest articles on Forem by André Matulionis (@andrewmat).</description>
    <link>https://forem.com/andrewmat</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%2F138257%2Fd84e9549-8f27-43c7-90cf-886b249027c8.jpg</url>
      <title>Forem: André Matulionis</title>
      <link>https://forem.com/andrewmat</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/andrewmat"/>
    <language>en</language>
    <item>
      <title>How to reuse your UI</title>
      <dc:creator>André Matulionis</dc:creator>
      <pubDate>Fri, 26 Jul 2024 12:49:01 +0000</pubDate>
      <link>https://forem.com/andrewmat/how-to-reuse-your-ui-5fa0</link>
      <guid>https://forem.com/andrewmat/how-to-reuse-your-ui-5fa0</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;If you'd rather read it in portuguese, I've made a &lt;a href="https://dev.to/andrewmat/como-reutilizar-sua-ui-4cpp"&gt;pt-BR version&lt;/a&gt; of this post.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Basically everyone I know ends up creating reusable components when learning about the DRY concept. This is a deceptively simple abstraction: it's easy to create a Button, but it's surprisingly difficult to reuse it across all use cases in a project.&lt;/p&gt;

&lt;p&gt;I've learned a few things over the years, and I see that a lot of people end up messing around without realizing it. Let me share some tips to avoid a messy code.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I have a React bias but everything can be applied in other contexts, as long as there is UI componentization.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Quick Access
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Avoid margins&lt;/li&gt;
&lt;li&gt;Based on HTML props&lt;/li&gt;
&lt;li&gt;Compose components&lt;/li&gt;
&lt;li&gt;Use headless libraries&lt;/li&gt;
&lt;li&gt;Avoid external dependencies&lt;/li&gt;
&lt;li&gt;Migration&lt;/li&gt;
&lt;li&gt;Putting it all together&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  1) Avoid margins
&lt;/h2&gt;

&lt;p&gt;&lt;small&gt;🔗&lt;/small&gt;&lt;/p&gt;

&lt;p&gt;Placing margins in your component ends up breaking the expectation of component reuse. Spacing is important, and your component does not know the context where it will be applied.&lt;/p&gt;

&lt;p&gt;Instead, leave the spacing responsibility to the parent containing the components. It is possible that it uses a different way to manage spacing, such as paddings and gaps.&lt;/p&gt;

&lt;p&gt;There are several ideas &lt;a href="https://markus.oberlehner.net/blog/css-the-spacing-between-elements-should-be-determined-by-the-parent-element/" rel="noopener noreferrer"&gt;¹&lt;/a&gt; &lt;a href="https://mxstbr.com/thoughts/margin" rel="noopener noreferrer"&gt;²&lt;/a&gt; &lt;a href="https://youtu.be/jnV1u67_yVg?si=pTHh4k06pMdu6WXU&amp;amp;t=582" rel="noopener noreferrer"&gt;³&lt;/a&gt; about how spacing should be created in components. But generally the conclusion is not to put spacing externally inerent to your component. It is more reliable for its parent component to handle margins.&lt;/p&gt;

&lt;p&gt;And speaking of the parent component...&lt;/p&gt;

&lt;h2&gt;
  
  
  2) Based on HTML props
&lt;/h2&gt;

&lt;p&gt;&lt;small&gt;🔗&lt;/small&gt;&lt;br&gt;
It is important that components are used in an expected way. Using an interface that everyone knows helps with this, and HTML attributes are a known interface.&lt;/p&gt;

&lt;p&gt;If you want to insert a margin into the component, instead of creating a prop dedicated to the margin, your component can make it a generic &lt;code&gt;div&lt;/code&gt; and accept styles and classes as props. The parent component will have the context and control to extend its component for unexpected cases.&lt;/p&gt;

&lt;p&gt;"But this pattern is very common in the project, should I repeat its declaration in the parent?" Some props can be &lt;strong&gt;added&lt;/strong&gt; alongside the traditional props. It's usually a &lt;code&gt;variant&lt;/code&gt; prop, or &lt;code&gt;size&lt;/code&gt; or similar. I recommend taking a look at libs like &lt;a href="https://cva.style/docs" rel="noopener noreferrer"&gt;&lt;code&gt;CVA&lt;/code&gt;&lt;/a&gt; or &lt;a href="https://vanilla-extract.style/documentation/api/style-variants/" rel="noopener noreferrer"&gt;&lt;code&gt;vanilla-extract&lt;/code&gt;&lt;/a&gt; to manage these props in a scalable way.&lt;/p&gt;

&lt;p&gt;If the prop has a standard HTML name, it also requires no documentation. For new devs it is easier to learn, and for experienced people they create expectations and in turn increases productivity.&lt;/p&gt;

&lt;p&gt;And this tip includes not only the name of each prop but also the value. Avoid creating an innovative contract for the prop, such as enums and objects. Instead, classic strings and JSX props make it easier to use.&lt;/p&gt;

&lt;p&gt;JSX is also used to...&lt;/p&gt;

&lt;h2&gt;
  
  
  3) Compose components
&lt;/h2&gt;

&lt;p&gt;&lt;small&gt;🔗&lt;/small&gt;&lt;/p&gt;

&lt;p&gt;Don't try to create components with too much structure. Create atomic components that are easy to control and reuse, and instead of adding props for bits of UI, use JSX.&lt;/p&gt;

&lt;p&gt;For example, I've already made (and seen) components with props scattered throughout:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;

&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;IconButton&lt;/span&gt;
  &lt;span class="na"&gt;icon&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"success"&lt;/span&gt;
  &lt;span class="na"&gt;iconSize&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"16px"&lt;/span&gt;
  &lt;span class="na"&gt;iconColor&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"black"&lt;/span&gt;
  &lt;span class="na"&gt;iconPosition&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"end"&lt;/span&gt;
&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Click here&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;These props remove control from who will use your component. If customization is required, this person will have to modify the &lt;code&gt;&amp;lt;IconButton/&amp;gt;&lt;/code&gt;, which is rarely a good idea.&lt;/p&gt;

&lt;p&gt;If you split responsibilities and support for children, the code will have a clear structure and whoever uses it will have more control over what they want to do:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;

&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  Click here
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;SuccessIcon&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"icon"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;style&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  .icon &lt;span class="si"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="nx"&gt;px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="nx"&gt;px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;black&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;style&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Over time, some complex components can be structured, always based on these simpler components. New structures can be created based on these atomic components, but these new structures should not stop you from reusing the atomic components.&lt;/p&gt;

&lt;h2&gt;
  
  
  4) Use headless libraries
&lt;/h2&gt;

&lt;p&gt;&lt;small&gt;🔗&lt;/small&gt;&lt;/p&gt;

&lt;p&gt;We have &lt;a href="https://open-ui.org/" rel="noopener noreferrer"&gt;&lt;em&gt;many&lt;/em&gt;&lt;/a&gt; UI patterns that HTML does not support natively today and that devs need to implement from scratch. A classic example is the switch component. It is similar to the checkbox, but both its appearance and interaction have its peculiarities that differ from the standard HTML checkbox.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2a4rnivst1nbhoucgf1l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2a4rnivst1nbhoucgf1l.png" alt="Example switch component, with label "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You create a switch from scratch. It's a cool exercise and you do a good job. But it's likely that you didn't handle the component's keyboard and screen reader navigation correctly.&lt;/p&gt;

&lt;p&gt;You read the specification of &lt;a href="https://www.w3.org/WAI/ARIA/apg/patterns/switch/" rel="noopener noreferrer"&gt;WAI-ARIA&lt;/a&gt; and implement accordingly. But now the code has become so complex that the rest of the team struggles following the code, someone else touches &lt;code&gt;&amp;lt;Switch/&amp;gt;&lt;/code&gt; and they feel insecure not knowing if it broke, and the only one who can update this piece of code is you.&lt;/p&gt;

&lt;p&gt;The project has dozens of reusable components, each bringing the same pain point. As it grows, it becomes easier to create a new component from scratch than to modify the one that already exists. Your reusable component ends up being not reusable.&lt;/p&gt;

&lt;p&gt;Libraries of pre-made components came to facilitate this work. Today there are many styleless libraries, commonly called headless UI, for example &lt;a href="https://react-spectrum.adobe.com/react-aria/components.html" rel="noopener noreferrer"&gt;React Aria&lt;/a&gt;, &lt;a href="https://www.radix-ui.com/primitives" rel="noopener noreferrer"&gt;Radix&lt;/a&gt; and &lt;a href="https://headlessui.com/" rel="noopener noreferrer"&gt;Headless UI&lt;/a&gt; . They implement the expected behavior and you only implement the style.&lt;/p&gt;

&lt;p&gt;You may rather use styled libraries. I haven't had much opportunity to use it, but I know the popular ones: &lt;a href="https://ant.design/components/overview" rel="noopener noreferrer"&gt;Ant Design&lt;/a&gt;, &lt;a href="https://mui.com/material-ui/all-components/" rel="noopener noreferrer"&gt;Material UI&lt;/a&gt; and &lt;a href="https://v2.chakra-ui.com/docs/components" rel="noopener noreferrer"&gt;Chakra UI&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The beauty of using pre-made components is that you have more confidence the page is accessible, without the need for a lot of code to maintain.&lt;/p&gt;

&lt;h2&gt;
  
  
  5) Avoid external dependencies
&lt;/h2&gt;

&lt;p&gt;&lt;small&gt;🔗&lt;/small&gt;&lt;/p&gt;

&lt;p&gt;The first reusable components I made were inputs. As the project standard was to use &lt;a href="https://formik.org/" rel="noopener noreferrer"&gt;Formik&lt;/a&gt; , I created the inputs integrated into Formik.&lt;/p&gt;

&lt;p&gt;This seemed like a good decision at the time. But as the project grew, there were cases that did not align with this expectation, and several of the inputs did not need Formik. This added unnecessary friction that was increasingly difficult to deal with, and made it difficult to migrate to alternative libraries to Formik.&lt;/p&gt;

&lt;p&gt;If your component is truly reusable, it should have no expectations from its context. The more context-free it is, the more reusable it is.&lt;/p&gt;

&lt;p&gt;We can extend it to any logic external to the component. State management (redux), themes (styled components), validations (react-hook-form), layout (flex/grid), and other dependency injections. All integrations must be injected by props or JSX to avoid blocking your component.&lt;/p&gt;

&lt;h2&gt;
  
  
  Extra: 6) Migration
&lt;/h2&gt;

&lt;p&gt;&lt;small&gt;🔗&lt;/small&gt;&lt;/p&gt;

&lt;p&gt;You might be inspired now, but it's possible that your project already has a reusable UI. Changing these components that are in widespread use is complex, and this discourages you from switching to better code.&lt;/p&gt;

&lt;p&gt;But I'm here to say: don't give up on change. Instead, take one step at a time:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Bring the idea to your team. Run proofs of concept, show the value of the changes, and avoid making changes that people don't want to make. Always remember that code is made by humans for humans.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Try to adapt your changes as much as possible with the code that already exists. Some changes add a lot of value to the project, and other changes don't have as much impact. Choose your focus to migrate easily and avoid disrupting workflow.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Think about a migration plan. It is important that everyone on the team is aligned. Add new code, help people use it, deprecate old code, and little by little remove old code from your base.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Putting it all together
&lt;/h2&gt;

&lt;p&gt;&lt;small&gt;🔗&lt;/small&gt;&lt;/p&gt;

&lt;p&gt;Finally, an example of a basic &lt;code&gt;&amp;lt;Button/&amp;gt;&lt;/code&gt;:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;ComponentPropsWithoutRef&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;forwardRef&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;Link&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-router-dom&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;Slot&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@radix-ui/react-slot&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;clsx&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;clsx&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./button.module.css&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Props&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ComponentPropsWithoutRef&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;button&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;asChild&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Button&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;forwardRef&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;HTMLButtonElement&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Props&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;asChild&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Comp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;asChild&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;Slot&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;button&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Comp&lt;/span&gt;
        &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;clsx&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Explaining the code above:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It is a component that accepts all generic attributes as props &lt;code&gt;&amp;lt;button/&amp;gt;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;It accepts a ref value&lt;/li&gt;
&lt;li&gt;It implements a class &lt;code&gt;.button&lt;/code&gt; that adds project-specific styles&lt;/li&gt;
&lt;li&gt;I've used the Radix &lt;code&gt;Slot&lt;/code&gt; component which helps me applying the button style to another component, it can be enabled using the prop &lt;code&gt;asChild&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;

&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"my-class"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;See details&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt; &lt;span class="na"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;buttonRef&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Send info&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt; &lt;span class="na"&gt;asChild&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Link&lt;/span&gt; &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/login"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Enter&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Link&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;In the end, reusable code helps a lot, but it is an abstraction and therefore must be well thought out. Creating reusable code that doesn't adapt to all contexts can create a snowball. It is important to use already recognized standards and give devs control to use them in unexpected ways.&lt;/p&gt;

</description>
      <category>frontend</category>
      <category>ui</category>
      <category>designsystem</category>
    </item>
    <item>
      <title>Como reutilizar sua UI</title>
      <dc:creator>André Matulionis</dc:creator>
      <pubDate>Wed, 03 Jul 2024 23:18:43 +0000</pubDate>
      <link>https://forem.com/andrewmat/como-reutilizar-sua-ui-4cpp</link>
      <guid>https://forem.com/andrewmat/como-reutilizar-sua-ui-4cpp</guid>
      <description>&lt;p&gt;Basicamente todo mundo que conheço acaba criando componentes reutilizáveis para reaproveitar o trabalho feito. Essa é uma abstração enganosamente simples: é fácil criar um Button, mas é surpreendentemente difícil conseguir reutilizar ele em todos os casos de uso em um projeto.&lt;/p&gt;

&lt;p&gt;Eu aprendi algumas coisas com o passar dos anos, e vejo que várias pessoas acabam metendo o pé na jaca sem perceber. Quero compartilhar algumas dicas para evitar que algumas jacas sejam pisadas.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Tenho um viés de React mas tudo pode ser aplicado em outros contextos, desde que tenha componentização da UI.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Acesso rápido
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Evite margens&lt;/li&gt;
&lt;li&gt;Se inspire em props HTML&lt;/li&gt;
&lt;li&gt;Componhe componentes&lt;/li&gt;
&lt;li&gt;Utilize bibliotecas headless&lt;/li&gt;
&lt;li&gt;Evite dependências externas&lt;/li&gt;
&lt;li&gt;Extra: Migração&lt;/li&gt;
&lt;li&gt;Juntando tudo&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  1) Evite margens 🔗
&lt;/h2&gt;

&lt;p&gt;Colocar margens no seu componente acaba quebrando a expectativa de reuso do componente. Espaçamento é algo importante, e seu componente não conhece onde vai ser aplicado.&lt;/p&gt;

&lt;p&gt;Ao invés disso, deixe a responsabilidade de espaçamento para o pai que contém os componentes. É possível que ele utilize uma forma nova para gerenciar espaçamentos, como paddings e gaps.&lt;/p&gt;

&lt;p&gt;Existem várias conversas &lt;a href="https://markus.oberlehner.net/blog/css-the-spacing-between-elements-should-be-determined-by-the-parent-element/"&gt;¹&lt;/a&gt; &lt;a href="https://mxstbr.com/thoughts/margin"&gt;²&lt;/a&gt; &lt;a href="https://youtu.be/jnV1u67_yVg?si=pTHh4k06pMdu6WXU&amp;amp;t=582"&gt;³&lt;/a&gt; sobre como deve ser criado espaçamentos nos componentes. Mas geralmente a conclusão é não colocar espaçamento externo. É mais confiável que seu componente pai lide com margens.&lt;/p&gt;

&lt;p&gt;E falando no componente pai...&lt;/p&gt;

&lt;h2&gt;
  
  
  2) Se inspire em props HTML 🔗
&lt;/h2&gt;

&lt;p&gt;É importante que componentes sejam utilizados de uma forma esperada. Utilizar uma interface que todo mundo conhece ajuda nisso, e os atributos HTML são uma interface conhecida.&lt;/p&gt;

&lt;p&gt;Caso queira inserir uma margem no componente, ao invés de criar uma prop dedicada à margem seu componente pode fazer como uma &lt;code&gt;div&lt;/code&gt; genérica e aceitar estilos e classes como prop. O componente pai vai ter o contexto e o controle para estender seu componente para casos não esperados.&lt;/p&gt;

&lt;p&gt;"Mas esse padrão é muito comum no projeto, vou ter que declarar sempre no pai?". Algumas props podem ser colocadas &lt;strong&gt;a mais&lt;/strong&gt; com as props tradicionais ainda tendo destaque. Geralmente é uma prop &lt;code&gt;variant&lt;/code&gt;, &lt;code&gt;size&lt;/code&gt;, ou similar. Recomendo dar uma olhada em libs como &lt;a href="https://cva.style/docs"&gt;CVA&lt;/a&gt; ou &lt;a href="https://vanilla-extract.style/documentation/api/style-variants/"&gt;vanilla-extract&lt;/a&gt; pra gerenciar essas props de forma escalável.&lt;/p&gt;

&lt;p&gt;Se a prop tiver um nome padrão do HTML ela também dispensa documentação. Para devs novos é mais fácil aprender, e para pessoas experientes já tem uma expectativa e isso aumenta a produtividade.&lt;/p&gt;

&lt;p&gt;E isso inclui não só o nome de cada prop mas também o valor. Evite criar um contrato muito inovador na prop, como enums e objetos. Ao invés disso, as strings clássicas e JSX conseguem facilitar o uso.&lt;/p&gt;

&lt;p&gt;E falando em JSX...&lt;/p&gt;

&lt;h2&gt;
  
  
  3) Componhe componentes 🔗
&lt;/h2&gt;

&lt;p&gt;Não tente criar componentes com muita estrutura. Crie componentes atômicos que sejam fáceis de controlar e reutilizar, e ao invés de colocar props para pedaços de UI, use JSX.&lt;/p&gt;

&lt;p&gt;Por exemplo, já fiz (e vi) props espalhadas no componente:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;IconButton&lt;/span&gt;
  &lt;span class="na"&gt;icon&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"success"&lt;/span&gt;
  &lt;span class="na"&gt;iconSize&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"16px"&lt;/span&gt;
  &lt;span class="na"&gt;iconColor&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"black"&lt;/span&gt;
  &lt;span class="na"&gt;iconPosition&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"end"&lt;/span&gt;
&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Clique Aqui&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Essas props removem o controle de quem vai utilizar seu componente. Caso precise de customização, a pessoa vai ter que modificar o IconButton, o que raramente é uma boa ideia.&lt;/p&gt;

&lt;p&gt;Caso você separe as responsabilidades e suporte children, o código vai ter uma estrutura clara e quem o utilizar vai ter mais controle do que querem fazer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  Clique aqui
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;SuccessIcon&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"icon"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;style&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  .icon &lt;span class="si"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="nx"&gt;px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="nx"&gt;px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;black&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;style&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Com o tempo, alguns componentes complexos podem ser estruturados mas sempre com base nesses componentes mais simples. Novas estruturas vão ser criadas com base nesses componentes atômicos, mesmo assim não esconda eles por trás dessas estruturas.&lt;/p&gt;

&lt;h2&gt;
  
  
  4) Utilize bibliotecas headless 🔗
&lt;/h2&gt;

&lt;p&gt;Temos &lt;em&gt;muitos&lt;/em&gt; padrões de UI que hoje o HTML não suporta nativamente e que devs precisam implementar do zero. Um exemplo clássico é o componente de switch. Ele é parecido com o checkbox, mas tanto seu visual quanto sua interação tem suas peculiaridades que diferem do checkbox padrão do HTML.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2a4rnivst1nbhoucgf1l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2a4rnivst1nbhoucgf1l.png" alt="Componente switch de exemplo, com a label " width="372" height="99"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Você cria um switch do zero. É um exercício legal e você faz um bom trabalho. Mas é provável  que você não lidou corretamente com a navegação por teclado e leitor de tela do componente.&lt;/p&gt;

&lt;p&gt;Você lê a &lt;a href="https://www.w3.org/WAI/ARIA/apg/patterns/switch/"&gt;especificação no WAI-ARIA&lt;/a&gt; e implementa de acordo com ela. Mas agora o código ficou tão complexo que todo o resto do time tem dificuldades para acompanhar o código, e o único que consegue mexer nele é você. Se outra pessoa mexe no &lt;code&gt;&amp;lt;Switch /&amp;gt;&lt;/code&gt; ela fica insegura sem saber se quebrou algo.&lt;/p&gt;

&lt;p&gt;O projeto tem dezenas de componente reutilizáveis cada um trazendo essa dor. Conforme cresce fica mais rápido fazer um componente do zero do que modificar o que já existe. Seu componente reutilizável acaba não reutilizado.&lt;/p&gt;

&lt;p&gt;Bibliotecas de componentes pré-feitos vieram pra facilitar esse trabalho. Hoje existem muitas bibliotecas sem estilos, chamadas de headless UI, por exemplo &lt;a href="https://react-spectrum.adobe.com/react-aria/components.html"&gt;React Aria&lt;/a&gt;, &lt;a href="https://www.radix-ui.com/primitives"&gt;Radix&lt;/a&gt; e &lt;a href="https://headlessui.com/"&gt;Headless UI&lt;/a&gt;. Elas implementam o comportamento esperado e você implementa o estilo.&lt;/p&gt;

&lt;p&gt;Se preferir, tem como utilizar bibliotecas estilizadas. Eu não tive muita oportunidade de utilizar, mas conheço as populares &lt;a href="https://ant.design/components/overview"&gt;Ant Design&lt;/a&gt;, &lt;a href="https://mui.com/material-ui/all-components/"&gt;Material UI&lt;/a&gt; e &lt;a href="https://v2.chakra-ui.com/docs/components"&gt;Chakra UI&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;A beleza de utilizar componentes pré-prontos é que você cria mais confiança que a página esteja acessível, sem a necessidade de muito código para manter.&lt;/p&gt;

&lt;h2&gt;
  
  
  5) Evite dependências externas 🔗
&lt;/h2&gt;

&lt;p&gt;Os primeiros componentes reutilizáveis que fiz foram inputs. Como o padrão do projeto era utilizar &lt;a href="https://formik.org/"&gt;Formik&lt;/a&gt;, criei os inputs integrados ao Formik.&lt;/p&gt;

&lt;p&gt;Isso parecia uma decisão acertada na época. Mas conforme o projeto foi crescendo tinham casos que não se alinhavam com essa expectativa, e vários dos inputs não precisavam do Formik. Isso adicionava uma fricção desnecessária cada vez mais difícil de lidar, e dificultou a migração para bibliotecas alternativas ao Formik.&lt;/p&gt;

&lt;p&gt;Se seu componente é realmente reutilizável, ele não deve ter expectativas do seu contexto. Quanto mais ele sabe for livre do contexto, mais reutilizável ele é.&lt;/p&gt;

&lt;p&gt;Podemos estender para qualquer lógica externa ao componente. Gerenciamento de estado (redux), temas (styled components), validações (react-hook-form), layout (flex/grid), e outras injeções de dependências. Toda as integrações devem ser injetadas por props para não engessar seu componente.&lt;/p&gt;

&lt;h2&gt;
  
  
  Extra: 6) Migração 🔗
&lt;/h2&gt;

&lt;p&gt;Talvez você fique inspirado agora, mas é possível que seu projeto já tenha UI reutilizável. Mudar esses componentes que têm seu uso generalizado é uma tarefa complicada, e isso desencoraja a mudança para um código melhor.&lt;/p&gt;

&lt;p&gt;Não desista da mudança. Dê um passo de cada vez:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Traga a ideia para o seu time. Faça provas de conceito, mostre o valor das mudanças, e evite fazer mudanças que as pessoas não querem fazer. Lembre-se que o código é feito para os humanos.&lt;/li&gt;
&lt;li&gt;Tente adaptar ao máximo com o código que já existe. Algumas mudanças adicionam muito valor ao projeto, e outras mudanças não tem tanto impacto. Escolha seu foco pra facilitar o uso.&lt;/li&gt;
&lt;li&gt;Pense em um plano de migração. É importante que todos do time estejam alinhados. Adicione o código novo, ajude pessoas a utilizá-lo, depreque código antigo, e de pouco em pouco remova o código antigo da sua base.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Juntando tudo 🔗
&lt;/h2&gt;

&lt;p&gt;Para terminar, um exemplo de um &lt;code&gt;&amp;lt;Button /&amp;gt;&lt;/code&gt; básico.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;ComponentPropsWithoutRef&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;forwardRef&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;Link&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react-router-dom&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;Slot&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@radix-ui/react-slot&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;clsx&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;clsx&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./button.module.css&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Props&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ComponentPropsWithoutRef&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;button&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;asChild&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Button&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;forwardRef&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;HTMLButtonElement&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Props&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;asChild&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Comp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;asChild&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;Slot&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;button&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Comp&lt;/span&gt;
        &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;clsx&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Explicando o código acima:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;É um componente que aceita como props todos os atributos do &lt;code&gt;&amp;lt;button /&amp;gt;&lt;/code&gt; genérico.&lt;/li&gt;
&lt;li&gt;Ele aceita receber &lt;code&gt;ref&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Ele implementa uma classe &lt;code&gt;.button&lt;/code&gt; que adiciona os estilos do projeto&lt;/li&gt;
&lt;li&gt;Caso você queira aplicar o estilo do botão em um outro componente, é possível através da prop &lt;code&gt;asChild&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"minha-classe"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Ver detalhes&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt; &lt;span class="na"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;buttonRef&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Enviar dados&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt; &lt;span class="na"&gt;asChild&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Link&lt;/span&gt; &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/login"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Entrar&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Link&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No fim, código reutilizável ajuda bastante, mas ele é uma abstração e portanto deve ser bem pensado. Criar código reutilizável que não se adapta a todos os contextos pode criar uma bola de neve. É importante utilizar padrões já reconhecidos e dar controle para os devs utilizarem de formas não esperadas.&lt;/p&gt;

</description>
      <category>braziliandevs</category>
      <category>frontend</category>
      <category>ui</category>
      <category>designsystem</category>
    </item>
    <item>
      <title>Acessibilidade = Usabilidade</title>
      <dc:creator>André Matulionis</dc:creator>
      <pubDate>Fri, 21 Jun 2024 22:43:53 +0000</pubDate>
      <link>https://forem.com/andrewmat/acessibilidade-usabilidade-362c</link>
      <guid>https://forem.com/andrewmat/acessibilidade-usabilidade-362c</guid>
      <description>&lt;p&gt;Nós devs frontend não devemos pensar em acessibilidade como uma coisa separada de usabilidade. Usabilidade é um termo empregado pra dizer quão fácil é que o usuário consiga alcançar o que deseja com o produto. E o design tem que ser pensado considerando o perfil de usuário para melhorar a usabilidade.&lt;/p&gt;

&lt;p&gt;Um exemplo são os atalhos de teclado como &lt;code&gt;o Ctrl C&lt;/code&gt; / &lt;code&gt;Ctrl V&lt;/code&gt;, que facilitam a tarefa para uma porção de usuários. Ao mesmo tempo, é importante deixar alternativas para usuários sem ciência desse atalho, por conta disso que no menu de contexto (botão direito do mouse) geralmente você encontra um "copiar" e um "colar" ali.&lt;/p&gt;

&lt;p&gt;Acessibilidade é a mesma coisa que usabilidade, só que empregada para perfis específicos de usuário, geralmente portadores de deficiência. Um campo inacessível é um bug crítico de usabilidade com impacto igual a (ou maior que) um botão difícil de usar ou um carregamento lento.&lt;/p&gt;

&lt;p&gt;Algumas coisitas que podemos fazer para melhorar no nosso dia a dia de dev frontend:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Aprenda mais sobre acessibilidade. Muitas gente aprende sobre "alt" e "tags semânticas" e pára aí. Aprenda sobre WCAG, WAI-ARIA, media features, e dissemine seu aprendizado.&lt;/li&gt;
&lt;li&gt;Não reinvente a roda. HTML tem bastante coisa nativamente, e onde ele sozinho não consegue, use bibliotecas de componentes headless, tem muitas alternativas mas pessoalmente gosto de usar o Radix.&lt;/li&gt;
&lt;li&gt;Batalhe pelo usuário. Quando for implementar algo novo, sempre considere como fator de implementação adaptar esse algo para uma gama de necessidades de usuários diferentes.&lt;/li&gt;
&lt;li&gt;Teste o que criou, não fique só na teoria. Use leitores de tela, ou outras ferramentas de acessibilidade, para confirmar que o que fez está correto.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>braziliandevs</category>
      <category>frontend</category>
      <category>a11y</category>
    </item>
    <item>
      <title>Um rant sobre API mal feita</title>
      <dc:creator>André Matulionis</dc:creator>
      <pubDate>Sat, 09 Mar 2024 13:42:47 +0000</pubDate>
      <link>https://forem.com/andrewmat/um-rant-sobre-api-mal-feita-1p9h</link>
      <guid>https://forem.com/andrewmat/um-rant-sobre-api-mal-feita-1p9h</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Esse post é mais reclamação do que um argumento bem feito. Por favor não leve tão a sério.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Eu trabalhei vários anos com Formik. Não gosto muito dele, já que ele tem um aspecto "boilerplate". Por conta disso, queria aprender como lidar com forms de outras maneiras.&lt;/p&gt;

&lt;p&gt;No projeto que estou trabalhando hoje, já temos o &lt;code&gt;react-hook-form&lt;/code&gt; instalado. Eu não tenho experiência com ele, então resolvi aproveitar a oportunidade.&lt;/p&gt;

&lt;p&gt;Resumindo bastante, eu odiei. Fiquei trabalhando até tarde para tentar resolver um form com ele, e no final eu desisti e usei React puro. A API dele é bem complexa, e a documentação não ajuda.&lt;/p&gt;

&lt;h2&gt;
  
  
  Um exemplo
&lt;/h2&gt;

&lt;p&gt;Eu estava usando um form simples que tem um único campo de username. Esse campo não aceita espaços, e se o usuário inputar espaço, ele deve ignorar. Além disso, o campo tem algumas validações.&lt;/p&gt;

&lt;p&gt;Utilizando React puro, essa solução é possível.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;UsernameForm&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="nx"&gt;onSubmit&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;form&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useForm&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setUsername&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isValid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;validateUsername&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt; &lt;span class="na"&gt;onSubmit&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;handleSubmit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;onSubmit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt;
        &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"username"&lt;/span&gt;
        &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; 
            &lt;span class="nf"&gt;setUsername&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replaceAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; &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="p"&gt;))&lt;/span&gt;
        &lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt; &lt;span class="na"&gt;disabled&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;isValid&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Salvar&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Observação: nesse exemplo de username, remover espaços do input sem feedback é frustrante ao usuário e não recomendo. No meu caso real, o campo era um tanto mais complicado e o design já lidava com isso.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Esse exemplo deriva do conceito de &lt;code&gt;controlled inputs&lt;/code&gt; que está na &lt;a href="https://react.dev/reference/react-dom/components/input#reference"&gt;documentação oficial do React&lt;/a&gt;. É um exemplo simples do que pode ser feito em React.&lt;/p&gt;

&lt;p&gt;Porém, isso entra em conflito com o &lt;code&gt;react-hook-form&lt;/code&gt;. Tanto eu quanto ele precisamos ter controle das props do componente. Como vamos resolver esse conflito?&lt;/p&gt;

&lt;p&gt;A API dele ajuda bastante em alguns casos. Se eu quero adicionar um &lt;code&gt;onChange&lt;/code&gt; no meu input, eu consigo passar pra ele.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt;
  &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;username&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;onChange&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`username agora é &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No caso de controlled component, eu preciso de duas props: value e onChange.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt;
  &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;username&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;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setUsername&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replaceAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; &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="p"&gt;))&lt;/span&gt;
    &lt;span class="na"&gt;validate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;validateUsername&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Funcionou! Quer dizer, mais ou menos. Ele não tá validando o form quando atualizo o username. &lt;code&gt;formState.isValid&lt;/code&gt; sempre está retornando &lt;code&gt;false&lt;/code&gt;, mesmo quando o username está válido.&lt;/p&gt;

&lt;h2&gt;
  
  
  Debugando
&lt;/h2&gt;

&lt;p&gt;Fiquei tentando entender isso durante bastante tempo. Debuguei minha função de validação, fiz várias mudanças nos parâmetros de &lt;code&gt;useForm&lt;/code&gt; e &lt;code&gt;register&lt;/code&gt;, refatorei meu input, mas não mudava nada.&lt;/p&gt;

&lt;p&gt;Depois de meia hora procurando na documentação, achei um pequeno ponto na API do &lt;code&gt;register&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;value: Set up value for the registered input. This prop should be utilised inside useEffect or invoke once, each re-run will update or overwrite the input value which you have supplied.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Então eu tava utilizando &lt;code&gt;register&lt;/code&gt; de forma errada! Eu não deveria mandar &lt;code&gt;value&lt;/code&gt; como prop diretamente no componente. Mas então, como faço pra controlar meu componente?&lt;/p&gt;

&lt;p&gt;Depois de mais meia hora procurando na documentação, eu achei algo que parecia o que eu queria. E tentei aplicar.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;UsernameForm&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="nx"&gt;onSubmit&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;form&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useForm&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;username&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;watch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;username&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;username&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;validate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;validateUsername&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;register&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt; &lt;span class="na"&gt;onSubmit&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;handleSubmit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;onSubmit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt;
        &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt;
        &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
            &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;username&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replaceAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; &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="p"&gt;))&lt;/span&gt;
        &lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Salvar&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para ver esse código no doc, precisa acessar &lt;a href="https://react-hook-form.com/advanced-usage#ControlledmixedwithUncontrolledComponents"&gt;esse link&lt;/a&gt; e clicar em &lt;em&gt;Custom register&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Achei isso incrivelmente frustrante. Na documentação, esse código está num canto escondido da parte avançada. O código também cria vários átomos de código que estão separados, mas que são bem entrelaçadas. E ainda por cima, ele adiciona um &lt;code&gt;useEffect&lt;/code&gt;, um hook que idealmente seria utilizado pra sincronizar com sistemas &lt;em&gt;externos&lt;/em&gt;, embora o form seja bem autossuficiente.&lt;/p&gt;

&lt;p&gt;A API inicialmente fez algo muito bom, colocar &lt;code&gt;onChange&lt;/code&gt; no &lt;code&gt;register&lt;/code&gt; é uma solução simples e completa. Só que criar um &lt;code&gt;value&lt;/code&gt; que não age como o esperado é uma decisão tão burra que me falta palavras pra descrever. Eu tenho certeza que essa decisão trouxe bugs em aplicações e frustrações para devs.&lt;/p&gt;

&lt;p&gt;Ao mesmo tempo, a solução oficial de utilizar um conjunto de &lt;code&gt;watch&lt;/code&gt;, um &lt;code&gt;useEffect&lt;/code&gt; com &lt;code&gt;register&lt;/code&gt;, e um &lt;code&gt;setValue&lt;/code&gt; parece uma solução tão mal pensada que estou incrédulo até agora. Como &lt;code&gt;react-hook-form&lt;/code&gt; é algo tão popular se não lida com um caso de uso simples?&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusão
&lt;/h2&gt;

&lt;p&gt;Vou usar Zod puro agora&lt;/p&gt;

</description>
      <category>react</category>
      <category>braziliandevs</category>
    </item>
    <item>
      <title>Sobre cores no CSS</title>
      <dc:creator>André Matulionis</dc:creator>
      <pubDate>Fri, 08 Sep 2023 20:02:10 +0000</pubDate>
      <link>https://forem.com/andrewmat/sobre-cores-no-css-1gg9</link>
      <guid>https://forem.com/andrewmat/sobre-cores-no-css-1gg9</guid>
      <description>&lt;p&gt;Recentemente &lt;a href="https://www.youtube.com/watch?v=lDxj2hVkDPs" rel="noopener noreferrer"&gt;vi um vídeo&lt;/a&gt; onde várias pessoas conversavam sobre cores. No final do vídeo, o moço Tom Scott mostrou suas habilidades de desenvolvedor mostrando que sabe traduzir um código hexadecimal (#BADBED) a sua cor equivalente:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;BA é um valor alto de vermelho&lt;/li&gt;
&lt;li&gt;DB é um valor mais alto ainda de verde&lt;/li&gt;
&lt;li&gt;ED é um valor quase absoluto de azul&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Misturando essas cores, ele concluiu que a cor seria um "ciano bem pastel", o que deixou todo mundo estupefato. Isso pode parecer incrível, mas é cotidiano para algum programador frontend mais experiente. Se você quiser converter para números, também temos a notação &lt;code&gt;rgb()&lt;/code&gt; que converte números de 0 a 255 para os três canais de cores: &lt;code&gt;rgb(186 219 237)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Mesmo assim, existe algo com RGB que não me agrada. Resolver ele não é intuitivo, você tem que fazer "contas" com as cores, na hora &lt;br&gt;
de converter para uma porcentagem e na hora de misturar as cores.&lt;/p&gt;

&lt;p&gt;Computadores entendem RGB, eles foi feita pra isso, mas para humanos, o processo é cansativo, já que não é o jeito que pensamos em cores.&lt;/p&gt;
&lt;h2&gt;
  
  
  Entra HSL
&lt;/h2&gt;

&lt;p&gt;Quando vou descrever cores para pessoas, não uso notação RGB, "essa cor tem muito vermelho, e muito verde e só metade de verde". Eu geralmente falo "um amarelo claro", ou "um vermelho bem forte".&lt;/p&gt;

&lt;p&gt;Criar cores HSL é mais intuitivo porque acaba adotando uma linguagem similiar. Nela temos três argumentos para descrever a cor:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;h&lt;/code&gt;: &lt;strong&gt;Hue&lt;/strong&gt; (ou matiz) controla a cor em si. É um valor que vai de 0deg a 360deg&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;s&lt;/code&gt;: &lt;strong&gt;Saturation&lt;/strong&gt; controla quanto da cor é colocado. 0% transforma em cinza e 100% cria uma cor saturada&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;l&lt;/code&gt;: &lt;strong&gt;Lightness&lt;/strong&gt; controla quanto de luminosidade é inserida na cor. 10% cria uma cor bem escuro, e 90% uma cor bem clara.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Pra ser sincero, não gosto muito do controle de Hue, não é muito intuitivo pensar em cores através de uma roda.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fupload.wikimedia.org%2Fwikipedia%2Fcommons%2Fb%2Fbb%2FLinear_RGB_color_wheel.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fupload.wikimedia.org%2Fwikipedia%2Fcommons%2Fb%2Fbb%2FLinear_RGB_color_wheel.png" alt="Roda de cores"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Mesmo assim, é fácil pegar o jeito, e depois disso não precisa fazer mais cálculos com cores.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;0deg é vermelho&lt;/li&gt;
&lt;li&gt;180deg é ciano&lt;/li&gt;
&lt;li&gt;entre 0deg e 180deg tem laranja, amarelo e verde&lt;/li&gt;
&lt;li&gt;entre 180deg e 360deg tem azul, rosa e lilás&lt;/li&gt;
&lt;li&gt;Se eu me perder, lembro de um arco-íris&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Uma combinação assim não é só mais intuitiva, também tem um controle mais simples e facilita a criação de temas.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;

&lt;span class="nd"&gt;:root&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;--hue-primary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;220deg&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;--color-primary-light&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hsl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--hue-primary&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="m"&gt;60%&lt;/span&gt; &lt;span class="m"&gt;80%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;--color-primary-dark&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hsl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--hue-primary&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="m"&gt;90%&lt;/span&gt; &lt;span class="m"&gt;20%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="py"&gt;--hue-secondary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--hue-blue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;+&lt;/span&gt; &lt;span class="m"&gt;120deg&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;--color-secondary-light&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hsl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--hue-secondary&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="m"&gt;60%&lt;/span&gt; &lt;span class="m"&gt;80%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="py"&gt;--color-secondary-dark&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hsl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;--hue-secondary&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="m"&gt;90%&lt;/span&gt; &lt;span class="m"&gt;20%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;(Eu duvido que consegue fazer isso usando notação rgb)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;iframe src="https://codesandbox.io/embed/hsl-colors-5m52sj"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  OKLCH
&lt;/h2&gt;

&lt;p&gt;Temos HSL, e até recentemente eu estava bem satisfeito com essa notação.&lt;/p&gt;

&lt;p&gt;Descobri recentemente sobre a notação &lt;code&gt;oklch()&lt;/code&gt;. Ela resolve problemas que eu nem tinha percebido que existiam. É mais intuitiva, mais fácil de controlar, e abrange novas cores que não existem na RGB.&lt;/p&gt;

&lt;p&gt;Embora a notação seja maior, &lt;code&gt;oklch()&lt;/code&gt; ainda tem três argumentos. Ignora o 'ok' no nome e considera somente o 'lch':&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;l&lt;/code&gt;: &lt;strong&gt;Lightness&lt;/strong&gt; controla a luminosidade igual ao &lt;code&gt;hsl()&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;c&lt;/code&gt;: &lt;strong&gt;Chroma&lt;/strong&gt; controla a intensidade, diferente da saturação do &lt;code&gt;hsl()&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;h&lt;/code&gt;: &lt;strong&gt;Hue&lt;/strong&gt; controla a cor em si igual ao &lt;code&gt;hsl()&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Chroma vs Saturation
&lt;/h3&gt;

&lt;p&gt;Uma coisa que acabei aprendendo a lidar com &lt;code&gt;hsl()&lt;/code&gt; é que cores de matizes diferentes tem "intensidades diferentes".&lt;/p&gt;

&lt;p&gt;Um exemplo: três cores, todas com saturação máxima de 100%.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;

&lt;span class="nc"&gt;.red&lt;/span&gt;   &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hsl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0deg&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt; &lt;span class="m"&gt;50%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.green&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hsl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;120deg&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt; &lt;span class="m"&gt;50%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.blue&lt;/span&gt;  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hsl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;240deg&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt; &lt;span class="m"&gt;50%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;&lt;iframe src="https://codesandbox.io/embed/saturation-intensity-qplkjy"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Na minha experiência eu me adequei com valores de saturação diferentes para matizes diferentes. No exemplo, o texto no quadrado azul está bem menos visível do que o texto no quadrado verde.&lt;/p&gt;

&lt;p&gt;Com &lt;code&gt;oklch()&lt;/code&gt;, isso não é mais necessário. Ele se restringe de forma que distribui melhor a intensidade&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;

&lt;span class="nc"&gt;.red&lt;/span&gt;   &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;oklch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;60%&lt;/span&gt; &lt;span class="m"&gt;50%&lt;/span&gt; &lt;span class="m"&gt;30deg&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.green&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;oklch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;60%&lt;/span&gt; &lt;span class="m"&gt;50%&lt;/span&gt; &lt;span class="m"&gt;150deg&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.blue&lt;/span&gt;  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;oklch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;60%&lt;/span&gt; &lt;span class="m"&gt;50%&lt;/span&gt; &lt;span class="m"&gt;250deg&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;&lt;iframe src="https://codesandbox.io/embed/stoic-robinson-qmqj9h"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Isso facilita bastante na hora de criar paletas de cores, já que elas são bem consistentes na faixa completa de matizes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cores novas e mais vivas
&lt;/h3&gt;

&lt;p&gt;Uma das coisas que &lt;code&gt;oklch()&lt;/code&gt; traz, junto com outras notações, é a possibilidade de descrever cores em um espaço de cor mais completo.&lt;/p&gt;

&lt;p&gt;Sem entrar em muita tecnicalidade, mas por anos o padrão de espaço de cor foi o &lt;a href="https://en.wikipedia.org/wiki/SRGB" rel="noopener noreferrer"&gt;sRGB&lt;/a&gt;, um espaço de cor que funciona muito bem.&lt;/p&gt;

&lt;p&gt;Porém, mais recentemente, a Apple, com esse negócio de criar design que ela gosta, criou e adotou um espaço de cor mais completo, o &lt;a href="https://webkit.org/blog/10042/wide-gamut-color-in-css-with-display-p3/" rel="noopener noreferrer"&gt;Display-P3&lt;/a&gt;, que resolve pequenos problemas que sRGB tinham, além de aumentar o espaço de cores possíveis de serem exibidas.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwebkit.org%2Fwp-content%2Fuploads%2Fsrgb-vs-display-p3-intro.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwebkit.org%2Fwp-content%2Fuploads%2Fsrgb-vs-display-p3-intro.png" alt="Comparativo de gradientes de cores do arco-íris dos espaços sRGB e P3, o P3 é mais vivo que o sRGB"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Com o tempo, dispositivos além da Apple começaram a suportar P3. Hoje ainda não é amplamente disponível, mas com certeza faz a diferença para monitores e celulares que são capazes de utilizar esse espaço de cor.&lt;/p&gt;

&lt;h3&gt;
  
  
  Gradientes com grey zones
&lt;/h3&gt;

&lt;p&gt;Alguns gradientes tem o problema clássico de criarem um espaço cinza na transição de cores.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuj4n5as6o2r02vfzvqo5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuj4n5as6o2r02vfzvqo5.png" alt="Diagrama mostrando a transição de gradiente na roda de cores, onde a linha de gradiente entre o amarelo e o azul cruzam o meio da roda que tem saturação baixa"&gt;&lt;/a&gt;&lt;br&gt;Imagem retirada de &lt;a href="https://css-tricks.com/the-gray-dead-zone-of-gradients/" rel="noopener noreferrer"&gt;CSS Tricks&lt;/a&gt;
  &lt;/p&gt;

&lt;p&gt;Esse problema é comum no espaço sRGB. Como oklch() se expressa através do espaço P3, temos suavidade no gradiente, já que o gradiente se "curva" para usar mais as cores e diminuir a zona cinza.&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://codesandbox.io/embed/gradient-gray-dead-zone-yy548g"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Suporte
&lt;/h2&gt;

&lt;p&gt;A notação &lt;code&gt;hsl()&lt;/code&gt; já é segura e &lt;a href="https://caniuse.com/mdn-css_types_color_hsl" rel="noopener noreferrer"&gt;pode ser utilizada&lt;/a&gt; em qualquer browser. Até IE9 suporta ela!&lt;/p&gt;

&lt;p&gt;A notação &lt;code&gt;oklch()&lt;/code&gt; já &lt;a href="https://caniuse.com/mdn-css_types_color_oklch" rel="noopener noreferrer"&gt;tem suporte&lt;/a&gt; de todos os browsers modernos. Safari implementou no começo de 2022, e browsers como Chrome, Edge, Opera, Firefox e Samsung Internet começaram a suportar em 2023.&lt;/p&gt;

&lt;p&gt;Infelizmente, o espaço de cor P3 precisam de suporte do hardware, o que ainda é restritivo para boa parte das pessoas. Porém, a notação &lt;code&gt;oklch()&lt;/code&gt; já pode ser utilizada mesmo para dispositivos que usem sRGB.&lt;/p&gt;

&lt;h2&gt;
  
  
  Finalmentes
&lt;/h2&gt;

&lt;p&gt;Eu espero que tenha convencido você de mudar do hexadecimal/rgb clássicos para notações mais intuitivas e humanas de aplicar cores. Experimente criar cores com a ajuda da &lt;code&gt;oklch()&lt;/code&gt;, e use &lt;code&gt;hsl()&lt;/code&gt; para projetos em produção. Argumento não falta para mudar.&lt;/p&gt;

&lt;h2&gt;
  
  
  Veja mais argumentos (em inglês)
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://evilmartians.com/chronicles/oklch-in-css-why-quit-rgb-hsl" rel="noopener noreferrer"&gt;https://evilmartians.com/chronicles/oklch-in-css-why-quit-rgb-hsl&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.smashingmagazine.com/2023/08/oklch-color-spaces-gamuts-css/" rel="noopener noreferrer"&gt;https://www.smashingmagazine.com/2023/08/oklch-color-spaces-gamuts-css/&lt;/a&gt;&lt;br&gt;
&lt;a href="https://webkit.org/blog/10042/wide-gamut-color-in-css-with-display-p3/" rel="noopener noreferrer"&gt;https://webkit.org/blog/10042/wide-gamut-color-in-css-with-display-p3/&lt;/a&gt;&lt;br&gt;
&lt;a href="https://blog.logrocket.com/oklch-css-consistent-accessible-color-palettes/" rel="noopener noreferrer"&gt;https://blog.logrocket.com/oklch-css-consistent-accessible-color-palettes/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>css</category>
      <category>braziliandevs</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Procurando a motivação</title>
      <dc:creator>André Matulionis</dc:creator>
      <pubDate>Thu, 20 Apr 2023 19:44:43 +0000</pubDate>
      <link>https://forem.com/andrewmat/procurando-a-motivacao-49kg</link>
      <guid>https://forem.com/andrewmat/procurando-a-motivacao-49kg</guid>
      <description>&lt;p&gt;Esse post não é sobre código. Mesmo se não souber programar, você não deve ter dificuldades em acompanhar 😄&lt;/p&gt;




&lt;p&gt;Eu já ouvi bastante feedback no meu trabalho. O mais constante sendo melhorias de comunicação, que até hoje tenho certo problema. &lt;/p&gt;

&lt;p&gt;Um problema que ocorria frequentemente era que as minhas explicações que eram muito técnicas. Na minha conversa com o time de produto isso complicava tudo. Por exemplo, eu explicava todo o contexto por volta de uma nova implementação de feature. Levantava as possibilidades que conseguia pensar, trazendo as facilidades e dificuldades que trariam na implementação inicial e na manutenção do código. Eu estava pensando comigo mesmo e sendo transparente com todo mundo.&lt;/p&gt;

&lt;p&gt;Isso era relevante se fosse discutir com pessoas mais seniores, mas raramente era o caso. O que aprendi com o tempo era entender o escopo do que as pessoas &lt;em&gt;precisavam&lt;/em&gt; saber, e trazer isso a elas. Entender o porquê daquela comunicação existir, e relevar o que exatamente eu precisava comunicar de acordo com esse motivo.&lt;/p&gt;

&lt;p&gt;Aplicando isso, as mensagens de Slack que eram 5 parágrafos gigantes explicando os pormenores da entrega viravam 5 frases breves focando no que a pessoa precisava saber. Pra escrever as 5 frases eu ainda demoro, mas a comunicação fica bem mais fluída assim.&lt;/p&gt;




&lt;p&gt;Eu lembro quando eu criava testes de componentes React usando Enzyme. Foi ótimo aprender o mundo frontend com ele, porque eram simples, e qualquer um poderia criar testes sem esforço.&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="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;renders&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;wrapper&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;shallow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;wrapper&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toMatchSnapshot&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Eu gosto de pensar nesses testes como "snacks", eles são rápidos de serem escritos e entendidos, e raramente quebram. Se quebrar, era um processo simples corrigir eles, geralmente eu apertava U no teclado e o snapshot atualizava sozinho, eu nem precisava verificar.&lt;/p&gt;

&lt;p&gt;Mas uma coisa que ficava escondida para mim era que os testes, sendo fáceis de serem mantidos, eram também &lt;em&gt;muito&lt;/em&gt; inúteis. Muitos bugs passavam nesse método, e no final o valor dos testes era bem limitado.&lt;/p&gt;

&lt;p&gt;React Testing Library chega na minha vida. Ela vem com um princípio:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The more your tests resemble the way your software is used, the more confidence they can give you.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Essa pequena frase afeta bastante. Para seguir esse princípio, a React Testing Library tem &lt;strong&gt;menos&lt;/strong&gt; possibilidades do que a Enzyme, mas o que pra mim parecia um detrator da lib acabava sendo uma vantagem. Isso diminui o foco na estrutura do código, e aumenta o foco no usuário como valor principal dos testes.&lt;/p&gt;

&lt;p&gt;Eu só fazia testes porque era considerado boa prática, mas nenhum momento eu tinha pensado em um Objetivo dos testes, que colocava valor nos testes em si. Eu nem precisava da React Testing Library pra aplicar esse princípio. Ao me restringir dentro do Enzyme, eu criava testes com mais valor.&lt;/p&gt;




&lt;p&gt;DRY (&lt;em&gt;Don't Repeat Yourself&lt;/em&gt; ou &lt;em&gt;Não Se Repita&lt;/em&gt;) é um acrônimo bem popular de boa prática no mundo da programação. A ideia dele é reduzir retrabalho com a regra de não duplicar código.&lt;/p&gt;

&lt;p&gt;Essa regra é aplicada não só no frontend, mas em todos os níveis de programação que já vi. E de longe é a mais popular e mais implementada por times. Uma crítica recente a essa "boa prática" é que ela introduz códigos complexos demais com o tempo.&lt;/p&gt;

&lt;p&gt;O processo acaba sendo o seguinte: uma pessoa evita repetir o código introduzindo uma abstração. Outra pessoa, considerando que precisa dessa abstração, usa ela e altera pro seu caso. E mais uma pessoa, e outra, assim vai indo. Até que a abstração não faz mais sentido, mas é utilizada por todos.&lt;/p&gt;

&lt;p&gt;Outras regras foram introduzidas para mitigar esse problema. WET (&lt;em&gt;Write Everything Twice&lt;/em&gt; ou &lt;em&gt;Escreva Tudo Duas Vezes&lt;/em&gt;) é uma regra que diz: "Todo código deve ser escrito no máximo duas vezes". É uma regra que mitiga esses problemas, mas ao meu ver tem outra regra, ou melhor, ideia, que diminui a complexidade de código, o &lt;a href="https://dev.to/cher/avoiding-hasty-abstractions-aha-programming-3d3b"&gt;AHA&lt;/a&gt;: "Avoid Hasty Abstractions" (ou Evite Abstrações Apressadas).&lt;/p&gt;

&lt;p&gt;A ideia do AHA programming é introduzir abstrações no código quando elas forem necessárias, e diminuir o uso de abstrações simplesmente por abstrair.&lt;/p&gt;

&lt;p&gt;A vantagem (e desvantagem) do AHA é que ele não dá uma regra fácil de ser seguida. Ele abre mão de uma regra definida para que a pessoa desenvolvendo consiga determinar vários fatores que definam se tal abstração é necessária. Isso faz com que alguns casos apareçam meio estranhos, por exemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;DEBUG_QUERY_PARAM&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;shouldDebug&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;search&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useLocation&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;doSomething&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;shouldDebug&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;URLQueryParams&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;search&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;has&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;DEBUG_QUERY_PARAM&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;shouldDebug&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;debugging happening&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="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Esse código tem duas abstrações relevantes: &lt;code&gt;DEBUG_QUERY_PARAM&lt;/code&gt; e &lt;code&gt;shouldDebug&lt;/code&gt;. Ambas existem mas só são utilizadas uma vez.&lt;/p&gt;

&lt;p&gt;Se for se basear só nas regras de DRY ou WET, ambas as abstrações não fazem sentido, elas estão sendo usadas só uma vez no código. Mas é importante capturar o propósito real por traz delas antes de removê-las.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;DEBUG_QUERY_PARAM&lt;/code&gt; tem uma valor de documentar o comportamento. Ele informa pra quem está lendo que existe uma função de debug do código, e ele é controlado pela query param &lt;code&gt;shouldDebug&lt;/code&gt;. A intenção do código não é reuso, mas sim documentação de uma feature.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;shouldDebug&lt;/code&gt; tem o propósito de abstrair um código complexo em um código fácil de ser entendido por um humano, pode inclusive ensinar através dessa interface amigável. Além disso, ele representa melhor a intenção da pessoa que o criou, fazendo o trabalho de manutenção mais fácil caso haja algum bug.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠️ Eu não estou necessariamente dizendo que o código escrito é um bom código. Leve em conta o contexto dele antes de aplicar o mesmo racional.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Por quê?
&lt;/h2&gt;

&lt;p&gt;Essas historietas estão conectadas por uma ideia, sintetizada por uma/duas palavra(s): "Por quê?" Pra trazer valor em uma tarefa, eu preciso entender o motivo dela.&lt;/p&gt;

&lt;p&gt;Já vi uma técnica chamada "Os 5 porquês", criada com o objetivo de chegar à raiz do problema. Nela, você entra numa recursão: pergunta o motivo de um problema ocorrer, e depois disso procura explicar porque esse motivo existe, e continuamente. &lt;/p&gt;

&lt;p&gt;Essa técnica pode ser aplicada onde você ainda não enxerga problemas. Tente entender a motivação por trás. Essa motivação não precisa ser a melhor do mundo, mas tem que ser sincera. Se você quer usar TypeScript invés de JS, você não precisa falar que tem mais qualidade ou os mesmos argumentos de sempre. Os argumentos podem ser baseados no seu contexto: talvez você queira experimentar TS no seu projeto, ou você queira melhorar seu portifólio profissional.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;em&gt;Post Scriptum&lt;/em&gt;
&lt;/h2&gt;

&lt;p&gt;Sendo um pouco meta aqui e aplicando o post no próprio. Eu já tentei escrever muito, mas nunca terminei de escrever. Falei sobre esse assunto no post porque é um assunto que tenho muito o que falar, o que facilita a escrever. E no final, quero escrever posts como esse como parte da minha vida profissional.&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>programming</category>
      <category>braziliandevs</category>
    </item>
  </channel>
</rss>
