The core building block of Pup's user interface is React components. In Pup, there are several components pre-defined for you that can either be used as-is, or modified to fit the particular needs of your product.
Components in Pup are split into three directories, nested under the
/ui directory at the root of the project:
- /ui/layouts - Components that are responsible for building layouts that combine a set of static elements (e.g., the application's navigation bar) with dynamic elements. In Pup, the
<App />component serves as the main layout component and is used to render every page in the application.
- /ui/pages - Components that are compositions of other components, rendered within the dynamic portion of a layout component and corresponding to a particular route in the application (e.g., the
/loginroute renders the
<Login />page component). Some page components are wrapped with Apollo component enhancers to provide them with data via GraphQL.
- /ui/components - Standalone components that can be used independently or composed together with other components in a page.
Organizing Component Directories
While components are split into the three sub-directories outlined above within the
/ui directory at the root of the project, all components themselves follow a similar directory structure.
For example, let's consider the
<Login /> page component defined at
/ui/pages/Login in the app. If we look inside this folder, we'll find a few different files:
index.e2e.js- The end-to-end tests for the component, defined using TestCafe.
index.js- The actual component definition.
styles.js- The CSS styles for the component, defined using styled-components.
This is the recommended pattern for defining components in Pup. Here, our goal is to isolate all of the code related to a single component in its own folder. You're encouraged to place any files specific to a component in this directory (e.g., if you'd like to add unit tests to your components, you could add a file like
index convention here is adopted from Node.js. When imported into another file, index files are implied, meaning, if we write an import statement like this:
import Login from '/ui/pages/Login';
We're effectively saying "load the
index.js file located at
/ui/pages/Login/index.js." In other words, including the
index.js at the end is optional.