+------------------------+
| Metadata               |
+----------+-------------+
| Template | guides      |
+----------+-------------+
| Image    | ![][image0] |
+----------+-------------+
| Category | resources   |
+----------+-------------+

+-------------------+
| Section Metadata  |
+---------+---------+
| style   | content |
+---------+---------+

![][image0]

# What is the Sidekick Library?

The Sidekick Library is an extension for the AEM Sidekick that enables developers to create UI-driven tooling for content authors. It includes a built-in blocks plugin that can display a list of all blocks to authors in an intuitive manner, removing the need for authors to remember or search for every variation of a block. Developers can also write their own plugins for the sidekick library.

## How to use the Sidekick Library?

The steps below detail how to setup the sidekick library and configure the blocks plugin.

### Library Sheet Setup

The sidekick library is populated with your plugins and plugin content using a sheet.

1\. Start by creating a directory in sharepoint or gdrive where you want to store the content for the library. We recommend storing the content in `/tools/sidekick` (or any other name) in the root of the mountpoint. The next steps will assume the directory is called `/tools/sidekick`.

2\. Next, create a workbook (an Excel file) in the `/tools/sidekick` directory called `library` (or any other name). Each sheet in the workbook represents a plugin that will be loaded by the Sidekick Library. The name of the sheet determines the name of the plugin that will be loaded. Any data contained in the sheet will be passed to the plugin when loaded. The plugin sheet name must be prepended with `helix-`. For example, if you want to load a plugin called `tags`, you would create a sheet named `helix-tags`.

3\. For this tutorial we will create a sheet for our `blocks` plugin. Create a sheet (or rename the default sheet) and call it \`helix-blocks\` and leave it empty for now.

### Blocks Plugin

The Sidekick library comes with a `blocks` plugin.

+--------------------------------------------------+
| video                                            |
+--------------------------------------------------+
| <https://www.aem.live/docs/sidekick-library.mp4> |
+--------------------------------------------------+

#### Blocks Plugin Setup

To generate content for the blocks plugin, you need to prepare a separate Word document for each block you want to include.

1\. Create a directory inside the `/tools/sidekick` directory where you will store all the block variations. For example, you could create a directory called `blocks` inside `/tools/sidekick`.\
2\. For this example, let's assume we want to define all the variations of a block called `columns`. First create a Word document called `columns` inside the `blocks` directory and provide examples of all the variations of the `columns` block. After each variation of the block add in a [section delimiter](https://www.aem.live/docs/authoring#sections).\
3\. Preview and publish the `columns` document.\
4\. Open the library workbook created in the last section, inside the `helix-blocks` sheet, create two columns named `name` and `path`.\
6\. Next we need to add a row for our `columns` block. Add the name of the block in the first column and the url to the document that defines the block variations in the second column. For instance, if you want to add the `columns` block, you could create a row with the name `Columns` and the path `/tools/sidekick/blocks/columns`. In order for the library to work across environments (page, live, prod) you should not use an absolute url for the path column.\
7\. Preview and publish the `library` workbook.

\> Since the example blocks are being published you should use [bulk metadata](https://www.aem.live/docs/bulk-metadata) to exclude the content inside of `/tools/**` from being indexed.

![Screenshot 2024-04-09 at 2 54 19 PM][image1]

##### Example `library.xlsx`

![][image2]

## Library Metadata

The blocks plugins supports a special type of block called `library metadata` which provides a way for developers to tell the blocks plugin some information about the block or how it should be rendered.

### Supported library metadata options

+------------------------------------------------------------------------------------------------------+
| table                                                                                                |
+------------------------------------------------------------------------------------------------------+
| +----------------------------+----------------------------+-----------------------------+----------+ |
| | Key Name                   | Value                      | Description                 | Required | |
| +----------------------------+----------------------------+-----------------------------+----------+ |
| | name                       | Name of the block          | Allows you to set a custom  | false    | |
| |                            |                            | name for the block          |          | |
| +----------------------------+----------------------------+-----------------------------+----------+ |
| | description                | A description of the block | Allows you to set a custom  | false    | |
| |                            |                            | description for a block     |          | |
| +----------------------------+----------------------------+-----------------------------+----------+ |
| | type                       | The type of the block      | This tells the blocks       | false    | |
| |                            |                            | plugin how to group the     |          | |
| |                            |                            | content that makes up your  |          | |
| |                            |                            | block. Possible options are |          | |
| |                            |                            | template or section         |          | |
| |                            |                            | (details below)             |          | |
| +----------------------------+----------------------------+-----------------------------+----------+ |
| | include next sections      | How many sections to       | Use if your block requires  | false    | |
| |                            | include in the block item  | content from subsequence    |          | |
| |                            |                            | sections in order to        |          | |
| |                            |                            | render. Should be a number  |          | |
| |                            |                            | value that indicates how    |          | |
| |                            |                            | much subsequent sections to |          | |
| |                            |                            | include.                    |          | |
| +----------------------------+----------------------------+-----------------------------+----------+ |
| | searchtags                 | A comma seperated list of  | Allows you to define other  | false    | |
| |                            | search terms               | terms that could be used    |          | |
| |                            |                            | when searching for this     |          | |
| |                            |                            | block in the blocks plugin  |          | |
| +----------------------------+----------------------------+-----------------------------+----------+ |
| | tableHeaderBackgroundColor | A hex color (ex #ff3300)   | Overrides the table header  | false    | |
| |                            |                            | background color for any    |          | |
| |                            |                            | blocks in the section or    |          | |
| |                            |                            | page.                       |          | |
| +----------------------------+----------------------------+-----------------------------+----------+ |
| | tableHeaderForegroundColor | A hex color (ex #ffffff)   | Overrides the table header  | false    | |
| |                            |                            | foreground color for any    |          | |
| |                            |                            | blocks in the section or    |          | |
| |                            |                            | page.                       |          | |
| +----------------------------+----------------------------+-----------------------------+----------+ |
| | contentEditable            | A boolean value (default:  | Set to false to disable     | false    | |
| |                            | true)                      | content editing in the      |          | |
| |                            |                            | preview window.             |          | |
| +----------------------------+----------------------------+-----------------------------+----------+ |
| | disableCopy                | A boolean value (default:  | Set to true to disable the  | false    | |
| |                            | false)                     | copy button in the preview  |          | |
| |                            |                            | window.                     |          | |
| +----------------------------+----------------------------+-----------------------------+----------+ |
| | hideDetailsView            | A boolean value (default:  | Hide the block details      | false    | |
| |                            | false)                     | panel inside the preview    |          | |
| |                            |                            | window.                     |          | |
| +----------------------------+----------------------------+-----------------------------+----------+ |
+------------------------------------------------------------------------------------------------------+

### Default Library metadata vs Library metadata

There are two types of `library metadata`. Library metadata that lives within a section containing the block, or *default* `library metadata` that applies to the document as a whole and lives in a section on it's own (a block called `library metadata` as the only child in a section).

Let's take an example of a hero block that has 5 variants. Suppose you want to add the same description for each variation of the block, rather than duplicating the `library metadata` with the description into each section containing the variations. You could instead use *default* `library metadata` to apply the same description to every variation of the block. If you decide that one variation actually needs a slightly different description you could add `library metadata` to the section containing the variation and it would override the *default* `library metadata` description when it's rendered within the blocks plugin.

### Authoring block names and descriptions using Library Metadata

By default the block name (with variation) will be used to render the item in the blocks plugin. For example, if the name of the block is `columns (center, background)` then that name will be used as the label when it’s rendered in the blocks plugin. This can be customized by creating a `library metadata` section within the same section as the block. Library metadata can also be used to author a description of the block as well as adding `searchTags` to include an alias for the block when using the search feature.

Example block with custom name and description

**Content**

![Screenshot 2023-06-08 at 1 11 09 PM][image3]

**Display**

![Screenshot 2023-06-08 at 1 13 32 PM][image4]

### Autoblocks and Default Content

The blocks plugin is capable of rendering [default content](https://www.aem.live/developer/markup-sections-blocks#default-content) and [autoblocks](https://www.aem.live/developer/markup-sections-blocks#auto-blocking). In order to achieve this, it is necessary to place your `default content` or `autoblock` within a dedicated section, which should include a `library metadata` table defining a `name` property, as previously described. If no name is specified in the library metadata, the item will be labeled as "Unnamed Item."

### Blocks composed of content in subsequent sections

There are situations where developers may want a block to consist of content from subsequent sections. This pattern is discouraged for reasons stated [here](https://www.aem.live/docs/davidsmodel#rule-3-limit-row-and-column-spans), but if you choose to use it the blocks plugin can render these items using the `include next sections` property in `library metadata`.

![][image5]

### Templates

Templates are a way to group an entire document into a single element in the sidekick library. To mark a document as a template set `type` to `template` in `default library metadata`.

\> Important, the `library metadata` needs to be in it's own section and be the only child to be considered `default library metadata`.

Supporting `metadata` is also desirable for templates. To add a metadata table to the template you can use a `Page metadata` block.

![266064147-12883ee0-147b-4171-b89a-c313e33eef24][image6]

When the template is copied a `metadata` with the values will be added along with the content to the clipboard.

## Sidekick plugin setup

Since the sidekick library is hosted on the same origin as the content, a static HTML page needs to be created to load and configure the content.

1\. Create a file called `library.html` in `tools/sidekick/`;

2\. Paste the following code in `library.html`.

```
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1.0, viewport-fit=cover"
    />
    <meta name="Description" content="AEM Sidekick Library" />
    <meta name="robots" content="noindex" />
    <base href="/" />

    <style>
      html,
      body {
        margin: 0;
        padding: 0;
        font-family: sans-serif;
        background-color: #ededed;
        height: 100%;
      }
      
      helix-sidekick { display: none }
    </style>
    <title>Sidekick Library</title>
  </head>

  <body>
    <script
      type="module"
      src="https://www.aem.live/tools/sidekick/library/index.js"
    ></script>
    <script>
      const library = document.createElement('sidekick-library')
      library.config = {
        base: '/tools/sidekick/library.json',
      }

      document.body.prepend(library)
    </script>
  </body>
</html>
```

In the code above we load the sidekick library from `aem.live` and then create a custom `sidekick-library` element and add it to the page. The `sidekick-library` element accepts a `config` object that is required to configure the sidekick library.

### Supported configuration parameters

+--------------------------------------------------------------------------------------+
| table                                                                                |
+--------------------------------------------------------------------------------------+
| +----------------+--------------------------+---------------------------+----------+ |
| | Parameter Name | Value                    | Description               | Required | |
| +----------------+--------------------------+---------------------------+----------+ |
| | base           | Path to the library      | The base library to be    | true     | |
| |                |                          | loaded                    |          | |
| +----------------+--------------------------+---------------------------+----------+ |
| | extends        | Absolute URL to the      | A library to extend the   | false    | |
| |                | extended library         | base library with         |          | |
| +----------------+--------------------------+---------------------------+----------+ |
| | plugins        | An object containing     | The plugins object can be | false    | |
| |                | plugins to register with | used to register plugins  |          | |
| |                | the sidekick library.    | and configure data that   |          | |
| |                |                          | should be passed to the   |          | |
| |                |                          | plugin                    |          | |
| +----------------+--------------------------+---------------------------+----------+ |
+--------------------------------------------------------------------------------------+

The blocks plugin supports the following configuration properties that can be set using the plugins object.

### Blocks plugin configuration parameters

+--------------------------------------------------------------------------------------------+
| table                                                                                      |
+--------------------------------------------------------------------------------------------+
| +-----------------+-----------------------------+-----------------------------+----------+ |
| | Parameter Name  | Value                       | Description                 | Required | |
| +-----------------+-----------------------------+-----------------------------+----------+ |
| | encodeImages    | A boolean value that        | If your site has a Zero     | true     | |
| |                 | indicates if images should  | trust network access (ZTNA) |          | |
| |                 | be encoded during copy      | service enabled such as     |          | |
| |                 | operations                  | Cloudflare Access then      |          | |
| |                 |                             | images should be encoded    |          | |
| |                 |                             | for copy/paste operations   |          | |
| |                 |                             | to work correctly with      |          | |
| |                 |                             | images.                     |          | |
| +-----------------+-----------------------------+-----------------------------+----------+ |
| | viewPorts       | Full or simplified          | Configuration to overwrite  | false    | |
| |                 | configuration object, see   | the default viewport sizes. |          | |
| |                 | examples below.             | The default is 480px fo     |          | |
| |                 |                             | mobile, 768px for tablet    |          | |
| |                 |                             | and 100% of the current     |          | |
| |                 |                             | window for desktop.         |          | |
| +-----------------+-----------------------------+-----------------------------+----------+ |
| | contentEditable | A boolean value to disable  | Set to false to disable     | false    | |
| |                 | content editing globally in | content editing.            |          | |
| |                 | previews.                   |                             |          | |
| +-----------------+-----------------------------+-----------------------------+----------+ |
+--------------------------------------------------------------------------------------------+

#### Examples

Encoding images

```
const library = document.createElement('sidekick-library')
library.config = {
  base: '/tools/sidekick/library.json',
  plugins: {
    blocks: {
      encodeImages: true,
    }
  }
}
```

Custom viewports (short form)

```
const library = document.createElement('sidekick-library')
library.config = {
  base: '/tools/sidekick/library.json',
  plugins: {
    blocks: {
      viewPorts: [600, 900],
    }
  }
}
```

Custom viewports

```
const library = document.createElement('sidekick-library')
library.config = {
  base: '/tools/sidekick/library.json',
  plugins: {
    blocks: {
      viewPorts: [
        {
          width: '599px',
          label: 'Small',
          icon: 'device-phone',
        },
        {
          width: '899px',
          label: 'Medium',
          icon: 'device-tablet',
        },
        {
          width: '100%',
          label: 'Large',
          icon: 'device-desktop',
          default: true,
        },
      ],
    }
  }
}
```

### Custom table header colors

You can customize the table header background and foreground color when pasting a block, section metadata or metadata that was copied from the blocks plugin.

Default styles can be set in `library.html` using css variables.

```
 <style>
    :root {
      --sk-block-table-background-color: #03A;
      --sk-block-table-foreground-color: #fff;

      --sk-section-metadata-table-background-color: #f30;
      --sk-section-metadata-table-foreground-color: #000;

      --sk-metadata-table-background-color: #000;
      --sk-metadata-table-foreground-color: #fff;
    }
  </style>
```

These values can be overridden using [library metadata](https://www.aem.live/docs/sidekick-library#supported-library-metadata-options).

\> Depending on the system color scheme selected for the users computer (dark mode), Word may alter the chosen colors in an attempt to improve accessibility.

### Custom plugin setup

The example below defines a `tags` plugin in the config. The keys of the plugins object must match the name of the plugin, any other properties defined in the plugin object will be available to the plugin via the context argument of the [decorate](https://www.aem.live/docs/sidekick-library#building-a-plugin) method.

```
const library = document.createElement('sidekick-library')
library.config = {
  base: '/tools/sidekick/library.json',
  plugins: {
    tags: {
      src: '/tools/sidekick/plugins/tags/tags.js',
      foo: 'bar'
    }
  }
}
```

### Extended Libraries

In some cases merging two block libraries may be desirable. When an extended library is defined the sidekick library application will merge the base library and the extended library together into a single library list for authors.

The example below defines a base library and an extended library (on another origin) that will be merged into the base library.

```
const library = document.createElement('sidekick-library')
library.config = {
  base: '/tools/sidekick/library.json',
  extends: 'https://main--repo--owner.hlx.live/tools/sidekick/library.json'
}
```

\> The `Access-Control-Allow-Origin` headers will need to be set on the `library.json` and blocks of the extended library in order for them to load in the sidekick library. See [Custom HTTP Response Headers](https://www.aem.live/docs/custom-headers) for more info.

\> Due to same-origin policies enforced by browsers on iframes a preview of an extended block cannot be loaded at this time.

### Sidekick config setup

Next, in order for the sidekick library to appear in the sidekick we need to add the plugin to the sidekick object in the configuration service.

```
curl -X POST https://admin.hlx.page/config/{org}/sites/{site}/sidekick.json \
  -H 'content-type: application/json' \
  -H 'x-auth-token: {your-auth-token}' \
  --data '{
    "project": "Example",
    "plugins": [{
      "id": "library",
      "title": "Library",
      "environments": ["edit"],
      "url": "/tools/sidekick/library.html",
      "includePaths": ["**.docx**"]
    }]
  }'
```

The `url` property in the plugin configuration indicates the location from which the sidekick should load the plugin. This should point to the `library.html` file we previously created.

\> If you have already configured the sidekick, be careful not to overwrite the sidekick config with the request above. You should GET the config first and add the plugin to the existing configuration if it exists.

## Considerations when building blocks for the library

The sidekick library renders blocks by first fetching the `plain.html` rendition of the the block and then strips it of any other blocks in the content (for example if there are multiple variations of a block in the response). It then requests the same page (without `.plain.html`) and replaces the `main` element with the stripped block and loads the entire document into an `iframe` using the [srcdoc](https://developer.mozilla.org/en-US/docs/Web/API/HTMLIFrameElement/srcdoc) attribute.

### Use of `window.location`

Since the block is loaded in an iframe using the `srcdoc` attribute, the instance of the `window.location` object used by your sites code will not contain the typical values you would expect to see.

Example `window.location` object when running in the library

```
{
  "host": "",
  "hostname": "",
  "href": "about:srcdoc"
  "origin": "null"
  "pathname": "srcdoc"
  "port": ""
  "protocol": "about:"
}
```

For this reason, if your block requires use of the `window.location` object we recommend adding the following functions to your `scripts.js` file and importing them into your function for use.

```
/**
 * Returns the true origin of the current page in the browser.
 * If the page is running in a iframe with srcdoc, the ancestor origin is returned.
 * @returns {String} The true origin
 */
export function getOrigin() {
  const { location } = window;
  return location.href === 'about:srcdoc' ? window.parent.location.origin : location.origin;
}

/**
 * Returns the true of the current page in the browser.mac
 * If the page is running in a iframe with srcdoc,
 * the ancestor origin + the path query param is returned.
 * @returns {String} The href of the current page or the href of the block running in the library
 */
export function getHref() {
  if (window.location.href !== 'about:srcdoc') return window.location.href;

  const { location: parentLocation } = window.parent;
  const urlParams = new URLSearchParams(parentLocation.search);
  return `${parentLocation.origin}${urlParams.get('path')}`;
}
```

### Use of `createOptimizedPicture` in lib-aem

The `createOptimizedPicture` function in `lib-aem` also [uses](https://github.com/adobe/helix-project-boilerplate/blob/c6ab59278d89a251c864fad1100f6de03a63a6fe/scripts/lib-franklin.js#L480) `window.location.href`. If you are using this function we recommend moving it into `scripts.js` and modify it to use the `getHref()` function above.

### Checking for the presence of the sidekick library

Sometimes you may want to know if the page or the block is running in the sidekick library. To do this there are a couple of options.

1\. Check if `window.location.href === 'about:srcdoc'`

2\. The `main` element and the block element will contain the `sidekick-library` class

## Building a Plugin

Developing a plugin is similar to constructing a block in AEM. Once a user tries to load the plugin, the sidekick library will trigger the `decorate()` method on your plugin. This method receives the container to render the plugin in and any data that is included in the plugins sheet.

```
/**
 * Called when a user tries to load the plugin
 * @param {HTMLElement} container The container to render the plugin in
 * @param {Object} data The data contained in the plugin sheet
 * @param {String} query If search is active, the current search query
 * @param {Object} context contains any properties set when the plugin was registered
 */
export async function decorate(container, data, query, context) {
  // Render your plugin
}
```

\> The `decorate()` function must be exported from the plugin.

### Plugin default export & search

The default export from a plugin allows authors to customize the plugin name displayed in the header upon loading, as well as activate the search functionality within the sidekick library.

```
export default {
  title: 'Tags',
  searchEnabled: true,
};
```

When the `searchEnabled` property is true, the library header will display a search icon upon loading the plugin. If the user initiates a search by entering a query, the `decorate()` function of the plugin will be triggered again, this time with the search string passed in the query parameter of the `decorate()` function.

### Plugin web components

Plugin authors can utilize a select set of web components from [Spectrum](https://opensource.adobe.com/spectrum-web-components/index.html) when building a custom plugin.

The following components from Spectrum are available

+---------------------------------------------------------------------------------------------------------------------------+
| table                                                                                                                     |
+---------------------------------------------------------------------------------------------------------------------------+
| +------------------------+----------------------------------------------------------------------------------------------+ |
| | Component              | Documentation Link                                                                           | |
| +------------------------+----------------------------------------------------------------------------------------------+ |
| | sp-tooltip             | [Docs](https://opensource.adobe.com/spectrum-web-components/components/tooltip/)             | |
| +------------------------+----------------------------------------------------------------------------------------------+ |
| | sp-toast               | [Docs](https://opensource.adobe.com/spectrum-web-components/components/toast/)               | |
| +------------------------+----------------------------------------------------------------------------------------------+ |
| | sp-textfield           | [Docs](https://opensource.adobe.com/spectrum-web-components/components/textfield/)           | |
| +------------------------+----------------------------------------------------------------------------------------------+ |
| | sp-sidenav-item        | [Docs](https://opensource.adobe.com/spectrum-web-components/components/sidenav-item/)        | |
| +------------------------+----------------------------------------------------------------------------------------------+ |
| | sp-sidenav             | [Docs](https://opensource.adobe.com/spectrum-web-components/components/sidenav/)             | |
| +------------------------+----------------------------------------------------------------------------------------------+ |
| | sp-search              | [Docs](https://opensource.adobe.com/spectrum-web-components/components/search/)              | |
| +------------------------+----------------------------------------------------------------------------------------------+ |
| | sp-progress-circle     | [Docs](https://opensource.adobe.com/spectrum-web-components/components/progress-circle/)     | |
| +------------------------+----------------------------------------------------------------------------------------------+ |
| | sp-picker              | [Docs](https://opensource.adobe.com/spectrum-web-components/components/picker/)              | |
| +------------------------+----------------------------------------------------------------------------------------------+ |
| | sp-menu-item           | [Docs](https://opensource.adobe.com/spectrum-web-components/components/menu/)                | |
| +------------------------+----------------------------------------------------------------------------------------------+ |
| | sp-menu-group          | [Docs](https://opensource.adobe.com/spectrum-web-components/components/menu/)                | |
| +------------------------+----------------------------------------------------------------------------------------------+ |
| | sp-menu-divider        | [Docs](https://opensource.adobe.com/spectrum-web-components/components/menu/)                | |
| +------------------------+----------------------------------------------------------------------------------------------+ |
| | sp-menu                | [Docs](https://opensource.adobe.com/spectrum-web-components/components/menu/)                | |
| +------------------------+----------------------------------------------------------------------------------------------+ |
| | sp-illustrated-message | [Docs](https://opensource.adobe.com/spectrum-web-components/components/illustrated-message/) | |
| +------------------------+----------------------------------------------------------------------------------------------+ |
| | sp-divider             | [Docs](https://opensource.adobe.com/spectrum-web-components/components/divider/)             | |
| +------------------------+----------------------------------------------------------------------------------------------+ |
| | sp-card                | [Docs](https://opensource.adobe.com/spectrum-web-components/components/card/)                | |
| +------------------------+----------------------------------------------------------------------------------------------+ |
| | sp-button-group        | [Docs](https://opensource.adobe.com/spectrum-web-components/components/button-group/)        | |
| +------------------------+----------------------------------------------------------------------------------------------+ |
| | sp-button              | [Docs](https://opensource.adobe.com/spectrum-web-components/components/button/)              | |
| +------------------------+----------------------------------------------------------------------------------------------+ |
| | sp-action-button       | [Docs](https://opensource.adobe.com/spectrum-web-components/components/action-button/)       | |
| +------------------------+----------------------------------------------------------------------------------------------+ |
| | overlay-trigger        | [Docs](https://opensource.adobe.com/spectrum-web-components/components/overlay-trigger/)     | |
| +------------------------+----------------------------------------------------------------------------------------------+ |
+---------------------------------------------------------------------------------------------------------------------------+

The following icons from Spectrum are also available

+----------------------------------------------------------------------------------------------------------------------+
| table                                                                                                                |
+----------------------------------------------------------------------------------------------------------------------+
| +------------------------+-----------------------------------------------------------------------------------------+ |
| | Component              | Documentation Link                                                                      | |
| +------------------------+-----------------------------------------------------------------------------------------+ |
| | sp-icon-search         | [Docs](https://opensource.adobe.com/spectrum-web-components/components/icons-workflow/) | |
| +------------------------+-----------------------------------------------------------------------------------------+ |
| | sp-icon-file-template  | [Docs](https://opensource.adobe.com/spectrum-web-components/components/icons-workflow/) | |
| +------------------------+-----------------------------------------------------------------------------------------+ |
| | sp-icon-file-code      | [Docs](https://opensource.adobe.com/spectrum-web-components/components/icons-workflow/) | |
| +------------------------+-----------------------------------------------------------------------------------------+ |
| | sp-icon-device-phone   | [Docs](https://opensource.adobe.com/spectrum-web-components/components/icons-workflow/) | |
| +------------------------+-----------------------------------------------------------------------------------------+ |
| | sp-icon-device-tablet  | [Docs](https://opensource.adobe.com/spectrum-web-components/components/icons-workflow/) | |
| +------------------------+-----------------------------------------------------------------------------------------+ |
| | sp-icon-device-desktop | [Docs](https://opensource.adobe.com/spectrum-web-components/components/icons-workflow/) | |
| +------------------------+-----------------------------------------------------------------------------------------+ |
| | sp-icon-magic-wand     | [Docs](https://opensource.adobe.com/spectrum-web-components/components/icons-workflow/) | |
| +------------------------+-----------------------------------------------------------------------------------------+ |
| | sp-icon-copy           | [Docs](https://opensource.adobe.com/spectrum-web-components/components/icons-workflow/) | |
| +------------------------+-----------------------------------------------------------------------------------------+ |
| | sp-icon-preview        | [Docs](https://opensource.adobe.com/spectrum-web-components/components/icons-workflow/) | |
| +------------------------+-----------------------------------------------------------------------------------------+ |
| | sp-icon-info           | [Docs](https://opensource.adobe.com/spectrum-web-components/components/icons-workflow/) | |
| +------------------------+-----------------------------------------------------------------------------------------+ |
| | sp-icon-view-detail    | [Docs](https://opensource.adobe.com/spectrum-web-components/components/icons-workflow/) | |
| +------------------------+-----------------------------------------------------------------------------------------+ |
| | sp-icon-chevron-right  | [Docs](https://opensource.adobe.com/spectrum-web-components/components/icons-workflow/) | |
| +------------------------+-----------------------------------------------------------------------------------------+ |
| | sp-icon-chevron-left   | [Docs](https://opensource.adobe.com/spectrum-web-components/components/icons-workflow/) | |
| +------------------------+-----------------------------------------------------------------------------------------+ |
+----------------------------------------------------------------------------------------------------------------------+

### <br>Plugin Events

Plugin authors can dispatch events from their plugin to the parent sidekick library in order to display a loader or to show a toast message.

#### Toast Messages

```
import { PLUGIN_EVENTS } from 'https://www.aem.live/tools/sidekick/library/events/events.js';

export async function decorate(container, data, query) {
  // Show a toast message
  container.dispatchEvent(new CustomEvent(PLUGIN_EVENTS.TOAST,  { detail: { message: 'Toast Shown!', variant: 'positive | negative' } }))
}
```

#### Show and Hide Loader

```
import { PLUGIN_EVENTS } from 'https://www.aem.live/tools/sidekick/library/events/events.js';

export async function decorate(container, data, query) {
  // Show loader
  container.dispatchEvent(new CustomEvent(PLUGIN_EVENTS.SHOW_LOADER))
  ...
  // Hide loader
  container.dispatchEvent(new CustomEvent(PLUGIN_EVENTS.HIDE_LOADER))
}
```

### Example plugin

[Tags Plugin](https://github.com/dylandepass/boilerplate-with-library/blob/main/tools/sidekick/plugins/tags/tags.js)

[Plugin API Example](https://github.com/dylandepass/boilerplate-with-library/blob/main/tools/sidekick/plugins/api-test/api-test.js)

[image0]: https://mian--helix-website--adobe.aem.page/media_1e5fb8dc7e6733da52dfc650a8634e9edf483eee5.jpg#width=1103&height=827

[image1]: https://mian--helix-website--adobe.aem.page/media_1c24bdcb68375b65304fd478204b3558e7b2e1153.png#width=441&height=44

[image2]: https://mian--helix-website--adobe.aem.page/media_1cf667308be4eddf5d9b96ee6663d70febccae1af.png#width=342&height=174

[image3]: https://mian--helix-website--adobe.aem.page/media_1e8ca209a88408b18847f9e290dbc1b0b4ee0f1f6.png#width=644&height=706

[image4]: https://mian--helix-website--adobe.aem.page/media_1c7627edc617de392d1e308aa6547618028fbcf94.png#width=1501&height=996

[image5]: https://mian--helix-website--adobe.aem.page/media_1671c45e263255331b3f2c47b48b7887157308651.png#width=1600&height=300

[image6]: https://mian--helix-website--adobe.aem.page/media_13d086c555905679d232dd82ef88dc4bc1f49d9f0.png#width=648&height=269
