<?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: Chris Simmons</title>
    <description>The latest articles on DEV Community by Chris Simmons (@endigo9740).</description>
    <link>https://dev.to/endigo9740</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%2F904540%2Ff99c54e4-43e3-458c-911e-302be93891f9.jpeg</url>
      <title>DEV Community: Chris Simmons</title>
      <link>https://dev.to/endigo9740</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/endigo9740"/>
    <language>en</language>
    <item>
      <title>Introducing Skeleton: A fully featured Svelte component library.</title>
      <dc:creator>Chris Simmons</dc:creator>
      <pubDate>Fri, 26 Aug 2022 22:02:00 +0000</pubDate>
      <link>https://dev.to/endigo9740/introducing-skeleton-a-fully-featured-svelte-component-library-1ban</link>
      <guid>https://dev.to/endigo9740/introducing-skeleton-a-fully-featured-svelte-component-library-1ban</guid>
      <description>&lt;p&gt;I recently had the privilege of writing an article for &lt;a href="https://www.smashingmagazine.com/" rel="noopener noreferrer"&gt;Smashing Magazine&lt;/a&gt; introducing &lt;a href="https://skeleton.brainandbonesllc.com/" rel="noopener noreferrer"&gt;Skeleton&lt;/a&gt;, a new open-source UI component library for &lt;a href="https://svelte.dev/" rel="noopener noreferrer"&gt;Svelte&lt;/a&gt; and &lt;a href="https://tailwindcss.com/" rel="noopener noreferrer"&gt;Tailwind&lt;/a&gt;. If you're looking for a quick introduction, I'd recommend starting here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.smashingmagazine.com/2022/08/skeleton-svelte-tailwind-reactive-uis/" rel="noopener noreferrer"&gt;Smashing Magazine: Meet Skeleton: Svelte + Tailwind For Reactive UIs&lt;/a&gt;&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%2Fhdpd7yv8svqv5wiibpmk.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%2Fhdpd7yv8svqv5wiibpmk.png" alt="Image description"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;However I wanted to go a bit further, as it's not every day you get to hear the origins of the tools we use as frontend developers. I want to share details on how my team and I started the library, explain the challenges faced during development, and of course review the progress made since the public debut. My hope is that this can help inspire others seeking to build and share their own web-based libraries as well.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Origin of Skeleton
&lt;/h2&gt;

&lt;p&gt;Over the last two years I've worked for a tech startup called &lt;a href="https://www.brainandbonesllc.com/" rel="noopener noreferrer"&gt;Brain &amp;amp; Bones&lt;/a&gt;, made up a small team of five individuals. As with most startups you tend to wear a lot of hats, so my job covered everything from tech to design - deciding the tech stack, product design, implementing the frontend applications, guiding development efforts for our platform API, as well as managing two very talented developers.&lt;/p&gt;

&lt;p&gt;Day to day, we managed number of web-based applications, which meant our choice in frontend framework had a major impact on our ability to build and maintain the platform for the company. Angular was an obvious choice for me, given I've used it professionally for around 10 years. I've watched it grow from the early v1.x days, through the v2.x launch, and eventually evolving into the mature framework we know today. I'm still a fan of Angular's opinionated design philosophy, as well as Angular Material, their official offshoot of &lt;a href="https://material.io/design" rel="noopener noreferrer"&gt;Material Design&lt;/a&gt;. The Material aesthetic provides a simple but clean interface, and their component system allows for rapid develop of large scale web-based apps.&lt;/p&gt;

&lt;p&gt;Last year we welcome a budding young developer to our team, named &lt;a href="https://github.com/thomasbjespersen" rel="noopener noreferrer"&gt;Thomas Jespersen&lt;/a&gt;. Thomas joined with the mission of improving our QA (quality assurance) and testing efforts, but immediately had interest in expanding into frontend development. So I set aside time and began teaching him everything I could, drawing from my 20 years of experience in the field.&lt;/p&gt;

&lt;p&gt;We explored the basics of HTML/CSS/JS, various frontend frameworks like React/Vue/Svelte, with our final goal being an introduction to Angular. However, an interesting thing happened along the way. We had a bit of a revelation after covering Svelte. Like many in the frontend space, we were captivated by Svelte's superb DX (developer experience). We knew our platform relied on Angular, but craved the chance to introduce and use Svelte and &lt;a href="https://kit.svelte.dev/" rel="noopener noreferrer"&gt;SvelteKit&lt;/a&gt; (Svelte's app framework) in our production environment. Unfortunately we were unsure how to introduce it at the time.&lt;/p&gt;

&lt;p&gt;Fast forward to February of this year and we began the planning phases for our next generation and evolution of our platform. We immediately began brainstorming a means to transition from Angular to Svelte/Kit. However, as we searched for UI libraries to replace Angular Material we came up short. Sure options like &lt;a href="https://sveltematerialui.com/" rel="noopener noreferrer"&gt;Svelte Material UI&lt;/a&gt; were available. However, we had growing concerns about the trajectory of Material Design. &lt;a href="https://m3.material.io/" rel="noopener noreferrer"&gt;Material Design v3&lt;/a&gt; hasn't really been a resounding success, having only a small handful of components (even today), and is currently limited exclusively to Android. Even Angular Material, a Google-owned project, has been slow to adopt v3. Progress has been moving at a snail's pace. This left us with a dilemma.&lt;/p&gt;

&lt;p&gt;It was at this point we started started toying with the idea of building our own component library. Looking deeper into SvelteKit, we realized it provided a turnkey solution for building and maintaining home grown component libraries using &lt;a href="https://kit.svelte.dev/docs/packaging" rel="noopener noreferrer"&gt;built-in packaging options&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This would make it trivial for us to generate components that could meet the requirements of each of our products, while retaining full control over how they looked and operated. Unfortunately this would require more development effort upfront, but after some internal debate, we decided this was fair trade off in the long term. Thus Skeleton was born!&lt;/p&gt;

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

&lt;p&gt;While planning our vision for the new library, we began auditing and reviewing every competitor we could find. Searching for inspiration, deciding what components to add, and helping define the conventions we would follow.&lt;/p&gt;

&lt;p&gt;Here's a small sample of the libraries we reviewed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://material.io/design" rel="noopener noreferrer"&gt;Material Design&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://getbootstrap.com/" rel="noopener noreferrer"&gt;Bootstrap&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bulma.io/" rel="noopener noreferrer"&gt;Bulma&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://chakra-ui.com/" rel="noopener noreferrer"&gt;Chakra&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://mui.com/" rel="noopener noreferrer"&gt;MUI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://vuetifyjs.com/en/" rel="noopener noreferrer"&gt;Vuetify&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://carbondesignsystem.com/" rel="noopener noreferrer"&gt;Carbon&lt;/a&gt;&lt;/li&gt;
&lt;/ul&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%2F0zvx7w8dw5yj1mh1l26t.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%2F0zvx7w8dw5yj1mh1l26t.png" alt="Image description"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;After some time and effort, this process led us to a library called &lt;a href="https://mantine.dev/" rel="noopener noreferrer"&gt;Mantine&lt;/a&gt;, a React-focused component library offering a huge set of components, deep customization, all housed within top-notch interactive documentation. This quickly became our go-to source for inspiration and has influenced many of the design decisions for our library, most notably in presentation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using Tailwind
&lt;/h2&gt;

&lt;p&gt;We knew right from the start that we wanted take advantage of &lt;a href="https://tailwindcss.com/" rel="noopener noreferrer"&gt;Tailwind CSS&lt;/a&gt;. It's powerful utility-based class system aligned with conventions used in our own project for years, but could help standardize the process. This would allow us to develop a turnkey design system and managed styling both inside our components and throughout each app. The first challenge was how to properly utilize Tailwind within Svelte components. There wasn't a lot of precedence available to draw from other libraries. Many libraries we reviewed opted for either vanilla CSS or preprocessors like SASS.&lt;/p&gt;

&lt;p&gt;Plus, we needed a way to handle all styles and customization for components using Tailwind classes. Originally we tried writing all classes inline in the HTML, as is standard practice. However this posed issues with CSS inheritance. Providing a default class in a template, then overwriting with another doesn't always cascade over the original style one might expect.&lt;/p&gt;

&lt;p&gt;Through experimentation we came up with a creative approach - we would define all CSS classes in the component script tag, then use a layered or conditional statements to control the classes defined on each element.&lt;/p&gt;

&lt;p&gt;In the component script tag we would define our base (read: default) styles for an element as shown:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;cBase&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`p-4 space-y-4`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We would also allow for customizable Tailwind classes to be passed as Svelte component props:&lt;br&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;export&lt;/span&gt; &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`bg-slate-900`&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;let&lt;/span&gt; &lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`text-white`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We then created Svelte reactive properties to merge these into a "flat" class string:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;classesBase&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;cBase&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="nx"&gt;background&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="nx"&gt;color&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By doing this, we concatenate the base and custom prop values and, define the order in in which classes are defined, and also open the door to conditional classes, like so:&lt;br&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;export&lt;/span&gt; &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;hover&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nl"&gt;$&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;classesHover&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;hover&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bg-emerald-500&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="nl"&gt;$&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;classesBase&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;cBase&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="nx"&gt;classesHover&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This prevented cramming a ton of conditional logic into the component's HTML template markup. Abstracting this provides a simple and well-define paradigm to follow.&lt;/p&gt;

&lt;p&gt;Using JavaScript logic we can intercept and modify our classes, allowing for a deep level of control over presentation. We can even accept single prop values that expand to a set of Tailwind classes:&lt;br&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;export&lt;/span&gt; &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sm&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// small&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;cSize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&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;switch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sm&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;cSize&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-sm&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;md&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;cSize&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-4 text-base&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lg&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;cSize&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-5 text-lg&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nl"&gt;$&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nl"&gt;classesBase&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="nx"&gt;cSize&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, we append the reactive class value to the element. This keeps our templates clean and reduces the Tailwind class "bloat" that turns many folks away:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;{classesBase}&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;...&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One thing to note with this approach, however, is that Tailwind's compiler does NOT allow for dynamically constructed classes. If you try to pass a partial value like color name (ex: &lt;code&gt;emerald&lt;/code&gt;) and generate &lt;code&gt;bg-${colorName}-500&lt;/code&gt;, this will fail. The Tailwind compiler is looking for the exact string match in each file, but Tailwind reads the value literally and will not recognize this. This was a source of many headaches for us early on, so beware!&lt;/p&gt;

&lt;h2&gt;
  
  
  Themes
&lt;/h2&gt;

&lt;p&gt;The next challenge we faced was how to properly handle themes. Having to overwrite the same prop value over and over for each component would not scale well. Thankfully Tailwind provides a perfect solution via &lt;a href="https://tailwindcss.com/docs/customizing-colors#using-css-variables" rel="noopener noreferrer"&gt;custom color definitions&lt;/a&gt;. These work best with RGBA color values, allowing alpha transparency to be adjusted for each color. In other words &lt;code&gt;bg-emerald-500/40&lt;/code&gt; would mean the color is set to 40% opacity.&lt;/p&gt;

&lt;p&gt;To handle theme colors, we generate four uniquely named values:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Primary - the primary brand color&lt;/li&gt;
&lt;li&gt;Accent - a secondary color for offsets or neutral actions&lt;/li&gt;
&lt;li&gt;Warning - for alerts and critical items&lt;/li&gt;
&lt;li&gt;Surface - a foundation, such as background colors&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We hand craft our default theme using Tailwind's default color palette (emerald, indigo, rose, and gray), but converted each color shade from hex to RGBA. These were defined using &lt;a href="https://github.com/Brain-Bones/skeleton/blob/dev/src/themes/theme-skeleton.css" rel="noopener noreferrer"&gt;CSS custom properties&lt;/a&gt; (read: CSS variables), and injected into the Tailwind config file via a &lt;a href="https://github.com/Brain-Bones/skeleton/blob/dev/src/lib/tailwind.cjs" rel="noopener noreferrer"&gt;custom Tailwind plugin&lt;/a&gt;. We have since made this process much easier by offering a set of &lt;a href="https://skeleton.brainandbonesllc.com/guides/themes" rel="noopener noreferrer"&gt;preset themes and theme generator&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This means no colors are hardcoded into components. We draw from each of these sets and apply color styling in logical fashion.&lt;/p&gt;

&lt;p&gt;Need to define a Card component background? Use this as your default:&lt;br&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;export&lt;/span&gt; &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bg-surface-800&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Need to style a Button component using your primary branding color? Use this:&lt;br&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;export&lt;/span&gt; &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bg-primary-500&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Dark Mode
&lt;/h2&gt;

&lt;p&gt;Finally, we needed a solution to intelligently adapt each component theme for &lt;a href="https://tailwindcss.com/docs/dark-mode" rel="noopener noreferrer"&gt;Tailwind's dark modes&lt;/a&gt;. The solution was to balance colors like a weighted scale. We paired colors from either side of the spectrum.&lt;/p&gt;

&lt;p&gt;Here's what that looks like visualized:&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%2F7wveukghnzrfyb11i1at.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%2F7wveukghnzrfyb11i1at.png" alt="Image description"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;In execution, the means if you set your body element's light theme background to &lt;code&gt;bg-surface-50&lt;/code&gt;, then the dark theme equivalent should be &lt;code&gt;bg-surface-900&lt;/code&gt; to balance. Here's what the CSS looks like in practice:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;body&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="err"&gt;@apply&lt;/span&gt; &lt;span class="err"&gt;bg-surface-50&lt;/span&gt; &lt;span class="py"&gt;dark&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;bg-surface-900&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;If you want to style a Card component that's slightly elevated (visually) from the background, you use:&lt;br&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;export&lt;/span&gt; &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bg-surface-100 dark:bg-surface-800&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Regardless of what color &lt;code&gt;surface&lt;/code&gt; represents, regardless of light or dark mode, the card element always gives the desired effect. Even though this a delicate balancing act, it's still easy to test during development. Just be mindful to review your components in different different themes and with light/dark mode toggled regularly as you progress.&lt;/p&gt;

&lt;h2&gt;
  
  
  The First Four Months
&lt;/h2&gt;

&lt;p&gt;From February through May, Thomas and I defined these conventions and began building each component. Internally we had a shared list of component needed to satisfy the requirements of our projects. This included Buttons, Cards, Tabs, etc.&lt;/p&gt;

&lt;p&gt;By using Svelte, Tailwind, and our design patterns we had produced a majority of the library within the first four months. Unfortunately, as is often the case with startups, we received news that the company would be shutting down and the team would be let go by the end of the month. Obviously this was devastating to hear. We had a wonderful and supportive culture, we were fully invested in the products were were creating, and of course we were excited to get Skeleton off the ground. In some ways this felt like the things were over before they even really began.&lt;/p&gt;

&lt;p&gt;However, since the beginning, we had discussed the possibly of making the library open source. We knew we had something that could be beneficial to many Svelte community. However, the library didn't legally belong to us. Luckily Thomas and I have a wonderful working relationship and friendship with the founder of the company. After a bit of a summer break, we came together and agreed to release the library as open source. It was at that point I resumed work on the project, joined soon after by Thomas, we set about opening it to the public.&lt;/p&gt;

&lt;h2&gt;
  
  
  Launching the Public Beta
&lt;/h2&gt;

&lt;p&gt;At the end of June we added our final polish to the documentation, added the MIT license, and finally set the GitHub repo and NPM package public. We then began promoting and announcing the project within various Svelte-focused communities.&lt;/p&gt;

&lt;p&gt;Since launch we've received a slew of useful feedback and positive comments on &lt;a href="https://www.reddit.com/r/sveltejs/comments/w8odl6/introducing_skeleton_a_svelte_ui_component/" rel="noopener noreferrer"&gt;Reddit&lt;/a&gt; and the Svelte Discord. People were asking hard questions, making great suggestions, and generally pretty excited for what we've created. This of course has fueled our ambition to push forward with the project, especially after the delay in May. In some ways it felt like the Phoenix rising from the ashes!&lt;/p&gt;

&lt;p&gt;Since the public launch we've put a lot of effort into building up the Skeleton community on &lt;a href="https://github.com/Brain-Bones/skeleton/discussions" rel="noopener noreferrer"&gt;Github&lt;/a&gt;, &lt;a href="https://twitter.com/SkeletonUI" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;, and &lt;a href="https://discord.gg/EXqV7W8MtY" rel="noopener noreferrer"&gt;Discord&lt;/a&gt;. On a whim, I reached to new sources like &lt;a href="https://www.smashingmagazine.com/" rel="noopener noreferrer"&gt;Smashing Magazine&lt;/a&gt;. To our surprise, we received a very pleasant response from &lt;a href="https://www.smashingmagazine.com/author/vitaly-friedman/" rel="noopener noreferrer"&gt;Vitaly Friedman&lt;/a&gt;. He offered us a chance to write the articled which is now linked at the top of this page. Smashing Magazine has been a huge influence in my career. I've learned a lot about web development from them over the years. Honestly, I'm still kind of shell shocked that this happened at all!&lt;/p&gt;

&lt;p&gt;Likewise we've been thrilled with the Svelte community's reaction - being treated to congrats from folks like &lt;a href="https://github.com/benmccann" rel="noopener noreferrer"&gt;Ben McCann&lt;/a&gt;, the second highest contributor to SvelteKit after Rich Harris (creator of Svelte).&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%2Fluopc4mcv48wkhoq4uq8.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%2Fluopc4mcv48wkhoq4uq8.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As well as compliments from members of the &lt;a href="https://astro.build/" rel="noopener noreferrer"&gt;Astro&lt;/a&gt; core team and even a member of the &lt;a href="https://sveltesirens.dev/" rel="noopener noreferrer"&gt;Svelte Sirens&lt;/a&gt;. Both are made up of good people and worth a look!&lt;/p&gt;

&lt;h2&gt;
  
  
  A Bright Future
&lt;/h2&gt;

&lt;p&gt;We continue to push forward with progress on Skeleton, &lt;a href="https://github.com/Brain-Bones/skeleton/discussions/148" rel="noopener noreferrer"&gt;including a large release this week&lt;/a&gt; adding a11y improvements and support for Vite and Astro. We're not stopping there though, we &lt;a href="https://github.com/Brain-Bones/skeleton/wiki/%F0%9F%9B%A3%EF%B8%8F-The-Skeleton-Roadmap-(proposal)" rel="noopener noreferrer"&gt;have so much more planned&lt;/a&gt; and see a bright future for the library.&lt;/p&gt;

&lt;p&gt;It's my hope we can continue to to work on Skeleton for as long as possible and build the best UI component library available for Svelte. If you're interested in giving it a try checkout the official documentation here:&lt;br&gt;
&lt;a href="https://skeleton.brainandbonesllc.com/" rel="noopener noreferrer"&gt;https://skeleton.brainandbonesllc.com/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Join us on Github&lt;br&gt;
&lt;a href="https://github.com/Brain-Bones/skeleton" rel="noopener noreferrer"&gt;https://github.com/Brain-Bones/skeleton&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Or drop by and say hello on Discord:&lt;br&gt;
&lt;a href="https://discord.gg/EXqV7W8MtY" rel="noopener noreferrer"&gt;https://discord.gg/EXqV7W8MtY&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We would be glad to have you and welcome contributions from anyone willing and able! Seriously, thanks to everyone that continues to help make this possible! 🙏&lt;/p&gt;

</description>
      <category>svelte</category>
      <category>tailwindcss</category>
      <category>webdev</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Let's Talk About Framework-Specific UI Component Libraries</title>
      <dc:creator>Chris Simmons</dc:creator>
      <pubDate>Thu, 11 Aug 2022 07:20:04 +0000</pubDate>
      <link>https://dev.to/endigo9740/lets-talk-about-framework-specific-ui-component-libraries-non</link>
      <guid>https://dev.to/endigo9740/lets-talk-about-framework-specific-ui-component-libraries-non</guid>
      <description>&lt;h2&gt;
  
  
  A Brief Retrospect of Web UI
&lt;/h2&gt;

&lt;p&gt;To understand how far we’ve come with interface design for the web it's important to understand the progress made over the last 15 years. During this time, tech giants such as Google and Twitter were tasked with creating consistent design across their vast catalog of online products and services. This prompted them to create what I like to refer to as “general purpose” UI frameworks, which included the likes of &lt;a href="https://getbootstrap.com/"&gt;Bootstrap&lt;/a&gt; and &lt;a href="https://material.io/design"&gt;Material Design&lt;/a&gt;. These brought comprehensive guidelines that covered common UX patterns, addressed accessibility, and a provided a consistent visual aesthetic. Each has had a dramatic impact on web design as we know it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--QE3IsFVO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7tomallgz4ijjafi46xp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--QE3IsFVO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7tomallgz4ijjafi46xp.png" alt="Bootstrap by Twitter" width="880" height="652"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;As time has moved on, monumental advancements have been made for core web technologies. When we think about interfaces, we tend to focus on visual aspects created using HTML and CSS. However, one would be remiss to overlook the impact Javascript has had on user interaction within then frontend space. Early UI frameworks such as Bootstrap opted to integrate &lt;a href="https://jquery.com/"&gt;jQuery&lt;/a&gt; and use direct DOM manipulation to handle interactive elements such as modals and dialogs. But as you may know, this has fallen out of favor due its &lt;a href="https://medium.com/@trombino.marco/you-might-not-need-jquery-a-2018-performance-case-study-aa6531d0b0c3"&gt;less than stellar performance&lt;/a&gt;, resulting it it eventually being &lt;a href="https://github.com/twbs/bootstrap/pull/23586"&gt;removed from Bootstrap&lt;/a&gt; in 2022. Replaced instead with standard Javascript features.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ak9edOXx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sjgq2xuj8pne59t952x5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ak9edOXx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sjgq2xuj8pne59t952x5.png" alt="jQuery DOM manipulation library" width="880" height="652"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Other libraries, such as &lt;a href="https://bulma.io/"&gt;Bulma&lt;/a&gt;, opted for a different approach. They made the decision to &lt;a href="https://bulma.io/documentation/components/modal/#javascript-implementation-example"&gt;forego javascript&lt;/a&gt; altogether and focus purely on the the UI “shell” (the HTML and CSS). Leaving the onus on developers to code their own interactive logic or introduce additional third party dependencies to handle interactive elements.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TSjpXTo1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q2ylmyduhwerefy8xl3d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TSjpXTo1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q2ylmyduhwerefy8xl3d.png" alt="React UI Library" width="880" height="652"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;These days, UI frameworks tend to make heavy use of modern Javascript and utilize components and reactive patterns to handle real-time interaction. &lt;a href="https://angular.io/"&gt;Angular&lt;/a&gt;, &lt;a href="https://reactjs.org/"&gt;React&lt;/a&gt;, and &lt;a href="https://vuejs.org/"&gt;Vue&lt;/a&gt; are now &lt;a href="https://2021.stateofjs.com/en-US/libraries/front-end-frameworks/"&gt;well established as the standard&lt;/a&gt; for what we know as modern frontend development. Alongside these, we’ve seen the rise of framework-specific UI libraries that aim to provide a “batteries included” approach to UI, with deep integration of each framework’s unique set of features. This includes &lt;a href="https://material.angular.io/"&gt;Angular Material&lt;/a&gt;, &lt;a href="https://mantine.dev/"&gt;Mantine&lt;/a&gt; (for React), and &lt;a href="https://vuetifyjs.com/en/"&gt;Vuetify&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introducing Skeleton
&lt;/h2&gt;

&lt;p&gt;With the emergence of new frameworks such as Svelte, we might expect to see similar tooling appear to pair with these technologies. In fact, that's where &lt;a href="https://skeleton.brainandbonesllc.com/"&gt;Skeleton&lt;/a&gt; comes in - a brand new open-source UI component library that tightly integrates both &lt;a href="https://svelte.dev/"&gt;Svelte&lt;/a&gt; and &lt;a href="https://tailwindcss.com/"&gt;Tailwind&lt;/a&gt;. In short, it provides a broad set of Svelte components that can easily be adjusted using Tailwind’s powerful utility class system.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yyFr9ZeG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/euoyeno0pdk3jj4s4zyy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yyFr9ZeG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/euoyeno0pdk3jj4s4zyy.png" alt="Introducing Skeleton!" width="880" height="637"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://skeleton.brainandbonesllc.com/"&gt;Visit the Skeleton documentation site&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Skeleton is a project that's very near and dear to my heart, as I'm both the creator and one of a handful of core contributors. Over the last couple years I've found myself really impressed with Svelte and what it brings to the frontend developer’s arsenal. Earlier this year I was working at &lt;a href="https://www.brainandbonesllc.com/"&gt;Brain &amp;amp; Bones&lt;/a&gt; when we made the decision to start migrating away from Angular and moving towards Svelte and SvelteKit. The ecosystem is still early days of course, so we immediately realized there was an opportunity to combine Svelte’s intuitive component system with the utility-driven design systems of Tailwind, and thus Skeleton was born.&lt;/p&gt;

&lt;p&gt;My team and I realize Skeleton has the potential to benefit many in the Svelte community, and as such we’ve decided to make it &lt;a href="https://github.com/Brain-Bones/skeleton"&gt;open-source&lt;/a&gt;. Our hope is to continue to grow the project into a powerful UI toolkit that can help a lot of developers. Whether your skills lie within the frontend space or not.&lt;/p&gt;

&lt;p&gt;Skeleton is currently available in early access beta, but feel free to visit the &lt;a href="https://skeleton.brainandbonesllc.com/"&gt;documentation&lt;/a&gt; to learn more. The site provides detailed guides to help get you started and covers all available components. You can report issues, request walkthroughs, or contribute code at our &lt;a href="https://github.com/Brain-Bones/skeleton"&gt;GitHub&lt;/a&gt;. You’re also welcome to join the &lt;a href="https://discord.com/invite/EXqV7W8MtY"&gt;Discord community&lt;/a&gt; to chat with me and other contributors.&lt;/p&gt;

&lt;p&gt;There's so much more I want to share about the project, including a deep into the technical decisions that lead to it's creation. As well as detailing the process for creating and maintaining a project of this scale. Expect posts covering this and more in the near future!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>design</category>
      <category>tooling</category>
    </item>
    <item>
      <title>How I built my new portfolio using Pixi.js</title>
      <dc:creator>Chris Simmons</dc:creator>
      <pubDate>Sat, 06 Aug 2022 21:18:00 +0000</pubDate>
      <link>https://dev.to/endigo9740/my-new-portfolio-3ke6</link>
      <guid>https://dev.to/endigo9740/my-new-portfolio-3ke6</guid>
      <description>&lt;h2&gt;
  
  
  My New Portfolio
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;View the site here: &lt;a href="http://endigodesign.com" rel="noopener noreferrer"&gt;endigodesign.com&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I recently launched a new version of Endigo Design, my personal portfolio. This is a process I undergo every few years. I devote a few days building a simple site that covers the essentials of who I am and what I do. This time though, I decided I wanted to go big. To flex my combined knowledge and skill between web and game development and create a unique showcase of my work. In this post I’ll review the site and discuss some of the technology and techniques powering it behind the scenes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Exploring the Site
&lt;/h2&gt;

&lt;p&gt;To begin, let’s take a look at the homepage.&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%2Fcdn-images-1.medium.com%2Fmax%2F3414%2F1%2A12mzEWWIutz0Soam0QRKaw.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%2Fcdn-images-1.medium.com%2Fmax%2F3414%2F1%2A12mzEWWIutz0Soam0QRKaw.png" alt="The homepage includes selection between game and traditional modes."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here you’re provided two options. The first, to view an interactive game-like experience. This operates similar to a virtual art gallery. Whereas you browse a virtual 2D world and inspect each of my projects, represented as monuments or tall black pillars. You’re also provided a means to fallback to a traditional site — which adheres to standard UI and UX patterns for navigating between each project and the About page. This is the safety net and fallback for users that are either in a hurry, or don’t have a device or network connection to property fun the game experience.&lt;/p&gt;

&lt;p&gt;For the game experience you’re immediately presented with several unique characters to interact with, as well as a large monument — which triggers a modal embedded version of my biography page. When tapping each character, it trigger a traditional RPG-styled dialog box to appear. Each character provides small hints at how to interact with the world. A throw back to old school 2D Pokemon games.&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%2Fcdn-images-1.medium.com%2Fmax%2F3414%2F1%2A9B0OgcDsJGx5tOAWU1KCfg.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%2Fcdn-images-1.medium.com%2Fmax%2F3414%2F1%2A9B0OgcDsJGx5tOAWU1KCfg.png" alt="The initial view of the game experience. Showcasing a stone monument and NPC characters."&gt;&lt;/a&gt;&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%2Fcdn-images-1.medium.com%2Fmax%2F3414%2F1%2AYaQm04AUJHGKh0roXDRt-A.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%2Fcdn-images-1.medium.com%2Fmax%2F3414%2F1%2AYaQm04AUJHGKh0roXDRt-A.png" alt="Talking with my likeness via a small dialog."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At this point you’re set loose to navigate the rest of the world. Using your mouse or finger, you can tap and drag to move the camera. There are several uniquely styled biomes provide, which provided a means to group each set of projects. Along the way you’ll find pillars that represent each project I’ve worked on or contributed to. Tapping a pillar provides a description and other media within popup modal.&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%2Fcdn-images-1.medium.com%2Fmax%2F3414%2F1%2ARcIwT9c7gENfmUufEsL7wQ.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%2Fcdn-images-1.medium.com%2Fmax%2F3414%2F1%2ARcIwT9c7gENfmUufEsL7wQ.png" alt="Discovering one of the project pillars."&gt;&lt;/a&gt;&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%2Fcdn-images-1.medium.com%2Fmax%2F3414%2F1%2Afxbo8wWJA1gjCCgdjEl2Gw.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%2Fcdn-images-1.medium.com%2Fmax%2F3414%2F1%2Afxbo8wWJA1gjCCgdjEl2Gw.png" alt="Tapping a pillar reveals the details, including a description and media."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Each pillar you locate and interact with will immediately begin to animate. This helps visually identify which you have and have not yet visited. Overall it provides a really fun and unique experience, allowing you to take in the sights and sounds of this little world, while browsing my full catalog of work.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tooling and Technology
&lt;/h2&gt;

&lt;p&gt;When I set out to design this site, I knew right right away I wanted to create a presentation that looked and felt like a traditional 2D top-down RPG game. It would also need to live within the confines of available browser APIs and modern web-based technology. Given this, the use of the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API" rel="noopener noreferrer"&gt;canvas&lt;/a&gt; element and &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API" rel="noopener noreferrer"&gt;WebGL&lt;/a&gt; were a given. When paired, these allow you to render graphics within either a 2D or 3D context. For 2D this means drawing primitive shapes like rectangles and circles, images (textures), all with direct interaction and input from end users. When combined, these provide the basic building blocks of a game.&lt;/p&gt;

&lt;h3&gt;
  
  
  Game Rendering
&lt;/h3&gt;

&lt;p&gt;My early prototypes made use of pure HTML and Javascript paired with a canvas element. This would have involved building everything from the ground up. However, I quickly realized this would not be a scale well for a presentation of this size. I was lacking mainstays of game development, such as animated spritesheets and found interaction to be quite tricky. Instead I opted to use Pixi.js.&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%2Fcdn-images-1.medium.com%2Fmax%2F3414%2F1%2A_OU5y5VzWHpCm-MsZd_Oiw.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%2Fcdn-images-1.medium.com%2Fmax%2F3414%2F1%2A_OU5y5VzWHpCm-MsZd_Oiw.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you’re not familiar with Pixi, it provides several quality of life improvements and features over your standard canvas integration. This includes, but not limited to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Containers&lt;/strong&gt;: which allow you to create a group of elements, similar to Game Objects in engines like Unity.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Textures&lt;/strong&gt;: preloaded image assets that may be used within your scene.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Graphics&lt;/strong&gt;: dynamically rendered primitives such as rectangles, arcs, etc.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Sprites/Spritesheets&lt;/strong&gt;: typically made up of one or more graphics or textures. Pixi even provides animated spritesheets using row and column based references from a single image for character animations.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Interaction&lt;/strong&gt;: the Pixi API provides a very means to listen to and act on events for any scene object.&lt;br&gt;
&lt;strong&gt;Render Loop&lt;/strong&gt;: a standardized loop meant to handle animation and monitor elapsed time within your scene.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Text&lt;/strong&gt;: direct support for text, fonts, and even rasterized bitmap for high performance.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Web Application Framework
&lt;/h3&gt;

&lt;p&gt;Next I knew I’d want to utilize UI components and a fully featured web application framework to build the foundation of the site. For this I turned to &lt;a href="https://svelte.dev/" rel="noopener noreferrer"&gt;Svelte&lt;/a&gt; and &lt;a href="https://kit.svelte.dev/" rel="noopener noreferrer"&gt;Sveltekit&lt;/a&gt;. When combined these fulfill a similar role to tools such as &lt;a href="https://angular.io/" rel="noopener noreferrer"&gt;Angular&lt;/a&gt;, &lt;a href="https://nextjs.org/" rel="noopener noreferrer"&gt;Next.js&lt;/a&gt; for React, and &lt;a href="https://nuxtjs.org/" rel="noopener noreferrer"&gt;Nuxt&lt;/a&gt; for Vue.&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%2Fcdn-images-1.medium.com%2Fmax%2F3414%2F1%2AwJFMrhUQURJZhSOQOVGd2Q.jpeg" 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%2Fcdn-images-1.medium.com%2Fmax%2F3414%2F1%2AwJFMrhUQURJZhSOQOVGd2Q.jpeg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I used the follow features extensively via Svelte and Sveltekit:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Components&lt;/strong&gt;: the reusable blocks of code/templates/styles that create a set of building blocks for the site. Things like the reusable footers, page templates, etc.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Routing&lt;/strong&gt;: Sveltekit provides a great file-based routing system for helping control navigation of my site and pages.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;State Management&lt;/strong&gt;: which is handled via Svelte writables. The data stores use a pub/sub like model for data flow.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Build &amp;amp; Bundling&lt;/strong&gt;: Sveltekit was developed on-top of &lt;a href="https://vitejs.dev/" rel="noopener noreferrer"&gt;Vite&lt;/a&gt;, a build tool created by Evan You (of Vue fame). It provides a very fast and responsive set of tooling for creating local servers, handle hot module refresh, Typescript compilation, building, bundling, and more.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Style and Design
&lt;/h3&gt;

&lt;p&gt;Finally, I needed means to style and control the layout and design of each page and component. For this I turned to &lt;a href="https://tailwindcss.com/" rel="noopener noreferrer"&gt;Tailwind CSS&lt;/a&gt;. Tailwind provides a full suite of utility CSS classes, while still allowing you to “draw outside the lines” with arbitrary overrides. It’s an acquired taste for sure, but a tool that can dramatically increase productivity in the right hands. It pairs really well with component libraries, such as Svelte, React, or Vue.&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%2Fcdn-images-1.medium.com%2Fmax%2F3414%2F1%2AO4vAQDExBpPpj9X3NFvjtQ.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%2Fcdn-images-1.medium.com%2Fmax%2F3414%2F1%2AO4vAQDExBpPpj9X3NFvjtQ.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Pulling it All Together
&lt;/h2&gt;

&lt;p&gt;While each tool is great in their own right, one of the key struggles of building web applications (at any scale) is finding the proper way to make everything work in unison. I’d like to take some time to explain how I paired everything together to build the most critical portions of the experience, with a focus on core game features.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Pixi Component
&lt;/h3&gt;

&lt;p&gt;The first challenge I faced was determining where to house the canvas element and begin rendering to the screen with Pixi. For this I opted for a simple standalone component. This allowed me to create a basic game manager, and included all logic, layout, and styles all within a single file. This made it quick and easy to jump between shared references and iterate the code.&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%2Fcdn-images-1.medium.com%2Fmax%2F3416%2F1%2A27lF-8qoHScXj89yatMN9Q.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%2Fcdn-images-1.medium.com%2Fmax%2F3416%2F1%2A27lF-8qoHScXj89yatMN9Q.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The rough order of operations goes something like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;The canvas element is bound using Svelte’s bind:this={elemRef} syntax.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The Pixi application is initialized, which takes in the element reference and sets global settings, such as display size.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A Pixi loader ingests a set of static resources, which allows you to ensure all required elements are preloaded ahead of time. This can be tapped to present a loading progress bar on screen.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When the game app is fully loaded a number of steps occur…&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The over world map is generated via a preloaded texture, then injected into the “level” container. This container houses the map and all other entities such as NPCs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Next, the camera class is initialized, which primarily controls the x/y position of the level container within the 2D world space. I explain this in greater detail in the section below.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I initialize a grid class, which can optionally be enabled to visually display the individual “tile” segmentation and coordinates on-screen for debugging purposes. Tiles have a base of 16x16 pixels here.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A slew of game objects, such as the pillars, npcs, and creatures are initialized and added as children to the level container.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The level container is added to the Pixi stage (the scene). Which finally makes it visible on screen.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;On load, I adjust the camera focus to center on my personal character.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Finally the game render loop it started, which enables all animation and movement to function. The camera, container level, and entities have their respective render methods updated per frame.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Camera Controls
&lt;/h3&gt;

&lt;p&gt;Cameras present an interest challenge when rendering in a 2D virtual space. If you have created a game using an engine such as Unity or Godot you may take these for granted, as most provide these turn key. Pixi and canvas require you to solve this yourself. One method for accomplishing this requires a bit of an illusion for the end users. I’ve provided an illustration below to visualize this.&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%2Fcdn-images-1.medium.com%2Fmax%2F2512%2F1%2AppufIowBZfTQFSAT_RQ9Ig.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%2Fcdn-images-1.medium.com%2Fmax%2F2512%2F1%2AppufIowBZfTQFSAT_RQ9Ig.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Since the canvas (red) is fixed within the visible page canvas, it cannot actually move. Instead, effect of camera movement is created by moving the the contents rendered within the canvas area itself. This typically involves creating a container that houses your game world map (green). This container may also contain children, such npcs, creatures, and buildings (blue).&lt;/p&gt;

&lt;p&gt;Instead of a small guy carrying a camera (ala Mario 64) following you around, it’s the map and it’s children that actually move! It’s a really neat trick that works very well in execution.&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%2Fcdn-images-1.medium.com%2Fmax%2F2800%2F0%2As1ig8534uulFEY0G" 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%2Fcdn-images-1.medium.com%2Fmax%2F2800%2F0%2As1ig8534uulFEY0G"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To actually handle this in the code, the Camera class simply controls how far a user has dragged from Point A to Point B and sets an offset value represented a x and y. These offset values are then read during the animation loop to update the position of the level container.&lt;/p&gt;

&lt;h3&gt;
  
  
  Game Objects
&lt;/h3&gt;

&lt;p&gt;Game Objects are not inherent to Pixi. Instead they are a concept borrowed from Unity. These objects may present anything that exists within you game. This is typically handled by creating a containing element (like a group) that includes visual elements (such as an animated sprite), and pairs pairs this with the code containing the logic and rules for how the object should interact with the world.&lt;/p&gt;

&lt;p&gt;An NPC (non-playable character) is a good example of one of these. In my game I have multiple NPC entities, each containing their animated sprites for visual idle and walking animations. But also includes a set of logic for handling what happens when you mouse over and click the entity.&lt;/p&gt;

&lt;p&gt;A common convention for implementing this via code is using &lt;a href="https://en.wikipedia.org/wiki/Object-oriented_programming" rel="noopener noreferrer"&gt;Object-Oriented Programming&lt;/a&gt;(OOP for short). OOP involves creating a structured Class that describes the properties of an object, as well as containing the logic for how it should function. One or more of these classes can be instantiated to created standalone copies of that entity.&lt;/p&gt;

&lt;p&gt;Returning to that NPC example — my GameObject class describes each NPC’s properties such as name, which texture image to display, and other descriptive details. While also including its own logic, such as an onclick handler that triggers a dialog to appear.&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%2Fcdn-images-1.medium.com%2Fmax%2F3424%2F1%2AzU7XV6UFLuHrC-ZV9qCzaw.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%2Fcdn-images-1.medium.com%2Fmax%2F3424%2F1%2AzU7XV6UFLuHrC-ZV9qCzaw.png" alt="The core GameObject class, for which all entities use or extend."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This GameObject class contains all the core and shared properties and functional logic available to all entities in my game. I use this class to instantiate everything from NPCs, to crabs, to even the project pillars. Each instance has its own name, animated sprite reference, coordinate positions, and dimensions. They also share common functionality, via the class methods, that allow them to move on pre-defined paths and handle input events. Note that I do not use every feature on every entity though. Crabs don’t “talk” in my game…but they certainly could!&lt;/p&gt;

&lt;p&gt;You might be asking yourself, though, what happens when you need properties or features outside the scope of the base GameObject class? This is where another key feature of OOP comes into play — class inheritance. To do this, I create a separate class that extends the GameObject. This means it inherits all properties and methods of the base class, while still allowing you to overwrite or extend the features specific for this unique type of entity.&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%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2Axvbz-sfz5CCqrGXWOjfzrA.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%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2Axvbz-sfz5CCqrGXWOjfzrA.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I use this to great effect with Layla the Cat, the NPC-like entity that appears near the start of the game. Here I create a Cat class that extends the base GameObject class — which means she can still have her own name, animated sprite, and still trigger features such as dialogs. While still allowing me to overwrite and extend her base functionality. In this case, entities of the Cat type can flip the sprite on the X axis based on the mouse position. This makes her appear to follow the position of the mouse cursor on screen. This is a feature that’s unique to cats, since we know cats love to chase mice!&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;While there’s much more I’d love to cover, it may be keen to save those for later articles! However, if you’re curious to learn more about how the site was built, I invite you to explore the source code, which is available on Github:&lt;br&gt;
&lt;a href="https://github.com/endigo9740/endigo-design" rel="noopener noreferrer"&gt;&lt;strong&gt;GitHub - endigo9740/endigo-design: The portfolio of Chris Simmons&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I offer a number of ways to contact me if you would like to follow up and ask me any questions directly as well.&lt;/p&gt;

&lt;p&gt;For now thanks for reading and please enjoy the site!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>svelte</category>
      <category>tailwindcss</category>
      <category>gamedev</category>
    </item>
    <item>
      <title>Legacy Posts on Medium</title>
      <dc:creator>Chris Simmons</dc:creator>
      <pubDate>Sat, 06 Aug 2022 21:14:33 +0000</pubDate>
      <link>https://dev.to/endigo9740/legacy-posts-on-medium-47ho</link>
      <guid>https://dev.to/endigo9740/legacy-posts-on-medium-47ho</guid>
      <description>&lt;p&gt;I've used Medium to host my personal blog since 2015, however I'm in the process of migrating to here. If you would like to read any of my older posts, please check them out here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://medium.com/@endigo9740"&gt;https://medium.com/@endigo9740&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;All new posts will appear on here going forward.&lt;/p&gt;

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