Getting Started With ClarityUI

Getting Started With ClarityUI

· Read in about 13 min · (2762 words) ·

Introduction

VMware ClarityUI is VMware’s standard set of UI controls which our platform interfaces are built from. Prior to ClarityUI; each business unit independently designed their interfaces, which led to quite a diverse set of interfaces - and a bit of a reputation in the community which was was not a good one… The Clarity team introduced this set of Angular components for quickly bootstrapping and building next generation user interfaces and more importantly, improved user experiences.

I’ve been doing a lot of work in the web application space lately. A lot of this is creating demonstration applications or utility applications for interacting with the various platforms I’m working on. As an example, I recently wrote an application that bolts onto the Cloud Automation Services API to act as a UI for managing the access to the training groups we have.

In this blog, I’m going to show you how to quickly get started with ClarityUI - and begin your journey to building your first Angular application!

Getting Started

We need to install NodeJS to get started. This is going to give us access to NPM, or Node Package Manager. NPM is a very nice tool that we can use to easily install a variety of packages, including ClarityUI!

On Windows, it’s a simple MSI based installation. You can install it with YUM and APT on Linux. On MacOS you can install it via homebrew. I won’t detail out the “how” of NodeJS here, since it’s quite easy to figure out how to install.

With NPM installed, we can go 2 paths. The Clarity team has put together a pretty stellar “Getting Started” document that covers much of this. I’ll cover the steps, and add my own commentary along the way.

Pure CSS and HTML

ClarityUI is largely an Angular component kit, however, a significant portion of the kit is simply HTML and CSS components. If you look at the blog page you are currently reading - this is not an Angular application. It’s a static site generated using Hugo. Everything on here is simple HTML and CSS and in order to expose the non-Angular Clarity items, all I’ve had to do is inject the CSS and JS files for ClartyUI. In order to pull those down, we can use NPM!

npm install @clr/ui --save

This commands tells NPM to install the ClarityUI package, and save the files permanently. These files will be stored in your node_modules directory.

An easy way to find your NPM directory on a Mac is to run…

npm root -g

Which will output the location of your node modules. In my environment, I can then cd to /usr/local/lib/node_modules/ and list the directory. In that folder I’ll see the @clr folder, which has a sub directory UI that holds all of the CSS files.

These steps all apply if you want to bring down the CSS files locally and store them with your web project. The alternative path is to just call the Clarity CSS modules via the Content Delivery Network (CDN) they have provided.

Those are available here (as documented on https://v1.clarity.design/get-started)

<!-- Load the latest version -->
<link rel="stylesheet" href="https://unpkg.com/@clr/ui/clr-ui.min.css" />
<!-- Or load a specific version -->
<link rel="stylesheet" href="https://unpkg.com/@clr/ui@0.12.5/clr-ui.min.css" />

Firing Up Some Angular

Now the above steps are great if you want to get started with just the HTML components, but what if we want to build a basic page using the angular components as well? AngularCLI makes that super easy to do.

First, lets make sure we have AngularCLI installed

npm install -g @angular/cli

With that installed, we have access to a bunch of great tools for quickly bootstrapping an Angular project. We use the -g flag to indicate a global install as opposed to a project level installation.

Go ahead and cd into a directory that makes sense (I stayed in my /user/CodyDeArkland/Documents directory). The next command is going to create a sub directory for us. I’m going to list off the quick commands to get this project bootstrapped, and up and running!

ng new clarity-demo-app --style scss 
cd clarity-demo-app 
npm install ajv @clr/icons @clr/angular @clr/ui @webcomponents/custom-elements@1.0.0 --save
ng serve

You will likely be prompted on if you want to add routing or not. Select no at this time. Routing is for another day :)

Let’s breakdown what happens here…

  • We create a new Angular application called clarity-demo-app
  • Switch into its directory
  • Install our necessary tools (Angular, AJV, Clarity Icons, ClarityUI, WebComponents)
  • We tell Angular to serve our application up in development mode

The application will compile, and if you head to http://localhost:4200 you’ll notice it’s up and running. People who are familiar with ClarityUI’s unique styling will notice that none of that styling has been applied at this point. We are simply seeing the default Angular project. We need to load the ClarityUI components in order for them to display.

Applying Some Style

I’m going to assume that you have a local editor setup on your system to work with various code “things”. If you don’t, I highly recommend using VSCode and loading up a number of extensions. It’s extremely helpful!

In VSCode, or some other IDE, navigate to the project directory, and access the “angular.json” file. We’re going to browse to around line 29 in this file, and make a few changes.

    "assets": [
        "src/favicon.ico",
        "src/assets"
    ],
    "styles": [
        "src/styles.scss"
    ],
    "scripts": []

Currently the styles are blank. We can see that when we did our NPM install, it added a node_modules directory to our project. Looking at the steps on https://v1.clarity.design/get-started we can see that we just need to add the paths for the CSS styles and scripts. Let’s update the code block with the appropriate relative paths…

    "assets": [
        "src/favicon.ico",
        "src/assets"
    ],
   "styles": [
      "node_modules/@clr/icons/clr-icons.min.css",
      "node_modules/@clr/ui/clr-ui.min.css",
      "src/styles.scss"
    ],
    "scripts": [
    "node_modules/@webcomponents/custom-elements/custom-elements.min.js",
    "node_modules/@clr/icons/clr-icons.min.js"
    ]

Save the file and run ng serve again. Refreshing our page shows that the styling has been applied! The font is updated and the spacing has very obviously changed on the page. We’re definitely on our way, but not quite done yet. We still need to add the Angular modules.

Adding Angular Modules for ClarityUI

From within our IDE, switch into the /src/app/ directory, and access the app.module.ts file. Currently, this folder should look something like this…

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

We’re going to add in our Angular components for Clarity now, update the file to look like the below…

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { BrowserAnimationsModule } from "@angular/platform-browser/animations";
import { ClarityModule } from "@clr/angular";
import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    BrowserAnimationsModule,
    ClarityModule,
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

Save, and now we’ve added in the ClarityModule and the BrowserAnimations module! We’re ready to start building our quick sample page! Go ahead and fire up ng serve and we’ll let it sit there. As we make our changes to our page, AngularCLI will reload the data each time we save and our page should update live!

Scaffolding Our Page

In a typical Angular application, we would add a number of components to logically break our application into parts. There are a number of reasons for this around modularity - but in this small demo, we’re going to hang out in the “app” component. Just note that this is typically a bad idea, as its a pain to refactor out of later.

That being said… we should still be in the /src/app/ directory. Let’s take a quick tour of the files around us…

  • app.component.html - This file is going to be where we will do all of our HTML work. We’ll add in our “website” here and build the look of our page
  • app.component.scss - This is our styling sheet for this page. We could add custom styles in here to change the look and feel of our page - or to override some of the ClarityUI styles with ones we specifically want
  • app.component.spec.ts - This file is automatically generated by Angular and typically should not need to be modified for the purposes of this post
  • app.component.ts - This is the Typescript app component file for this specific component. We can place all of our Typescript logic in here. As an example, if we wanted to perform REST calls, or perform some level of programmatic logic against our page - it would all happen here. We’re going to use this file later on to add some static data to
  • app.module.ts - This is the main file for importing additional modules for this specific component

Navigate into the app.component.html directory, and nuke all the contents from orbit.

The ClarityUI teams documentation provides a number of really quick and easy to consume objects that we can use to quickly scaffold our application. Some of these are Angular objects, others are pure CSS/HTMl styling objects. We place these objects within a number of DIV’s (logical HTML “area” dividers) that are configured with specific classes to assist in styling. It’s important that when you are first getting started to pay attention to the examples that are provided. They will help make sure your page renders correctly across multiple browsers/device types!

For a simple starter exercise, we’ll grab some code from the “Headers” section and drop it in. We’re going to cheat a little bit - since I know the necessary DIV structure that will come into play later on, so i’ll include that in the sample code below…

<div class="main-container">
  <header class="header-6">
    <div class="branding">
        <a href="..." class="nav-link">
            <clr-icon shape="vm-bug"></clr-icon>
            <span class="title">Project Clarity</span>
        </a>
    </div>
    <div class="header-nav">
        <a href="..." class="active nav-link"><span class="nav-text">Dashboard</span></a>
        <a href="..." class="nav-link"><span class="nav-text">Interactive Analytics</span></a>
    </div>
    <div class="header-actions">
        <a href="..." class="nav-link nav-icon">
            <clr-icon shape="cog"></clr-icon>
        </a>
    </div>
</header>
</div>

Save, and observe how the page re-renders and generates our new header!

It’s a very basic header, and it’s pre-configured with some details. Lets make a couple of adjustments to the icon, title span class, and the header-nav, as well as remove some unnecessary information…

<div class="main-container">
  <header class="header-6">
    <div class="branding">
        <a href="..." class="nav-link">
            <clr-icon shape="cloud"></clr-icon>
            <span class="title">ClarityUI Demo</span>
        </a>
    </div>
    <div class="header-nav">
        <a href="..." class="nav-link"><span class="nav-text">Home</span></a>
    </div>
</header>
</div>

Again, save and observe the new render!

Now we’re cooking with fire! If you go back and look at the documentation for “header” you’ll notice there is a number of different customization options we could apply to change color, button placement, highlighting style, etc… Feel free to change things around as you see fit!

Adding More Controls

Let’s add a “Vertical Nav” to our page. The Vertical Nav control will be our first Angular control we’re adding, and it’s configuration details can be seen here. Below is the code snippet we will want to update with. We’ll want to add this DIRECTLY below our </header> closing tag, but still INSIDE our </div> closing tag!

<div class="content-container">
        <div class="content-area">
        </div>
        <clr-vertical-nav>
            <a clrVerticalNavLink routerLink="./charmander" routerLinkActive="active">Charmander</a>
            <a clrVerticalNavLink routerLink="./jigglypuff" routerLinkActive="active">Jigglypuff</a>
            <a clrVerticalNavLink routerLink="./pikachu" routerLinkActive="active">Pikachu</a>
            <a clrVerticalNavLink routerLink="./raichu" routerLinkActive="active">Raichu</a>
            <a clrVerticalNavLink routerLink="./snorlax" routerLinkActive="active">Snorlax</a>
            <div class="nav-divider"></div>
            <a clrVerticalNavLink routerLink="./credit" routerLinkActive="active">Credit</a>
        </clr-vertical-nav>
    </div>

Here we have the default Vertical-Nav control, but as usual, lets add some customization! We’ll remove the routerLink objects since we’re not using Angular routing at this time and replace them with href’s to open outside URLs. We’ll also change this menu to be collapsible, and add some…clever… icons to each of our friends blogs!

  <div class="content-container">
    <div class="content-area">
    </div>
    <clr-vertical-nav [clrVerticalNavCollapsible]="true" [(clrVerticalNavCollapsed)]="collapsed">
     <a clrVerticalNavLink href="https://www.thehumblelab.com" routerLinkActive="active">
      <clr-icon clrVerticalNavIcon shape="upload-cloud"></clr-icon>TheHumbleLab Blog</a>
      <a clrVerticalNavLink href="http://www.vaficionado.com/" routerLinkActive="active">
        <clr-icon clrVerticalNavIcon shape="heart-broken"></clr-icon>Jon's Blog</a>
      <a clrVerticalNavLink href="https://grantorchard.com" routerLinkActive="active">
        <clr-icon clrVerticalNavIcon shape="thumbs-up"></clr-icon>Grant's Blog</a>
      <a clrVerticalNavLink href="https://www.virtualjad.com/" routerLinkActive="active">
        <clr-icon clrVerticalNavIcon shape="sad-face"></clr-icon>Jad's Dormant Blog</a>
      <a clrVerticalNavLink href="https://www.digitalvspace.com/" routerLinkActive="active">
        <clr-icon clrVerticalNavIcon shape="user"></clr-icon>Tony's Blog</a>
      <a clrVerticalNavLink href="https://alarasheedblog.wordpress.com/" routerLinkActive="active">
        <clr-icon clrVerticalNavIcon shape="happy-face"></clr-icon>Al's Blog</a>
      <div class="nav-divider"></div>
      <a clrVerticalNavLink href="https://twitter.com/vgigacast?lang=en" routerLinkActive="active">
        <clr-icon clrVerticalNavIcon shape="talk-bubbles"></clr-icon>vGigacast Twitter</a>
    </clr-vertical-nav>
  </div>

Save, and observe the rendering as per usual!

Progress! I dig it. We can see a list of some of our favorite blogs, as well as some largely accurate description and supporting icons! If we click our collapse icon (which we can also change if we wanted to…) the menu will shrink off to the side. Awesome! What you can’t see however, is that there is a huge blank space next to this page menu. Let’s fill it in with something interesting.

Adding the ClarityUI Datagrid

Now we’re going to step up our game a little bit. First, lets head over to our app.component.ts file. Inside the brackets next to “AppComponent”, lets delete out title = 'clarity-demo-app'. We’re going to replace it with some data that we will pull into our datagrid!

Update your code to reflect this, or something like it!

import { Component } from '@angular/core';

export interface Person {
  name: string
  blogurl: string
  twitter: string
}

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})

export class AppComponent {
  
  people: Person[] = [
    {name: 'Cody De Arkland', blogurl: 'https://www.thehumblelab.com', twitter: "@CodyDeArkland"},
    {name: 'Grant Orchard', blogurl: 'https://www.grantorchard.com', twitter: "@GrantOrchard"},
    {name: 'Jon Schulman', blogurl: 'http://www.vaficionado.com', twitter: "@vAficionado"},
    {name: 'Jad El-Zein', blogurl: 'https://www.virtualjad.com', twitter: "@virtualjad"},
    {name: 'Tony Reeves', blogurl: 'https://www.digitalvspace.com', twitter: "@importcarguy"},
    {name: 'Al Rasheed', blogurl: 'https://alarasheedblog.wordpress.com/', twitter: "@al_rasheed"}
  ]
}

We’ve done a couple of more advanced things here…

  • We’ve created an interface for a future object. This interface gives us a static type around the object that we are working with - in this case, a Person object. This object will always contain a name, blogurl, and twitter handle. All of these values are strings.
  • Under our AppComponent, we’ve instantiated an object name “people” which is an array (multiple items) of “Persons” from our previous interface.

We are going to use this data within our datagrid! Go ahead and save, and switch back to our app.component.html file

If you look carefully in our most recently added set of HTML (the Vertical Nav) you’ll notice the following block…

<div class="content-area">
    </div>

This block is specifically designed for content that will go within the page; so this is where we will drop our datagrid object. I’m going to drop in the already customized code below, since we’ve gone through the before and after exercise a few times already…

<div class="content-area">
        <clr-datagrid>
        <clr-dg-column>Blogger's Name</clr-dg-column>
        <clr-dg-column>Blog URL</clr-dg-column>
        <clr-dg-column>Twitter Handle</clr-dg-column>
        
        <clr-dg-row *ngFor="let person of people">
            <clr-dg-cell>{{person.name}}</clr-dg-cell>
            <clr-dg-cell><a href>{{person.blogurl}}</a></clr-dg-cell>
            <clr-dg-cell>{{person.twitter}}</clr-dg-cell>
        </clr-dg-row>
    
        <clr-dg-footer>{{people.length}} users</clr-dg-footer>
    </clr-datagrid>
</div>

Whew! There is a lot happening in here…

  • We’ve established a clarity datagrid object (clr-datagrid)
  • We’ve created our column structure (Blogger’s name, Blog URL, and Twitter handle)
  • We’re creating our rows, and we’re using an Angular directive called “*ngFor” which is effectively a “for loop”. We’ define each item in the array of “people” as “person”
  • We establish a cell for each value within that newly established variable
  • Finally we display a count of how many total “people” are in the list

Note that the datagrid object has a TON of different possible Angular driven customization’s that can be done to it including a number of different rendering options as well as filtering, sorting, or even custom actions. I highly suggest you review this list.

At this point, our basic application is complete! We’ve created a simple application that shows some of our most active (and a couple majorly inactive…) bloggers in the VMware space!

Wrapping Up and Where From Here?

This blog was meant to be the first of several blogs covering how to do some interesting things with ClarityUI. The major goal I had was “demystifying” the process of getting started. It’s pretty easy to get started, but like all things, grows in complexity as you get into the details. The ClarityUI team has done a fantastic job of making it easy to quickly scaffold a starter project however!

I’ve stashed the example project in a GitHub repository here for you to take for a spin on your own.

As one last bit of fun, navigate into the angular.json file from the beginning of the project, and locate the style section again

"styles": [
              "node_modules/@clr/icons/clr-icons.min.css",
              "node_modules/@clr/ui/clr-ui.min.css",
              "src/styles.scss"
            ],

Modify the values for the clr-ui.min.css entry to the following…

"styles": [
              "node_modules/@clr/icons/clr-icons.min.css",
              "node_modules/@clr/ui/clr-ui-dark.min.css",
              "src/styles.scss"
            ],

This enables the ClarityUI Dark Mode, a VERY popular customization!

In future blogs, we’ll cover topics such as…

  • Using purely CSS/HTML elements to build a page in Python Flask
  • Hosting this application in NGINX
  • Adding Additional Components and Introducing Routing
  • Creating a Docker Container for this Application
  • Automating the Build of this Application in VMware Code Stream