Extension Factories
Extension API
Extension Points

Rate this page:

Extension Handlers

Client-side Extensions comes with a set of default extension types, each requiring their own API to work correctly.

Some of them are very simple, but others require a large API that can be difficult to provide on your own, so CSE provides default handlers that help you render extensions with Atlaskit components.

These default handlers are provided by the @atlassian/clientside-extensions-components package, so make sure to install it:

1
2
3
4
5
yarn add -D @atlassian/clientside-extensions-components

// or

npm install --save-dev @atlassian/clientside-extensions-components

Here are some examples on how to render each type of extension, and how to use these default handlers.

Links are a static set of attributes with at least a url and label property. You can then decide how to handle the case of rendering links as you see fit.

schema.cse.graphql

1
2
3
4
5
6
7
8
9
10
11
12
"""
---
extensionPoint: example.extension-point
---
"""
type Schema {
    type: LinkExtension!

    label: String!

    url: String!
}

my-extension-point.jsx

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import React from "react";
import { useExtensions } from "./schema.cse.graphql";

const ExampleExtensionPoint = ({ context }) => {
    const extensions = useExtensions(context);

    return (
        <>
            {extensions.map(({attributes}) => (
                <a href={attributes.link}>{attributes.label}</a>
            )}
        </>
    )
}

export default ExampleExtensionPoint;

Button

Buttons provide a way for extension developers to execute an action when their button is clicked.

They declare such action by adding an onAction method to their attributes, so you should bind that method to your button click handler when rendering.

schema.cse.graphql

1
2
3
4
5
6
7
8
9
10
11
12
"""
---
extensionPoint: example.extension-point
---
"""
type Schema {
    type: ButtonExtension!

    label: String!

    onAction: Function!
}

my-extension-point.jsx

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import React from "react";
import { useExtensions } from "./schema.cse.graphql";

const ExampleExtensionPoint = ({ context }) => {
    const extensions = useExtensions(context);

    return (
        <>
            {extensions.map(({attributes}) => (
                <button onClick={attributes.onAction}>{attributes.label}</button>
            )}
        </>
    )
}

export default ExampleExtensionPoint;

Panel

Panels provide a container for extension developers to render custom HTML content (they are the equivalent of legacy web-panels).

In this case, the onAction method should receive an API with a onMount and onUnmount methods, and you should handle calling this methods with the arguments when needed.

Since this can be a bit difficult to implement, CSE provides a default handler that creates a container and a Panel API object for you.

Supported props

PropTypeDescription
render *functionThe `onAction` attribute of an extension that recieves a Panel API object.
contextanyAn object representing some context to be shared at the moment of rendering. This is mostly used for AsyncPanels
RootTypestringThe type of HTML element to render the panel into. Default: div.

* required

Usage

schema.cse.graphql

1
2
3
4
5
6
7
8
9
10
"""
---
extensionPoint: example.extension-point
---
"""
type Schema {
    type: PanelExtension!

    onAction: PanelOnAction!
}

my-extension-point.jsx

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import React from "react";
import { PanelHandler } from "@atlassian/clientside-extensions-components";
import { useExtensions } from "./schema.cse.graphql";

const ExampleExtensionPoint = ({ context }) => {
    const extensions = useExtensions(context);

    return (
        <>
            {extensions.map(({attributes}) => (
                <PanelHandler render={attributes.onAction} />
            )}
        </>
    )
}

export default ExampleExtensionPoint;

AsyncPanel

Async panels work very similar to regular Panels, with the difference that they defer the loading of the resources needed to render until they are necessary. They are useful when loading very heavy features that are not always rendered.

CSE also provides a default handler for this kind of extensions.

Supported props

PropTypeDescription
location *stringThe name of the extension point used to provide better debugging information to developers when an error happens with their extension.
fallback *JSX.ElementA JSX element to render while the extension render module is loading.
renderProvider *functionThe `onAction` attribute of an AsyncPanel extension.
contextProviderfuctionA function used to retreive the context to be shared with the extension before rendering.
extensionKeystringThey key of the extension comming from its descriptor. Useful for better debugging information to developers when an error happens with their extension.
RootTypestringThe type of HTML element to render the panel into. Default: div.

* required

Usage

schema.cse.graphql

1
2
3
4
5
6
7
8
9
10
"""
---
extensionPoint: example.extension-point
---
"""
type Schema {
    type: AsyncPanelExtension!

    onAction: AsyncPanelOnAction!
}

my-exension-point.jsx

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import React from "react";
import { AsyncPanelHandler } from "@atlassian/clientside-extensions-components";
import { useExtensions } from "./schema.cse.graphql";

const ExampleExtensionPoint = ({ context }) => {
    const extensions = useExtensions(context);

    return (
        <>
            {extensions.map(({key, attributes}) => (
                <AsyncPanelHandler
                    location="example.extension-point"
                    extensionKey={key}
                    renderProvider={attributes.onAction}
                    contextProvider={attributes.contextProvider}
                    fallback={<div>loading...</div>}/>
            )}
        </>
    )
}

export default ExampleExtensionPoint;

Modals provide a button that opens a modal, and then a container in the body of that modal to render custom HTML content. It also provides a set of APIs to interact with the modal.

A handler is provided to ease the implementation of this large API.

Supported props

PropTypeDescription
render *functionThe `onAction` attribute of an extension that recieves a Modal API object.
isOpenbooleanA boolean that indicates if the handler should open the modal.
onClosefunctionA callback to be executed when the modal is closed.

* required

Usage

schema.cse.graphql

1
2
3
4
5
6
7
8
9
10
11
12
"""
---
extensionPoint: example.extension-point
---
"""
type Schema {
    type: ModalExtension!

    label: string!

    onAction: ModalOnAction!
}

my-extension-point.jsx

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import React from "react";
import { ModalWithActionHandler } from "@atlassian/clientside-extensions-components";
import { useExtensions } from "./schema.cse.graphql";

const ModalExtensionRenderer = ({ extension }) => {
    const { onAction, label, ...attributes } = extension.attributes;

    return (
        <ModalWithActionHandler render={onAction} {...attributes}>
            {label}
        </ModalWithActionHandler>
    );
};

const ExampleExtensionPoint = ({ context }) => {
    const extensions = useExtensions(context);

    return (
        <>
            {extensions.map((extension) => (
                <ModalExtensionRenderer extension={extension} />
            )}
        </>
    )
}

export default ExampleExtensionPoint;

Rate this page: