# Components

## Creating a Component

{% embed url="<https://www.youtube.com/watch?v=GO4ALhphlnY&feature=youtu.be>" %}

1. Focus on a row on the page
2. Click 'Component' in the toolbar
3. Write code under the 'Code' tab, create fields under the 'Fields' tab

## Component Code

### HTML

![](https://2146102850-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MI5zCYEN4cqBl6YZTet%2F-MLdJ3ZoDe-URWVOUuDZ%2F-MLdJggV_6cGnn0tPAK6%2Fimage.png?alt=media\&token=6a21505b-3c15-4c6f-a9f0-e4ca6304969a)

* See an instant preview of what your code looks like
* Use \[Handlebars]\(<https://handlebarsjs.com/>) to wire up your fields
* Use \[Emmet]\(<https://docs.emmet.io/abbreviations/syntax/>) to quickly write HTML (e.g. `div>div>h1.heading`and press Tab)

### CSS

![](https://2146102850-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MI5zCYEN4cqBl6YZTet%2F-MLdJ3ZoDe-URWVOUuDZ%2F-MLdO6xAe0pKaVg0wpeF%2Fimage.png?alt=media\&token=9b123422-fa96-491f-ae4e-0d02c7893316)

* Styles are encapsulated (so if you only have one image tag in your component, you can safely select it with `img.`
* Nested styles are supported (using \[postcss-nested]\(<https://github.com/postcss/postcss-nested>))

### JavaScript

* You can import any JS modules by name with `import module from 'module-name'` , where `module-name` is the module's name on \[npm]\(<https://www.npmjs.com/>). In the background, primo turns that into a request to \[Skypack]\(<https://skypack.dev/>) that looks like

  `import module from 'https://cdn.skypack.dev/module-name'.`Skypack is a CDN that sends visitors pre-optimized packages.&#x20;
* Additional values related to the component can be found under a variable named `primo` . `primo` contains three properties:&#x20;
  * **`id`** is the component's unique ID. Typically used to select the component's node.&#x20;
  * **`data`** contains the component's field values
  * **`fields`**&#x63;ontains the component's fields

{% hint style="info" %}
Sometimes you'll need to call a function from your HTML

```
<button onclick="doSomething()">click</button>
```

To do so, you'll need to define the function globally from the component's JS&#x20;

```
window.doSomething = function() {}
```

To avoid overwriting a global function (especially when reusing a component), create a global namespace using the component's ID.&#x20;

```
window[primo.id] = {
    ...window[`component${primo.id}`] || {},
    doSomething: function() {}
}
```

And access it from the component's HTML&#x20;

```
<button onclick="{{id}}.doSomething()">click</button>
```

{% endhint %}

## Component fields

Fields let you easily change content inside HTML from the CMS side.&#x20;

### Create a field

1. From within the Component Editor, click the Fields tab
2. Add a field, selecting a field type based on the data type
   * **Repeater:** Lists
   * **Group:** Objects
   * **Content:** Markdown
   * **Switch:** Boolean&#x20;
   * **Text, Number, URL**
3. Give the new field a **label** and an **ID**
   * **Label:** Labels the input field in the CMS
   * **ID:** Used from within the component's HTML to access the field value

### Connect field to HTML

primo uses the \[Handlebars]\(<https://handlebarsjs.com/>) compiler to build HTML from field values. Once you create a field, you can access their values from within the component HTML using the field's **ID.**

{% hint style="info" %}
Some handlebars features like partials aren't supported yet
{% endhint %}

{% tabs %}
{% tab title="Repeater" %}

```markup
<!-- This assumes we created and populated a repeater field with the ID of `nav` -->
{{#each nav}}
    <a href="{{url}}">{{title}}</a>
{{/each}}
```

{% endtab %}

{% tab title="Group" %}

```markup
<div>
    <h3>{{teaser.title}}</p>
    <p>{{teaser.description}}</p>
</div>
```

{% endtab %}

{% tab title="Text" %}

```markup
<h1>{{heading}}</h1>
```

{% endtab %}

{% tab title="Image" %}

```markup
<img src="{{header.url}}" alt="{{header.alt}}" />
```

{% endtab %}

{% tab title="Number" %}

```markup
<span>{{count}}</span>
```

{% endtab %}

{% tab title="Content" %}

```markup
<!-- Since this field produces html, we'll need to wrap it in three brackets -->
<!-- 'primo-copy' gives the div the same copy styles as copy rows on the page -->
<div class="primo-copy">
    {{{ page_content }}}
</div>
```

{% endtab %}

{% tab title="Switch" %}

```markup
{{#if show_contact}}
  <address>
    <a href="mailto:jon@doe.com">jon@doe.com</a><br>
    <a href="tel:+13115552368">(311) 555-2368</a>
  </address>
{{else}}
  <h1>Unfortunately, we're currently unavailable for hire</h1>
{{/if}}
```

{% endtab %}

{% tab title="URL" %}

```markup
<a href="{{detail_url}}">See More Details</a>
```

{% endtab %}

{% tab title="Link" %}

```
<a href="{{cta.url}}">{{cta.title}}</a>
```

{% endtab %}
{% endtabs %}


---

# 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://primo.gitbook.io/usage/basic-usage/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.
