text: (window.webpackJsonp=window.webpackJsonp||[]).push([[2110],{"013z":function(e,t,n){"use strict";var a=n("q1tI"),r=n.n(a),o=n("NmYn"),i=n.n(o),l=n("Wbzz"),c=n("Xrax"),p=n("a7k6"),s=n("TSYQ"),b=n.n(s),d=n("QH2O"),u=n("qKvR");var m=({title:e,tabs:t=[]})=>Object(u.b)("div",{className:b()(d.pageHeader,{[d.withTabs]:t.length})},Object(u.b)("div",{className:"bx--grid"},Object(u.b)("div",{className:"bx--row"},Object(u.b)("div",{className:"bx--col-lg-12"},Object(u.b)("h1",{id:"page-title",className:d.text},e))))),h=n("BAC9");var j=({relativePagePath:e,repository:t})=>{const{site:{siteMetadata:{repository:n}}}=Object(l.useStaticQuery)("1364590287"),{baseUrl:a,subDirectory:r,branch:o}=t||n,i=`${a}/edit/${o}${r}/src/pages${e}`;return a?Object(u.b)("div",{className:"bx--row "+h.row},Object(u.b)("div",{className:"bx--col"},Object(u.b)("a",{className:h.link,href:i},"Edit this page on GitHub"))):null},g=n("FCXl"),O=n("I8xM");class N extends r.a.Component{render(){const{tabs:e,slug:t}=this.props,n=t.split("/").filter(Boolean).slice(-1)[0],a=e.map(e=>{const a=i()(e,{lower:!0,strict:!0}),r=a===n,o=new RegExp(n+"/?(#.*)?$"),c=t.replace(o,a);return Object(u.b)("li",{key:e,className:b()({[O.selectedItem]:r},O.listItem)},Object(u.b)(l.Link,{className:O.link,to:""+c},e))});return Object(u.b)("div",{className:O.tabsContainer},Object(u.b)("div",{className:"bx--grid"},Object(u.b)("div",{className:"bx--row"},Object(u.b)("div",{className:"bx--col-lg-12 bx--col-no-gutter"},Object(u.b)("nav",null,Object(u.b)("ul",{className:O.list},a))))))}}var f=N,y=n("MjG9");t.a=({pageContext:e,children:t,location:n,Title:a})=>{const{frontmatter:r={},relativePagePath:o,titleType:s}=e,{tabs:b,title:d,theme:h,description:O,keywords:N}=r,{site:{pathPrefix:w}}=Object(l.useStaticQuery)("2456312558"),C=w?n.pathname.replace(w,""):n.pathname,T=b?C.split("/").filter(Boolean).slice(-1)[0]||i()(b[0],{lower:!0}):"";return Object(u.b)(p.a,{tabs:b,homepage:!1,theme:h,pageTitle:d,pageDescription:O,pageKeywords:N,titleType:s},Object(u.b)(m,{title:a?Object(u.b)(a,null):d,label:"label",tabs:b}),b&&Object(u.b)(f,{slug:C,tabs:b,currentTab:T}),Object(u.b)(y.a,{padded:!0},t,Object(u.b)(j,{relativePagePath:o})),Object(u.b)(g.a,{pageContext:e,location:n,slug:C,tabs:b,currentTab:T}),Object(u.b)(c.a,null))}},BAC9:function(e,t,n){e.exports={bxTextTruncateEnd:"EditLink-module--bx--text-truncate--end--2pqje",bxTextTruncateFront:"EditLink-module--bx--text-truncate--front--3_lIE",link:"EditLink-module--link--1qzW3",row:"EditLink-module--row--1B9Gk"}},I8xM:function(e,t,n){e.exports={bxTextTruncateEnd:"PageTabs-module--bx--text-truncate--end--267NA",bxTextTruncateFront:"PageTabs-module--bx--text-truncate--front--3xEQF",tabsContainer:"PageTabs-module--tabs-container--8N4k0",list:"PageTabs-module--list--3eFQc",listItem:"PageTabs-module--list-item--nUmtD",link:"PageTabs-module--link--1mDJ1",selectedItem:"PageTabs-module--selected-item--YPVr3"}},QH2O:function(e,t,n){e.exports={bxTextTruncateEnd:"PageHeader-module--bx--text-truncate--end--mZWeX",bxTextTruncateFront:"PageHeader-module--bx--text-truncate--front--3zvrI",pageHeader:"PageHeader-module--page-header--3hIan",withTabs:"PageHeader-module--with-tabs--3nKxA",text:"PageHeader-module--text--o9LFq"}},n9M8:function(e,t,n){"use strict";n.r(t),n.d(t,"_frontmatter",(function(){return c})),n.d(t,"default",(function(){return j}));n("3bBZ"),n("q1tI");var a=n("7ljp"),r=n("013z"),o=n("V8m9");n("qKvR");function i(){return(i=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var a in n)Object.prototype.hasOwnProperty.call(n,a)&&(e[a]=n[a])}return e}).apply(this,arguments)}function l(e,t){if(null==e)return{};var n,a,r=function(e,t){if(null==e)return{};var n,a,r={},o=Object.keys(e);for(a=0;a<o.length;a++)n=o[a],t.indexOf(n)>=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(a=0;a<o.length;a++)n=o[a],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}const c={},p=e=>function(t){return console.warn("Component "+e+" was not imported, exported, or provided by MDXProvider as global scope"),Object(a.b)("div",t)},s=p("PageDescription"),b=p("AnchorLinks"),d=p("AnchorLink"),u=p("InlineNotification"),m={_frontmatter:c},h=r.a;function j(e){let{components:t}=e,n=l(e,["components"]);return Object(a.b)(h,i({},m,n,{components:t,mdxType:"MDXLayout"}),Object(a.b)(s,{mdxType:"PageDescription"},Object(a.b)("p",null,"Starting with Create React App, let’s install Carbon and begin using Carbon\ncomponents. By the end you will have a React app that uses the UI Shell to\nnavigate between pages.")),Object(a.b)(b,{mdxType:"AnchorLinks"},Object(a.b)(d,{mdxType:"AnchorLink"},"Fork, clone and branch"),Object(a.b)(d,{mdxType:"AnchorLink"},"Build and start"),Object(a.b)(d,{mdxType:"AnchorLink"},"Install Carbon"),Object(a.b)(d,{mdxType:"AnchorLink"},"Install and build Sass"),Object(a.b)(d,{mdxType:"AnchorLink"},"Add UI Shell"),Object(a.b)(d,{mdxType:"AnchorLink"},"Create pages"),Object(a.b)(d,{mdxType:"AnchorLink"},"Add routing"),Object(a.b)(d,{mdxType:"AnchorLink"},"Submit pull request")),Object(a.b)("h2",null,"Preview"),Object(a.b)("p",null,"A ",Object(a.b)("a",i({parentName:"p"},{href:"https://react-step-2--carbon-tutorial.netlify.com"}),"preview")," of what you will\nbuild:"),Object(a.b)(o.a,{height:"200",title:"Carbon Tutorial Step 1",src:"https://react-step-2--carbon-tutorial.netlify.com",frameBorder:"no",allowtransparency:"true",allowFullScreen:"true",mdxType:"Preview"}),Object(a.b)("h2",null,"Fork, clone and branch"),Object(a.b)("p",null,"This tutorial has an accompanying GitHub repository called\n",Object(a.b)("a",i({parentName:"p"},{href:"https://github.com/carbon-design-system/carbon-tutorial"}),"carbon-tutorial")," that\nwe’ll use as a starting point for each step."),Object(a.b)("h3",null,"Fork"),Object(a.b)("p",null,"To begin, fork\n",Object(a.b)("a",i({parentName:"p"},{href:"https://github.com/carbon-design-system/carbon-tutorial"}),"carbon-tutorial")," using\nyour GitHub account."),Object(a.b)("h3",null,"Clone"),Object(a.b)("p",null,"Go to your forked repository, copy the SSH or HTTPS URL and in your terminal run\nthe two commands to get the repository in your local file system and enter that\ndirectory."),Object(a.b)("pre",null,Object(a.b)("code",i({parentName:"pre"},{className:"language-bash"}),"git clone [your fork SSH/HTTPS]\ncd carbon-tutorial\n")),Object(a.b)("h3",null,"Add upstream remote"),Object(a.b)("p",null,"Add a remote called ",Object(a.b)("inlineCode",{parentName:"p"},"upstream")," so we can eventually submit a pull request once\nyou have completed this tutorial step."),Object(a.b)("pre",null,Object(a.b)("code",i({parentName:"pre"},{className:"language-bash"}),"git remote add upstream git@github.com:carbon-design-system/carbon-tutorial.git\n")),Object(a.b)("p",null,"Or, if you prefer to use HTTPS instead of SSH with your remotes:"),Object(a.b)("pre",null,Object(a.b)("code",i({parentName:"pre"},{className:"language-bash"}),"git remote add upstream https://github.com/carbon-design-system/carbon-tutorial.git\n")),Object(a.b)("p",null,"Verify that your forked repository remotes are correct:"),Object(a.b)("pre",null,Object(a.b)("code",i({parentName:"pre"},{className:"language-bash"}),"git remote -v\n")),Object(a.b)("p",null,"Your terminal should output something like this:"),Object(a.b)("pre",null,Object(a.b)("code",i({parentName:"pre"},{className:"language-bash"}),"origin  [your forked repo] (fetch)\norigin  [your forked repo] (push)\nupstream    git@github.com:carbon-design-system/carbon-tutorial.git (fetch)\nupstream    git@github.com:carbon-design-system/carbon-tutorial.git (push)\n")),Object(a.b)("h3",null,"Branch"),Object(a.b)("p",null,"Now that we have our repository set up, let’s check out the branch for this\ntutorial step’s starting point. Run the two commands:"),Object(a.b)("pre",null,Object(a.b)("code",i({parentName:"pre"},{className:"language-bash"}),"git fetch upstream\ngit checkout -b react-step-1 upstream/react-step-1\n")),Object(a.b)("h2",null,"Build and start"),Object(a.b)("p",null,"We have the repository forked to your GitHub account, cloned down to your\nmachine, and the starting branch checked out. Next, install the React app’s\ndependencies with:"),Object(a.b)("pre",null,Object(a.b)("code",i({parentName:"pre"},{className:"language-bash"}),"yarn\n")),Object(a.b)("p",null,"After the dependencies are installed, you can start the app with:"),Object(a.b)("pre",null,Object(a.b)("code",i({parentName:"pre"},{className:"language-bash"}),"yarn start\n")),Object(a.b)("p",null,"Your default browser should open up with an empty page that says:\n",Object(a.b)("inlineCode",{parentName:"p"},"Hello Carbon! Well, not quite yet. This is the starting point for the Carbon tutorial.")),Object(a.b)("h2",null,"Install Carbon"),Object(a.b)("p",null,"Even though we installed existing dependencies, we’ve yet to install the Carbon\npackages."),Object(a.b)("ul",null,Object(a.b)("li",{parentName:"ul"},Object(a.b)("inlineCode",{parentName:"li"},"carbon-components")," - component styles"),Object(a.b)("li",{parentName:"ul"},Object(a.b)("inlineCode",{parentName:"li"},"carbon-components-react")," - React components"),Object(a.b)("li",{parentName:"ul"},Object(a.b)("inlineCode",{parentName:"li"},"@carbon/icons-react")," - React icons")),Object(a.b)("p",null,"Stop your development server with ",Object(a.b)("inlineCode",{parentName:"p"},"CTRL-C")," and install Carbon dependencies with:"),Object(a.b)("pre",null,Object(a.b)("code",i({parentName:"pre"},{className:"language-bash"}),"yarn add carbon-components@10.3.0 carbon-components-react@7.3.0 @carbon/icons-react@10.3.0 carbon-icons@7.0.7\n")),Object(a.b)("h2",null,"Install and build Sass"),Object(a.b)("p",null,"We need to run a Sass build as the Carbon styles are authored in Sass, so run\nthe following command to install ",Object(a.b)("inlineCode",{parentName:"p"},"node-sass")," as a dependency."),Object(a.b)("pre",null,Object(a.b)("code",i({parentName:"pre"},{className:"language-bash"}),"yarn add node-sass@4.12.0\n")),Object(a.b)("p",null,"To avoid having to add the ",Object(a.b)("inlineCode",{parentName:"p"},"~")," prefix when importing SCSS files from\n",Object(a.b)("inlineCode",{parentName:"p"},"node_modules"),", create a ",Object(a.b)("inlineCode",{parentName:"p"},".env")," file at the project root that contains:"),Object(a.b)("pre",null,Object(a.b)("code",i({parentName:"pre"},{className:"language-bash",metastring:"path=.env",path:".env"}),'SASS_PATH="node_modules"\n')),Object(a.b)("p",null,"For the Windows operating system, use:"),Object(a.b)("pre",null,Object(a.b)("code",i({parentName:"pre"},{className:"language-bash",metastring:"path=.env",path:".env"}),"SASS_PATH=./node_modules\n")),Object(a.b)("p",null,"Then, start the app again. If your app’s currently running, you’ll need to\nrestart it for the new environment variable to be used."),Object(a.b)("pre",null,Object(a.b)("code",i({parentName:"pre"},{className:"language-bash"}),"yarn start\n")),Object(a.b)("p",null,"The app looks as it did before. Next, let’s prepare our app for a Sass build."),Object(a.b)("p",null,"In the ",Object(a.b)("inlineCode",{parentName:"p"},"src")," directory, rename ",Object(a.b)("inlineCode",{parentName:"p"},"index.css")," as ",Object(a.b)("inlineCode",{parentName:"p"},"index.scss"),". Then in ",Object(a.b)("inlineCode",{parentName:"p"},"index.js"),"\nupdate the ",Object(a.b)("inlineCode",{parentName:"p"},"index.css")," import to ",Object(a.b)("inlineCode",{parentName:"p"},"index.scss"),"."),Object(a.b)("h3",null,"Import carbon-component styles"),Object(a.b)("p",null,"In ",Object(a.b)("inlineCode",{parentName:"p"},"index.scss"),", import the Carbon styles by adding the following at the top of\nthe file:"),Object(a.b)("pre",null,Object(a.b)("code",i({parentName:"pre"},{className:"language-scss",metastring:"path=src/index.scss",path:"src/index.scss"}),"@import 'carbon-components/scss/globals/scss/styles.scss';\n")),Object(a.b)("p",null,"Making this change to ",Object(a.b)("inlineCode",{parentName:"p"},"index.scss")," will cause all of the Carbon Sass to\nre-compile. Once finished re-compiling the Carbon base styling is applied (IBM\nPlex Sans font family, font size, weight, colors, etc.)"),Object(a.b)("p",null,"Re-compiling all of the Carbon Sass takes a while, even on fast systems. Let’s\nspeed this up by moving our custom app Sass into a separate file, ",Object(a.b)("inlineCode",{parentName:"p"},"app.scss")," in\nthe ‘src’ directory, and import that from ",Object(a.b)("inlineCode",{parentName:"p"},"App.js"),"."),Object(a.b)("pre",null,Object(a.b)("code",i({parentName:"pre"},{className:"language-javascript",metastring:"path=src/App.js",path:"src/App.js"}),"import './app.scss';\n")),Object(a.b)("p",null,"By modifying ",Object(a.b)("inlineCode",{parentName:"p"},"index.scss")," as little as possible and storing all app-specific\nstyling in ",Object(a.b)("inlineCode",{parentName:"p"},"app.scss")," we will make compile times much quicker. Storing the\napp-specific styling in a separate file also makes good organizational sense."),Object(a.b)("p",null,"Next, we’ll import a ",Object(a.b)("inlineCode",{parentName:"p"},"Button")," from Carbon to test that our dependencies are\nworking properly. At the top of ",Object(a.b)("inlineCode",{parentName:"p"},"App.js"),", import the ",Object(a.b)("inlineCode",{parentName:"p"},"Button")," by adding the\nfollowing:"),Object(a.b)("pre",null,Object(a.b)("code",i({parentName:"pre"},{className:"language-javascript",metastring:"path=src/App.js",path:"src/App.js"}),"import { Button } from 'carbon-components-react';\n")),Object(a.b)("p",null,"In the ",Object(a.b)("inlineCode",{parentName:"p"},"App")," component return, you can now replace:"),Object(a.b)("pre",null,Object(a.b)("code",i({parentName:"pre"},{className:"language-html",metastring:"path=src/App.js",path:"src/App.js"}),"<div>\n  Hello Carbon! Well, not quite yet. This is the starting point for the Carbon tutorial.\n</div>\n")),Object(a.b)("p",null,"with:"),Object(a.b)("pre",null,Object(a.b)("code",i({parentName:"pre"},{className:"language-html",metastring:"path=src/App.js",path:"src/App.js"}),"<Button>Button</Button>\n")),Object(a.b)("p",null,"Congratulations, you’ve imported your first component! You should see a Carbon\nstyled button on the page."),Object(a.b)("h2",null,"Add UI Shell"),Object(a.b)(u,{mdxType:"InlineNotification"},Object(a.b)("p",null,Object(a.b)("strong",{parentName:"p"},"Note:")," The UI Shell has experimental status at the moment. We do not\nrecommend using it for production until it is stable, but if doing so, know that\nthere may be breaking changes in the future.")),Object(a.b)("p",null,"Next, we’re going to create a React component called ",Object(a.b)("inlineCode",{parentName:"p"},"TutorialHeader")," to use\nwith the UI Shell Carbon component. In the ",Object(a.b)("inlineCode",{parentName:"p"},"src")," directory, create a\n",Object(a.b)("inlineCode",{parentName:"p"},"components")," directory and inside of that, a ",Object(a.b)("inlineCode",{parentName:"p"},"TutorialHeader")," directory. Create\nthe following files inside ",Object(a.b)("inlineCode",{parentName:"p"},"src/components/TutorialHeader"),":"),Object(a.b)("pre",null,Object(a.b)("code",i({parentName:"pre"},{className:"language-bash"}),"src/components/TutorialHeader\n├──_tutorial-header.scss\n├──index.js\n└──TutorialHeader.js\n")),Object(a.b)("h3",null,"Add UI Shell Sass"),Object(a.b)("p",null,"In ",Object(a.b)("inlineCode",{parentName:"p"},"index.scss")," add the following feature-flag ",Object(a.b)("strong",{parentName:"p"},"above")," the Carbon styles\nimport like so:"),Object(a.b)("pre",null,Object(a.b)("code",i({parentName:"pre"},{className:"language-scss",metastring:"path=src/index.scss",path:"src/index.scss"}),"$feature-flags: (\n  ui-shell: true,\n);\n")),Object(a.b)("p",null,"This is because our UI Shell is in experimental mode and the styles need to be\nmanually imported."),Object(a.b)("p",null,"Next, in ",Object(a.b)("inlineCode",{parentName:"p"},"app.scss"),", we’ll import our ",Object(a.b)("inlineCode",{parentName:"p"},"TutorialHeader")," styles. Your file should\nnow look like this:"),Object(a.b)("pre",null,Object(a.b)("code",i({parentName:"pre"},{className:"language-scss",metastring:"path=src/app.scss",path:"src/app.scss"}),"@import './components/TutorialHeader/tutorial-header.scss';\n")),Object(a.b)("h3",null,"Import and export the header"),Object(a.b)("p",null,"In ",Object(a.b)("inlineCode",{parentName:"p"},"src/components/TutorialHeader/index.js"),", import and export our\n",Object(a.b)("inlineCode",{parentName:"p"},"TutorialHeader")," component like so:"),Object(a.b)("pre",null,Object(a.b)("code",i({parentName:"pre"},{className:"language-javascript",metastring:"path=src/components/TutorialHeader/index.js",path:"src/components/TutorialHeader/index.js"}),"import TutorialHeader from './TutorialHeader';\nexport default TutorialHeader;\n")),Object(a.b)("p",null,"Next we’ll import our Carbon UI Shell components into ",Object(a.b)("inlineCode",{parentName:"p"},"TutorialHeader.js"),". Set\nup the file like so:"),Object(a.b)("pre",null,Object(a.b)("code",i({parentName:"pre"},{className:"language-javascript",metastring:"path=src/components/TutorialHeader/TutorialHeader.js",path:"src/components/TutorialHeader/TutorialHeader.js"}),'import React from \'react\';\nimport {\n  Header,\n  HeaderName,\n  HeaderNavigation,\n  HeaderMenuItem,\n  HeaderGlobalBar,\n  HeaderGlobalAction,\n  SkipToContent,\n} from \'carbon-components-react\';\n\nconst TutorialHeader = () => (\n  <Header aria-label="Carbon Tutorial">\n    <SkipToContent />\n    <HeaderName href="/" prefix="IBM">\n      Carbon Tutorial\n    </HeaderName>\n    <HeaderNavigation aria-label="Carbon Tutorial">\n      <HeaderMenuItem href="/repos">Repositories</HeaderMenuItem>\n    </HeaderNavigation>\n    <HeaderGlobalBar />\n  </Header>\n);\n\nexport default TutorialHeader;\n')),Object(a.b)(u,{mdxType:"InlineNotification"},Object(a.b)("p",null,Object(a.b)("strong",{parentName:"p"},"Note:")," you can find a description of the different components used UI Shell\nin our\n",Object(a.b)("a",i({parentName:"p"},{href:"https://github.com/carbon-design-system/carbon/tree/master/packages/react/src/components/UIShell"}),"carbon-components-react"),"\npackage.")),Object(a.b)(u,{mdxType:"InlineNotification"},Object(a.b)("p",null,Object(a.b)("strong",{parentName:"p"},"Note:")," When creating navigation headers, it’s important to have a\n",Object(a.b)("inlineCode",{parentName:"p"},"Skip to content")," link so keyboard users can skip the navigation items and go\nstraight to the main content.")),Object(a.b)(u,{mdxType:"InlineNotification"},Object(a.b)("p",null,Object(a.b)("strong",{parentName:"p"},"Note:")," It’s important that the ",Object(a.b)("inlineCode",{parentName:"p"},"TutorialHeader")," returns the Carbon ",Object(a.b)("inlineCode",{parentName:"p"},"Header"),"\nas its containing element, as we’ll later be rendering ",Object(a.b)("inlineCode",{parentName:"p"},"TutorialHeader")," in\n",Object(a.b)("inlineCode",{parentName:"p"},"App.js")," as a preceding sibling of ",Object(a.b)("inlineCode",{parentName:"p"},"Content"),", another UI Shell component. Those\ncomponents need to live one after another for the UI Shell to properly render.")),Object(a.b)("h3",null,"Import icons"),Object(a.b)("p",null,"Now let’s import the icons from our ",Object(a.b)("inlineCode",{parentName:"p"},"@carbon/icons-react")," elements package. In\nthe ",Object(a.b)("inlineCode",{parentName:"p"},"TutorialHeader.js")," file, we need to import each individual icon we will\nuse."),Object(a.b)("pre",null,Object(a.b)("code",i({parentName:"pre"},{className:"language-javascript",metastring:"path=src/components/TutorialHeader/TutorialHeader.js",path:"src/components/TutorialHeader/TutorialHeader.js"}),"import {\n  AppSwitcher20,\n  Notification20,\n  UserAvatar20,\n} from '@carbon/icons-react';\n")),Object(a.b)("p",null,"Then we need to add the ",Object(a.b)("inlineCode",{parentName:"p"},"HeaderGlobalAction")," component inside of the\n",Object(a.b)("inlineCode",{parentName:"p"},"HeaderGlobalBar")," where we will add our icons. These represent actions in the\nheader a user can make. Replace:"),Object(a.b)("pre",null,Object(a.b)("code",i({parentName:"pre"},{className:"language-html",metastring:"path=src/components/TutorialHeader/TutorialHeader.js",path:"src/components/TutorialHeader/TutorialHeader.js"}),"<HeaderGlobalBar />\n")),Object(a.b)("p",null,"With:"),Object(a.b)("pre",null,Object(a.b)("code",i({parentName:"pre"},{className:"language-html",metastring:"path=src/components/TutorialHeader/TutorialHeader.js",path:"src/components/TutorialHeader/TutorialHeader.js"}),'<HeaderGlobalBar>\n  <HeaderGlobalAction aria-label="Notifications">\n    <Notification20 />\n  </HeaderGlobalAction>\n  <HeaderGlobalAction aria-label="User Avatar">\n    <UserAvatar20 />\n  </HeaderGlobalAction>\n  <HeaderGlobalAction aria-label="App Switcher">\n    <AppSwitcher20 />\n  </HeaderGlobalAction>\n</HeaderGlobalBar>\n')),Object(a.b)("h3",null,"Render the header"),Object(a.b)("p",null,"Next we’ll render our UI Shell by importing our ",Object(a.b)("inlineCode",{parentName:"p"},"TutorialHeader")," component and\n",Object(a.b)("inlineCode",{parentName:"p"},"Content")," into ",Object(a.b)("inlineCode",{parentName:"p"},"App.js"),". Your imports should look like this:"),Object(a.b)("pre",null,Object(a.b)("code",i({parentName:"pre"},{className:"language-javascript",metastring:"path=src/App.js",path:"src/App.js"}),"import React, { Component } from 'react';\nimport './app.scss';\nimport { Button, Content } from 'carbon-components-react';\nimport TutorialHeader from './components/TutorialHeader';\n")),Object(a.b)("p",null,"Our ",Object(a.b)("inlineCode",{parentName:"p"},"return")," currently just contains a ",Object(a.b)("inlineCode",{parentName:"p"},"Button"),". Let’s update that to include\nour imported components. This should look like the following:"),Object(a.b)("pre",null,Object(a.b)("code",i({parentName:"pre"},{className:"language-javascript",metastring:"path=src/App.js",path:"src/App.js"}),"class App extends Component {\n  render() {\n    return (\n      <>\n        <TutorialHeader />\n        <Content>\n          <Button>Button</Button>\n        </Content>\n      </>\n    );\n  }\n}\n")),Object(a.b)("p",null,"You should now see a styled UI Shell header and a button below it."),Object(a.b)("h2",null,"Create pages"),Object(a.b)("p",null,"Next thing we need to do is create the files for our content. Start by creating\na folder called ",Object(a.b)("inlineCode",{parentName:"p"},"content")," in ",Object(a.b)("inlineCode",{parentName:"p"},"src"),". This should be a sibling of\n",Object(a.b)("inlineCode",{parentName:"p"},"src/components"),"."),Object(a.b)("p",null,"Since our app will have two pages, we’ll create two folders in ",Object(a.b)("inlineCode",{parentName:"p"},"src/content"),"."),Object(a.b)("pre",null,Object(a.b)("code",i({parentName:"pre"},{className:"language-bash"}),"src/content\n├── LandingPage\n└── RepoPage\n")),Object(a.b)("p",null,"Next, we’ll set up these folders the same way we set up\n",Object(a.b)("inlineCode",{parentName:"p"},"src/components/TutorialHeader"),"."),Object(a.b)("p",null,"Create the following files in the ",Object(a.b)("inlineCode",{parentName:"p"},"LandingPage")," folder:"),Object(a.b)("pre",null,Object(a.b)("code",i({parentName:"pre"},{className:"language-bash"}),"src/content/LandingPage\n├── _landing-page.scss\n├── index.js\n└── LandingPage.js\n")),Object(a.b)("p",null,"Create the following files in the ",Object(a.b)("inlineCode",{parentName:"p"},"RepoPage")," folder:"),Object(a.b)("pre",null,Object(a.b)("code",i({parentName:"pre"},{className:"language-bash"}),"src/content/RepoPage\n├── _repo-page.scss\n├── index.js\n└── RepoPage.js\n")),Object(a.b)("h3",null,"Set up content Sass"),Object(a.b)("p",null,"Next, we’ll import our content Sass files in ",Object(a.b)("inlineCode",{parentName:"p"},"app.scss"),", like so:"),Object(a.b)("pre",null,Object(a.b)("code",i({parentName:"pre"},{className:"language-scss",metastring:"path=src/app.scss",path:"src/app.scss"}),"@import './components/TutorialHeader/tutorial-header.scss';\n@import './content/LandingPage/landing-page.scss';\n@import './content/RepoPage/repo-page.scss';\n")),Object(a.b)("h3",null,"Import and export content pages"),Object(a.b)("p",null,"Now that our stylesheets are set up, we need to create our pages’ components.\nStarting with ",Object(a.b)("inlineCode",{parentName:"p"},"LandingPage"),", just like with our header, we need to export the\ncomponent in ",Object(a.b)("inlineCode",{parentName:"p"},"src/content/LandingPage/index.js")," by adding:"),Object(a.b)("pre",null,Object(a.b)("code",i({parentName:"pre"},{className:"language-javascript",metastring:"path=src/content/LandingPage/index.js",path:"src/content/LandingPage/index.js"}),"import LandingPage from './LandingPage';\nexport default LandingPage;\n")),Object(a.b)("p",null,"Next in ",Object(a.b)("inlineCode",{parentName:"p"},"LandingPage.js"),", we’ll create our component."),Object(a.b)("pre",null,Object(a.b)("code",i({parentName:"pre"},{className:"language-javascript",metastring:"path=src/content/LandingPage/LandingPage.js",path:"src/content/LandingPage/LandingPage.js"}),"import React from 'react';\n\nconst LandingPage = () => {\n  return <div>LANDING PAGE</div>;\n};\n\nexport default LandingPage;\n")),Object(a.b)("p",null,"We’ll repeat this process with ",Object(a.b)("inlineCode",{parentName:"p"},"RepoPage"),"."),Object(a.b)("p",null,"In ",Object(a.b)("inlineCode",{parentName:"p"},"src/content/RepoPage/index.js"),", import and export the ",Object(a.b)("inlineCode",{parentName:"p"},"RepoPage")," component\nlike so:"),Object(a.b)("pre",null,Object(a.b)("code",i({parentName:"pre"},{className:"language-javascript",metastring:"path=src/content/RepoPage/index.js",path:"src/content/RepoPage/index.js"}),"import RepoPage from './RepoPage';\nexport default RepoPage;\n")),Object(a.b)("p",null,"Then in ",Object(a.b)("inlineCode",{parentName:"p"},"RepoPage.js")," create the component."),Object(a.b)("pre",null,Object(a.b)("code",i({parentName:"pre"},{className:"language-javascript",metastring:"path=src/content/RepoPage/RepoPage.js",path:"src/content/RepoPage/RepoPage.js"}),"import React from 'react';\n\nconst RepoPage = () => {\n  return <div>REPO PAGE</div>;\n};\n\nexport default RepoPage;\n")),Object(a.b)("p",null,"Awesome! We’ve just created our content pages. Next thing we need to do is\nrender them with our router."),Object(a.b)("h2",null,"Add routing"),Object(a.b)("p",null,"We’ve updated our app to render our header, but now we need to add routing\nfunctionality. To do this we need to install ",Object(a.b)("inlineCode",{parentName:"p"},"react-router-dom"),". Go ahead and\nstop your development server (with ",Object(a.b)("inlineCode",{parentName:"p"},"CTRL-C"),") and then:"),Object(a.b)("pre",null,Object(a.b)("code",i({parentName:"pre"},{className:"language-bash"}),"yarn add react-router-dom@5.0.0\nyarn start\n")),Object(a.b)("p",null,"First, we need to wrap our app in the ",Object(a.b)("inlineCode",{parentName:"p"},"Router")," component. In the root\n",Object(a.b)("inlineCode",{parentName:"p"},"index.js"),", add the import:"),Object(a.b)("pre",null,Object(a.b)("code",i({parentName:"pre"},{className:"language-javascript",metastring:"path=src/index.js",path:"src/index.js"}),"import { HashRouter as Router } from 'react-router-dom';\n")),Object(a.b)(u,{mdxType:"InlineNotification"},Object(a.b)("p",null,Object(a.b)("strong",{parentName:"p"},"Note:")," We’re using ",Object(a.b)("inlineCode",{parentName:"p"},"HashRouter")," instead of ",Object(a.b)("inlineCode",{parentName:"p"},"BrowserRouter")," to simplify\ndeployments in upcoming tutorial steps. Learn more about the React Router\n",Object(a.b)("a",i({parentName:"p"},{href:"https://reacttraining.com/react-router/web/api/BrowserRouter"}),"here"),".")),Object(a.b)("p",null,"Then, update the ",Object(a.b)("inlineCode",{parentName:"p"},"render()")," function to include the ",Object(a.b)("inlineCode",{parentName:"p"},"Router"),"."),Object(a.b)("pre",null,Object(a.b)("code",i({parentName:"pre"},{className:"language-javascript",metastring:"path=src/index.js",path:"src/index.js"}),"ReactDOM.render(\n  <Router>\n    <App />\n  </Router>,\n  document.getElementById('root')\n);\n")),Object(a.b)("p",null,"In order to render our content pages, we need to add the following imports in\n",Object(a.b)("inlineCode",{parentName:"p"},"App.js")," below our existing imports."),Object(a.b)("pre",null,Object(a.b)("code",i({parentName:"pre"},{className:"language-javascript",metastring:"path=src/App.js",path:"src/App.js"}),"import { Route, Switch } from 'react-router-dom';\nimport LandingPage from './content/LandingPage';\nimport RepoPage from './content/RepoPage';\n")),Object(a.b)("p",null,"This allows us to use our page content components and routing components from\n",Object(a.b)("inlineCode",{parentName:"p"},"react-router-dom"),"."),Object(a.b)("p",null,"The next thing we need to do is update what we’re returning to ",Object(a.b)("inlineCode",{parentName:"p"},"App.js"),". We\ncurrently just have a button in our content. In order to render our pages\ncorrectly, we need to delete the ",Object(a.b)("inlineCode",{parentName:"p"},"Button")," component within ",Object(a.b)("inlineCode",{parentName:"p"},"Content")," (and remove\nthe Button import)."),Object(a.b)("p",null,"Now inside ",Object(a.b)("inlineCode",{parentName:"p"},"Content")," we’ll add the following:"),Object(a.b)("pre",null,Object(a.b)("code",i({parentName:"pre"},{className:"language-html",metastring:"path=src/App.js",path:"src/App.js"}),'<Switch>\n  <Route exact path="/" component={LandingPage} />\n  <Route path="/repos" component={RepoPage} />\n</Switch>\n')),Object(a.b)("p",null,"After that we need to do a couple quick fixes to the UI Shell to have it work\nwith the React router."),Object(a.b)("p",null,"Add the ",Object(a.b)("inlineCode",{parentName:"p"},"Link")," import in ",Object(a.b)("inlineCode",{parentName:"p"},"TutorialHeader.js"),":"),Object(a.b)("pre",null,Object(a.b)("code",i({parentName:"pre"},{className:"language-javascript",metastring:"path=src/components/TutorialHeader/TutorialHeader.js",path:"src/components/TutorialHeader/TutorialHeader.js"}),"import { Link } from 'react-router-dom';\n")),Object(a.b)("p",null,"We need to use the ",Object(a.b)("inlineCode",{parentName:"p"},"Link")," component instead of the default anchor elements to\nprevent full page reload when navigating to different pages with React Router.\nTo use ",Object(a.b)("inlineCode",{parentName:"p"},"Link"),", update the ",Object(a.b)("inlineCode",{parentName:"p"},"HeaderName")," component to use the ",Object(a.b)("inlineCode",{parentName:"p"},"element")," prop and\nreplace the ",Object(a.b)("inlineCode",{parentName:"p"},"href")," with ",Object(a.b)("inlineCode",{parentName:"p"},"to"),":"),Object(a.b)("pre",null,Object(a.b)("code",i({parentName:"pre"},{className:"language-javascript",metastring:"path=src/components/TutorialHeader/TutorialHeader.js",path:"src/components/TutorialHeader/TutorialHeader.js"}),'<HeaderName element={Link} to="/" prefix="IBM">\n  Carbon Tutorial\n</HeaderName>\n')),Object(a.b)("p",null,"Do the same with the component that contains ",Object(a.b)("inlineCode",{parentName:"p"},'href="/repos"'),", updating to:"),Object(a.b)("pre",null,Object(a.b)("code",i({parentName:"pre"},{className:"language-javascript",metastring:"path=src/components/TutorialHeader/TutorialHeader.js",path:"src/components/TutorialHeader/TutorialHeader.js"}),'<HeaderMenuItem element={Link} to="/repos">\n  Repositories\n</HeaderMenuItem>\n')),Object(a.b)("p",null,"You should now have a working header that routes to different pages without full\npage reload!"),Object(a.b)("h2",null,"Submit pull request"),Object(a.b)("p",null,"We’re going to submit a pull request to verify completion of this tutorial step\nand demonstrate a couple of related concepts."),Object(a.b)("h3",null,"Continuous integration (CI) check"),Object(a.b)("p",null,"We have a ",Object(a.b)("inlineCode",{parentName:"p"},"ci-check")," script defined in ",Object(a.b)("inlineCode",{parentName:"p"},"package.json")," that verifies file\nformatting for files that have been touched since the last Git commit with a\ntool called ",Object(a.b)("a",i({parentName:"p"},{href:"https://prettier.io"}),"Prettier"),". You’d typically also have that\nscript run your test suite as part of your CI build. Go ahead and make sure\neverything looks good with:"),Object(a.b)("pre",null,Object(a.b)("code",i({parentName:"pre"},{className:"language-bash"}),"yarn ci-check\n")),Object(a.b)(u,{mdxType:"InlineNotification"},Object(a.b)("p",null,Object(a.b)("strong",{parentName:"p"},"Note:")," If the ",Object(a.b)("inlineCode",{parentName:"p"},"ci-check")," is giving an error, it’s likely that some of your\nsource files are not properly formatted. This could happen if your text editor\nisn’t formatting with Prettier on save. To get ",Object(a.b)("inlineCode",{parentName:"p"},"ci-check")," to pass, run\n",Object(a.b)("inlineCode",{parentName:"p"},"yarn format")," then re-run ",Object(a.b)("inlineCode",{parentName:"p"},"yarn ci-check"),".")),Object(a.b)("h3",null,"Git commit and push"),Object(a.b)("p",null,"Before we can create a pull request, stage and commit all of your changes:"),Object(a.b)("pre",null,Object(a.b)("code",i({parentName:"pre"},{className:"language-bash"}),'git add --all && git commit -m "feat(tutorial): complete step 1"\n')),Object(a.b)(u,{mdxType:"InlineNotification"},Object(a.b)("p",null,Object(a.b)("strong",{parentName:"p"},"Note:")," You’ll notice that your commit includes binaries in the\n",Object(a.b)("inlineCode",{parentName:"p"},".yarn-offline-mirror")," folder. That’s expected as the repository is configured\nto run ",Object(a.b)("a",i({parentName:"p"},{href:"https://yarnpkg.com/blog/2016/11/24/offline-mirror"}),"Yarn offline")," for\nmore reliable builds. Future tutorial steps that don’t install new packages\nwon’t have ",Object(a.b)("inlineCode",{parentName:"p"},".yarn-offline-mirror")," commit changes.")),Object(a.b)("p",null,"Then, push to your repository:"),Object(a.b)("pre",null,Object(a.b)("code",i({parentName:"pre"},{className:"language-bash"}),"git push origin react-step-1\n")),Object(a.b)(u,{mdxType:"InlineNotification"},Object(a.b)("p",null,Object(a.b)("strong",{parentName:"p"},"Note:")," If your Git remote protocol is HTTPS instead of SSH, you may be\nprompted to authenticate with GitHub when you push changes. If your GitHub\naccount has two-factor authentication enabled, we recommend that you follow\nthese instructions to\n",Object(a.b)("a",i({parentName:"p"},{href:"https://help.github.com/en/articles/creating-a-personal-access-token-for-the-command-line"}),"create a personal access token for the command line"),".\nThat lets you use your token instead of password when performing Git operations\nover HTTPS.")),Object(a.b)(u,{mdxType:"InlineNotification"},Object(a.b)("p",null,Object(a.b)("strong",{parentName:"p"},"Note:")," If you receive a ",Object(a.b)("inlineCode",{parentName:"p"},"non-fast-forward")," error, it’s likely that your\nforked repository is behind the original repository and needs to be updated.\nThis can happen if the tutorial was updated after you began working on it. To\nfix, run ",Object(a.b)("inlineCode",{parentName:"p"},"git pull upstream react-step-1")," to merge the changes into your branch,\nthen you can try pushing again. Or, you can\n",Object(a.b)("a",i({parentName:"p"},{href:"https://help.github.com/en/articles/syncing-a-fork"}),"manually merge")," in the\nupstream changes.")),Object(a.b)("h3",null,"Pull request (PR)"),Object(a.b)("p",null,"Finally, visit\n",Object(a.b)("a",i({parentName:"p"},{href:"https://github.com/carbon-design-system/carbon-tutorial"}),"carbon-tutorial")," to\n“Compare & pull request”. In doing so, make sure that you are comparing to\n",Object(a.b)("inlineCode",{parentName:"p"},"react-step-1")," into ",Object(a.b)("inlineCode",{parentName:"p"},"base: react-step-1"),". Take notice of the\n",Object(a.b)("a",i({parentName:"p"},{href:"https://www.netlify.com"}),"Netlify")," bot that deploys a preview of your PR every\ntime that you push new commits. These previews can be shared and viewed by\nanybody to assist the PR review process."),Object(a.b)(u,{mdxType:"InlineNotification"},Object(a.b)("p",null,Object(a.b)("strong",{parentName:"p"},"Note:")," Expect your tutorial step PRs to be reviewed by the Carbon team but\nnot merged. We’ll close your PR so we can keep the repository’s remote branches\npristine and ready for the next person!")),Object(a.b)(u,{mdxType:"InlineNotification"},Object(a.b)("p",null,Object(a.b)("strong",{parentName:"p"},"Note:")," If your PR fails the CircleCI test with the error\n",Object(a.b)("inlineCode",{parentName:"p"},"Can't make a request in offline mode"),", try running the following command:\n",Object(a.b)("inlineCode",{parentName:"p"},"rm -rf .yarn-offline-mirror node_modules && yarn cache clean && yarn install"),".\nAdd and commit the changes once this completes, and try pushing again.")))}j.isMDXComponent=!0}}]);