---
title: Panel API - Client-side Extensions
platform: server
product: clientside-extensions
category: reference
subcategory: api
date: '2024-04-02'
---

# Panel API

## About

API to render and manipulate extensions of type Panel.

### Signature

```ts
type LifecycleCallback = (container: HTMLElement) => void;

interface PanelApi {
    onMount: (callback: LifecycleCallback) => PanelApi;

    onUnmount: (callback: LifecycleCallback) => PanelApi;
}
```

## onMount()

Provides a container to render custom content in it.

### Callback Parameters

<table>
    <thead>
        <tr class="header">
            <th>Name</th>
            <th>Type</th>
            <th>Description</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>container</td>
            <td><code>HTMLElement</code></td>
            <td>HTML element to be used as a container to render custom content.</td>
        </tr>
    </tbody>
</table>

### Usage

```ts
import { PanelExtension } from '@atlassian/clientside-extensions';

/**
 * @clientside-extension
 * @extension-point reff.plugins-example-location
 */
export default PanelExtension.factory(() => {
    function getPanelContent() {
        return `
            <h4>Cool panel</h4>
            <p>This is some cool content generated with JS</p>
        `;
    }

    return {
        onAction: (panelApi) => {
            panelApi.onMount((container) => {
                container.innerHTML = getPanelContent();
            });
        },
    };
});
```

## onUnmount()

Allows to set a cleanup callback to be called when the provided container is about to be deleted.

### Callback Parameters

<table>
    <thead>
        <tr class="header">
            <th>Name</th>
            <th>Type</th>
            <th>Description</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>container</td>
            <td><code>HTMLElement</code></td>
            <td>HTML element that was provided to render custom content in it. It's important to unmount any React component
            you've mounted in there to avoid keeping the component alive when the container is destroyed.</td>
        </tr>
    </tbody>
</table>

### Usage

```ts
import { PanelExtension } from '@atlassian/clientside-extensions';

/**
 * @clientside-extension
 * @extension-point reff.plugins-example-location
 */
export default PanelExtension.factory(() => {
    const onClick = () => {
        alert('You clicked a button');
    };

    return {
        label: 'JS Panel',
        onAction: (panelApi) => {
            let button;

            panelApi
                .onMount((container) => {
                    button = document.createElement('button');
                    button.innerText = 'Click me!';
                    button.addEventListener('click', onClick);

                    container.appendChild(button);
                })
                .onUnmount((container) => {
                    // use to cleanup any event listener, subscription, or unmount components
                    button.removeEventListener('click', onClick);
                });
        },
    };
});
```
