import { Meta } from '@storybook/addon-docs/blocks';

<Meta title="Docs/Getting Started/Build components" />

# Build components

## Structure

React components are located in the src directory and separated into the `atoms`, `components`, and `composite-demos` subdirectories.

Put each component/atom in its own self-titled directory in kebab-case inflection (`src/atoms/my-atom`). Use PascalCase inflection to name the component's files (MyAtom.jsx). Use the following file structure for each component:

```
src
+-- my-atom
|	+-- stories
|	|   +-- MyAtom.story.mdx
|	+-- styles
|	|   +-- MyAtom.scss
|	+-- tests
|	|   +-- MyAtom.test.jsx
|	+-- MyAtom.jsx
```

## Components

Components are the core elements that are placed in the theme, and typically linked to the datastore. Therefore, they are exported and available to the theme, and are the entry points inside of which everything cascades in a typical React pattern. Think of components as mini-apps that are placed in different containers, and are therefore isolated from one another. Normally, components should not have other components as their children. Use atoms for that.

Components get their props from GraphQL, the global datastore object, and from their settings forms.

### `withListener` higher-order component

Components that get their props from the dataStore are wrapped as a higher-order component (HOC) called `withListener`, found in the root folder of the components (`src/components/withListener.jsx`). Export them by default wrapped in the HOC:

```
export default withListener(MyComponent);
```

Components wrapped with `withListener` can only have two props, both of which are objects: 
- `data` : data that comes from the datastore
- `settings` : user-defined settings that come from the settings form

Structure everything that the components need in one of these two props. The withListener HOC, as its name implies, listens to changes in the data store and passes the props accordingly to its wrapped component through the `data` and `settings` containers.

The description of which data is selected by `withListener` to pass to the component is strucutured in the component's `Schema.marketplaceData` object. [More details](?path=/story/docs-customization-intro--page)

### `withGraphQL` higher-order component

Components that get their props from GraphQL are wrapped as an higher-order component (HOC) called `withGraphQL`, found in the root folder of the components (`src/components/withGraphQL.jsx`).

## Atoms

Atoms are not connected to the global datastore and are placed within components or other atoms. They get their props from their parents. Atoms are designed to be usable by different components, for example a `Button` might be used anywhere in any component.

Some atoms are less generic than others, in that they might depend on a particular data structure, for example to display a product's details. Still, an atom should always be considered reusable by multiple components.

When building components that need some parts to be extracted, for example a sub-component in a loop, and these parts are not reusable by other components, they should be placed inside that component's directory, in an `atoms` directory that is private to that component.

## Composite demos

Do not use composite demos within the theme. Their purpose is merely to mock the behavior of the theme from within the Storybook when multiple components are placed on the same page, and to test and develop their interactions with one another.
