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 2yarn 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""" --- extensionPoint: example.extension-point --- """ type Schema { type: LinkExtension! label: String! url: String! }
my-extension-point.jsx
1 2import 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;
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""" --- extensionPoint: example.extension-point --- """ type Schema { type: ButtonExtension! label: String! onAction: Function! }
my-extension-point.jsx
1 2import 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;
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.
Prop | Type | Description |
---|---|---|
render * | function | The `onAction` attribute of an extension that recieves a Panel API object. |
context | any | An object representing some context to be shared at the moment of rendering. This is mostly used for AsyncPanels |
RootType | string | The type of HTML element to render the panel into. Default: div. |
* required
schema.cse.graphql
1 2""" --- extensionPoint: example.extension-point --- """ type Schema { type: PanelExtension! onAction: PanelOnAction! }
my-extension-point.jsx
1 2import 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;
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.
Prop | Type | Description |
---|---|---|
location * | string | The name of the extension point used to provide better debugging information to developers when an error happens with their extension. |
fallback * | JSX.Element | A JSX element to render while the extension render module is loading. |
renderProvider * | function | The `onAction` attribute of an AsyncPanel extension. |
contextProvider | fuction | A function used to retreive the context to be shared with the extension before rendering. |
extensionKey | string | They key of the extension comming from its descriptor. Useful for better debugging information to developers when an error happens with their extension. |
RootType | string | The type of HTML element to render the panel into. Default: div. |
* required
schema.cse.graphql
1 2""" --- extensionPoint: example.extension-point --- """ type Schema { type: AsyncPanelExtension! onAction: AsyncPanelOnAction! }
my-exension-point.jsx
1 2import 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.
Prop | Type | Description |
---|---|---|
render * | function | The `onAction` attribute of an extension that recieves a Modal API object. |
isOpen | boolean | A boolean that indicates if the handler should open the modal. |
onClose | function | A callback to be executed when the modal is closed. |
* required
schema.cse.graphql
1 2""" --- extensionPoint: example.extension-point --- """ type Schema { type: ModalExtension! label: string! onAction: ModalOnAction! }
my-extension-point.jsx
1 2import 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: