Create a Borderlands-style skill tree in 5 minutes
Tags: react, typescript, javascript
Published: 2019-08-21 06:36:05


## How to combine your two favourite things to make an exciting and engaging experience for your users.

Growing up, I spent my spare time doing what most programmers did; played video games every waking moment. I loved Adventure games and what a time sink they were; if time was the Mary Rose, and I was the French, my artillery were games like Kingdom Hearts, Ōkami, and Borderlands. 

Why did I, and others, spend so much of our spare time exploring, surviving, dying, and (so, so much)grinding? Hundreds of factors contribute toward making an engaging experience, but the one I'm going to focus on is the notion of progression.

The idea of gamnification isn't new, with many popular applications (like [todoist](https://todoist.com/?lang=en), or [challenge timer](https://productivitychallengetimer.com/)) incorporating some sort of progression scheme to make us, the consumer, use their app, give them money, and hand over our personal data. So I decided to go about my way of enabling others to do just that, through beautiful skill trees! Note: I expect neither money nor data from those using my personal skill trees.

The last few weeks have seen me toil away to create what I hope to be a pleasant plug'n'play React package to help you create exciting skill trees. You can test it yourself by following the tutorial. I hope it to be a frictionless experience.

We hope to have something resembling the skill tree below.

https://thepracticaldev.s3.amazonaws.com/i/sn9tgrqpv98tm4ftqvqx.png

Grab the starter repo by using `git clone git@github.com:andrico1234/borderlands-skill-tree.git`

Move into the directory and run the starting script,  `yarn start`. Give the site a whirl, you'll see nothing but the Borderlands logo and environment.

`beautiful-skill-tree` exposes three components: the `SkillProvider`, `SkillTreeGroup`, and the `SkillTree` components.

`SkillProvider`: This takes in no props and supplies the children with the skill tree's context. This puppy handles all of the global data related to the skill tree. 

`SkillTreeGroup`: Is more involved in that it can take an optional `theme` property, where we can pass in some custom styling, to make our skill tree feel very Borderlands. The `SkillTreeGroup` also uses the children-as-a-function pattern to give us access to some imperative api functionality, such as skill tree reset, selected skills counter, etc. We don't need to worry about any of those for the scope of this article.

`SkillTree`: This is the most exciting of the package's exports, unless you're a sucker for typings (which are also exported, for all you TS fans). The `SkillTree` doesn't take any children but requires 3 props: `treeId`, `title`, and `data`. The `treeId` should be an id that's unique to each skill tree, but should be persistent across user sessions as this is used as the key for getting and setting the data to local storage. I'm not going to explain what the `title` prop does, I'll leave you to experiment. The `data` is the mixing pot of the application. You'll pass in your skill tree data structure which the app will use to render a `beautiful-skill-tree`.  Let's get a real basic tree going before we move on to our multi-tree, multi-branch Borderlands spectacular. 

In App.tsx, import the 3 components like so:

```typescript
import { SkillProvider, SkillTreeGroup, SkillTree } from 'beautiful-skill-tree';
```

Place it underneath your `img` tag, outside of the image's container div, but within the outer div. Add the `SkillProvider`, passing the `SkillTreeGroup` as a child. Before you do the same with the `SkillTree`, remember that as `SkillTreeGroup` uses function-as-a-child pattern, you'll need to render a function that returns the child components. Return a single `SkillTree` and give it a `treeId` and a `title` prop. Pass an empty array into the `data` prop so your `App.tsx` looks like this.

```typescript
function App() {
  return (
    // <div>
    //  <div headercontent />
        <SkillProvider>
          <SkillTreeGroup>
            {() => {
              return (
                <SkillTree treeId="basic-birch" title="First Skill Tree" data={[]} />
              )
            }}
          </SkillTreeGroup>
        </SkillProvider>
    // </div>
  );
}
```

Go to [localhost:3000](http://localhost:3000) to see the application running. You should see the logo, background, and a grey rectangle. If you're running into any errors, go through the introduction again and check to see if there any syntax error or incorrect imports. 

Next, let's create a real basic tree. Just 3 items that move in a linear line. The data structure for `data` looks like this:

```typescript
type Skill = { 
    id: string;
    icon?: string;
    title: string;
    tooltip: {
      description : string;
    },
    children: Skill[];
}
```

Each skill requires four properties, with one being optional. You should also notice that the `children` property is a recursive type, meaning that it takes an array of the same data structure, which it uses to render the children of the skill. This can go on infinitely, and make for some real complicated, winding trees. I'll create the first skill for you, and I'll trust you with carrying on for the next two items.

```typescript
const data = [
  {
    id: 'first-skill',
    title: 'The root node',
    tooltip: {
      description : "The parent node, all of the descendants will be locked until it's selected",
    }
    children: [
      // rinse and repeat; always repeat.
    ]
  } 
```

Add the above snippet to the `App.tsx` file, and replace the empty array inside of the `SkillTree`'s `data` property with our `data` definition. Load your page, and you should have an interactive node. Give it a hover and a click and it should be reacting to your actions. If things are working, then I'll task you with creating two (or more) child nodes. Experiment with children and sibling lengths, to see what you can come up with. (If you also happen to break my precious package, leave me a [GitHub issue]() so I can patch things up).

Once you're comfortable with creating a skill tree, let's go ahead and create our Borderlands skill tree. Fortunately, I've done all of the tedious work for you and have already created the data structures and accumulated the images.

You'll need to import the three trees from the `data` file, which can be done via

```typescript
import { motion, harmony, cataclysm } from "./data/data";
```

The next step is creating two additional `SkillTrees` alongside the current one. You'll need to wrap them in a `React.Fragment` as your `SkillTreeGroup` will now be trying to render 3 top level components. Pass in the data accordingly, and if you're unsure, I've posted the code snippet below. 

```typescript
<React.Fragment>
  <SkillTree treeId="motion" title="Motion" data={motion} />
  <SkillTree treeId="harmony" title="Harmony" data={harmony} />
  <SkillTree treeId="cataclysm" title="Cataclysm" data={cataclysm} />
</React.Fragment>
```

Go ahead and check your web browser, it should be **aaallmoost** ready. We've got the skills rendered, but the styling feels a little lackluster. It doesn't feel very Borderlands. Fortunately for you, I'm a regular [Neil Buchanan](https://www.youtube.com/watch?v=0evlWSY8kTc) and prepared a custom theme. Import the theme and pass it through to the `SkillTreeGroup`'s `theme` prop. The theme object is export via `import theme from './data/theme';`. Easy!

https://thepracticaldev.s3.amazonaws.com/i/efhb04w09pc44j8z44dr.png

Once you've done the above, check out the finished product. If you're still not satisfied with the styles, check out the theme object and customise it yourself, there are a bunch of additional attributes whose styles can be adjusted, so just peek into the typings of the package.

I mentioned earlier that there are a few additional properties and values that can be used to tweak the skill tree, so have a mess around yourself, and link me to any cool trees you create. I'd love to add it to the growing list of trees found [here](https://github.com/andrico1234/beautiful-skill-tree#examples). [Here's](https://calisthenicsskills.com/) an example of the skill tree that kickstarted this obsession. 

I hope you've enjoyed tinkering with the `beautiful-skill-tree` package. I'm always adding new features and updating, so give it a star on github! You can find an online demo of the borderlands skill tree [here](http://borderlands-skill-tree.s3-website.eu-west-2.amazonaws.com/)

You can find me on [Instagram]() or GitHub if you want to chat code, music or fitness!