import { Meta } from "@storybook/addon-docs";

<Meta title="Guidelines/Add Component" />

# Adding new components

## When to create a new component

**Creating a new component is the easy part, deciding when/if one should be created can sometimes be a challenge. If the following is true, you should definitely create a new component:**

- **Reusability** The code will be reusable in multiple interfaces, both visually and functional.
- **Size** When a component grows beyond a few hundred lines of code, it should be separated into smaller components, these components will usually be useful elsewhere.
- **Maintainability** There are already existing/similar versions of the component in any of the apps that can be consolidated into one component.
- **Consistency** Consistency created trust and familiarity for your users, using components is an easy way to make sure things stay and look consistent with one another.

## Atoms, molecules and organisms?

You're probably wondering WTF chemistry has to do with components?

The first thing you'll need to decide once you've figured out a component is required, is where to categorize it within Luminary.

We use the [atomic design methodology by Brad Frost](https://atomicdesign.bradfrost.com/) to break down components.

### Atomic design takes cues from chemistry:

- **[Atoms](https://atomicdesign.bradfrost.com/chapter-2/#atoms)** If atoms are the basic building blocks of matter, then the atoms of our interfaces serve as the foundational building blocks that comprise all our user interfaces. These atoms include basic HTML elements like form labels, inputs, buttons, and others that can’t be broken down any further without ceasing to be functional.

- **[Molecules](https://atomicdesign.bradfrost.com/chapter-2/#molecules)** In chemistry, molecules are groups of atoms bonded together that take on distinct new properties. For instance, water molecules and hydrogen peroxide molecules have their own unique properties and behave quite differently, even though they’re made up of the same atomic elements (hydrogen and oxygen). In interfaces, molecules are relatively simple groups of UI elements functioning together as a unit. For example, a form label, search input, and button can join together to create a search form molecule.

- **[Organisms](https://atomicdesign.bradfrost.com/chapter-2/#organisms)** Organisms can consist of similar or different molecule types. A header organism might consist of dissimilar elements such as a logo image, primary navigation list, and search form. We see these types of organisms on almost every website we visit. While some organisms might consist of different types of molecules, other organisms might consist of the same molecule repeated over and over again. For instance, visit a category page of almost any e-commerce website and you’ll see a listing of products displayed in some form of grid.

There are also [Templates](https://atomicdesign.bradfrost.com/chapter-2/#templates) and [Pages](https://atomicdesign.bradfrost.com/chapter-2/#pages), but those don't need to be covered here. However, it's worth the read nonetheless.

## Naming components

The non-negotiable important factors in naming a component are:

- Consistency
- Clarity
- Meaning

### Components

Different disciplines use component names to communicate about them. Hence, they must be short, meaningful and pronounceable.

- **Components should be prefixed with `L` eg. `LButton`** to avoid conflicts with native HTML elements as well as 3rd party components we have no control over.
- **Components should aways use camelcase as the `filename` and `name`**, however, don't need to be used as such. eg. `LButton.vue`, and used as `<l-button />`.
- **Noun rather than verb**: Components are not actions, they are conceptually “things.” It is better to use nouns instead of verbs. “LInput,” “LTab,” and “LNav,” are some examples.
- **Short**: Maximum of 2 or 3 words.
- **Pronounceable**: We want to be able talk about them.

### CSS Classes

We use a simplified version of BEM to keep our CSS classes maintainable and consistent.

- All CSS class names for components should follow the component naming. eg. an `LButton.vue` will have the following base CSS class: `.l-button`
- All child class names should have the following structure `.l-button-<child>`. eg `.l-button-inner`
- For modifiers/variants use a double dash, eg. `.l-button--primary`

## Variants & Tokens

**Component specific tokens can be used to create different variants of a component.**

The traditional way of creating variants of components is usually done by creating a CSS class for the specific variant.

```
<template>
  <component
    :class="classes"
  >
    ...
  </component>
</template>
<script>
  ...
  computed: {
    classes() {
      return [
        "l-button",
        "l-button--" + this.buttonType,
      ];
    },
  }
</script>
<style>
.l-button {
  ...
}
.l-button--primary {
  ...
}
.l-button--secondary {
  ...
}
...
</style>
```

In some cases, this is still benificial. But in most cases, especially when there are quite a few variants it's better to use CSS variables/tokens.

**Using scoped tokens**

```
<template>
  <component
    class="l-button"
    :style="{
      '--button-bg': buttonBG,
      '--button-hover': buttonHoverBg,
    }"
  >
    ...
  </component>
</template>
<style>
.l-button {
  background-color: var(--button-bg);
}
</style>
```

## Testing & Publishing

### Testing

Before implementing the component in an app, do thorough tests in Storybook.

1. Test the component at different screen sizes (remember to use the mobile first approach from the Luminary guidelines)
2. Test in all major browsers (Browserstack is a great tool for testing)
3. Test all variants/states of the component

Once thoroughly tested, implement the component in an app and go through all the steps again and test with real data.

### Status

The status of the component lets others know if they should use the component, there are the following states available:

- **experiment** Use for PoC and ideas.
- **development** Status until component has been tested.
- **review** Once tested the component needs to be reviewed by the design system team.
- **released** Released and ready for production.
- **deprecated** Component has been deprecated and should not be used/phased out in production.

Status of a component can be set in the `.stories.js` file.

### Distribute

1. Add the new component to the manifest (`/index.js`)
2. Make sure you have publishing right for the [package on NPM](https://www.npmjs.com/package/luminary).
3. Commit and merge all changes to the `master` branch.
4. Run `yarn publish` in the luminary directory and follow the prompts.

### Versioning

We follow the NPM recommended [Semantic versioning](https://docs.npmjs.com/about-semantic-versioning)
