diff --git a/docs/javascript/assets/use-case-wrex-toolbar-item.png b/docs/javascript/assets/use-case-wrex-toolbar-item.png
new file mode 100644
index 0000000..c29a712
Binary files /dev/null and b/docs/javascript/assets/use-case-wrex-toolbar-item.png differ
diff --git a/docs/javascript/use-cases.md b/docs/javascript/use-cases.md
index 5823a3f..b409cfd 100644
--- a/docs/javascript/use-cases.md
+++ b/docs/javascript/use-cases.md
@@ -191,6 +191,227 @@ window.lumapps.customize(({ targets, components, render, placement, constants })
});
```
+## Add new button on the rich text editor toolbar (widget RTE, article or event)
+
+
+
+In this use case, you'll probably want to have a new button on the rich text editor toolbar allowing you to insert specific elements from an external provider.
+
+```js
+window.lumapps.customize(
+ ({ targets, components, render, placement, constants, state }) => {
+ const {
+ DropdownSection,
+ DropdownItem,
+ RawHTML,
+ FlexBox,
+ Button,
+ List,
+ ListItem,
+ } = components;
+ const { Orientation, Size, Emphasis, Alignment } = constants;
+
+ /** Fetch the items from your external provider
+ * You can use our api wrapper(https://lumapps.github.io/customizations-api-doc/javascript/api.html#api-1)
+ */
+ const fetchItems = async () => {
+ const fetchedItems = new Promise((resolve) => {
+ setTimeout(() => {
+ resolve([
+ { id: "54", title: "First item", src: "https://lumapps.com" },
+ { id: "57", title: "Second item", src: "https://picsum.photos/" },
+ ]);
+ }, 500);
+ });
+ return fetchedItems;
+ };
+
+ /** Callback on search button click
+ * - Fetch external items
+ * - Render those items on a list
+ */
+ async function onItemsSearch() {
+ const context = state.get("context");
+ const input = document.querySelector("input#items-search-input");
+ const searchQuery = input.value;
+
+ // Trigger the loading state of the dialog while we fetch items
+ context.openWrexConfigurationDialog({
+ isLoading: true,
+ });
+
+ const items = await fetchItems();
+
+ const { componentToRender } = setupConfiguration({ items, searchQuery });
+
+ await context.openWrexConfigurationDialog({
+ componentToRender,
+ isLoading: false,
+ });
+ }
+
+ /** Callback when the user select an item from the list
+ * - Update the attributes on the element we want to insert
+ * - Rerender the list to display the selected state on the item
+ */
+ const onItemPickChange = (item, configurationData) => {
+ const context = state.get("context");
+
+ context.setWrexIframeAttributes({
+ src: item.src,
+ provider: "my-website",
+ });
+
+ const { componentToRender } = setupConfiguration({
+ ...configurationData,
+ selectedItemId: item.id,
+ });
+
+ context.openWrexConfigurationDialog({
+ componentToRender,
+ });
+ };
+
+ /**
+ * Return the components to render on the configuration dialog
+ * - Display only an input + a search button without fetched items
+ * - Display the items in a list when available
+ */
+ function setupConfiguration(configurationData = {}) {
+ const { items, searchQuery, selectedItemId } = configurationData;
+ const componentsToDisplay = [
+ FlexBox({
+ children: [
+ // Note: this allow to display an input the same way as other place of the product
+ RawHTML({
+ html: `
+
`,
+ }),
+ Button({
+ children: "Search",
+ emphasis: Emphasis.low,
+ onClick: onItemsSearch,
+ }),
+ ],
+ orientation: Orientation.horizontal,
+ gap: Size.regular,
+ hAlign: Alignment.center,
+ }),
+ ];
+
+ if (items && items.length > 0) {
+ const listItems = [];
+
+ for (const item of items) {
+ listItems.push(
+ ListItem({
+ children: item.title,
+ size: Size.tiny,
+ onItemSelected: () => onItemPickChange(item, configurationData),
+ isSelected: selectedItemId === item.id,
+ })
+ );
+ }
+
+ componentsToDisplay.push(
+ List({
+ children: listItems,
+ })
+ );
+ }
+
+ const componentToRender = FlexBox({
+ children: componentsToDisplay,
+ orientation: Orientation.vertical,
+ gap: Size.huge,
+ });
+
+ return { componentToRender };
+ }
+
+ /** Callback when the user click on our video custom button */
+ const onVideoButtonClick = async (context) => {
+ state.set("context", context);
+ const { componentToRender } = setupConfiguration();
+
+ context.openWrexConfigurationDialog({
+ componentToRender,
+ });
+ };
+
+ render({
+ placement: placement.UNDER,
+ target: targets.WREX_TOOLBAR,
+ toRenderWithContext: (context) => {
+ return DropdownSection({
+ children: [
+ DropdownItem({
+ title: "My videos",
+ icon: "video-account",
+ onClick: () => onVideoButtonClick(context),
+ }),
+ ],
+ });
+ },
+ });
+ }
+);
+```
+### Use case information
+
+**openWrexConfigurationDialog** Function
+
+Open the configuration dialog and allows you to define his content.
+
+| Parameter | Description | Is required? | Option type | Default Value |
+|-----------|------|----------|---------|-------------|
+| `configuration` | Configuration options | Yes | object | `{}` |
+| `configuration.componentToRender` | The component to render inside the dialog | Yes | Component | `undefined` |
+| `configuration.isLoading` | Whether the dialog should be in a loading state | No | boolean | `false` |
+
+**setWrexIframeAttributes** Function
+
+Allows you to define the data of the iframe to insert
+
+*Note: calling this function will not insert an iframe, the insertion is done through the configuration dialog*
+
+| Parameter | Description | Is required? | Option type | Default Value |
+|-----------|------|----------|---------|-------------|
+| `attributes` | Configuration options | Yes | object | `{}` |
+| `attributes.src` | The url of the page to embed | Yes | string | `undefined` |
+| `attributes.srcDoc` | The html content of the iframe | No | string | `undefined` |
+| `attributes.title` | The title of the iframe, used for accessibility | No | string | `undefined` |
+| `attributes.provider` | The name of the provider of the iframe, used to identify an iframe | No | string | `undefined` |
+
+**setWrexImageAttributes** Function
+
+Allows you to define the data of the image to insert
+
+*Note: calling this function will not insert an image, the insertion is done through the configuration dialog*
+
+| Parameter | Description | Is required? | Option type | Default Value |
+|-----------|------|----------|---------|-------------|
+| `attributes` | Configuration options | Yes | object | `{}` |
+| `attributes.title` | The caption of the image group | No | string | `undefined` |
+| `attributes.images` | The image(s) to display | Yes | Image[] | `[]` |
+
+**Image** Object
+
+| Parameter | Description | Is required? | Option type | Default Value |
+|-----------|------|----------|---------|-------------|
+| `src` | The image url | Yes | string | `''` |
+| `alt` | The image alt text, should describe the image for accessibility purpose | No | string | `''` |
+| `height` | The image height (in px) | No | integer | `undefined` |
+| `width` | The image width (in px) | No | integer | `undefined` |
+
## Disabling bookmarks
Bookmarks can be disabled in order to avoid them to be displayed by adding the following line of JavaScript to your site.