Introducing a2k - A UI library designed to capture that retro 2000s feeling
Tags: webcomponents, javascript, webdev, css
Published: 2022-12-01 21:34:19

Take a look at a new 2000s-inspired component library. You’ll learn what a2k is, how it’s been built, and how to use it to build retro applications in React, Vue, vanilla, or your favourite frontend framework.

## What is a2k?

[a2k](https://github.com/andrico1234/a2k) is a web component library designed to evoke memories of the early 2000s era of computing.

![Introducing a2k](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2fxdz2qbv2gcb5oy43kr.png)

## Why does a2k exist?

### To embrace the browser platform

Over the years, the browser has introduced several mechanisms to allow developers to create reusable custom components. These are known as [web components](https://developer.mozilla.org/en-US/docs/Web/Web_Components). Web components are a native way of reusing custom markup across several places in a codebase, or different codebases entirely.

Web components make it easy to author components for others to use in their own projects. As a consumer, it requires little more than to import a component and then use it like an HTML element.

This makes it a great tool for building a2k.

### To create a framework agnostic component library

You may be familiar with frameworks like React and Vue, which popularised the notion of building user interfaces using components. While these tools exist for more than writing and using components, there is an entire ecosystem dedicated to component libraries. [MUI](https://mui.com/) and [Chakra UI](https://chakra-ui.com/), are both excellent examples of React component libraries that allow developers to build complex user interfaces from battle-tested components.

There is a catch when it comes to writing components using frameworks. Libraries written in React can’t be used in Vue projects and vice versa. In fact, component libraries written in [Vue 2 aren’t necessarily compatible with Vue 3](https://twitter.com/claviska/status/1575505203763335169). Building a2k using web components means that we have an interoperable way of building retro user interfaces that won’t be obsolete by the next cycle of frontend tooling

![Vanilla, Vue, and React components side-by-side](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mdbnqehoa3jx2yvpbybn.png)

### To put the fun back in uhh.. fruntend (😅) development

a2k is designed to evoke a feeling of nostalgia and to help others form the foundations of their own retro web applications. For me, this alone is a motivating enough reason to pursue a project.

[Andricos2000](https://a2000.netlify.app/) is a fun example of a project that uses a2k to build a retro web application

<video controls style="width:100%">
  <source src="https://public-images-and-stuff.s3.amazonaws.com/a2000-video.mp4" type="video/mp4" />
</video>

## How does a2k work?

Like with many UI libraries, a2k is comprised of a base stylesheet and a suite of fully-functional components

### Base Stylesheet

This CSS file has a bunch of jobs. First off, it sets the base styles, like the default font family, loading cursor assets, setting the default element appearances, etc.

The file also defines some utility classes. For common styles that don’t need to be entire components, we can create utilities that we can reuse across our entire application.

Finally, the CSS file also creates the variables which we can use throughout our entire site. It also defines the variables for individual components. The file also applies the default values for these variables, which can be overridden by the user.

### Component Suite

a2k exports a growing number of different web components. Many of these components can be categorised based on complexity or expected usage.

### Layout UI

These are components with no built-in interactivity but are used to help build component/application layouts. One example is the `a2k-panel`, which is a box that applies some retro styling. It can be used alone, but it’s also used to build more complex components, like the `a2k-window`.

### Behavioural UI

These are the common UI patterns, like buttons, select menus, and progress bars. You can use these components any place you’d use the native counterpart with the same behaviour but with the added benefit of cool retro UI.

Components like `a2k-button` offer style and functionality outside of the box. More complex UI components like `a2k-select` are built with the [ARIA authoring practices](https://www.w3.org/WAI/ARIA/apg/) in mind, so they’re accessible alternatives to the native browser components.

### Composite Components

These are complex components that are built on top of other layout or behavioural components.

The `a2k-taskbar` is one such example. The taskbar is a complex UI pattern that’s built using a mix of HTML, `a2k-button`, `a2k-icon`, and `a2k-panel`.

![Can you spot all the different components used?](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mzsl85l43yo0w0k8yqzx.png)

These components are highly specialised and you will likely not need to use them frequently. They might be used to build desktop-inspired UIs. You can even build your composite components using the building blocks that a2k provides.

## Getting started with a2k

Because a2k is built using web components, it’s easy to integrate with different frameworks, like Vue and React.

I’ve provided some handy guides below to get a2k up and running using different frameworks; vanilla JS, Vue, and React.

### Vanilla JS

To begin, we’ll need to do a little repo setup. We’ll be using [Web Dev Server](https://modern-web.dev/guides/dev-server/getting-started/), which we’ll use to run a local development server. This will allow us to easily use the node modules we install via npm.

We’ll also use [Lit](https://lit.dev/docs/), which is a simple library to help build web components. While we won’t use this library directly, a2k uses it under the hood so we need to ensure that it’s available.

Start by initialising your project using:

```bash
npm init -y
```

You can now install the necessary node modules:

```bash
npm i @a2000/styles @a2000/select @web/dev-server lit
```

In the root of your project, create an index.html file with the following contents:

```html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <title>a2k web components</title>
  </head>
  <body>
    <div style="width: 300px">
      <a2k-select placeholder="Favourite OS">
        <option>Windows</option>
        <option>Linux</option>
        <option>Apple</option>
      </a2k-select>
    </div>
  </body>
</html>
```

Lastly, kick off your development server with the following script:

```bash
npx wds --node-resolve --open --watch
```

Open up your site at localhost:8000 and you should be greeted with some unstyled HTML. This is completely expected as we haven’t linked up the a2k styles yet. We also haven’t registered our web components either, so the browser will display the fallback content. In this case, the contents are the three option elements.

Inside the head element add the following HTML tag:

```html
<link rel="stylesheet" href="./node_modules/@a2000/styles/a2k-styles.css" />
```

If you jump back to localhost:8000, you can see that the font family and the sizes of the HTML have changed, which shows that the stylesheet is being imported properly.

The final step is to register our web component. We do this by simply calling importing the script that a2k uses to register the select component. At the bottom of your `body` element, paste the following:

```html
<script type="module">
  import "@a2000/select/a2k-select.js"
</script>
```

Jump back to localhost:8000, and you should see a fully functioning select component.

<video controls style="width:100%">
  <source src="https://public-images-and-stuff.s3.amazonaws.com/select-menu.mov" type="video/mp4" />
</video>

And that’s it!

The a2k web components are working in your basic HTML file. Try and experiment with some of the other components laid out in the [documentation](https://a2000-docs.netlify.app/). If you come up with anything cool, please share it with me on [Twitter](https://twitter.com/AndricoKaroulla) or [Mastodon](https://front-end.social/@andrico).

### Vue

Because Vue scores a perfect score in the [Custom Elements tests](https://custom-elements-everywhere.com/libraries/vue/results/results.html), integrating web components in your Vue project should be a breeze. Let’s see how we can do this with a2k.

In a new directory, run the following script:

```bash
npm init vue@latest
```

The terminal will prompt you with a few options but for the sake of this tutorial, you can choose no for all of them.

Move into the directory and install all the necessary dependencies:

```bash
cd vue-example
npm i @a2000/styles @a2000/select lit
```

Once that’s done, you can kick off your dev server with the following

```bash
npm run dev
```

Begin by updating your `App.vue` so that it looks like the following:

```html
<script setup></script>

<template> </template>

<style scoped></style>
```

If you open up [localhost:5173](http://localhost:5173) in your browser, you should see an empty page. Let’s go ahead and add some web components.

First off, add the following to your `index.html`'s `head` component:

```html
<link rel="stylesheet" href="./node_modules/@a2000/styles/a2k-styles.css" />
```

Update your `App.vue` file to import and render the a2k select component:

```html
<script setup>
  import "@a2000/select/a2k-select.js"
</script>

<template>
  <div style="width: 300px">
    <a2k-select placeholder="Favourite OS">
      <option>Windows</option>
      <option>Linux</option>
      <option>Apple</option>
    </a2k-select>
  </div>
</template>

<style scoped>
  a2k-select {
    color: black;
  }
</style>
```

Jump back to [localhost:5173](http://localhost:5173) and you should see the select menu in the browser. That’s it!

### React

Sadly, React’s support for custom elements isn’t as comprehensive as Vue’s, so we’ll have to do a little extra work to get this working.

Let’s create a react project by running the following in your terminal:

```bash
npx create-react-app react-example
```

let’s install the necessary packages:

```bash
npm i @a2000/styles @a2000/select lit @lit-labs/react
```

The packages we’re installing are pretty much the same as earlier, but with an additional package, `@lit-labs/react`. This is a [handy package](https://www.npmjs.com/package/@lit-labs/react) by the Lit team to integrate web components with React.

Clean out your `App.js` file so it looks like the following:

```jsx
function App() {
  return <div></div>
}

export default App
```

Kickoff the dev server using:

```bash
npm run start
```

Your [localhost:3000](http://localhost:3000) should be empty at this point.

Go ahead and create a new file in your `src` directory called `SelectComponent.js` with the following contents:

```jsx
import * as React from "react"
import { createComponent } from "@lit-labs/react"
import { A2kSelect } from "@a2000/select"
import "@a2000/select/a2k-select.js"

export const SelectComponent = createComponent({
  tagName: "a2k-select",
  elementClass: A2kSelect,
  react: React,
  events: {
    onactivate: "activate",
    onchange: "change",
  },
})
```

Without getting too much into the weeds, I’m simply following the documentation for the `createComponent` API. I am however importing twice from `@a2000/select` twice. Once to access the `A2kSelect` component class itself, the second to register the custom element to the window. In the future, I’ll look to simplify this process.

This file exports a component which is a wrapper around the web component. The wrapper ensures that any props and events are handled correctly as they’re passed through to the custom element.

Next, let’s import our styles and use our component. Clear out `App.js` and replace it with the following:

```jsx
import "@a2000/styles/a2k-styles.css"
import { SelectComponent } from "./SelectComponent"

function App() {
  return (
    <div style={{ width: "300px" }}>
      <SelectComponent placeholder="Favourite OS">
        <option>Windows</option>
        <option>Linux</option>
        <option>Apple</option>
      </SelectComponent>
    </div>
  )
}

export default App
```

For the most part, the markup looks very similar to the vanilla and Vue examples, so everything should look familiar to you. Jump back into your browser and have a little play with the components. Everything should be working as expected.

## How can I support a2k?

a2k is still a work in progress, so any feedback is welcome. If you run into any problems while following the set-up guides, please open a [GitHub issue](https://github.com/andrico1234/a2k).

Other ways you can support the library is by using a2k in your own projects and requesting the changes and features you’d like to see.

Finally, if you enjoyed the article and want to show a little support. You can simply give [a2k a star on GitHub](https://github.com/andrico1234/a2k).

## What does the future look like for a2k?

I’m nowhere near finished building a2k, there’s still much more I’d like to add in the near/long-term future. Some of the cool things I’d like to add include:

- Support for server-side rendered components using declarative shadow DOM.
- More components
- Improved customisation
- React components for each component

I’d also like to use a2k as a springboard for any cool and interesting ideas that I have. I’m also happy for others in the web community to contribute with some great ideas too.

Thanks for reading, and I hope that you have a lot of fun using a2k in your own projects.