Using UIKit Blocks

This document covers various examples to help you use the Apps-Engine UI blocks so you can create meaningful user interactions in your apps. The UI blocks are triggered by an action or a condition. In these examples, the UI blocks will be triggered when a message is starred. First, we will see how to create a single block and then we will add more elements to create complex visual layouts.

Create a section block

Let’s create a basic section that contains some text. This will be displayed in a room when a message is starred. The main app class looks like this:

import {
    IAppAccessors, IConfigurationExtend, ILogger, IHttp, IModify, IPersistence, IRead, IMessageBuilder, IMessageRead
} from '@rocket.chat/apps-engine/definition/accessors';
import { App } from '@rocket.chat/apps-engine/definition/App';
import { IAppInfo } from '@rocket.chat/apps-engine/definition/metadata';
import { UIKitInteractionType, IUIKitInteractionHandler, UIKitSurfaceType } from '@rocket.chat/apps-engine/definition/uikit';
import { OpenCtxBarCommand } from './contextbar';
import { uiKitMessage } from '@rocket.chat/ui-kit';
import { IMessage, IMessageStarContext, IPostMessageSent, IPostMessageStarred } from '@rocket.chat/apps-engine/definition/messages';

export class uiblocksApp extends App implements IPostMessageStarred {

    async executePostMessageStarred(context: IMessageStarContext, read: IRead, http: IHttp, persistence: IPersistence, modify: IModify): Promise<void> {
        const messageCreator = modify.getCreator().startMessage();

        messageCreator.setBlocks([
            {
                type: 'section', // the type of block
                text: {
                    type: 'plain_text',
                    text: 'Message starred! :)',
                    emoji: true
                }
            },
        ])
        messageCreator.setRoom(context.message.room);
        await modify.getCreator().finish(messageCreator);
    }
}

Whenever a message is starred, the app bot returns the text message as shown in this screenshot:

Stack multiple blocks

In the same example, we are going to add more blocks and elements to demonstrate how you can create complex UI layouts.

Add an image block

async executePostMessageStarred(context: IMessageStarContext, read: IRead, http: IHttp, persistence: IPersistence, modify: IModify): Promise<void> {
        const messageCreator = modify.getCreator().startMessage();

        messageCreator.setBlocks([
            {
                type: 'section', // section block
                text: {
                    type: 'plain_text',
                    text: 'Message starred! :)',
                    emoji: true
                }
            },
            {
                type: 'image', // image block
                imageUrl: 'https://cdn0.iconfinder.com/data/icons/new-year-holidays-set/200/NewYearIcon7-01-1024.png',
                altText: 'test image'
            },
        ])

        //messageCreator.setText('Message starred! :)');
        messageCreator.setRoom(context.message.room);
        await modify.getCreator().finish(messageCreator);
    }

Add a divider block and an action block

Now, instead of the image, we will add a divider and an action block. The action block contains a button element.

async executePostMessageStarred(context: IMessageStarContext, read: IRead, http: IHttp, persistence: IPersistence, modify: IModify): Promise<void> {
        const messageCreator = modify.getCreator().startMessage();
        const appId = this.getID();

        messageCreator.setBlocks([
            {
                type: 'section', // the section block
                blockId: 'section_1',
                text: {
                    type: 'plain_text',
                    text: 'Message starred! :)',
                    emoji: true
                }
            },
            {
                type: 'divider', // the divider block
                appId: appId,
                blockId: 'divider_block_1'
            },
            {
                type: 'actions', // the action block
                appId: appId,
                blockId: 'action_block_1',
                elements: [ // the elements parameter contains the action element details, in this case, a button element
                    {
                        type: 'button',
                        actionId: 'button_action_1',
                        appId: appId,
                        blockId: 'button_action_block_1',
                        text: {
                            type: 'plain_text',
                            text: 'Learn more!'
                        },
                        style: 'primary',
                        value: 'Button element'
                    }
                ]
            },
        ])

        //messageCreator.setText('Message starred! :)');
        messageCreator.setRoom(context.message.room);
        await modify.getCreator().finish(messageCreator);
    }

The following screenshot shows the UI:

Add an input block

We will define an input block containing the static menu element type:

async executePostMessageStarred(context: IMessageStarContext, read: IRead, http: IHttp, persistence: IPersistence, modify: IModify): Promise<void> {
        const messageCreator = modify.getCreator().startMessage();
        const appId = this.getID();

        messageCreator.setBlocks([
            {
                type: 'section', // the section block
                blockId: 'section_1',
                text: {
                    type: 'plain_text',
                    text: 'Message starred! :)',
                    emoji: true
                }
            },
            {
                type: 'divider', // the divider block
                appId: appId,
                blockId: 'divider_block_1'
            },
            {
                type: 'actions', // the action block
                appId: appId,
                blockId: 'action_block_1',
                elements: [ // the elements parameter contains the action element details, in this case, a button element
                    {
                        type: 'button',
                        actionId: 'button_action_1',
                        appId: appId,
                        blockId: 'button_action_block_1',
                        text: {
                            type: 'plain_text',
                            text: 'Learn more!'
                        },
                        style: 'primary',
                        value: 'Button element'
                    }
                ]
            },
            {
                type: 'input', // the input block
                appId: appId,
                blockId: 'input_block',
                label: {
                    type: 'plain_text',
                    text: 'static_input'
                },
                element: { // the "element" object contains the definition of the type of input block you want to use, in this case, a static select menu
                    type: 'static_select',
                    actionId: 'static_select_action_1',
                    appId: appId,
                    blockId: 'static_select_block_1',
                    placeholder: {
                        type: 'plain_text',
                        text: 'Select an option:',
                    },
                    options: [
                        {
                            value: 'option_1',
                            text: {
                                type: 'plain_text',
                                text: 'This is your first option'
                            }
                        },
                        {
                            value: 'option_2',
                            text: {
                                type: 'plain_text',
                                text: 'This is your second option'
                            }
                        }
                    ]
                }
            }
        ])

        //messageCreator.setText('Message starred! :)');
        messageCreator.setRoom(context.message.room);
        await modify.getCreator().finish(messageCreator);
    }

The following screenshot shows the blocks returned by the app bot:

Add a context block

To the previous code snippet, we will add a context block definition as follows:

{
                type: 'context', // the context block
                appId: appId,
                blockId: 'context_block',
                elements: [
                  {
                    type: 'plain_text',
                    text: 'This is a context block'
                  }
                ]
              },
        ])

        //messageCreator.setText('Message starred! :)');
        messageCreator.setRoom(context.message.room);
        await modify.getCreator().finish(messageCreator);
    }

The following screenshot shows what the context block looks like:

Add a preview block

To this example, we will now add a preview block as follows:

{
                type: 'preview', // the preview block
                description: [
                  {
                    type: 'plain_text',
                    text: 'Description of preview'
                  }
                ],
                title: [
                  {
                    type: 'plain_text',
                    text: 'Title of preview'
                  }
                ]
              },        
        
        ])

        //messageCreator.setText('Message starred! :)');
        messageCreator.setRoom(context.message.room);
        await modify.getCreator().finish(messageCreator);
    }

The following screenshot shows how the preview block appears in the UI: