<?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: Gregor Woiwode</title>
    <description>The latest articles on DEV Community by Gregor Woiwode (@gregonnet).</description>
    <link>https://dev.to/gregonnet</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%2F262208%2F84019399-21d8-4b66-9422-83a57dfb7b3a.jpeg</url>
      <title>DEV Community: Gregor Woiwode</title>
      <link>https://dev.to/gregonnet</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/gregonnet"/>
    <language>en</language>
    <item>
      <title>Build a consistent Style API for Angular Components</title>
      <dc:creator>Gregor Woiwode</dc:creator>
      <pubDate>Thu, 06 Jun 2024 10:13:15 +0000</pubDate>
      <link>https://dev.to/gregonnet/build-a-consistent-style-api-for-angular-components-4l82</link>
      <guid>https://dev.to/gregonnet/build-a-consistent-style-api-for-angular-components-4l82</guid>
      <description>&lt;p&gt;While creating a new component library for an ERP-System, we invested a bit of time to rethink how we want to make styling of components easier than before.&lt;/p&gt;

&lt;p&gt;Of course, nearly every Component library offers a way of creating themes. Nevertheless, there are special requirements that afford a style-override that absolutely fits in the design, but is not part of the library at this point in time.&lt;br&gt;
Possibly, you want to slightly adjust a colour or spacing.&lt;br&gt;
Perhaps, you wish to be able to use another template for a list-item inside a component, but the Component's API does not allow you to.&lt;/p&gt;

&lt;h2&gt;
  
  
  🕺🏻 The “CSS Override Dance”
&lt;/h2&gt;

&lt;p&gt;In order to solve our design-challenge, we used to…&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;… find the HTML-Element in the respective Component that requires styling.&lt;/li&gt;
&lt;li&gt;… inspect the Element to determine which CSS class requires an override.&lt;/li&gt;
&lt;li&gt;… come up with the correct CSS-override.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In the past, our team used the following ways to override Component Styles:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Adding another CSS class that can be appended to the Component's Host-Element itself&lt;/li&gt;
&lt;li&gt;Overriding an existing CSS class by turning off &lt;em&gt;ViewEncapsulation&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Using &lt;a href="https://angular.dev/guide/components/styling#ng-deep" rel="noopener noreferrer"&gt;::ng-deep&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Playing with the &lt;a href="https://www.w3schools.com/css/css_important.asp" rel="noopener noreferrer"&gt;!important-Rule&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;If provided, using a Hook of the Component library to override styles (e.g. &lt;a href="https://primeng.org" rel="noopener noreferrer"&gt;PrimeNG&lt;/a&gt; provides the &lt;em&gt;input()/@Input()&lt;/em&gt; styleClass for lots of their components).&lt;/li&gt;
&lt;li&gt;In exceptional cases, we have re-implemented the component for our needs. 🤫&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To be honest, we are not happy working like this.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Most of the time, we came up with a different approach for overriding styles that need to be explained to fellow team members&lt;/li&gt;
&lt;li&gt;We had to invest more time in finalizing a feature than expected due to the additional workload to customize a component.&lt;/li&gt;
&lt;li&gt;Once the Component library received a major update, our overrides do not work any more, due to breaking changes.&lt;/li&gt;
&lt;li&gt;Custom Style-APIs like PrimeNG's &lt;em&gt;styleClass&lt;/em&gt; help, but aren't consistently applied everywhere. Sometimes it works, sometimes not.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The aim
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Instead of trying out different ways of customizing a Component, we want &lt;strong&gt;one clear API&lt;/strong&gt;, that is easy to use for everybody in the team.&lt;/li&gt;
&lt;li&gt;This API should be consistent across all components.&lt;/li&gt;
&lt;li&gt;Ideally, we can stick with the web-standards.&lt;/li&gt;
&lt;li&gt;Provide a Style-API for our teammates, allowing them to customize our Components with ease.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;h3&gt;
  
  
  QwikUi
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://qwikui.com/" rel="noopener noreferrer"&gt;https://qwikui.com/&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We started looking for alternative solutions. We were surprised to see, that style overrides are a very common and simple thing to do in Frameworks using &lt;a href="https://react.dev/learn/writing-markup-with-jsx" rel="noopener noreferrer"&gt;JSX&lt;/a&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;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Label&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;component$&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;LabelProps&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;props&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="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;HeadlessLabel&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="na"&gt;class&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;cn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;font-medium peer-disabled:cursor-not-allowed peer-disabled:opacity-70&lt;/span&gt;&lt;span class="dl"&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="kd"&gt;class&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;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Slot&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;HeadlessLabel&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;&lt;a href="https://github.com/qwikifiers/qwik-ui/blob/13e0d53a7b0debceb2e41a01dcca02bb6aca0b61/packages/kit-styled/src/components/label/label.tsx#L11" rel="noopener noreferrer"&gt;Source: Qwik UI&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The snippet demonstrates the class-overrides can simply be passed down the Component-Tree. Provided CSS classes can be merged dynamically based on certain conditions.&lt;/p&gt;

&lt;p&gt;💫 Our team was excited by the fact that styling can be done using Web-Standards without workarounds.&lt;/p&gt;

&lt;h3&gt;
  
  
  Angular Material
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://material.angular.io/" rel="noopener noreferrer"&gt;https://material.angular.io/&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now, it was our turn to try if we can come up with a solution in Angular. We were wondering if we can come up with a clean solution by manipulating the &lt;em&gt;class&lt;/em&gt;-Attribute of the Component's host element. In our experience, this approach is not widely used, but we remembered that we have seen this in &lt;em&gt;Angular Material&lt;/em&gt; components.&lt;br&gt;
That's why we started looking at the implementation and gained confidence to go with the Host-Binding-Approach. Nearly every component in Angular Material specifies host-classes (see &lt;a href="https://github.com/angular/components/blob/main/src/material/button/fab.ts#L66" rel="noopener noreferrer"&gt;MatFabButton&lt;/a&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  Our consistent Component-Style-API
&lt;/h2&gt;

&lt;p&gt;We do not consider to have found the silver bullet yet. We just want to share our findings with you and are &lt;strong&gt;happy to receive feedback&lt;/strong&gt; in order to check if we are on the right path or if we might consider other ways.&lt;/p&gt;

&lt;h3&gt;
  
  
  Style-API Rules
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;We provide basic styling, to allow the team to use the Components right away.&lt;/li&gt;
&lt;li&gt;Every developer can customize each Component using the &lt;code&gt;class&lt;/code&gt;-Attribute.&lt;/li&gt;
&lt;li&gt;We agree on a standardized way of applying CSS classes to be able to optimize them, behind the scenes.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  👩🏻‍💻 Let's code
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;You will find the full working example &lt;a href="https://github.com/GregOnNet/ng-consitant-component-style-api/blob/consistant-component-style-api-1/src/app/label.component.ts" rel="noopener noreferrer"&gt;on GitHub&lt;/a&gt; here.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We start simple with a Component representing a Label.&lt;br&gt;
By default, the label has a gray text. If needed, the text-color can be overridden.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;By the way, we use &lt;a href="https://tailwindcss.com/" rel="noopener noreferrer"&gt;TailwindCSS&lt;/a&gt; to have a standardized way of applying CSS classes&lt;/p&gt;
&lt;/blockquote&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%2Fvnra2ovro7y15g37i4ba.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%2Fvnra2ovro7y15g37i4ba.png" alt="A gray and a green label next to each other"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's start by having a look at the usage.&lt;br&gt;
You will see it is like working with standardized HTML-Elements.&lt;/p&gt;

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

&lt;span class="c"&gt;&amp;lt;!-- Component Template --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;app-label&amp;gt;&lt;/span&gt;Default&lt;span class="nt"&gt;&amp;lt;/app-label&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;app-label&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"text-green-500"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Green&lt;span class="nt"&gt;&amp;lt;/app-label&amp;gt;&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;The &lt;em&gt;class&lt;/em&gt;-Attribute is applied to the Component-Host-Element.&lt;br&gt;
Next, we will dive into the implementation of the &lt;em&gt;LabelComponent&lt;/em&gt;.&lt;/p&gt;

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

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;input&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;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&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;twMerge&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;tailwind-merge&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="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;app-label&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;standalone&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="na"&gt;host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[class]&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="s1"&gt;hostClass()&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&amp;lt;ng-content&amp;gt;&amp;lt;/ng-content&amp;gt;`&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LabelComponent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nx"&gt;classDefaults&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;p-2 text-slate-600&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="err"&gt;= &lt;/span&gt;&lt;span class="nc"&gt;input&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;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="k"&gt;protected&lt;/span&gt; &lt;span class="nx"&gt;hostClass&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;computed&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;classOverrides&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;class&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;twMerge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nx"&gt;classDefaults&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;classOverrides&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;ul&gt;
&lt;li&gt;In the &lt;em&gt;Component-Decorator&lt;/em&gt;, we bind a &lt;a href="https://angular.dev/guide/signals#computed-signal-dependencies-are-dynamic" rel="noopener noreferrer"&gt;computed signal&lt;/a&gt; to the class attribute.&lt;/li&gt;
&lt;li&gt;In the Component-Class, we add the &lt;em&gt;input()&lt;/em&gt; &lt;code&gt;class&lt;/code&gt; to allow style overrides.&lt;/li&gt;
&lt;li&gt;The computed &lt;em&gt;hostClass()&lt;/em&gt; allows us to merge the &lt;code&gt;#classDefaults&lt;/code&gt; with the &lt;code&gt;classOverrides&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;In &lt;em&gt;JSX&lt;/em&gt; we achieve the same by writing &lt;code&gt;class={&lt;/code&gt;p-2 ${...props.class}&lt;code&gt;}&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The package &lt;a href="https://github.com/dcastil/tailwind-merge" rel="noopener noreferrer"&gt;tailwind-merge&lt;/a&gt; helps us to combine the tailwind classes, safely. It will replace the defaults once an override is provided. For example, &lt;em&gt;text-slate-600&lt;/em&gt;, will be removed as soon as &lt;em&gt;text-green-500&lt;/em&gt; has been provided. &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%2Fmbkjjn6x8ls3wqkfeful.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%2Fmbkjjn6x8ls3wqkfeful.png" alt="HTML Code showing two labels and which CSS has been applied"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The simpler way
&lt;/h2&gt;

&lt;p&gt;We found an open issue in the Angular repository that would simplify the whole styling process. &lt;/p&gt;

&lt;p&gt;Eventually, we will get the possibility to manipulate the Component's host-Element in the template: &lt;a href="https://github.com/angular/angular/issues/19119" rel="noopener noreferrer"&gt;see &amp;lt;ng-host&amp;gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;We encountered difficulties customizing components to fit certain design requirements. We got inspired by different Frameworks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://material.angular.io/" rel="noopener noreferrer"&gt;Angular Material&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://primeng.org/" rel="noopener noreferrer"&gt;PrimeNg&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://qwikui.com/" rel="noopener noreferrer"&gt;QwikUI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://taiga-ui.dev/" rel="noopener noreferrer"&gt;TaigaUI&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.spartan.ng/" rel="noopener noreferrer"&gt;SpartenUI&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;🤝 We decided to provide a Style API that is as close as possible to existing Web-Standards. These are well known by web developers or can be easily communicated.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  🙏🏻 Special Thanks
&lt;/h2&gt;

&lt;p&gt;First, I want to thank you &lt;a href="https://www.linkedin.com/in/melory-ayala/" rel="noopener noreferrer"&gt;Melory&lt;/a&gt; for going through all the discussions with me to find a good approach for our Component library. You know, I appreciate your input and our constructive &amp;amp; productive discussions.&lt;/p&gt;

&lt;p&gt;I also thank all the community members for reviewing this article. I appreciated chatting with you all. Furthermore, I received valuable feedback from you.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://x.com/ArthurGroupp" rel="noopener noreferrer"&gt;@ArthurGroupp&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://x.com/GeromeDEV" rel="noopener noreferrer"&gt;@GeromeDEV&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://x.com/kuncevic" rel="noopener noreferrer"&gt;@kuncevic&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Rock on &amp;amp; Code&lt;br&gt;
Gregor&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
