1. Installing Carbon
Starting with Create React App, let’s install Carbon and begin using Carbon components. By the end you will have a React app that uses the UI Shell to navigate between pages.
- Fork, clone and branch
- Build and start
- Install Carbon
- Install and build Sass
- Add UI Shell
- Create pages
- Add routing
- Submit pull request
Preview
A preview of what you will build:
Fork, clone and branch
This tutorial has an accompanying GitHub repository called carbon-tutorial that we’ll use as a starting point for each step.
Fork
To begin, fork carbon-tutorial using your GitHub account.
Clone
Go to your forked repository, copy the SSH or HTTPS URL and in your terminal run the two commands to get the repository in your local file system and enter that directory.
git clone [your fork SSH/HTTPS]cd carbon-tutorial
Add upstream remote
Add a remote called upstream
so we can eventually submit a pull request once
you have completed this tutorial step. There are two choices: SSH or HTTPS
SSH
git remote add upstream git@github.com:carbon-design-system/carbon-tutorial.git
HTTPS
git remote add upstream https://github.com/carbon-design-system/carbon-tutorial.git
Verify that your forked repository remotes are correct:
git remote -v
Your terminal should output something like this:
origin [your forked repo] (fetch)origin [your forked repo] (push)upstream git@github.com:carbon-design-system/carbon-tutorial.git (fetch)upstream git@github.com:carbon-design-system/carbon-tutorial.git (push)
Branch
Now that we have our repository set up, let’s check out the branch for this tutorial step’s starting point. Run the two commands:
git fetch upstreamgit checkout -b v11-react-step-1 upstream/v11-react-step-1
Build and start
We have the repository forked to your GitHub account, cloned down to your machine, and the starting branch checked out. Next, install the React app’s dependencies with:
yarn
After the dependencies are installed, you can start the app with:
yarn start
Your default browser should open up with an empty page that says:
Hello Carbon! Well, not quite yet. This is the starting point for the Carbon tutorial.
Install Carbon
Even though we installed existing dependencies, we’ve yet to install our v11
Carbon package, @carbon/react
, which contains everything you need to build
with.
Stop your development server with CTRL-C
and install Carbon dependencies with:
yarn add @carbon/react@1.32.0
Install and build Sass
We need to run a Sass build as the Carbon styles are authored in Sass, so run
the following command to install sass
as a dependency.
yarn add sass@1.51.0
Then, start the app again. If your app’s currently running, you’ll need to restart it for the new environment variable to be used.
yarn start
The app looks as it did before. Next, let’s prepare our app for a Sass build.
In the src
directory, rename index.css
as index.scss
. Then in index.js
update the index.css
import to index.scss
.
Import carbon-component styles
In index.scss
, import the Carbon styles by adding the following at the top of
the file:
src/index.scss@use '@carbon/react';
Making this change to index.scss
will cause all of the Carbon Sass to
re-compile. Once finished re-compiling the Carbon base styling is applied (IBM
Plex Sans font family, font size, weight, colors, etc.)
Re-compiling all of the Carbon Sass takes a while, even on fast systems. Let’s
speed this up by moving our custom app Sass into a separate file, app.scss
in
the ‘src’ directory, and import that from App.js
.
src/App.jsimport './app.scss';
By modifying index.scss
as little as possible and storing all app-specific
styling in app.scss
we will make compile times much quicker. Storing the
app-specific styling in a separate file also makes good organizational sense.
Next, we’ll import a Button
from Carbon to test that our dependencies are
working properly. At the top of App.js
, import the Button
by adding the
following:
src/App.jsimport { Button } from '@carbon/react';
In the App
component return, you can now replace:
src/App.js<div>Hello Carbon! Well, not quite yet. This is the starting point for the Carbontutorial.</div>
with:
src/App.js<Button>Button</Button>
Congratulations, you’ve imported your first component! You should see a Carbon styled button on the page.
Add UI Shell
Next, we’re going to create a React component called TutorialHeader
to use
with the UI Shell Carbon component. In the src
directory, create a
components
directory and inside of that, a TutorialHeader
directory. Create
the following files inside src/components/TutorialHeader
:
src/components/TutorialHeader├──_tutorial-header.scss├──index.js└──TutorialHeader.js
Add UI Shell Sass
Next, in app.scss
, we’ll import our TutorialHeader
styles. Your file should
now look like this:
src/app.scss@use './components/TutorialHeader/tutorial-header';
Import and export the header
In src/components/TutorialHeader/index.js
, import and export our
TutorialHeader
component like so:
src/components/TutorialHeader/index.jsimport TutorialHeader from './TutorialHeader';export default TutorialHeader;
Next we’ll import our Carbon UI Shell components into TutorialHeader.js
. Set
up the file like so:
src/components/TutorialHeader/TutorialHeader.jsimport React from 'react';import {Header,HeaderContainer,HeaderName,HeaderNavigation,HeaderMenuButton,HeaderMenuItem,HeaderGlobalBar,
Import icons
Now let’s import the icons. In the TutorialHeader.js
file, we need to import
each individual icon we will use.
src/components/TutorialHeader/TutorialHeader.jsimport { Switcher, Notification, UserAvatar } from '@carbon/react/icons';
Then we need to add the HeaderGlobalAction
component inside of the
HeaderGlobalBar
where we will add our icons. These represent actions in the
header a user can make. Replace:
src/components/TutorialHeader/TutorialHeader.js<HeaderGlobalBar />
With:
src/components/TutorialHeader/TutorialHeader.js<HeaderGlobalBar><HeaderGlobalAction aria-label="Notifications" tooltipAlignment="center"><Notification size={20} /></HeaderGlobalAction><HeaderGlobalAction aria-label="User Avatar" tooltipAlignment="center"><UserAvatar size={20} /></HeaderGlobalAction><HeaderGlobalAction aria-label="App Switcher" tooltipAlignment="end"><Switcher size={20} />
Render the header
Next we’ll render our UI Shell by importing our TutorialHeader
component and
Content
into App.js
. Your imports should look like this:
src/App.jsimport React, { Component } from 'react';import './app.scss';import { Button, Content } from '@carbon/react';import TutorialHeader from './components/TutorialHeader';
Our return
currently just contains a Button
. Let’s update that to include
our imported components. This should look like the following:
src/App.jsclass App extends Component {render() {return (<><TutorialHeader /><Content><Button>Button</Button></Content></>
You should now see a styled UI Shell header and a button below it.
Create pages
Next thing we need to do is create the files for our content. Start by creating
a folder called content
in src
. This should be a sibling of
src/components
.
Since our app will have two pages, we’ll create two folders in src/content
.
src/content├── LandingPage└── RepoPage
Next, we’ll set up these folders the same way we set up
src/components/TutorialHeader
.
Create the following files in the LandingPage
folder:
src/content/LandingPage├── _landing-page.scss├── index.js└── LandingPage.js
Create the following files in the RepoPage
folder:
src/content/RepoPage├── _repo-page.scss├── index.js└── RepoPage.js
Set up content Sass
Next, we’ll import our content Sass files in app.scss
, like so:
src/app.scss@use './components/TutorialHeader/tutorial-header';@use './content/LandingPage/landing-page';@use './content/RepoPage/repo-page';
Import and export content pages
Now that our stylesheets are set up, we need to create our pages’ components.
Starting with LandingPage
, just like with our header, we need to export the
component in src/content/LandingPage/index.js
by adding:
src/content/LandingPage/index.jsimport LandingPage from './LandingPage';export default LandingPage;
Next in LandingPage.js
, we’ll create our component.
src/content/LandingPage/LandingPage.jsimport React from 'react';const LandingPage = () => {return <div>LANDING PAGE</div>;};export default LandingPage;
We’ll repeat this process with RepoPage
.
In src/content/RepoPage/index.js
, import and export the RepoPage
component
like so:
src/content/RepoPage/index.jsimport RepoPage from './RepoPage';export default RepoPage;
Then in RepoPage.js
create the component.
src/content/RepoPage/RepoPage.jsimport React from 'react';const RepoPage = () => {return <div>REPO PAGE</div>;};export default RepoPage;
Awesome! We’ve just created our content pages. Next thing we need to do is render them with our router.
Add routing
We’ve updated our app to render our header, but now we need to add routing
functionality. To do this we need to install react-router-dom
. Go ahead and
stop your development server (with CTRL-C
) and then:
yarn add react-router-dom@5.0.0yarn start
First, we need to wrap our app in the Router
component. In the root
index.js
, add the import:
src/index.jsimport { HashRouter as Router } from 'react-router-dom';
Then, update the render()
function to include the Router
.
src/index.jscreateRoot(document.getElementById('root')).render(<Router><App /></Router>);
In order to render our content pages, we need to add the following imports in
App.js
below our existing imports.
src/App.jsimport { Route, Switch, BrowserRouter } from 'react-router-dom';import { Content } from '@carbon/react';import LandingPage from './content/LandingPage';import RepoPage from './content/RepoPage';
This allows us to use our page content components and routing components from
react-router-dom
.
The next thing we need to do is update what we’re returning to App.js
. We
currently just have a div with some dummy content. In order to render our pages
correctly, we need to replace the div
with <BrowserRouter>
(and remove the
text inside).
Now inside App.js
we’ll add the following:
src/App.js<BrowserRouter><Content><Switch><Route exact path="/" component={LandingPage} /><Route path="/repos" component={RepoPage} /></Switch></Content></BrowserRouter>
After that we need to do a couple quick fixes to the UI Shell to have it work with the React router.
Add the Link
import in TutorialHeader.js
:
src/components/TutorialHeader/TutorialHeader.jsimport { Link } from 'react-router-dom';
We need to use the Link
component instead of the default anchor elements to
prevent full page reload when navigating to different pages with React Router.
To use Link
, update the HeaderName
component to use the element
prop and
replace the href
with to
:
src/components/TutorialHeader/TutorialHeader.js<HeaderName as={Link} to="/" prefix="IBM">Carbon Tutorial</HeaderName>
Do the same with the components that contain href="/repos"
, updating them to:
src/components/TutorialHeader/TutorialHeader.js<HeaderMenuItem as={Link} to="/repos">Repositories</HeaderMenuItem>
You should now have a working header that routes to different pages without full
page reload! However, our page does not match the design specs. We need to
change the header theme to g100
to match the specs.
In App.js
we will add inline theming for our navigation. First, we need to
import our new Theme
component.
src/App.jsimport { Content, Theme } from '@carbon/react';
Then, we will wrap Theme
around our header, and set the zoned theme using the
theme
prop, which accepts one of four strings: "white"
, "g10"
, "g90"
or
"g100"
.
src/App.js<BrowserRouter><Theme theme="g100"><TutorialHeader /></Theme><Content><Switch><Route exact path="/" component={LandingPage} /><Route path="/repos" component={RepoPage} /></Switch>
You might have noticed that the landing and repo page content disappeared. This
is because we now have a wrapper around the UI Shell, and the spacing is off. To
fix this, we’ll add the following override in index.scss
below our style
import:
src/index.scss.cds--content {margin-top: 3rem;}
We have one last thing to fix before we’re done. Because we changed the header
theme to dark, the <HeaderGlobalAction>
tooltips are now light instead of
dark, and when you scroll the page, it blends into the content. To fix this,
we’ll add some overriding styles in _tutorial-header.scss
:
src/components/TutorialHeader/_tutorial-header.scss@use '@carbon/react/scss/colors';// overriding header tooltip bg color// because the navigation is dark themed while the content is white// which means the dark theme tooltip bg blends into the white content bg.cds--header__global .cds--popover-content {background-color: colors.$gray-20;}
Submit pull request
We’re going to submit a pull request to verify completion of this tutorial step and demonstrate a couple of related concepts.
Continuous integration (CI) check
We have a ci-check
script defined in package.json
that verifies file
formatting for files that have been touched since the last Git commit with a
tool called Prettier. You’d typically also have that
script run your test suite as part of your CI build. Go ahead and make sure
everything looks good with:
yarn ci-check
Git commit and push
Before we can create a pull request, stage and commit all of your changes:
git add --all && git commit -m "feat(tutorial): complete step 1"
Then, push to your repository:
git push origin v11-react-step-1
Pull request (PR)
Finally, visit
carbon-tutorial to
“Compare & pull request”. In doing so, make sure that you are comparing to
v11-react-step-1
into base: v11-react-step-1
. Take notice of the
Netlify bot that deploys a preview of your PR every
time that you push new commits. These previews can be shared and viewed by
anybody to assist the PR review process.