# Components

## Register component in Shopstory config

Let's imagine the simplest possible component:

```typescript
import React from "react";

export type CustomComponentProps = {
  color: "white" | "purple" | "green",
  noBorder: boolean
}

export const CustomComponent : React.FC<CustomComponentProps> = (props) => {
  return <div style={{
    border: props.noBorder ? "none" : "2px solid black",
    background: props.color === "white" ? "white" : props.color === "green" ? "#83d1c4" : "#78517c",
    padding: 24,
    display: "flex",
    justifyContent: "center",
    alignItems: "center",
    textAlign: "center"
  }}>
    My custom component
  </div>
}
```

It displays a box with a border (that can be disabled with `noBorder` prop) and with background (controlled by a `background` prop).

To make it available in Shopstory the first thing we must do is to register it in the `components` array of Shopstory configuration file:

```typescript
export const shopstoryConfig: Config = {
    // ...
    components: [
      {
        id: "CustomComponent",
        label: "Custom component",
        schema: [
          {
            prop: "color",
            label: "Color",
            type: "select",
            options: [
              "white", "purple", "green"
            ]
          },
          {
            prop: "noBorder",
            label: "Disable border",
            type: "boolean"
          },
        ]
      }
    ]
}
```

Each component must have a unique `id`. `schema` determines the properties that user can change in the Shopstory sidebar panel. Full reference of available field types available [here](/schema-reference.md).

Our component is already available in Shopstory but when you try to add it you will see a "Missing" error:

<figure><img src="/files/dlhvIJxP6uLujE1cRPiN" alt=""><figcaption></figcaption></figure>

It's because Shopstory can't find the component instance.

## Add component instance to `ShopstoryProvider`

The remaining step is to allow Shopstory find `CustomComponent` instance. This task is handled by `ShopstoryProvider`. Let's open `src/shopstory/provider.tsx` file and add the component instance:

```typescript
import { ShopstoryProvider } from "@shopstory/core/react";
import { CustomComponent } from "../components/CustomComponent/CustomComponent";

export const DemoShopstoryProvider : React.FC = ({ children }) => {
  return <ShopstoryProvider
    components={{
      CustomComponent
    }}
  >
    { children }
  </ShopstoryProvider>
}
```

`DemoShopstoryProvider` must be added as a wrapper to all `<ShopstoryCanvas />` and `<Shopstory />` component calls. By doing that Shopstory will be able to access all custom component references and render them properly.

`pages/shopstory-canvas.tsx`:

```typescript
const ShopstoryCanvasPage: NextPage = () => {
  return <DemoShopstoryProvider>
    <Canvas config={shopstoryConfig} />
  </DemoShopstoryProvider>
}
```

`/pages/shopstory-block/[entryId].tsx`:

```typescript
const ShopstoryBlockPage: NextPage<ShopstoryBlockPageProps> = (props) => {
  return <DemoShopstoryProvider>
    <ShopstoryMetadataProvider meta={props.meta}>
      <Shopstory content={props.content} />
    </ShopstoryMetadataProvider>
  </DemoShopstoryProvider>
}
```

Voila! Let's see our component in action:

{% embed url="<https://vimeo.com/779558840>" %}

## Component types

There are 3 component types in Shopstory.

* `item` (default) - available only in stacks inside of components
* `card` - cards can be used in card grids or sliders.
* `section` - full-screen section, can be added only at a root level of page

We haven't specified `type` property for our `CustomComponent` so it's treated as an `item`.

If you want to change a type of custom component just set `type` property in the component object:

```typescript
export const shopstoryConfig: Config = {
    // ...
    components: [
      {
        id: "CustomComponent",
        label: "Custom component",
        type: "card"
        schema: [
          // ...
        ]
      }
    ]
}
```

Now the custom component should be available in a card picker.&#x20;

## Layout compatibility

When Shopstory renders a custom component it's always wrapped with a container `div` with `display: grid` set. So the resulting markup looks kind of like this:

```html
<div style={{display: "grid"}}>
    <YourCustomComponent />
</div>
```

You should assume that the container `div` might vary in size (it's controlled by Shopstory layout, not you). Thanks to the `display: grid` your component will always fill the container `div`. It's your job to make your component adapt properly to different widths and heights. However, in most cases you don't need to do much.

## Next steps

* [Custom buttons](/custom-code/buttons.md)
* [Connecting 3rd party resources](/resources.md) (like products from e-commerce platforms, CMS entries, assets, etc) to component properties
* [Available schema property types](/schema-reference.md)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.shopstory.app/custom-code/components.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
