Getting started with Barebones components

Getting started with Barebones components

A component library without design constraints built for Vue and Nuxt

·

7 min read

1. Backstory

In early May of this year, I lost my job as a Lead Developer at a subscription start-up, along with all my colleagues. When I joined the company they had recently had an investment of £4m (Around $4.8m) and since then we had been beating all of our targets. We’d been beating them to the point that company had managed to agree on a deal for a further £10m investment this year. Unfortunately for those of us that worked there, the current economic climate and threat of another recession in the UK by the end of 2022 led our biggest investors to pull out last minute, this led to other investors following and the deal falling apart. The company went into Administration the next day and we all lost our jobs.

2. The idea behind Barebones

After losing my job so suddenly I decided to take a little bit of time to work on some personal projects, trying to solve some of the issues that I’d come across while working at my last company. This is where the idea for Barebones was born. I wanted to create a component library that allowed developers to build applications fast without design constraints. Have access to all the types of components they’re using in almost every project, with complete design freedom.

3. How does Barebones work?

Put simply, Barebones uses local configuration to map styles to component parts. But, what does that mean exactly? Well, when installing Barebones in a project you must add the local configuration files. The local configuration for each component is made up of 2 files a .parts.ts file and a .props.ts file, which work in unison map styles to component parts, component parts are the elements which make up a component.

3.1. props.ts files

.props.ts files allow developers to set up props, which values can be mapped to styles for each component part. This allows developers and teams to set up their own preferred variables for styling components.

3.2. parts.ts files

.parts.ts files allow developers to define style mapping keys and values for any component part based on a prop defined in .parts.ts in the components .props.ts file.

3.3. Component parts

Each component element is a defined component part and can be referenced in the .parts.ts file and assigned relevant component props and values to map styles.

3.4. By example

Every component is different and has a different use case but by taking a simple component like the Text component we can see how simple for developers and teams to define their own props and style mapping to suit their preferred way of working.

The Text component has a single component part called component. This allows us to easily see the way two teams may approach styling the Text component.

3.4.1. Modular approach

Some developers and teams may choose a more modular approach to mapping styles to components in their projects. For example, the Text component may need to know Size, Color, and Font. To set up these props in the Text.props.ts file they may add the following props:

export const classProps: ClassProps = {
  size: {
    type: String,
    default: "default",
  },
  color: {
    type: String,
    default: "default",
  },
  font: {
    type: String,
    default: "default",
  },
};

The above would make the following props available to the Text component: size, color, and font, and each prop would default to the value default. However, as it stands they would not map any styles.

To map styles for each of these props we would need to open the Text.parts.ts file and add each prop to the relevant component parts with the available keys and their style values. Because the Text component only has one component part, component, each prop key will be a direct child property of component, in more complicated components developers can add props as property keys to only the parts that are affected by that prop. Text.parts.ts in this example may look something like this:

const parts: Parts = {
    component: {
      color: {
        default: ["color-black"],
        blue: ["color-blue"]
      },
      size: {
        default: ["size—default"],
        medium: ["size—medium"],
        large: ["size—large"],
      },
      font: {
        default: ["font-sans"],
        serif: ["font-serif weight-bold"]
      },
    },
  };

With the styles mapped, developers and their teams could now use the Text component in the following manner:

<BonesText font="serif" color="blue" size="large">Hello world</BonesText>

Which would output the following:

<p data-component="BonesText" data-part="component" class="font-serif weight-bold color-blue size-large">Hello world</p>

3.4.2. Broad approach

Alternatively, some developers and teams may choose a more broad approach to mapping styles to the Text component in their projects. For example, they may choose to encompass all the styles within a single prop named textStyle. To set up this prop in the Text.props.ts file they may add the following prop:

export const classProps: ClassProps = {
  textStyle: {
    type: String,
    default: "default",
  }
};

Like the more modular approach, the developers and teams would need to update the Text.parts.ts file to begin mapping styles for the textStyle prop.

To map styles for the textStyle prop we would need to open the Text.parts.ts file and add the prop to the relevant component parts with the available keys and their style values. Because the Text component only has one component part, component, textStyle will be a direct child property of component, in more complicated components developers can add props as property keys to only the parts that are affected by that prop. Text.parts.ts in this example may look something like this:

const parts: Parts = {
    component: {
      textStyle: {
        default: ["color-black size-default font-sans"],
        title: ["color-blue size-large font-serif weight-bold"]
      },
   },
};

With the styles mapped, developers and their teams could now use the Text component in the following manner:

<BonesText textStyle="title">Hello world</BonesText>

Which would output the following:

<p data-component="BonesText" data-part="component" class="font-serif weight-bold color-blue size-large">Hello world</p>

4. Getting started

To get started with Barebones, in a Vue 3 or Nuxt 3 begin by running one of the following commands in the root of your project:

4.1.1. Yarn users

yarn add @wearethreebears/barebones

4.1.2. NPM users

npm install @wearethreebears/barebones

Once Barebones is installed, you will need to configure it for use in your project:

4.2.1. Vue 3 users

Add the aliases to your paths in your tsconfig.json file:

{
    //
    "@barebones/*": [
        "node_modules/@wearethreebears/barebones/src/*"
    ],
    "@barebones-local/*": [
        "barebones/*"
    ],
    //
}

Add the aliases to your aliases in your vite.config.js file:

{
    //
    "@barebones": fileURLToPath(
        new URL(
        "./node_modules/@wearethreebears/barebones/src",
        import.meta.url
        )
    ),
    "@barebones-local": fileURLToPath(
        new URL("./barebones", import.meta.url)
    ),
    //
}

4.2.2. Nuxt 3 users

Add the aliases to your tsconfig.json file:

{
    //
    "compilerOptions": {
        "paths": {
        "@/*": [
            "./*"
        ],
        "@barebones/*": [
            "node_modules/@wearethreebears/barebones/src/*"
        ],
        "@barebones-local/*": [
            "barebones/*"
        ],
        }
    }
    //
}

Add the aliases to your nuxt.config.ts file:

import { resolve } from 'path'

export default defineNuxtConfig({
    {
        //
        alias: {
            "@": fileURLToPath(new URL("./src", import.meta.url)),
            "@barebones": fileURLToPath(new URL("./node_modules/@wearethreebears/barebones/src", import.meta.url)),
            "@barebones-local": fileURLToPath(new URL("./barebones", import.meta.url)),
        },
        //
    },
})

Auto import the components (By default this will prefix all Barebones components with Bones):

export default defineNuxtConfig({
    //
    buildModules: ['@wearethreebears/barebones/nuxt'],
    //
})

4.3. Add local configuration files

Next you will need to add the local configuration files using an NPX command. You can choose a blank canvas configuration, which will just contain the boilerplate for you to start adding your props and classes or you can choose from one of the pre-made theme configurations as a starting point. To start with a blank canvas run:

npx @wearethreebears/barebones theme blank

To use a pre-made theme you can run a variation of the following command:

npx @wearethreebears/barebones theme <cssLibrary>/<themeName>

Where <cssLibrary> is the name of the library (e.g. Tailwind, Vanilla) and <themeName> is a theme within that library. See all available themes here.

At the time of writing, the only pre-made theme is Tailwind Salient and will require Tailwind JIT to be set up in your application. To set up Tailwind in your application see the Tailwind Documentation. To add the Tailwind Salient theme, you would run:

npx @wearethreebears/barebones theme tailwind/salient

5. Start building

Now Barebones and its local configuration are installed, you can start building. To view all of the components Barebones makes available to you with their defined parts and examples please refer to the Barebones Documentation. The documentation, while it is still in its first draft, is fairly complete and should provide you with all of the knowledge you need to start using components Barebones quickly.

6. Conclusion

If you’ve found this article useful or the found the project interesting please drop the project a star on Github and please follow me on Medium, Dev.to and/ or Twitter.