Oruga: the new kid on the block
Tags: vue, css, ux, showdev
Published: 2021-03-03 16:04:38

If you're working with Vue.js you know that here are a lot of UI component libraries orbiting around the Vue.js world like Vuetify, Buefy, BootstrapVue and so on. Rather than coding and styling buttons, cards, and layouts, you can use these libraries to get access to all the necessary UI elements for creating beautiful, content-rich applications. However sometimes you want to switch to your custom design or try another UI framework that doesn't provide any ready-to-use Vue.js component. In such cases you would like to have a set of naked UI components on which you can apply your style: here's where Oruga comes into play!

## Say Hi to Oruga! 👋

[Oruga](https://oruga.io) is a new lightweight library of UI components for Vue.js (2.x and 3.x) without any CSS framework dependency. In fact, it doesn't depend on any specific style or CSS framework and it doesn't provide any grid system or CSS utility, it just offer a set of components that you can easily customize modifying your stylesheets or integrating it with a CSS framework. It also provides a default stylesheet containing only the essential rules to display Oruga components correctly such as `display`, `position`, `z-index` and other basic attributes. 
Oruga wants you to <b>focus only on UI/UX aspects</b> of your application and <b>be totally flexible to future changes</b> without having to touch a line of JavaScript.

👉🏻 You can find useful resources and links at the end of the article!

## Setup 🐛

Let's start a new project for Vue.js 2.x and install Oruga package (note that Oruga is available for Nuxt.js as well, [see the documentation](https://oruga.io/documentation/#nuxt-module))

```bash
yarn add @oruga-ui/oruga
```

Then, import Oruga default stylesheet, the `Config` component and the `Button` component

```js
import Vue from 'vue'
import {
  Config, Button
} from '@oruga-ui/oruga';

import '@oruga-ui/oruga/dist/oruga.css'

Vue.use(Button)
```

`Config` will be used for customization.

## Customization

Customization is the core feature of Oruga. You can easily override existing components style appending one or more classes using the `Config` component. Each component has some `class properties` that you can define to extend classes of the target component. Each class property affects a specific part of the component as you can discover using the Class props inspector in Oruga documentation. 

<video controls="controls" autoplay="autoplay" muted="muted" loop="loop" class="oruga-doc-video"><source src="https://oruga.io/inspectormov.mp4" type="video/mp4"></video>

Suppose we want to style our Oruga components using a cool CSS framework like [Nes.css](https://nostalgic-css.github.io/NES.css/) to give our app a cool 90s style.

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3stfvh0s0xn6lu5xuoqr.png) 

To install Nes.css run

```bash
yarn add nes.css 
```
(add `--ignore-engines` to the command above if you're using Node.js > 10.x)

And import it in your project

```js
import "nes.css/css/nes.min.css";
```

Let's start with a simple [Button component](https://oruga.io/components/Button.html) from Oruga.

```html
<o-button @click="search">Search</o-button>
```

Nes.css provides `nes-btn` class for buttons, so we can extend Oruga Button component using the Config object

```js
Vue.use(Config, {
  button: {
    rootClass: 'nes-btn'
  }
}
```

When you instantiate a new Oruga Button, you'll have the class `nes-btn` automagically applied to your component, alongside default classes applied on that part of the component. If you wish to override default classes and use only your custom class, you can assign to `rootClass` an object, with the `override` attribute set to `true`.

```js
Vue.use(Config, {
  button: {
    rootClass: {
      class: 'nes-btn',
      override: true
    }
  }
}
```

Using the Class props inspector we can easily find the class name to add a class when the button is disabled (in this case `disabledClass`), then we can extend our configuration overriding all the class props of o-button we need to customize

```js
Vue.use(Config, {
  button: {
    override: true,
    rootClass: 'nes-btn',
    disabledClass: 'is-disabled'
  }
})
```

Result

{% codesandbox musing-shannon-d34kk %}

Sometimes you may need more flexibility to extend classes and decide programmatically which class to apply to our component, especially when you have to deal with variant or position classes. Many Oruga components has some classes applied when certain properties change, like `position` and `variant`, on the other side Nes.css provides "variant" classes like `is-success` and `is-warning` and "position" classes like `is-centered`. For example, how can I apply the correct class in this case? 

```html
<o-button variant="warning">Warning!</o-button>
```

Follwing the Class prop inspector we can easily find that the Class prop we need to override is `variantClass` but its values are not fixed, it could be `is-warning`, `is-error`, `is-success` depending on variant value as you can see in the `Suffixes` column

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oce0a6w8c2oa0keb3rxk.png) 

Oruga provides an easy way to help us: you can extend classes using functions! A function will receive two parameters: 

- a `suffix` (that will receive for example `waring`, `success`, `error` in case of variants or `centered`, `right`.. in case of positions)
- a `context` containing the context of the component instance.

To extend variantClass with Nes.css for Button we can simply do that

```js
Vue.use(Config, {
  button: {
    rootClass: "nes-btn",
    variantClass: (suffix, context) => {
      return `is-${suffix}`
    }
  }
})
```

Result:

{% codesandbox crazy-almeida-bpk2s %}

`variantClass` is determined by a function that will receive `"warning"` as suffix when variant property of `o-button` is "warning". Using a function we can instruct Oruga to apply to our Button components a class whose name is composed by "is-" followed by the suffix value, in this case the variant. Thanks to the `context` parameter, you can take more refined decisions like not applying a variant if the component is outlined (see an example [here](https://github.com/oruga-ui/demo-multiframework/blob/master/src/views/Bootstrap.vue#L24))

## A Pokèmon finder with Oruga and Nes.css

Using Oruga and Nes.css I built a simple Pokèmon finder to search some statistics of my favourites Pokèmon taking advantage of the cool [PokèAPI](https://pokeapi.co/). 

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3n28nt2cgdlahxvl3rna.png) 

The app is really simple: it allows you to type Pokèmon name you want to find, press a button and then, through the API, get all the information you need and show them in a table. If the Pokèmon can't be found, the search input will turn red (variant="error") and an error message will be shown. You can play with the app on [Netlify](https://happy-mestorf-628bac.netlify.app/) and [browse the final code on GitHub](https://github.com/astagi/orugamon)

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hyd7rwbj6e49818vuxg8.png) 

As you can see in the [main.js file](https://github.com/astagi/orugamon/blob/master/src/main.js) the final configuration for Oruga is really simple.

## Useful resources

- [Oruga official website and documentation](https://oruga.io/)
- [GitHub organization](https://github.com/oruga-ui/oruga)
- [Discord channel](https://discord.com/invite/RuKuBYN)
- [Twitter](https://twitter.com/oruga_ui)

You can also play with other cool Oruga examples

- [TailwindCSS, Bootstrap 5, Bulma and Material demo](https://oruga-multiframework-demo.netlify.app) - [Source code](https://github.com/oruga-ui/demo-multiframework)
- [TailwindCSS 2 Recipe Demo](https://oruga-tailwindcss-demo.netlify.app) - [Source code](https://github.com/oruga-ui/demo-tailwindcss)