Skip to main contentCarbon Design System

4. Creating components

With two pages comprised entirely of Carbon components, let’s revisit the landing page and build a couple components of our own by using Carbon icons and tokens.

Preview

Carbon provides a solid foundation for building web applications through its color palette, layout, spacing, type, as well as common building blocks in the form of components. So far, we’ve only used Carbon components to build out two pages.

Next, we’re going to use Carbon assets to build application-specific components. We’ll create our components with considerations for accessibility and responsiveness.

A preview of what you’ll build (see bottom of page):

Fork, clone and branch

This tutorial has an accompanying GitHub repository called carbon-tutorial-angular that we’ll use as a starting point for each step. If you haven’t forked and cloned that repository yet, and haven’t added the upstream remote, go ahead and do so by following the step 1 instructions.

Branch

With your repository all set up, let’s check out the branch for this tutorial step’s starting point.

git fetch upstream
git checkout -b angular-step-4 upstream/angular-step-4

Build and start app

Install the app’s dependencies (in case you’re starting fresh in your current directory and not continuing from the previous step):

npm install

Then, start the app:

npm start

You should see something similar to where the previous step left off.

Review design

Here’s what we’re building – an informational section that has a heading and three subheadings. Each subheading has accompanying copy and a pictogram. We’ll assume that this informational section is used elsewhere on the site, meaning it’s a great opportunity to build it as a reusable component. As for naming, we’ll call it an InfoSection with three InfoCards as children.

Info section layout

Info section layout

Create components

First we need files for the components, so create an Info folder in src/components. Even though we’re building multiple components, their names all start with Info, so it makes sense to have them share one folder in components. Create these files:

Generate modules & components using the Angular CLI

Let’s generate a new module that’ll handle our InfoCard and InfoSection components:

ng generate module info

Now we generate our InfoCard and InfoSection components:

ng generate component info/info-card --lint-fix
ng generate component info/info-section --lint-fix

Running the above commands should get you the folder structure below:

src/app/info
└──info.module.ts
└──info-card
├──info-card.component.scss
├──info-card.component.ts
├──info-card.component.spec.ts
└──info-card.component.html
└──info-section
├──info-section.component.scss

Now let’s create a JSON file that’ll include our content to be shown in the components:

src/app/info/info.json
{
"title": "The Principles",
"items": [
{
"heading": "Carbon is Open",
"content": "It's a distributed effort, guided by the principles of the open-source movement. Carbon's users are also it's makers, and everyone is encouraged to contribute."
},
{
"heading": "Carbon is Modular",

Now we also need to tell typescript to resolve JSON files as modules when compiling:

src/tsconfig.app.json
{
"compilerOptions": {
"sourceMap": true,
"declaration": false,
...
"resolveJsonModule": true
},
...
}

InfoSection component

Let’s create the parent component that includes the “The Principles” heading. That markup currently looks like this in landing-page.component.html:

src/app/home/landing-page/landing-page.component.html
<div ibmRow class="landing-page__r3">
<div ibmCol [columnNumbers]="{'md': 4, 'lg': 4}">
<h3 class="landing-page__label">The Principles</h3>
</div>
<div ibmCol [columnNumbers]="{'md': 4, 'lg': 4}">Carbon is Open</div>
<div ibmCol [columnNumbers]="{'md': 4, 'lg': 4}">Carbon is Modular</div>
<div ibmCol [columnNumbers]="{'md': 4, 'lg': 4}">Carbon is Consistent</div>
</div>

We want to do a few things when abstracting it to a component. Firstly, we want to encapsulate the component’s styles within it’s dedicated stylesheet. We don’t want to include landing-page__r3 within the component template as that’s specific to the landing page. In order to allow the landing page to have access to styling this specific instance of an InfoSection component we could pass the class into the instance of the component. However, we won’t need to do any additional styling from the landing-page so we can just go ahead use the component as is.

We’ll also:

  • Add component class names like .info-section and .info-section__heading
  • Semantically use <section> instead of <div>
  • Update the grid columns to match the design
  • Update the component content to use info.json
  • Replace columns 2 - 4 with InfoCard components
  • Remove class styling from landing-page component
src/app/home/landing-page/landing-page.component.html
<app-info-section></app-info-section>
src/app/info/info-section/info-section.component.html
<section ibmRow class="info-section info-section__r1">
<div ibmCol [columnNumbers]="{'md': 8, 'lg': 4}">
<h3 class="info-section__heading">The Principles</h3>
</div>
<app-info-card ibmCol [columnNumbers]="{'md': 4, 'lg': 4}"> </app-info-card>
<app-info-card ibmCol [columnNumbers]="{'md': 4, 'lg': 4}"> </app-info-card>
<app-info-card ibmCol [columnNumbers]="{'md': 4, 'lg': 4}"> </app-info-card>
</section>

As you can see we’ve added instances of the InfoCard component. There is a few things that we need to do to resolve the errors in the browser. Firstly we need to update InfoModule to be able to use the GridModule. At the same time we will export the InfoSection and InfoCard components from the InfoModule so that we can use them in the HomeModule components (specifically landing-page).

src/app/info/info.module.ts
import { NgModule } from "@angular/core";
...
import { GridModule } from "carbon-components-angular";
@NgModule({
declarations: [InfoCardComponent, InfoSectionComponent],
imports: [
CommonModule,

We also need to import InfoModule into HomeModule otherwise we cannot use the InfoSection component within landing-page.

src/app/home/home.module.ts
...
import </