To use this variable in our multiple css modules, we’ll import it at the top of our CSS module and use it as though it has been declared at the top of the local file.
Back in our src/components/Header/styles.module.css, we can replace the :root definition with the import line:
@import url("../../styles/base.css");
/* ... */
.topbar { /* ... */
height: var(--height);
line-height: var(--height);
/* ... */
}
Now, we have one place to change the height of the topbar and still have the variable cascade across our app.
Splitting Up Components
With our topbar built, we can move to building the routes of our main application. Our app contains a sidebar and a changable content area that changes views upon changing context. That is, we’ll show a map to start out with and when our user clicks on a pin, we’ll change this to show details about the location the user has clicked on.
Let’s get started with the sidebar component that shows a listing of the places. We’ve done the hardwork up through this point. The React Way dictates that we define a component that uses a components to display the view (components all the way down – weeee). What this literally entails is that we’ll build a <Listing /> component that lists individual listing items. This way we can focus on the detail for each item listing rather than needing to worry about it from a high-level.
Let’s take our listing from a simple list to a <Sidebar /> component. Since we’ll create the
component as a shared one, let’s add it in the src/components/Sidebar directory. We’ll also create a JavaScript file and the CSS module:
$ mkdir src/components/Sidebar
$ touch src/components/Sidebar/{Sidebar.js,styles.module.css}
The <Sidebar /> component will be a fairly simple component that we can use to contain the listing of places and a wrapper for a sticky sidebar. Let’s place it in our <Container /> view initially, so we can get it listed in the view. In our src/views/Main/Container.js file, let’s import this new
<Sidebar /> component (yet to be built). Let’s import it and place it in our render() function:
import Sidebar from 'components/Sidebar/Sidebar'
export class Container extends React.Component { // ...
We’ll also want to pass a few props into the <Sidebar /> component. Since it is responsible for listing our places, we’ll definitely need to pass in the list of places we fetch from the google api. As of now, it’s stored in the state of the <Container />. We’ll come back to passing through a click handler (that gets called when a list item is clicked). Modifying our implementation, let’s pass through these props:
import Sidebar from 'components/Sidebar/Sidebar'
export class Container extends React.Component { // ...
With our <Sidebar /> component in the <Container />, let’s start building our <Sidebar />.
The component will mostly be used as a container to hold styles and dynamic data.
import React, { PropTypes as T } from 'react' import styles from './styles.module.css'
export class Sidebar extends React.Component { render() {
return (
<div className={styles.sidebar}>
<div className={styles.heading}>
Let’s also make sure we add the appropriate top positioning such that it isn’t rendered underneath the topbar. Let’s create the styles in src/components/Sidebar/styles.module.css and add some styles:
@import url("../../styles/base.css");
.sidebar { height: 100%;
top: var(--topbar-height);
left: 0;
overflow: hidden;
position: relative;
flex: 1;
Our <Sidebar /> component so far is straightforward and currently only renders the title prop we passed it above. Currently, we don’t have much interesting going on with our <Sidebar />
component. Let’s pass through our details to a new <Listing /> component.
We could display the listing directly inside the <Sidebar /> component, but this would not be the React Way.
Let’s create a <Listing /> component to list each place. We’ll use an additional component called
<Item /> to handle listing each individual item. That being said, let’s build the <Listing />
component. We’ll make the components, a css module, and the tests to go along with it:
$ mkdir src/components/Listing
$ touch src/components/Listing/{Listing.js,Item.js,styles.module.css}
$ touch src/components/Listing/{Listing.spec.js,Item.spec.js}
Since we’re doing some test driven development, let’s get our Listing.spec.js updated. The assumptions we’ll make about our <Listing /> component is that it has the styles we expect and that it lists an <Item /> component for each place in our places prop. The test can be stubbed as follows:
import React from 'react' import { expect } from 'chai' import { shallow } from 'enzyme'
import Listing from './Listing'
import styles from './styles.module.css'
describe('<Listing />', () => { let wrapper;
wrapper = shallow(<Listing places={places} />) });
it('wraps the component in a listing css class') it('has an item for each place in the places prop') })
Let’s go ahead and fill out these tests. It’s okay that they will ultimately fail when we run them at first (we haven’t implemented either the <Listing /> or the <Item /> components yet). The final tests will look like:
import React from 'react' import { expect } from 'chai' import { shallow } from 'enzyme'
import Listing from './Listing'
import styles from './styles.module.css'
describe('<Listing />', () => { let wrapper;
wrapper = shallow(<Listing title={'Cafes'}
places={places} />) });
it('wraps the component in a listing css class', () => { expect(wrapper.find(`.${styles.container}`))
.to.be.defined;
})
it('has an item for each place in the places prop', () => { expect(wrapper.find('Item').length)
.to.equal(places.length);
}) })